Skip to content

Commit 5e48435

Browse files
authored
Merge pull request #966 from FireDaemon/issues/order_by_kth_col
Order by kth column
2 parents 45818cb + f4c9052 commit 5e48435

17 files changed

+965
-734
lines changed

dev/alias.h

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
namespace sqlite_orm {
88

99
/**
10-
* This is base class for every class which is used as a custom table alias.
10+
* This is base class for every class which is used as a custom table alias, column alias or expression alias.
1111
* For more information please look through self_join.cpp example
1212
*/
1313
struct alias_tag {};
@@ -16,7 +16,7 @@ namespace sqlite_orm {
1616

1717
/**
1818
* This is a common built-in class used for custom single character table aliases.
19-
* Also you can use language aliases `alias_a`, `alias_b` etc. instead
19+
* For convenience there exist type aliases `alias_a`, `alias_b`, ...
2020
*/
2121
template<class T, char A>
2222
struct table_alias : alias_tag {
@@ -37,7 +37,7 @@ namespace sqlite_orm {
3737

3838
column_type column;
3939

40-
alias_column_t(){};
40+
alias_column_t() {}
4141

4242
alias_column_t(column_type column_) : column(std::move(column_)) {}
4343
};
@@ -72,6 +72,17 @@ namespace sqlite_orm {
7272
expression_type expression;
7373
};
7474

75+
/**
76+
* This is a common built-in class used for custom single-character column aliases.
77+
* For convenience there exist type aliases `colalias_a`, `colalias_b`, ...
78+
*/
79+
template<char A>
80+
struct column_alias : alias_tag {
81+
static std::string get() {
82+
return std::string(1u, A);
83+
}
84+
};
85+
7586
template<class T>
7687
struct alias_holder {
7788
using type = T;
@@ -151,4 +162,14 @@ namespace sqlite_orm {
151162
using alias_y = internal::table_alias<T, 'y'>;
152163
template<class T>
153164
using alias_z = internal::table_alias<T, 'z'>;
165+
166+
using colalias_a = internal::column_alias<'a'>;
167+
using colalias_b = internal::column_alias<'b'>;
168+
using colalias_c = internal::column_alias<'c'>;
169+
using colalias_d = internal::column_alias<'d'>;
170+
using colalias_e = internal::column_alias<'e'>;
171+
using colalias_f = internal::column_alias<'f'>;
172+
using colalias_g = internal::column_alias<'g'>;
173+
using colalias_h = internal::column_alias<'h'>;
174+
using colalias_i = internal::column_alias<'i'>;
154175
}

dev/ast_iterator.h

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -654,9 +654,23 @@ namespace sqlite_orm {
654654
}
655655
};
656656

657+
/**
658+
* Column alias or literal
659+
*/
657660
template<class T>
658-
struct ast_iterator<order_by_t<T>, void> {
659-
using node_type = order_by_t<T>;
661+
struct ast_iterator<
662+
T,
663+
std::enable_if_t<polyfill::disjunction_v<polyfill::is_specialization_of<T, alias_holder>,
664+
polyfill::is_specialization_of<T, literal_holder>>>> {
665+
using node_type = T;
666+
667+
template<class L>
668+
void operator()(const node_type& /*node*/, const L& /*l*/) const {}
669+
};
670+
671+
template<class E>
672+
struct ast_iterator<order_by_t<E>, void> {
673+
using node_type = order_by_t<E>;
660674

661675
template<class L>
662676
void operator()(const node_type& node, const L& l) const {

dev/conditions.h

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,16 @@
66
#include <tuple> // std::tuple, std::tuple_size
77
#include <sstream> // std::stringstream
88

9+
#include "cxx_polyfill.h"
10+
#include "type_traits.h"
911
#include "collate_argument.h"
1012
#include "constraints.h"
1113
#include "optional_container.h"
1214
#include "serializer_context.h"
1315
#include "tags.h"
1416
#include "expression.h"
17+
#include "type_printer.h"
18+
#include "literal.h"
1519

1620
namespace sqlite_orm {
1721

@@ -1172,14 +1176,28 @@ namespace sqlite_orm {
11721176
}
11731177

11741178
/**
1175-
* ORDER BY column
1176-
* Example: storage.select(&User::name, order_by(&User::id))
1179+
* ORDER BY column, column alias or expression
1180+
*
1181+
* Examples:
1182+
* storage.select(&User::name, order_by(&User::id))
1183+
* storage.select(as<colalias_a>(&User::name), order_by(get<colalias_a>()))
11771184
*/
1178-
template<class O>
1185+
template<class O, internal::satisfies_not<std::is_base_of, integer_printer, type_printer<O>> = true>
11791186
internal::order_by_t<O> order_by(O o) {
11801187
return {std::move(o)};
11811188
}
11821189

1190+
/**
1191+
* ORDER BY positional ordinal
1192+
*
1193+
* Examples:
1194+
* storage.select(&User::name, order_by(1))
1195+
*/
1196+
template<class O, internal::satisfies<std::is_base_of, integer_printer, type_printer<O>> = true>
1197+
internal::order_by_t<internal::literal_holder<O>> order_by(O o) {
1198+
return {{std::move(o)}};
1199+
}
1200+
11831201
/**
11841202
* ORDER BY column1, column2
11851203
* Example: storage.get_all<Singer>(multi_order_by(order_by(&Singer::name).asc(), order_by(&Singer::gender).desc())

dev/get_prepared_statement.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -123,9 +123,9 @@ namespace sqlite_orm {
123123
const auto& get(const internal::prepared_statement_t<T>& statement) {
124124
using statement_type = typename std::decay<decltype(statement)>::type;
125125
using expression_type = typename statement_type::expression_type;
126-
using node_tuple = typename internal::node_tuple<expression_type>::type;
126+
using node_tuple = internal::node_tuple_t<expression_type>;
127127
using bind_tuple = typename internal::bindable_filter<node_tuple>::type;
128-
using result_tupe = typename std::tuple_element<static_cast<size_t>(N), bind_tuple>::type;
128+
using result_tupe = std::tuple_element_t<static_cast<size_t>(N), bind_tuple>;
129129
const result_tupe* result = nullptr;
130130
auto index = -1;
131131
internal::iterate_ast(statement.expression, [&result, &index](auto& node) {
@@ -146,9 +146,9 @@ namespace sqlite_orm {
146146
auto& get(internal::prepared_statement_t<T>& statement) {
147147
using statement_type = typename std::decay<decltype(statement)>::type;
148148
using expression_type = typename statement_type::expression_type;
149-
using node_tuple = typename internal::node_tuple<expression_type>::type;
149+
using node_tuple = internal::node_tuple_t<expression_type>;
150150
using bind_tuple = typename internal::bindable_filter<node_tuple>::type;
151-
using result_tupe = typename std::tuple_element<static_cast<size_t>(N), bind_tuple>::type;
151+
using result_tupe = std::tuple_element_t<static_cast<size_t>(N), bind_tuple>;
152152
result_tupe* result = nullptr;
153153
auto index = -1;
154154
internal::iterate_ast(statement.expression, [&result, &index](auto& node) {

dev/literal.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#pragma once
2+
3+
#include <utility> // std::move
4+
5+
namespace sqlite_orm {
6+
namespace internal {
7+
8+
/*
9+
* Protect an otherwise bindable element so that it is always serialized as a literal value.
10+
*/
11+
template<class T>
12+
struct literal_holder {
13+
using type = T;
14+
15+
T value;
16+
};
17+
18+
}
19+
}

0 commit comments

Comments
 (0)