Skip to content
Merged
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 dev/column_result.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#pragma once

#include <type_traits> // std::enable_if, std::is_same, std::decay
#include <type_traits> // std::enable_if, std::is_same, std::decay, std::is_arithmetic
#include <tuple> // std::tuple
#include <functional> // std::reference_wrapper

Expand Down
3 changes: 3 additions & 0 deletions dev/error_code.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ namespace sqlite_orm {
invalid_collate_argument_enum,
failed_to_init_a_backup,
unknown_member_value,
incorrect_order,
};

}
Expand Down Expand Up @@ -60,6 +61,8 @@ namespace sqlite_orm {
return "Failed to init a backup";
case orm_error_code::unknown_member_value:
return "Unknown member value";
case orm_error_code::incorrect_order:
return "Incorrect order";
default:
return "unknown error";
}
Expand Down
24 changes: 17 additions & 7 deletions dev/index.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,38 @@
#include <string> // std::string
#include <utility> // std::forward

#include "indexed_column.h"

namespace sqlite_orm {

namespace internal {

struct index_base {
std::string name;
bool unique = false;
};

template<class... Cols>
struct index_t {
struct index_t : index_base {
using columns_type = std::tuple<Cols...>;
using object_type = void;

std::string name;
bool unique;
index_t(std::string name, bool unique, columns_type columns_) :
index_base{move(name), unique}, columns(move(columns_)) {}

columns_type columns;
};
}

template<class... Cols>
internal::index_t<Cols...> make_index(const std::string &name, Cols... cols) {
return {name, false, std::make_tuple(std::forward<Cols>(cols)...)};
internal::index_t<typename internal::indexed_column_maker<Cols>::type...> make_index(const std::string &name,
Cols... cols) {
return {name, false, std::make_tuple(internal::make_indexed_column(cols)...)};
}

template<class... Cols>
internal::index_t<Cols...> make_unique_index(const std::string &name, Cols... cols) {
return {name, true, std::make_tuple(std::forward<Cols>(cols)...)};
internal::index_t<typename internal::indexed_column_maker<Cols>::type...> make_unique_index(const std::string &name,
Cols... cols) {
return {name, true, std::make_tuple(internal::make_indexed_column(cols)...)};
}
}
71 changes: 71 additions & 0 deletions dev/indexed_column.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#pragma once

#include <string> // std::string

namespace sqlite_orm {

namespace internal {

template<class C>
struct indexed_column_t {
using column_type = C;

column_type column_or_expression;
std::string _collation_name;
int _order = 0; // -1 = desc, 1 = asc, 0 = not specified

indexed_column_t<column_type> collate(std::string name) {
auto res = std::move(*this);
res._collation_name = move(name);
return res;
}

indexed_column_t<column_type> asc() {
auto res = std::move(*this);
res._order = 1;
return res;
}

indexed_column_t<column_type> desc() {
auto res = std::move(*this);
res._order = -1;
return res;
}
};

template<class C>
struct indexed_column_maker {
using type = indexed_column_t<C>;

indexed_column_t<C> operator()(C col) const {
return {std::move(col)};
}
};

template<class C>
struct indexed_column_maker<indexed_column_t<C>> {
using type = indexed_column_t<C>;

indexed_column_t<C> operator()(indexed_column_t<C> col) const {
return std::move(col);
}
};

template<class C>
auto make_indexed_column(C col) {
indexed_column_maker<C> maker;
return maker(std::move(col));
}

}

/**
* Use this function to specify indexed column inside `make_index` function call.
* Example: make_index("index_name", indexed_column(&User::id).asc())
*/
template<class C>
internal::indexed_column_t<C> indexed_column(C column_or_expression) {
return {std::move(column_or_expression)};
}

}
62 changes: 61 additions & 1 deletion dev/statement_serializator.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

#include <sstream> // std::stringstream
#include <string> // std::string
#include <type_traits> // std::is_arithmetic, std::enable_if
#include <type_traits> // std::enable_if
#include <vector> // std::vector
#include <algorithm> // std::iter_swap

Expand All @@ -16,6 +16,8 @@
#include "column_names_getter.h"
#include "order_by_serializator.h"
#include "values.h"
#include "table_type.h"
#include "indexed_column.h"

namespace sqlite_orm {

Expand Down Expand Up @@ -1324,6 +1326,64 @@ namespace sqlite_orm {
}
};

template<class T>
struct statement_serializator<indexed_column_t<T>, void> {
using statement_type = indexed_column_t<T>;

template<class C>
std::string operator()(const statement_type &statement, const C &context) const {
std::stringstream ss;
ss << serialize(statement.column_or_expression, context);
if(!statement._collation_name.empty()) {
ss << " COLLATE " << statement._collation_name;
}
if(statement._order) {
switch(statement._order) {
case -1:
ss << " DESC";
break;
case 1:
ss << " ASC";
break;
default:
throw std::system_error(std::make_error_code(orm_error_code::incorrect_order));
}
}
return ss.str();
}
};

template<class... Cols>
struct statement_serializator<index_t<Cols...>, void> {
using statement_type = index_t<Cols...>;

template<class C>
std::string operator()(const statement_type &statement, const C &context) const {
std::stringstream ss;
ss << "CREATE ";
if(statement.unique) {
ss << "UNIQUE ";
}
using columns_type = typename std::decay<decltype(statement)>::type::columns_type;
using head_t = typename std::tuple_element<0, columns_type>::type::column_type;
using indexed_type = typename table_type<head_t>::type;
ss << "INDEX IF NOT EXISTS '" << statement.name << "' ON '"
<< context.impl.find_table_name(typeid(indexed_type)) << "' (";
std::vector<std::string> columnNames;
iterate_tuple(statement.columns, [&columnNames, &context](auto &v) {
columnNames.push_back(context.column_name(v.column_or_expression));
});
for(size_t i = 0; i < columnNames.size(); ++i) {
ss << "'" << columnNames[i] << "'";
if(i < columnNames.size() - 1) {
ss << ", ";
}
}
ss << ")";
return ss.str();
}
};

template<class T>
struct statement_serializator<where_t<T>, void> {
using statement_type = where_t<T>;
Expand Down
Loading