4#include "Stroika/Frameworks/StroikaPreComp.h"
10#include "Stroika/Foundation/Containers/Set.h"
19#include "ORMEmployeesDB.h"
27using namespace Stroika::Foundation::Database;
28using namespace Stroika::Foundation::Debug;
31using namespace Database::SQL;
32using namespace SQL::ORM;
42 bool fStillEmployed{};
54 {
"id"sv, &Employee::ID},
55 {
"Name"sv, &Employee::fName},
56 {
"Age"sv, &Employee::fAge},
57 {
"Address"sv, &Employee::fAddress},
58 {
"Salary"sv, &Employee::fSalary},
59 {
"Still-Employed"sv, &Employee::fStillEmployed},
61 {.fOmitNullEntriesInFromObject =
false});
81 {
"id"sv, &Paycheck::ID},
82 {
"Employee-Ref"sv, &Paycheck::fEmployeeRef},
83 {
"Amount"sv, &Paycheck::fAmount},
84 {
"Date"sv, &Paycheck::fDate},
86 {.fOmitNullEntriesInFromObject =
false});
97 mapper += Employee::kMapper;
98 mapper += Paycheck::kMapper;
106 const Schema::Table kEmployeesTableSchema_{
115 , {.fName =
"NAME"sv, .fVariantValueName =
"Name"sv, .fVariantValueType = VariantValue::eString}
116 , {.fName =
"AGE"sv, .fVariantValueName =
"Age"sv, .fVariantValueType = VariantValue::eInteger}, {.fName =
"ADDRESS"sv, .fVariantValueName =
"Address"sv, .fVariantValueType = VariantValue::eString}
117 , {.fName =
"SALARY"sv, .fVariantValueName =
"Salary"sv, .fVariantValueType = VariantValue::eFloat}, {.fName =
"STILL_EMPLOYED"sv, .fVariantValueName =
"Still-Employed"sv, .fVariantValueType = VariantValue::eInteger}},
118 Schema::CatchAllField{}};
125 const Schema::Table kPaychecksTableSchema_{
130 , {.fName =
"EMPLOYEEREF"sv, .fVariantValueName =
"Employee-Ref"sv, .fRequired =
true, .fVariantValueType = VariantValue::eInteger}
131 , {.fName =
"AMOUNT"sv, .fVariantValueName =
"Amount"sv, .fVariantValueType = VariantValue::eFloat}
132 , {.fName =
"DATE"sv, .fVariantValueName =
"Date"sv, .fVariantValueType = VariantValue::eDate}}};
142 auto employeeTableConnection = make_unique<SQL::ORM::TableConnection<Employee>> (conn, kEmployeesTableSchema_, kDBObjectMapper_);
145 employeeTableConnection->AddNew (Employee{.fName =
"Paul", .fAge = 32, .fAddress =
"California", .fSalary = 20000.00, .fStillEmployed =
true});
146 employeeTableConnection->AddNew (Employee{.fName =
"Allen", .fAge = 25, .fAddress =
"Texas", .fSalary = 15000.00, .fStillEmployed =
true});
147 employeeTableConnection->AddNew (Employee{.fName =
"Teddy", .fAge = 23, .fAddress =
"Norway", .fSalary = 20000.00, .fStillEmployed =
true});
148 employeeTableConnection->AddNew (Employee{.fName =
"Mark", .fAge = 25, .fAddress =
"Rich-Mond", .fSalary = 65000.00, .fStillEmployed =
true});
149 employeeTableConnection->AddNew (Employee{.fName =
"David", .fAge = 27, .fAddress =
"Texas", .fSalary = 85000.00, .fStillEmployed =
true});
150 employeeTableConnection->AddNew (Employee{.fName =
"Kim", .fAge = 22, .fAddress =
"South-Hall", .fSalary = 45000.00, .fStillEmployed =
true});
151 employeeTableConnection->AddNew (Employee{.fName =
"James", .fAge = 24, .fAddress =
"Houston", .fSalary = 10000.00, .fStillEmployed =
true});
153 default_random_engine generator;
154 uniform_int_distribution<int> distribution{1, 6};
159 static const Sequence<String> kNames_{
"Joe",
"Phred",
"Barny",
"Sue",
"Anne"};
160 uniform_int_distribution<int> namesDistr{0,
static_cast<int> (kNames_.size () - 1)};
161 uniform_int_distribution<int> ageDistr{25, 50};
162 static const Sequence<String> kAddresses{
"Houston",
"Pittsburg",
"New York",
"Paris",
"California"};
163 uniform_int_distribution<int> addressesDistr{0,
static_cast<int> (kAddresses.size () - 1)};
164 uniform_real_distribution<float> salaryDistr{10000.00, 50000.00};
167 uniform_int_distribution<int> whatTodoDistr{0, 3};
168 switch (whatTodoDistr (generator)) {
171 String name = kNames_[namesDistr (generator)];
172 cout <<
"Adding employee {}"_f(name) << endl;
173 employeeTableConnection->AddNew (Employee{nullopt, name, ageDistr (generator),
174 kAddresses[addressesDistr (generator)], salaryDistr (generator),
true});
178 auto activeEmps = employeeTableConnection->GetAll ();
179 if (not activeEmps.empty ()) {
180 uniform_int_distribution<int> empDistr{0,
static_cast<int> (activeEmps.size () - 1)};
181 Employee killMe = activeEmps[empDistr (generator)];
182 Assert (killMe.ID.has_value ());
183 cout <<
"Firing employee: {}, {}"_f(*killMe.ID, killMe.fName) << endl;
184 killMe.fStillEmployed =
false;
185 employeeTableConnection->Update (killMe);
192 cout <<
"Exception processing SQL - this should generally not happen: {}"_f(current_exception ()) << endl;
205 auto employeeTableConnection = make_unique<SQL::ORM::TableConnection<Employee>> (conn, kEmployeesTableSchema_, kDBObjectMapper_);
206 auto paycheckTableConnection = make_unique<SQL::ORM::TableConnection<Paycheck>> (conn, kPaychecksTableSchema_, kDBObjectMapper_);
209 for (
const auto& employee : employeeTableConnection->GetAll ()) {
210 Assert (employee.ID != nullopt);
211 cout <<
"Writing paycheck for employee #{} ({}) amount {}"_f(*employee.ID, employee.fName, employee.fSalary) << endl;
212 paycheckTableConnection->AddNew (Paycheck{nullopt, *employee.ID, employee.fSalary / 12, DateTime::Now ().GetDate ()});
217 cout <<
"Exception processing SQL - this should generally not happen: {}"_f(current_exception ()) << endl;
224void Stroika::Samples::SQL::ORMEmployeesDB (
const std::function<
Connection::Ptr ()>& connectionFactory)
240 Thread::New ([=] () { PeriodicallyUpdateEmployeesTable_ (conn1); }, Thread::eAutoStart,
"Update Employee Table"sv)};
242 Thread::New ([=] () { PeriodicallyWriteChecksForEmployeesTable_ (conn2); }, Thread::eAutoStart,
"Write Checks"sv)};
String is like std::u32string, except it is much easier to use, often much more space efficient,...
A Collection<T> is a container to manage an un-ordered collection of items, without equality defined ...
A generalization of a vector: a container whose elements are keyed by the natural numbers.
ObjectVariantMapper can be used to map C++ types to and from variant-union types, which can be transp...
nonvirtual void AddClass(const Traversal::Iterable< StructFieldInfo > &fieldDescriptions, const ClassMapperOptions< CLASS > &mapperOptions={})
nonvirtual void AddCommonType(ARGS &&... args)
nonvirtual WaitStatus WaitQuietly(Time::DurationSeconds timeout=Time::kInfinity)
Iterable<T> is a base class for containers which easily produce an Iterator<T> to traverse them.
Ptr New(const function< void()> &fun2CallOnce, const optional< Characters::String > &name, const optional< Configuration > &configuration)
void Sleep(Time::Duration seconds2Wait)
static constexpr string_view kDefaultExpression_AutoIncrement