Skip to content

Commit 3e662e0

Browse files
committed
Merge remote-tracking branch 'origin/dev' into experimental/sql-view
2 parents 1bc8fbd + be161fe commit 3e662e0

3 files changed

Lines changed: 61 additions & 58 deletions

File tree

dev/statement_serializer.h

Lines changed: 7 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -555,32 +555,15 @@ namespace sqlite_orm::internal {
555555
}
556556
};
557557

558-
template<>
559-
struct statement_serializer<window_ref_t, void> {
560-
using statement_type = window_ref_t;
561-
562-
template<class Ctx>
563-
SQLITE_ORM_STATIC_CALLOP std::string operator()(const statement_type& statement,
564-
const Ctx&) SQLITE_ORM_OR_CONST_CALLOP {
565-
return statement.name;
566-
}
567-
};
568-
569558
template<class Tuple, class Ctx>
570559
void serialize_over_arguments(std::stringstream& ss, const Tuple& arguments, const Ctx& context) {
571-
using args_tuple = std::decay_t<Tuple>;
572-
constexpr bool is_named_ref = std::tuple_size<args_tuple>::value == 1 &&
573-
std::is_same<std::tuple_element_t<0, args_tuple>, window_ref_t>::value;
574-
if constexpr (is_named_ref) {
560+
if constexpr (std::tuple_size<Tuple>::value == 0) {
561+
ss << " OVER ()";
562+
} else if constexpr (std::tuple_size<Tuple>::value == 1 &&
563+
std::is_same<typename std::tuple_element<0, Tuple>::type, window_ref_t>::value) {
575564
ss << " OVER " << std::get<0>(arguments).name;
576565
} else {
577-
ss << " OVER (";
578-
std::string separator;
579-
iterate_tuple(arguments, [&ss, &context, &separator](auto& arg) {
580-
ss << separator << serialize(arg, context);
581-
separator = " ";
582-
});
583-
ss << ")";
566+
ss << " OVER (" << streaming_actions_tuple(arguments, context) << ")";
584567
}
585568
}
586569

@@ -620,13 +603,8 @@ namespace sqlite_orm::internal {
620603
SQLITE_ORM_STATIC_CALLOP std::string operator()(const statement_type& statement,
621604
const Ctx& context) SQLITE_ORM_OR_CONST_CALLOP {
622605
std::stringstream ss;
623-
ss << "WINDOW " << statement.name << " AS (";
624-
std::string separator;
625-
iterate_tuple(statement.arguments, [&ss, &context, &separator](auto& arg) {
626-
ss << separator << serialize(arg, context);
627-
separator = " ";
628-
});
629-
ss << ")";
606+
ss << "WINDOW " << statement.name << " AS (" << streaming_actions_tuple(statement.arguments, context)
607+
<< ")";
630608
return ss.str();
631609
}
632610
};

include/sqlite_orm/sqlite_orm.h

Lines changed: 7 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -22598,32 +22598,15 @@ namespace sqlite_orm::internal {
2259822598
}
2259922599
};
2260022600

22601-
template<>
22602-
struct statement_serializer<window_ref_t, void> {
22603-
using statement_type = window_ref_t;
22604-
22605-
template<class Ctx>
22606-
SQLITE_ORM_STATIC_CALLOP std::string operator()(const statement_type& statement,
22607-
const Ctx&) SQLITE_ORM_OR_CONST_CALLOP {
22608-
return statement.name;
22609-
}
22610-
};
22611-
2261222601
template<class Tuple, class Ctx>
2261322602
void serialize_over_arguments(std::stringstream& ss, const Tuple& arguments, const Ctx& context) {
22614-
using args_tuple = std::decay_t<Tuple>;
22615-
constexpr bool is_named_ref = std::tuple_size<args_tuple>::value == 1 &&
22616-
std::is_same<std::tuple_element_t<0, args_tuple>, window_ref_t>::value;
22617-
if constexpr (is_named_ref) {
22603+
if constexpr (std::tuple_size<Tuple>::value == 0) {
22604+
ss << " OVER ()";
22605+
} else if constexpr (std::tuple_size<Tuple>::value == 1 &&
22606+
std::is_same<typename std::tuple_element<0, Tuple>::type, window_ref_t>::value) {
2261822607
ss << " OVER " << std::get<0>(arguments).name;
2261922608
} else {
22620-
ss << " OVER (";
22621-
std::string separator;
22622-
iterate_tuple(arguments, [&ss, &context, &separator](auto& arg) {
22623-
ss << separator << serialize(arg, context);
22624-
separator = " ";
22625-
});
22626-
ss << ")";
22609+
ss << " OVER (" << streaming_actions_tuple(arguments, context) << ")";
2262722610
}
2262822611
}
2262922612

@@ -22663,13 +22646,8 @@ namespace sqlite_orm::internal {
2266322646
SQLITE_ORM_STATIC_CALLOP std::string operator()(const statement_type& statement,
2266422647
const Ctx& context) SQLITE_ORM_OR_CONST_CALLOP {
2266522648
std::stringstream ss;
22666-
ss << "WINDOW " << statement.name << " AS (";
22667-
std::string separator;
22668-
iterate_tuple(statement.arguments, [&ss, &context, &separator](auto& arg) {
22669-
ss << separator << serialize(arg, context);
22670-
separator = " ";
22671-
});
22672-
ss << ")";
22649+
ss << "WINDOW " << statement.name << " AS (" << streaming_actions_tuple(statement.arguments, context)
22650+
<< ")";
2267322651
return ss.str();
2267422652
}
2267522653
};

tests/window_function_tests.cpp

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,3 +200,50 @@ TEST_CASE("window functions") {
200200
REQUIRE(std::get<2>(rows[5]) == 2);
201201
}
202202
}
203+
204+
TEST_CASE("window functions - issue #475 count over with where order by limit") {
205+
struct UserProfile {
206+
int id = 0;
207+
std::string firstName;
208+
std::string lastName;
209+
};
210+
211+
auto storage = make_storage("",
212+
make_table("user_profile",
213+
make_column("id", &UserProfile::id, primary_key().autoincrement()),
214+
make_column("first_name", &UserProfile::firstName),
215+
make_column("last_name", &UserProfile::lastName)));
216+
storage.sync_schema();
217+
218+
storage.insert(UserProfile{0, "Alice", "Smith"});
219+
storage.insert(UserProfile{0, "Bob", "Jones"});
220+
storage.insert(UserProfile{0, "Charlie", "Brown"});
221+
storage.insert(UserProfile{0, "Diana", "Davis"});
222+
storage.insert(UserProfile{0, "Eve", "Wilson"});
223+
224+
int refId = 0;
225+
int resultPerPage = 3;
226+
227+
// SQL: SELECT id, first_name, last_name, COUNT(id) OVER ()
228+
// FROM user_profile WHERE id > ? ORDER BY id LIMIT ?
229+
auto rows = storage.select(
230+
columns(&UserProfile::id, &UserProfile::firstName, &UserProfile::lastName, count(&UserProfile::id).over()),
231+
where(c(&UserProfile::id) > refId),
232+
order_by(&UserProfile::id),
233+
limit(resultPerPage));
234+
235+
REQUIRE(rows.size() == 3);
236+
// Every row should have total_count=5 (total rows in table)
237+
REQUIRE(std::get<0>(rows[0]) == 1);
238+
REQUIRE(std::get<1>(rows[0]) == "Alice");
239+
REQUIRE(std::get<2>(rows[0]) == "Smith");
240+
REQUIRE(std::get<3>(rows[0]) == 5);
241+
242+
REQUIRE(std::get<0>(rows[1]) == 2);
243+
REQUIRE(std::get<1>(rows[1]) == "Bob");
244+
REQUIRE(std::get<3>(rows[1]) == 5);
245+
246+
REQUIRE(std::get<0>(rows[2]) == 3);
247+
REQUIRE(std::get<1>(rows[2]) == "Charlie");
248+
REQUIRE(std::get<3>(rows[2]) == 5);
249+
}

0 commit comments

Comments
 (0)