diff --git a/include/sqlpp23/core/operator/comparison_functions.h b/include/sqlpp23/core/operator/comparison_functions.h index 7481522a..f7b71b5d 100644 --- a/include/sqlpp23/core/operator/comparison_functions.h +++ b/include/sqlpp23/core/operator/comparison_functions.h @@ -169,19 +169,42 @@ enum class sort_type { template requires(values_are_comparable::value) constexpr auto asc(L l) -> sort_order_expression { - return {l, sort_type::asc}; + return {std::move(l), sort_type::asc}; } template requires(values_are_comparable::value) constexpr auto desc(L l) -> sort_order_expression { - return {l, sort_type::desc}; + return {std::move(l), sort_type::desc}; } template requires(values_are_comparable::value) constexpr auto order(L l, sort_type order) -> sort_order_expression { - return {l, order}; + return {std::move(l), order}; +} + +enum class nulls_pos { + first, + last, +}; + +template + requires(values_are_comparable::value) +constexpr auto nulls_first(L l) -> sort_order_expression { + return {std::move(l), {std::nullopt , nulls_pos::first}}; +} + +template + requires(values_are_comparable::value) +constexpr auto nulls_last(L l) -> sort_order_expression { + return {std::move(l), {std::nullopt , nulls_pos::last}}; +} + +template + requires(values_are_comparable::value) +constexpr auto nulls_order(L l, nulls_pos pos) -> sort_order_expression { + return {std::move(l), {std::nullopt , std::move(pos)}}; } } // namespace sqlpp diff --git a/include/sqlpp23/core/operator/enable_comparison.h b/include/sqlpp23/core/operator/enable_comparison.h index 426eee4c..dcf78535 100644 --- a/include/sqlpp23/core/operator/enable_comparison.h +++ b/include/sqlpp23/core/operator/enable_comparison.h @@ -125,6 +125,24 @@ class enable_comparison { return ::sqlpp::order(std::forward(self), t); } + template + constexpr auto nulls_first(this Expr&& self) + -> decltype(::sqlpp::nulls_first(std::forward(self))) { + return ::sqlpp::nulls_first(std::forward(self)); + } + + template + constexpr auto nulls_last(this Expr&& self) + -> decltype(::sqlpp::nulls_last(std::forward(self))) { + return ::sqlpp::nulls_last(std::forward(self)); + } + + template + constexpr auto nulls_order(this Expr&& self, ::sqlpp::nulls_pos t) + -> decltype(::sqlpp::nulls_order(std::forward(self), t)) { + return ::sqlpp::nulls_order(std::forward(self), t); + } + template constexpr auto like(this Expr&& self, R r) -> decltype(::sqlpp::like(std::forward(self), std::move(r))) { diff --git a/include/sqlpp23/core/operator/sort_order_expression.h b/include/sqlpp23/core/operator/sort_order_expression.h index 9f41ab5d..fa0c83bb 100644 --- a/include/sqlpp23/core/operator/sort_order_expression.h +++ b/include/sqlpp23/core/operator/sort_order_expression.h @@ -32,22 +32,60 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include namespace sqlpp { + +template +struct sort_order_with_nulls_expression { + constexpr sort_order_with_nulls_expression(sort_order_expression lhs, nulls_pos rhs) + : _lhs(std::move(lhs)), _rhs(std::move(rhs)) {} + sort_order_with_nulls_expression(const sort_order_with_nulls_expression&) = default; + sort_order_with_nulls_expression(sort_order_with_nulls_expression&&) = default; + sort_order_with_nulls_expression& operator=(const sort_order_with_nulls_expression&) = default; + sort_order_with_nulls_expression& operator=(sort_order_with_nulls_expression&&) = default; + ~sort_order_with_nulls_expression() = default; + + private: + friend reader_t; + const sort_order_expression _lhs; + const nulls_pos _rhs; +}; + template struct sort_order_expression { - constexpr sort_order_expression(L l, sort_type r) - : _lhs(std::move(l)), _rhs(std::move(r)) {} + constexpr sort_order_expression(L lhs, sort_type rhs) + : _lhs(std::move(lhs)), _rhs(std::move(rhs)) {} sort_order_expression(const sort_order_expression&) = default; sort_order_expression(sort_order_expression&&) = default; sort_order_expression& operator=(const sort_order_expression&) = default; sort_order_expression& operator=(sort_order_expression&&) = default; ~sort_order_expression() = default; + constexpr auto nulls_first() -> sort_order_with_nulls_expression; + constexpr auto nulls_last() -> sort_order_with_nulls_expression; + constexpr auto nulls_order(::sqlpp::nulls_pos t) -> sort_order_with_nulls_expression; + private: friend reader_t; L _lhs; sort_type _rhs; }; + + +template +constexpr auto sort_order_expression::nulls_first() -> sort_order_with_nulls_expression { + return {std::move(_lhs), ::sqlpp::nulls_pos::first}; +} + +template +constexpr auto sort_order_expression::nulls_last() -> sort_order_with_nulls_expression { + return {std::move(_lhs), ::sqlpp::nulls_pos::last}; +}; + +template +constexpr auto sort_order_expression::nulls_order(::sqlpp::nulls_pos t) -> sort_order_with_nulls_expression { + return {std::move(_lhs), std::move(t)}; +} + template struct nodes_of> { using type = detail::type_vector; @@ -64,6 +102,20 @@ auto to_sql_string(Context&, const sort_type& t) -> std::string { return " DESC"; } +template +auto to_sql_string(Context&, const nulls_pos& t) -> std::string { + if (t == nulls_pos::first) { + return " NULLS FIRST"; + } + return " NULLS LAST"; +} + +template +auto to_sql_string(Context& context, const sort_order& t) + -> std::string { + return to_sql_string(context, read.lhs(t)) + to_sql_string(context, read.rhs(t)); +} + template auto to_sql_string(Context& context, const sort_order_expression& t) -> std::string {