Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/dev' into dev
Browse files Browse the repository at this point in the history
  • Loading branch information
trueqbit committed Jan 13, 2023
2 parents 80a30d9 + 5dee3f7 commit dae4287
Show file tree
Hide file tree
Showing 48 changed files with 522 additions and 349 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ set(CMAKE_CXX_EXTENSIONS OFF)

set(CMAKE_VERBOSE_MAKEFILE ON)

message(STATUS "Configuring ${CMAKE_PROJECT_NAME} ${sqlite_orm_VERSION}")
message(STATUS "Configuring ${PROJECT_NAME} ${sqlite_orm_VERSION}")

list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")

Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,14 +84,14 @@ Now we tell `sqlite_orm` library about our schema and provide database filename.
using namespace sqlite_orm;
auto storage = make_storage("db.sqlite",
make_table("users",
make_column("id", &User::id, autoincrement(), primary_key()),
make_column("id", &User::id, primary_key().autoincrement()),
make_column("first_name", &User::firstName),
make_column("last_name", &User::lastName),
make_column("birth_date", &User::birthDate),
make_column("image_url", &User::imageUrl),
make_column("type_id", &User::typeId)),
make_table("user_types",
make_column("id", &UserType::id, autoincrement(), primary_key()),
make_column("id", &UserType::id, primary_key().autoincrement()),
make_column("name", &UserType::name, default_value("name_placeholder"))));
```

Expand Down
2 changes: 1 addition & 1 deletion dev/ast/group_by.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ namespace sqlite_orm {
* Example: storage.get_all<Employee>(group_by(&Employee::name), having(greater_than(count(&Employee::name), 2)));
*/
template<class T>
internal::having_t<T> having(T expression) {
[[deprecated("Use group_by(...).having(...) instead")]] internal::having_t<T> having(T expression) {
return {std::move(expression)};
}
}
2 changes: 1 addition & 1 deletion dev/column.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ namespace sqlite_orm {
/*
* Encapsulates a tuple of column constraints.
*
* Op... is a constraints pack, e.g. primary_key_t, autoincrement_t etc
* Op... is a constraints pack, e.g. primary_key_t, unique_t etc
*/
template<class... Op>
struct column_constraints {
Expand Down
110 changes: 84 additions & 26 deletions dev/constraints.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,29 +27,34 @@ namespace sqlite_orm {
*/
struct autoincrement_t {};

enum class conflict_clause_t {
rollback,
abort,
fail,
ignore,
replace,
};

struct primary_key_base {
enum class order_by {
unspecified,
ascending,
descending,
};
struct {
order_by asc_option = order_by::unspecified;
conflict_clause_t conflict_clause = conflict_clause_t::rollback;
bool conflict_clause_is_on = false;
} options;
};

order_by asc_option = order_by::unspecified;
template<class T>
struct primary_key_with_autoincrement {
using primary_key_type = T;

operator std::string() const {
std::string res = "PRIMARY KEY";
switch(this->asc_option) {
case order_by::ascending:
res += " ASC";
break;
case order_by::descending:
res += " DESC";
break;
default:
break;
}
return res;
}
primary_key_type primary_key;

primary_key_with_autoincrement(primary_key_type primary_key_) : primary_key(primary_key_) {}
};

/**
Expand All @@ -59,22 +64,62 @@ namespace sqlite_orm {
*/
template<class... Cs>
struct primary_key_t : primary_key_base {
using self = primary_key_t<Cs...>;
using order_by = primary_key_base::order_by;
using columns_tuple = std::tuple<Cs...>;

columns_tuple columns;

primary_key_t(decltype(columns) c) : columns(move(c)) {}
primary_key_t(decltype(columns) columns) : columns(move(columns)) {}

self asc() const {
auto res = *this;
res.options.asc_option = order_by::ascending;
return res;
}

self desc() const {
auto res = *this;
res.options.asc_option = order_by::descending;
return res;
}

primary_key_with_autoincrement<self> autoincrement() const {
return {*this};
}

primary_key_t<Cs...> asc() const {
self on_conflict_rollback() const {
auto res = *this;
res.asc_option = order_by::ascending;
res.options.conflict_clause_is_on = true;
res.options.conflict_clause = conflict_clause_t::rollback;
return res;
}

primary_key_t<Cs...> desc() const {
self on_conflict_abort() const {
auto res = *this;
res.asc_option = order_by::descending;
res.options.conflict_clause_is_on = true;
res.options.conflict_clause = conflict_clause_t::abort;
return res;
}

self on_conflict_fail() const {
auto res = *this;
res.options.conflict_clause_is_on = true;
res.options.conflict_clause = conflict_clause_t::fail;
return res;
}

self on_conflict_ignore() const {
auto res = *this;
res.options.conflict_clause_is_on = true;
res.options.conflict_clause = conflict_clause_t::ignore;
return res;
}

self on_conflict_replace() const {
auto res = *this;
res.options.conflict_clause_is_on = true;
res.options.conflict_clause = conflict_clause_t::replace;
return res;
}
};
Expand Down Expand Up @@ -383,7 +428,13 @@ namespace sqlite_orm {
using is_foreign_key = polyfill::bool_constant<is_foreign_key_v<T>>;

template<class T>
using is_primary_key = polyfill::is_specialization_of<T, primary_key_t>;
struct is_primary_key : std::false_type {};

template<class... Cs>
struct is_primary_key<primary_key_t<Cs...>> : std::true_type {};

template<class T>
struct is_primary_key<primary_key_with_autoincrement<T>> : std::true_type {};

template<class T>
SQLITE_ORM_INLINE_VAR constexpr bool is_primary_key_v = is_primary_key<T>::value;
Expand All @@ -405,10 +456,12 @@ namespace sqlite_orm {
*/
template<typename T>
struct is_primary_key_insertable
: polyfill::disjunction<mpl::instantiate<mpl::disjunction<check_if_tuple_has<is_autoincrement>,
check_if_tuple_has_template<default_t>>,
constraints_type_t<T>>,
std::is_base_of<integer_printer, type_printer<field_type_t<T>>>> {
: polyfill::disjunction<
mpl::instantiate<mpl::disjunction<check_if_tuple_has<is_autoincrement>,
check_if_tuple_has_template<default_t>,
check_if_tuple_has_template<primary_key_with_autoincrement>>,
constraints_type_t<T>>,
std::is_base_of<integer_printer, type_printer<field_type_t<T>>>> {

static_assert(tuple_has<is_primary_key, constraints_type_t<T>>::value, "an unexpected type was passed");
};
Expand All @@ -421,6 +474,7 @@ namespace sqlite_orm {
check_if_is_template<unique_t>,
check_if_is_template<default_t>,
check_if_is_template<check_t>,
check_if_is_template<primary_key_with_autoincrement>,
check_if_is_type<collate_constraint_t>,
#if SQLITE_VERSION_NUMBER >= 3031000
check_if<is_generated_always>,
Expand Down Expand Up @@ -465,7 +519,11 @@ namespace sqlite_orm {
return {{}};
}

inline internal::autoincrement_t autoincrement() {
/**
* AUTOINCREMENT keyword. [Deprecation notice] Use `primary_key().autoincrement()` instead of using this function.
* This function will be removed in 1.9
*/
[[deprecated("Use primary_key().autoincrement()` instead")]] inline internal::autoincrement_t autoincrement() {
return {};
}

Expand Down
51 changes: 48 additions & 3 deletions dev/statement_serializer.h
Original file line number Diff line number Diff line change
Expand Up @@ -783,18 +783,63 @@ namespace sqlite_orm {
}
};

template<>
struct statement_serializer<conflict_clause_t, void> {
using statement_type = conflict_clause_t;

template<class Ctx>
std::string operator()(const statement_type& statement, const Ctx& context) const {
switch(statement) {
case conflict_clause_t::rollback:
return "ROLLBACK";
case conflict_clause_t::abort:
return "ABORT";
case conflict_clause_t::fail:
return "FAIL";
case conflict_clause_t::ignore:
return "IGNORE";
case conflict_clause_t::replace:
return "REPLACE";
}
return {};
}
};

template<class T>
struct statement_serializer<primary_key_with_autoincrement<T>, void> {
using statement_type = primary_key_with_autoincrement<T>;

template<class Ctx>
std::string operator()(const statement_type& statement, const Ctx& context) const {
return serialize(statement.primary_key, context) + " AUTOINCREMENT";
}
};

template<class... Cs>
struct statement_serializer<primary_key_t<Cs...>, void> {
using statement_type = primary_key_t<Cs...>;

template<class Ctx>
std::string operator()(const statement_type& c, const Ctx& context) const {
std::string operator()(const statement_type& statement, const Ctx& context) const {
std::stringstream ss;
ss << static_cast<std::string>(c);
ss << "PRIMARY KEY";
switch(statement.options.asc_option) {
case statement_type::order_by::ascending:
ss << " ASC";
break;
case statement_type::order_by::descending:
ss << " DESC";
break;
default:
break;
}
if(statement.options.conflict_clause_is_on) {
ss << " ON CONFLICT " << serialize(statement.options.conflict_clause, context);
}
using columns_tuple = typename statement_type::columns_tuple;
const size_t columnsCount = std::tuple_size<columns_tuple>::value;
if(columnsCount) {
ss << "(" << streaming_mapped_columns_expressions(c.columns, context) << ")";
ss << "(" << streaming_mapped_columns_expressions(statement.columns, context) << ")";
}
return ss.str();
}
Expand Down
43 changes: 0 additions & 43 deletions dev/storage.h
Original file line number Diff line number Diff line change
Expand Up @@ -1419,49 +1419,6 @@ namespace sqlite_orm {
return res;
}
#endif // SQLITE_ORM_OPTIONAL_SUPPORTED

template<class O>
bool has_dependent_rows(const O& object) {
auto res = false;
iterate_tuple<true>(
this->db_objects,
tables_index_sequence<db_objects_type>{},
[this, &object, &res](auto& table) {
if(res) {
return;
}
table.template for_each_foreign_key_to<O>([this, &table, &object, &res](auto& foreignKey) {
std::stringstream ss;
ss << "SELECT COUNT(*)"
<< " FROM " << streaming_identifier(table.name) << " WHERE ";
iterate_tuple(foreignKey.columns, [&ss, &table, first = true](auto& colRef) mutable {
auto* columnName = table.find_column_name(colRef);
if(!columnName) {
throw std::system_error{orm_error_code::column_not_found};
}

constexpr std::array<const char*, 2> sep = {" AND ", ""};
ss << sep[std::exchange(first, false)] << streaming_identifier(*columnName) << " = ?";
});
ss.flush();

auto con = this->get_connection();
sqlite3_stmt* stmt = prepare_stmt(con.get(), ss.str());
statement_finalizer finalizer{stmt};

auto& targetTable = this->get_table<O>();
tuple_value_binder{stmt}(foreignKey.references,
[&targetTable, &object](auto& memberPointer) {
return targetTable.object_field_value(object, memberPointer);
});
perform_step<SQLITE_ROW>(stmt);
auto countResult = sqlite3_column_int(stmt, 0);
res = countResult > 0;
perform_step(stmt);
});
});
return res;
}
}; // struct storage_t
}

Expand Down
2 changes: 0 additions & 2 deletions dev/storage_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,6 @@ namespace sqlite_orm {
[](sqlite3_context* context, void* functionVoidPointer, int argsCount, sqlite3_value** values) {
auto& function = *static_cast<F*>(functionVoidPointer);
args_tuple argsTuple;
using tuple_size = std::tuple_size<args_tuple>;
values_to_tuple{}(values, argsTuple, argsCount);
auto result = call(function, std::move(argsTuple));
statement_binder<return_type>().result(context, result);
Expand Down Expand Up @@ -315,7 +314,6 @@ namespace sqlite_orm {
[](sqlite3_context*, void* functionVoidPointer, int argsCount, sqlite3_value** values) {
auto& function = *static_cast<F*>(functionVoidPointer);
args_tuple argsTuple;
using tuple_size = std::tuple_size<args_tuple>;
values_to_tuple{}(values, argsTuple, argsCount);
call(function, &F::step, move(argsTuple));
},
Expand Down
2 changes: 1 addition & 1 deletion dev/table.h
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ namespace sqlite_orm {
call_as_template_base<column_field>([&lambda](const auto& column) {
lambda(column.member_pointer);
}));
this->for_each_primary_key([this, &lambda](auto& primaryKey) {
this->for_each_primary_key([&lambda](auto& primaryKey) {
iterate_tuple(primaryKey.columns, lambda);
});
}
Expand Down
2 changes: 1 addition & 1 deletion examples/chrono_binding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ int main(int argc, const char* argv[]) {

auto storage = make_storage(db_name,
make_table("Persons",
make_column("id", &Person::id, primary_key(), autoincrement()),
make_column("id", &Person::id, primary_key().autoincrement()),
make_column("name", &Person::name),
make_column("birthdate", &Person::birthdate)));

Expand Down
4 changes: 2 additions & 2 deletions examples/except_intersection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ int main() {

auto storage = make_storage("",
make_table("dept_master",
make_column("dept_id", &DeptMaster::deptId, autoincrement(), primary_key()),
make_column("dept_id", &DeptMaster::deptId, primary_key().autoincrement()),
make_column("dept_name", &DeptMaster::deptName)),
make_table("emp_master",
make_column("emp_id", &EmpMaster::empId, autoincrement(), primary_key()),
make_column("emp_id", &EmpMaster::empId, primary_key().autoincrement()),
make_column("first_name", &EmpMaster::firstName),
make_column("last_name", &EmpMaster::lastName),
make_column("salary", &EmpMaster::salary),
Expand Down
2 changes: 1 addition & 1 deletion examples/self_join.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ int main() {
auto storage =
make_storage("self_join.sqlite",
make_table("employees",
make_column("EmployeeId", &Employee::employeeId, autoincrement(), primary_key()),
make_column("EmployeeId", &Employee::employeeId, primary_key().autoincrement()),
make_column("LastName", &Employee::lastName),
make_column("FirstName", &Employee::firstName),
make_column("Title", &Employee::title),
Expand Down
2 changes: 1 addition & 1 deletion examples/unique.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ int main(int, char**) {
using namespace sqlite_orm;
auto storage = make_storage("unique.sqlite",
make_table("unique_test",
make_column("id", &Entry::id, autoincrement(), primary_key()),
make_column("id", &Entry::id, primary_key().autoincrement()),
make_column("unique_text", &Entry::uniqueColumn, unique()),
make_column("nullable_text", &Entry::nullableColumn)));
storage.sync_schema();
Expand Down
Loading

0 comments on commit dae4287

Please sign in to comment.