Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion include/sqlpp23/core/clause/union_order_by.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ struct simple_sort_order_expression {
private:
friend reader_t;
simple_column_t<L> _lhs;
sort_type _rhs;
sort_order _rhs;
};

template <typename Context, typename L>
Expand Down
29 changes: 26 additions & 3 deletions include/sqlpp23/core/operator/comparison_functions.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,19 +169,42 @@ enum class sort_type {
template <typename L>
requires(values_are_comparable<L, L>::value)
constexpr auto asc(L l) -> sort_order_expression<L> {
return {l, sort_type::asc};
return {std::move(l), {sort_type::asc, std::nullopt}};
}

template <typename L>
requires(values_are_comparable<L, L>::value)
constexpr auto desc(L l) -> sort_order_expression<L> {
return {l, sort_type::desc};
return {std::move(l), {sort_type::desc, std::nullopt}};
}

template <typename L>
requires(values_are_comparable<L, L>::value)
constexpr auto order(L l, sort_type order) -> sort_order_expression<L> {
return {l, order};
return {std::move(l), {std::move(order), std::nullopt}};
}

enum class nulls_pos {
first,
last,
};

template <typename L>
requires(values_are_comparable<L, L>::value)
constexpr auto nulls_first(L l) -> sort_order_expression<L> {
return {std::move(l), {std::nullopt , nulls_pos::first}};
}

template <typename L>
requires(values_are_comparable<L, L>::value)
constexpr auto nulls_last(L l) -> sort_order_expression<L> {
return {std::move(l), {std::nullopt , nulls_pos::last}};
}

template <typename L>
requires(values_are_comparable<L, L>::value)
constexpr auto nulls_order(L l, nulls_pos pos) -> sort_order_expression<L> {
return {std::move(l), {std::nullopt , std::move(pos)}};
}

} // namespace sqlpp
18 changes: 18 additions & 0 deletions include/sqlpp23/core/operator/enable_comparison.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,24 @@ class enable_comparison {
return ::sqlpp::order(std::forward<Expr>(self), t);
}

template <typename Expr>
constexpr auto nulls_first(this Expr&& self)
-> decltype(::sqlpp::nulls_first(std::forward<Expr>(self))) {
return ::sqlpp::nulls_first(std::forward<Expr>(self));
}

template <typename Expr>
constexpr auto nulls_last(this Expr&& self)
-> decltype(::sqlpp::nulls_last(std::forward<Expr>(self))) {
return ::sqlpp::nulls_last(std::forward<Expr>(self));
}

template <typename Expr>
constexpr auto nulls_order(this Expr&& self, ::sqlpp::nulls_pos t)
-> decltype(::sqlpp::nulls_order(std::forward<Expr>(self), t)) {
return ::sqlpp::nulls_order(std::forward<Expr>(self), t);
}

template <typename Expr, typename R>
constexpr auto like(this Expr&& self, R r)
-> decltype(::sqlpp::like(std::forward<Expr>(self), std::move(r))) {
Expand Down
56 changes: 53 additions & 3 deletions include/sqlpp23/core/operator/sort_order_expression.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,22 +32,58 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <sqlpp23/core/reader.h>

namespace sqlpp {

struct sort_order {
constexpr sort_order(std::optional<sort_type> l = std::nullopt, std::optional<nulls_pos> r = std::nullopt)
: _lhs(std::move(l)), _rhs(std::move(r)) {}
sort_order(const sort_order&) = default;
sort_order(sort_order&&) = default;
sort_order& operator=(const sort_order&) = default;
sort_order& operator=(sort_order&&) = default;
~sort_order() = default;

std::optional<sort_type> _lhs;
std::optional<nulls_pos> _rhs;
};

template <typename L>
struct sort_order_expression {
constexpr sort_order_expression(L l, sort_type r)
constexpr sort_order_expression(L l, sort_order r)
: _lhs(std::move(l)), _rhs(std::move(r)) {}
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_expression<L>;
constexpr auto nulls_last() -> sort_order_expression<L>;
constexpr auto nulls_order(::sqlpp::nulls_pos t) -> sort_order_expression<L>;

private:
friend reader_t;
L _lhs;
sort_type _rhs;
const L _lhs;
const sort_order _rhs;
};

template <typename L>
constexpr auto sort_order_expression<L>::nulls_first() -> sort_order_expression<L> {
static_assert(_rhs._rhs.has_value(), "nulls_first() can only be called when nulls_pos is not already set.");
return {std::move(_lhs), {std::move(_rhs._lhs), ::sqlpp::nulls_pos::first}};
}

template <typename L>
constexpr auto sort_order_expression<L>::nulls_last() -> sort_order_expression<L> {
static_assert(_rhs._rhs.has_value(), "nulls_last() can only be called when nulls_pos is not already set.");
return {std::move(_lhs), {std::move(_rhs._lhs), ::sqlpp::nulls_pos::last}};
};

template <typename L>
constexpr auto sort_order_expression<L>::nulls_order(::sqlpp::nulls_pos t) -> sort_order_expression<L> {
static_assert(_rhs._rhs.has_value(), "nulls_order(::sqlpp::nulls_pos t) can only be called when nulls_pos is not already set.");
return {std::move(_lhs), {std::move(_rhs._lhs), std::move(t)}};
}

template <typename L>
struct nodes_of<sort_order_expression<L>> {
using type = detail::type_vector<L>;
Expand All @@ -64,6 +100,20 @@ auto to_sql_string(Context&, const sort_type& t) -> std::string {
return " DESC";
}

template <typename Context>
auto to_sql_string(Context&, const nulls_pos& t) -> std::string {
if (t == nulls_pos::first) {
return " NULLS FIRST";
}
return " NULLS LAST";
}

template <typename Context>
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 <typename Context, typename L>
auto to_sql_string(Context& context, const sort_order_expression<L>& t)
-> std::string {
Expand Down
85 changes: 85 additions & 0 deletions tests/core/serialize/operator/sort_order_expression.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
* Copyright (c) 2024, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/

#include <sqlpp23/tests/core/all.h>

int main(int, char*[]) {
const auto val = sqlpp::value(1);
const auto expr = sqlpp::value(17) + 4;

// Operands are enclosed in parentheses where required.
SQLPP_COMPARE(val.nulls_last(), "1 NULLS LAST");
SQLPP_COMPARE(val.nulls_order(sqlpp::nulls_pos::first), "1 NULLS FIRST");
SQLPP_COMPARE(val.nulls_order(sqlpp::nulls_pos::last), "1 NULLS LAST");
SQLPP_COMPARE(val.nulls_first(), "1 NULLS FIRST");
SQLPP_COMPARE(val.asc(), "1 ASC");
SQLPP_COMPARE(val.asc().nulls_first(), "1 ASC NULLS FIRST");
SQLPP_COMPARE(val.asc().nulls_last(), "1 ASC NULLS LAST");
SQLPP_COMPARE(val.asc().nulls_order(sqlpp::nulls_pos::first), "1 ASC NULLS FIRST");
SQLPP_COMPARE(val.asc().nulls_order(sqlpp::nulls_pos::last), "1 ASC NULLS LAST");
SQLPP_COMPARE(val.desc(), "1 DESC");
SQLPP_COMPARE(val.desc().nulls_first(), "1 DESC NULLS FIRST");
SQLPP_COMPARE(val.desc().nulls_last(), "1 DESC NULLS LAST");
SQLPP_COMPARE(val.desc().nulls_order(sqlpp::nulls_pos::first), "1 DESC NULLS FIRST");
SQLPP_COMPARE(val.desc().nulls_order(sqlpp::nulls_pos::last), "1 DESC NULLS LAST");
SQLPP_COMPARE(val.order(sqlpp::sort_type::asc), "1 ASC");
SQLPP_COMPARE(val.order(sqlpp::sort_type::asc).nulls_first().nulls_first(), "1 ASC NULLS FIRST");
SQLPP_COMPARE(val.order(sqlpp::sort_type::asc).nulls_last(), "1 ASC NULLS LAST");
SQLPP_COMPARE(val.order(sqlpp::sort_type::asc).nulls_order(sqlpp::nulls_pos::first), "1 ASC NULLS FIRST");
SQLPP_COMPARE(val.order(sqlpp::sort_type::asc).nulls_order(sqlpp::nulls_pos::last), "1 ASC NULLS LAST");
SQLPP_COMPARE(val.order(sqlpp::sort_type::desc), "1 DESC");
SQLPP_COMPARE(val.order(sqlpp::sort_type::desc).nulls_first(), "1 DESC NULLS FIRST");
SQLPP_COMPARE(val.order(sqlpp::sort_type::desc).nulls_last(), "1 DESC NULLS LAST");
SQLPP_COMPARE(val.order(sqlpp::sort_type::desc).nulls_order(sqlpp::nulls_pos::first), "1 DESC NULLS FIRST");
SQLPP_COMPARE(val.order(sqlpp::sort_type::desc).nulls_order(sqlpp::nulls_pos::last), "1 DESC NULLS LAST");

SQLPP_COMPARE(expr.nulls_first(), "(17 + 4) NULLS FIRST");
SQLPP_COMPARE(expr.nulls_last(), "(17 + 4) NULLS LAST");
SQLPP_COMPARE(expr.nulls_order(sqlpp::nulls_pos::first), "(17 + 4) NULLS FIRST");
SQLPP_COMPARE(expr.nulls_order(sqlpp::nulls_pos::last), "(17 + 4) NULLS LAST");
SQLPP_COMPARE(expr.asc(), "(17 + 4) ASC");
SQLPP_COMPARE(expr.asc().nulls_first(), "(17 + 4) ASC NULLS FIRST");
SQLPP_COMPARE(expr.asc().nulls_last(), "(17 + 4) ASC NULLS LAST");
SQLPP_COMPARE(expr.asc().nulls_order(sqlpp::nulls_pos::first), "(17 + 4) ASC NULLS FIRST");
SQLPP_COMPARE(expr.asc().nulls_order(sqlpp::nulls_pos::last), "(17 + 4) ASC NULLS LAST");
SQLPP_COMPARE(expr.desc(), "(17 + 4) DESC");
SQLPP_COMPARE(expr.desc().nulls_first(), "(17 + 4) DESC NULLS FIRST");
SQLPP_COMPARE(expr.desc().nulls_last(), "(17 + 4) DESC NULLS LAST");
SQLPP_COMPARE(expr.desc().nulls_order(sqlpp::nulls_pos::first), "(17 + 4) DESC NULLS FIRST");
SQLPP_COMPARE(expr.desc().nulls_order(sqlpp::nulls_pos::last), "(17 + 4) DESC NULLS LAST");
SQLPP_COMPARE(expr.order(sqlpp::sort_type::asc), "(17 + 4) ASC");
SQLPP_COMPARE(expr.order(sqlpp::sort_type::asc).nulls_first(), "(17 + 4) ASC NULLS FIRST");
SQLPP_COMPARE(expr.order(sqlpp::sort_type::asc).nulls_last(), "(17 + 4) ASC NULLS LAST");
SQLPP_COMPARE(expr.order(sqlpp::sort_type::asc).nulls_order(sqlpp::nulls_pos::first), "(17 + 4) ASC NULLS FIRST");
SQLPP_COMPARE(expr.order(sqlpp::sort_type::asc).nulls_order(sqlpp::nulls_pos::last), "(17 + 4) ASC NULLS LAST");
SQLPP_COMPARE(expr.order(sqlpp::sort_type::desc), "(17 + 4) DESC");
SQLPP_COMPARE(expr.order(sqlpp::sort_type::desc).nulls_first(), "(17 + 4) DESC NULLS FIRST");
SQLPP_COMPARE(expr.order(sqlpp::sort_type::desc).nulls_last(), "(17 + 4) DESC NULLS LAST");
SQLPP_COMPARE(expr.order(sqlpp::sort_type::desc).nulls_order(sqlpp::nulls_pos::first), "(17 + 4) DESC NULLS FIRST");
SQLPP_COMPARE(expr.order(sqlpp::sort_type::desc).nulls_order(sqlpp::nulls_pos::last), "(17 + 4) DESC NULLS LAST");

return 0;
}