discord-bot/libs/sqlite_orm-1.8.2/tests/tests4.cpp

291 lines
12 KiB
C++

#include <sqlite_orm/sqlite_orm.h>
#include <catch2/catch_all.hpp>
#include <algorithm> // std::count_if
#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED
#include <optional> // std::optional
#endif // SQLITE_ORM_OPTIONAL_SUPPORTED
using namespace sqlite_orm;
TEST_CASE("Unique ptr in update") {
struct User {
int id = 0;
std::unique_ptr<std::string> name;
};
auto storage = make_storage(
{},
make_table("users", make_column("id", &User::id, primary_key()), make_column("name", &User::name)));
storage.sync_schema();
storage.insert(User{});
storage.insert(User{});
storage.insert(User{});
{
storage.update_all(set(assign(&User::name, std::make_unique<std::string>("Nick"))));
REQUIRE(storage.count<User>(where(is_null(&User::name))) == 0);
}
{
std::unique_ptr<std::string> ptr;
storage.update_all(set(assign(&User::name, std::move(ptr))));
REQUIRE(storage.count<User>(where(is_not_null(&User::name))) == 0);
}
}
#ifdef SQLITE_ORM_OPTIONAL_SUPPORTED
TEST_CASE("optional in update") {
struct User {
int id = 0;
std::optional<int> carYear; // will be empty if user takes the bus.
};
auto storage = make_storage(
{},
make_table("users", make_column("id", &User::id, primary_key()), make_column("car_year", &User::carYear)));
storage.sync_schema();
storage.insert(User{});
storage.insert(User{});
storage.insert(User{});
storage.insert(User{0, 2006});
REQUIRE(storage.count<User>(where(is_not_null(&User::carYear))) == 1);
{
storage.update_all(set(assign(&User::carYear, std::optional<int>{})));
REQUIRE(storage.count<User>(where(is_not_null(&User::carYear))) == 0);
}
{
storage.update_all(set(assign(&User::carYear, 1994)));
REQUIRE(storage.count<User>(where(is_null(&User::carYear))) == 0);
}
{
storage.update_all(set(assign(&User::carYear, nullptr)));
REQUIRE(storage.count<User>(where(is_not_null(&User::carYear))) == 0);
}
}
#endif // SQLITE_ORM_OPTIONAL_SUPPORTED
TEST_CASE("join") {
struct User {
int id = 0;
std::string name;
#ifndef SQLITE_ORM_AGGREGATE_NSDMI_SUPPORTED
User() = default;
User(int id, std::string name) : id{id}, name{std::move(name)} {}
#endif
};
struct Visit {
int id = 0;
int userId = 0;
time_t date = 0;
#ifndef SQLITE_ORM_AGGREGATE_NSDMI_SUPPORTED
Visit() = default;
Visit(int id, int userId, time_t date) : id{id}, userId{userId}, date{date} {}
#endif
};
auto storage =
make_storage({},
make_table("users", make_column("id", &User::id, primary_key()), make_column("name", &User::name)),
make_table("visits",
make_column("id", &Visit::id, primary_key()),
make_column("user_id", &Visit::userId),
make_column("date", &Visit::date)));
storage.sync_schema();
int id = 1;
User will{id++, "Will"};
User smith{id++, "Smith"};
User nicole{id++, "Nicole"};
storage.replace(will);
storage.replace(smith);
storage.replace(nicole);
id = 1;
storage.replace(Visit{id++, will.id, 10});
storage.replace(Visit{id++, will.id, 20});
storage.replace(Visit{id++, will.id, 30});
storage.replace(Visit{id++, smith.id, 25});
storage.replace(Visit{id++, smith.id, 35});
{
auto rows = storage.get_all<User>(left_join<Visit>(on(is_equal(&Visit::userId, 2))));
REQUIRE(rows.size() == 6);
}
{
auto rows = storage.get_all<User>(join<Visit>(on(is_equal(&Visit::userId, 2))));
REQUIRE(rows.size() == 6);
}
{
auto rows = storage.get_all<User>(left_outer_join<Visit>(on(is_equal(&Visit::userId, 2))));
REQUIRE(rows.size() == 6);
}
{
auto rows = storage.get_all<User>(inner_join<Visit>(on(is_equal(&Visit::userId, 2))));
REQUIRE(rows.size() == 6);
}
{
auto rows = storage.get_all<User>(cross_join<Visit>());
REQUIRE(rows.size() == 15);
}
{
auto rows = storage.get_all<User>(natural_join<Visit>());
REQUIRE(rows.size() == 3);
}
}
TEST_CASE("two joins") {
struct Statement {
int id_statement;
long date;
};
struct Concepto {
int id_concepto;
std::string name; // TFT-SINPE A: 15103-02**-****-8467
int fkey_account; // { 15103-02**-****-8467, ...}
};
struct Account {
int id_account;
std::string number; // 15103-02**-****-8467
int fkey_bank; // { BAC San Jose, "Barrio Dent", { Costa Rica} }
int fkey_account_owner; // { Juan Dent Herrera, ... }
std::string description; // AMEX Cashback Premium
bool is_tarjeta; // true
};
struct Pais {
int id_pais;
std::string name;
};
struct Banco {
int id_bank;
std::string nombre;
std::string ubicacion;
int fkey_pais;
};
struct AccountOwner {
int id_owner;
std::string name;
};
struct Transaccion {
int id_transaccion;
double amount_colones;
double amount_dolares;
int fkey_account_own; // Account
int fkey_account_other = 0; // Account optional
long line_date;
std::string descripcion;
int fkey_category;
int fkey_concepto;
int fkey_statement;
int row; // fkey_statement + row is unique
};
struct Categoria {
int id_categoria;
std::string name;
bool is_expense_or_income;
};
auto storage = make_storage(
{},
make_table("Statement",
make_column("id_statement", &Statement::id_statement, primary_key().autoincrement()),
make_column("date", &Statement::date)),
make_table("Categoria",
make_column("id_category", &Categoria::id_categoria, primary_key().autoincrement()),
make_column("name", &Categoria::name, collate_nocase()),
make_column("is_expense_or_income", &Categoria::is_expense_or_income)),
make_table("Concepto",
make_column("id_concepto", &Concepto::id_concepto, primary_key().autoincrement()),
make_column("name", &Concepto::name, collate_nocase()),
make_column("fkey_account", &Concepto::fkey_account),
foreign_key(&Concepto::fkey_account).references(&Account::id_account)),
make_table("Account",
make_column("id_account", &Account::id_account, primary_key().autoincrement()),
make_column("number", &Account::number, collate_nocase()),
make_column("fkey_bank", &Account::fkey_bank),
make_column("fkey_account_owner", &Account::fkey_account_owner),
make_column("description", &Account::description, collate_nocase()),
make_column("is_tarjeta", &Account::is_tarjeta),
foreign_key(&Account::fkey_account_owner).references(&AccountOwner::id_owner),
foreign_key(&Account::fkey_bank).references(&Banco::id_bank)),
make_table("Banco",
make_column("id_bank", &Banco::id_bank, primary_key().autoincrement()),
make_column("nombre", &Banco::nombre, collate_nocase()),
make_column("ubicacion", &Banco::ubicacion, collate_nocase()),
make_column("fkey_Pais", &Banco::fkey_pais),
foreign_key(&Banco::fkey_pais).references(&Pais::id_pais)),
make_table("AccountOwner",
make_column("id_owner", &AccountOwner::id_owner, primary_key().autoincrement()),
make_column("name", &AccountOwner::name, collate_nocase())),
make_table("Transaccion",
make_column("id_transaccion", &Transaccion::id_transaccion, primary_key().autoincrement()),
make_column("colones", &Transaccion::amount_colones),
make_column("dolares", &Transaccion::amount_dolares),
make_column("fkey_account_own", &Transaccion::fkey_account_own),
make_column("fkey_account_other", &Transaccion::fkey_account_other),
make_column("line_date", &Transaccion::line_date),
make_column("descripcion", &Transaccion::descripcion),
make_column("fkey_category", &Transaccion::fkey_category),
make_column("concepto", &Transaccion::fkey_concepto),
make_column("fkey_statement", &Transaccion::fkey_statement),
make_column("row", &Transaccion::row),
foreign_key(&Transaccion::fkey_account_own).references(&Account::id_account),
foreign_key(&Transaccion::fkey_account_other).references(&Account::id_account),
foreign_key(&Transaccion::fkey_category).references(&Categoria::id_categoria),
foreign_key(&Transaccion::fkey_concepto).references(&Concepto::id_concepto),
foreign_key(&Transaccion::fkey_statement).references(&Statement::id_statement)),
make_table("Pais",
make_column("id_pais", &Pais::id_pais, primary_key().autoincrement()),
make_column("name", &Pais::name, collate_nocase())));
storage.sync_schema();
using als_t = alias_t<Transaccion>;
using als_a = alias_a<Account>;
using als_b = alias_b<Account>;
std::ignore = storage.select(columns(alias_column<als_t>(&Transaccion::fkey_account_other),
alias_column<als_t>(&Transaccion::fkey_account_own),
alias_column<als_a>(&Account::id_account),
alias_column<als_b>(&Account::id_account)),
left_outer_join<als_a>(on(c(alias_column<als_t>(&Transaccion::fkey_account_other)) ==
alias_column<als_a>(&Account::id_account))),
inner_join<als_b>(on(c(alias_column<als_t>(&Transaccion::fkey_account_own)) ==
alias_column<als_b>(&Account::id_account))));
std::ignore = storage.select(columns(alias_column<als_t>(&Transaccion::fkey_account_other),
alias_column<als_t>(&Transaccion::fkey_account_own),
alias_column<als_a>(&Account::id_account),
alias_column<als_b>(&Account::id_account)),
left_join<als_a>(on(c(alias_column<als_t>(&Transaccion::fkey_account_other)) ==
alias_column<als_a>(&Account::id_account))),
inner_join<als_b>(on(c(alias_column<als_t>(&Transaccion::fkey_account_own)) ==
alias_column<als_b>(&Account::id_account))));
std::ignore = storage.select(columns(alias_column<als_t>(&Transaccion::fkey_account_other),
alias_column<als_t>(&Transaccion::fkey_account_own),
alias_column<als_a>(&Account::id_account),
alias_column<als_b>(&Account::id_account)),
join<als_a>(on(c(alias_column<als_t>(&Transaccion::fkey_account_other)) ==
alias_column<als_a>(&Account::id_account))),
inner_join<als_b>(on(c(alias_column<als_t>(&Transaccion::fkey_account_own)) ==
alias_column<als_b>(&Account::id_account))));
}