Stroika Library 3.0d18
 
Loading...
Searching...
No Matches
SQL/Sources/ComputerNetwork.cpp
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2025. All rights reserved
3 */
4#include "Stroika/Frameworks/StroikaPreComp.h"
5
6#include <cstdlib>
7#include <random>
8#include <tuple>
9
11#include "Stroika/Foundation/Common/GUID.h"
12#include "Stroika/Foundation/Containers/Set.h"
13#include "Stroika/Foundation/DataExchange/ObjectVariantMapper.h"
21
22#include "ComputerNetwork.h"
23
24using namespace std;
25
26using namespace Stroika::Foundation;
29using namespace Stroika::Foundation::Database;
30using namespace Stroika::Foundation::Database::SQL;
32using namespace Stroika::Foundation::Execution;
33using namespace Stroika::Foundation::Time;
34
35using Common::GUID;
36
37using SQL::ORM::Schema::StandardSQLStatements;
38
39namespace {
40 /// TWO ways to handle sets:
41 /// (1) store as BLOB
42 /// (2) Store in Cross-table
43
44 namespace Model {
45 struct Device {
46 GUID id;
47 Set<int> openPorts;
48 String name;
49 Set<String> hardwareAddresses;
50
51 static const ObjectVariantMapper kMapper;
52
53 nonvirtual bool operator== (const Device& rhs) const = default;
54 };
55 }
56
57 /**
58 * This defines the mapping from C++ to how we would display the object in our 'model' - like via a webservice
59 * or stored in external files, or for debugging.
60 */
61 const ObjectVariantMapper Model::Device::kMapper = [] () {
63
64 mapper.AddCommonType<Set<int>> ();
65 mapper.AddCommonType<Set<String>> ();
66
67 // ONLY DO THIS -- store GUIDs as BLOBs - WHEN WRITING TO DB (cuz more efficient)
68 mapper.AddCommonType<Common::GUID> (VariantValue::eBLOB);
69
70 mapper.AddClass<Device> ({
71 {"id"sv, &Device::id},
72 {"name"sv, &Device::name},
73 {"openPorts"sv, &Device::openPorts},
74 {"hardwareAddresses"sv, &Device::hardwareAddresses},
75 });
76
77 return mapper;
78 }();
79
80 /**
81 * This defines the mapping from our external data model (Device::kMapper) to the SQL data model.
82 */
83 const SQL::ORM::Schema::Table kDeviceTableSchema_{
84 "Devices"sv,
85 /*
86 * use the same names as the ObjectVariantMapper for simpler mapping, or specify an alternate name
87 * for ID, just as an example.
88 */
90 /**
91 * For ID, generate random GUID (BLOB) automatically in database
92 */
93 {.fName = "ID"sv, .fVariantValueName = "id"sv, .fRequired = true, .fVariantValueType = VariantValue::eBLOB, .fIsKeyField = true, .fDefaultExpression = "randomblob(16)"sv},
94 {.fName = "name"sv, .fRequired = true, .fVariantValueType = VariantValue::eString}},
95 SQL::ORM::Schema::CatchAllField{}};
96}
97
98void Stroika::Samples::SQL::ComputerNetworksModel (const std::function<Connection::Ptr ()>& connectionFactory)
99{
100 /*
101 */
102 Connection::Ptr conn = connectionFactory ();
103
104 constexpr Common::Version kCurrentVersion_ = Common::Version{1, 0, Common::VersionStage::Alpha, 0};
105 ORM::ProvisionForVersion (conn, kCurrentVersion_, Traversal::Iterable<ORM::Schema::Table>{kDeviceTableSchema_});
106
107 using Model::Device;
108 auto addDevice = [&] (const Device& d) {
109 Statement addDeviceStatement = conn.mkStatement (StandardSQLStatements{kDeviceTableSchema_}.Insert ());
110 addDeviceStatement.Execute (kDeviceTableSchema_.MapToDB (Device::kMapper.FromObject (d).As<Mapping<String, VariantValue>> ()));
111 };
112 auto getAllDevices = [&] () -> Sequence<Device> {
113 Statement getAllDevicesStatement = conn.mkStatement (StandardSQLStatements{kDeviceTableSchema_}.GetAllElements ());
114 return getAllDevicesStatement.GetAllRows ().Map<Sequence<Device>> (
115 [] (const Statement::Row& r) { return Device::kMapper.ToObject<Device> (VariantValue{kDeviceTableSchema_.MapFromDB (r)}); });
116 };
117 auto removeDevice = [&] (const GUID& id) {
118 Statement deleteDeviceStatement = conn.mkStatement (StandardSQLStatements{kDeviceTableSchema_}.DeleteByID ());
119 deleteDeviceStatement.Execute (initializer_list<Common::KeyValuePair<String, VariantValue>>{
120 {kDeviceTableSchema_.GetIDField ()->fName, VariantValue{static_cast<Memory::BLOB> (id)}}});
121 };
122
123 const Device kDevice1_ = Device{GUID::GenerateNew (), Set<int>{33}, "myLaptop"sv, Set<String>{"ff:33:aa:da:ff:33"}};
124 const Device kDevice2_ = Device{GUID::GenerateNew (), Set<int>{123, 145}, "some machine"sv, Set<String>{"33:aa:dd:ad:af:11"}};
125 if (not getAllDevices ().empty ()) {
126 Execution::Throw (Execution::RuntimeErrorException{"database should start empty"});
127 }
128 addDevice (kDevice1_);
129 addDevice (kDevice2_);
130 {
131 auto devices = getAllDevices ();
132 if (devices.size () != 2) {
133 Execution::Throw (Execution::RuntimeErrorException{"we should have the ones we just added"sv});
134 }
135 if (not devices.Contains (kDevice1_)) {
136 Execution::Throw (Execution::RuntimeErrorException{"we should have the ones we just added{1}"sv});
137 }
138 if (not devices.Contains (kDevice2_)) {
139 Execution::Throw (Execution::RuntimeErrorException{"we should have the ones we just added{2}"sv});
140 }
141 }
142 removeDevice (kDevice2_.id);
143 {
144 auto devices = getAllDevices ();
145 if (devices.size () != 1) {
146 Execution::Throw (Execution::RuntimeErrorException{"we should have the ones we just added"});
147 }
148 if (not devices.Contains (kDevice1_)) {
149 Execution::Throw (Execution::RuntimeErrorException{"we should have kDevice1_"});
150 }
151 }
152}
String is like std::u32string, except it is much easier to use, often much more space efficient,...
Definition String.h:201
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.
Set<T> is a container of T, where once an item is added, additionally adds () do nothing.
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)
Simple variant-value (case variant union) object, with (variant) basic types analogous to a value in ...
nonvirtual Sequence< Row > GetAllRows()
call Reset (), and then GetAllRemainingRows () - which always starts current statement with current b...
Definition Statement.inl:64
Iterable<T> is a base class for containers which easily produce an Iterator<T> to traverse them.
Definition Iterable.h:237
STL namespace.
static GUID GenerateNew() noexcept
Definition GUID.cpp:76