Stroika Library 3.0d22
 
Loading...
Searching...
No Matches
TrivialDocumentDB.cpp
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2025. All rights reserved
3 */
4#include "Stroika/Foundation/StroikaPreComp.h"
5
6#include <system_error>
7
10#include "Stroika/Foundation/Common/GUID.h"
15
16#include "TrivialDocumentDB.h"
17
18using namespace Stroika::Foundation;
19
20using namespace Characters;
21using namespace Containers;
22using namespace Debug;
23using namespace DataExchange;
24using namespace Database;
25using namespace Database::Document::TrivialDocumentDB;
26using namespace Execution;
27using namespace Time;
28
33
34// Comment this in to turn on aggressive noisy DbgTrace in this module
35// #define USE_NOISY_TRACE_IN_THIS_MODULE_ 1
36
37using Common::GUID;
39
40namespace {
41
42 /*
43 * Store collections entirely in RAM.
44 * \note \em Thread-Safety <a href='#Internally-Synchronized-Thread-Safety'>Internally-Synchronized-Thread-Safety</a>
45 */
46 struct MemoryDatabaseRep_ final : Database::Document::Connection::IRep {
47
48 using CollectionRep_ = Mapping<GUID, Document::Document>;
49
51
52 struct MyCollectionRep_ final : Document::Collection::IRep {
53 const shared_ptr<MemoryDatabaseRep_> fConnectionRep_; // save to bump reference count
54 const String fTableName_;
55
56 MyCollectionRep_ (const shared_ptr<MemoryDatabaseRep_>& connectionRep, const String& collectionName)
57 : fConnectionRep_{connectionRep}
58 , fTableName_{collectionName}
59 {
60 }
61 virtual IDType Add (const Document::Document& v) override
62 {
63#if USE_NOISY_TRACE_IN_THIS_MODULE_
64 TraceContextBumper ctx{"TrivialDocumentDB::MemoryDatabaseRep_::MyCollectionRep_::Add()"};
65#endif
66 auto rwLock = fConnectionRep_->fCollections_.rwget ();
67 CollectionRep_ collection = rwLock.cref ().LookupValue (fTableName_);
68 GUID id = GUID::GenerateNew ();
69 collection.Add (id, v);
70 rwLock.rwref ().Add (fTableName_, collection);
71 return id.ToString ();
72 }
73 virtual optional<Document::Document> GetOne (const IDType& id, const optional<Projection>& projection) override
74 {
75#if USE_NOISY_TRACE_IN_THIS_MODULE_
76 TraceContextBumper ctx{"TrivialDocumentDB::MemoryDatabaseRep_::MyCollectionRep_::GetOne()"};
77#endif
78 auto r = fConnectionRep_->fCollections_->LookupValue (fTableName_).Lookup (GUID{id});
79 if (r) {
80 r->Add (Document::kID, id);
81 }
82 if (projection && r) {
83 r = projection->Apply (*r);
84 }
85 return r;
86 }
87 virtual Sequence<Document::Document> GetAll (const optional<Filter>& filter, const optional<Projection>& projection) override
88 {
89#if USE_NOISY_TRACE_IN_THIS_MODULE_
90 TraceContextBumper ctx{"TrivialDocumentDB::MemoryDatabaseRep_::MyCollectionRep_::GetAll()", "filter={}, projection={}"_f,
91 filter, projection};
92#endif
93 return fConnectionRep_->fCollections_->LookupValue (fTableName_)
94 .Map<Sequence<Document::Document>> ([&] (const KeyValuePair<GUID, Document::Document>& kvp) -> optional<Document::Document> {
95 Document::Document d = kvp.fValue;
96 d.Add (Document::kID, kvp.fKey.ToString ());
97 if (filter and not filter->Matches (d)) {
98 return nullopt; // skip cuz didn't match filter
99 }
100 else {
101 if (projection) {
102 d = projection->Apply (d);
103 }
104 return d;
105 }
106 });
107 }
108 virtual void Update (const IDType& id, const Document::Document& newV, const optional<Set<String>>& onlyTheseFields) override
109 {
110#if USE_NOISY_TRACE_IN_THIS_MODULE_
111 TraceContextBumper ctx{"TrivialDocumentDB::MemoryDatabaseRep_::MyCollectionRep_::Update()"};
112#endif
113 Document::Document uploadDoc = newV;
114 if (onlyTheseFields) {
115 uploadDoc.RetainAll (*onlyTheseFields);
116 }
117 static const auto kExcept1_ = RuntimeErrorException{"no such table"};
118 static const auto kExcept_ = RuntimeErrorException{"no such id"};
119 auto rwLock = fConnectionRep_->fCollections_.rwget ();
120 CollectionRep_ collection = rwLock.cref ().LookupChecked (fTableName_, kExcept1_);
121 Document::Document d2Update = onlyTheseFields ? collection.LookupChecked (id, kExcept_) : uploadDoc;
122 // any fields listed in onlyTheseFields, but not present in newV need to be removed
123 if (onlyTheseFields) {
124 d2Update.AddAll (uploadDoc);
125 Set<String> removeMe = *onlyTheseFields - newV.Keys ();
126 d2Update.RemoveAll (removeMe);
127 }
128 collection.Add (id, d2Update);
129 rwLock.rwref ().Add (fTableName_, collection); // replace the actual collection in our master database of collections
130 }
131 virtual void Remove (const IDType& id) override
132 {
133#if USE_NOISY_TRACE_IN_THIS_MODULE_
134 TraceContextBumper ctx{"TrivialDocumentDB::MemoryDatabaseRep_::MyCollectionRep_::Remove()"};
135#endif
136 auto rwLock = fConnectionRep_->fCollections_.rwget ();
137 if (optional<CollectionRep_> oc = rwLock.cref ().Lookup (fTableName_)) {
138 CollectionRep_ c = *oc;
139 if (c.RemoveIf (id)) {
140 rwLock.rwref ().Add (fTableName_, c); // replace the actual collection in our master database of collections
141 }
142 }
143 }
144 };
145
146 struct MyTransactionRep_ final : Database::Document::Transaction::IRep {
147
148 virtual void Commit () override
149 {
150 // nothing todo
151 }
152 virtual void Rollback () override
153 {
155 }
156 virtual Disposition GetDisposition () const override
157 {
158 return Disposition::eCompleted;
159 }
160 };
161
162 MemoryDatabaseRep_ ([[maybe_unused]] const Options& options)
163 {
164 TraceContextBumper ctx{"TrivialDocumentDB::MemoryDatabaseRep_::MemoryDatabaseRep_"};
165 }
166 virtual shared_ptr<const EngineProperties> GetEngineProperties () const override
167 {
168 struct MyEngineProperties_ final : EngineProperties {
169 virtual String GetEngineName () const override
170 {
171 return "TrivialDocumentDB"sv;
172 }
173 };
174 static const shared_ptr<const EngineProperties> kProps_ = Memory::MakeSharedPtr<const MyEngineProperties_> ();
175 return kProps_;
176 }
177 virtual Set<String> GetCollections () override
178 {
179 return Set<String>{fCollections_.load ().Keys ()};
180 }
181 virtual void CreateCollection (const String& name) override
182 {
183 auto rwLock = fCollections_.rwget ();
184 if (not rwLock.cref ().Lookup (name)) {
185 rwLock.rwref ().Add (name, {});
186 }
187 }
188 virtual void DropCollection (const String& name) override
189 {
190 auto rwLock = fCollections_.rwget ();
191 rwLock.rwref ().RemoveIf (name);
192 }
193 virtual Document::Collection::Ptr GetCollection (const String& name) override
194 {
196 Memory::MakeSharedPtr<MyCollectionRep_> (Debug::UncheckedDynamicPointerCast<MemoryDatabaseRep_> (shared_from_this ()), name)};
197 }
198 virtual Document::Transaction mkTransaction () override
199 {
200 return Document::Transaction{make_unique<MyTransactionRep_> ()};
201 }
202 };
203
204 // TMPHACK since NYI
205 using FilesystemDatabaseRep_ = MemoryDatabaseRep_;
206}
207
208/*
209 ********************************************************************************
210 *********************** SQL::TrivialDocumentDB::New ****************************
211 ********************************************************************************
212 */
213auto Document::TrivialDocumentDB::New (const Options& options) -> Ptr
214{
215 if (get_if<Options::MemoryStorage> (&options.fStorage)) {
216 return Ptr{Memory::MakeSharedPtr<MemoryDatabaseRep_> (options)};
217 }
218 else if (get_if<Options::FilesystemStorage> (&options.fStorage)) {
219 return Ptr{Memory::MakeSharedPtr<FilesystemDatabaseRep_> (options)};
220 }
222 return nullptr;
223}
#define AssertNotImplemented()
Definition Assertions.h:401
String is like std::u32string, except it is much easier to use, often much more space efficient,...
Definition String.h:201
nonvirtual bool Add(ArgByValueType< key_type > key, ArgByValueType< mapped_type > newElt, AddReplaceMode addReplaceMode=AddReplaceMode::eAddReplaces)
Definition Mapping.inl:188
nonvirtual mapped_type LookupChecked(ArgByValueType< key_type > key, const THROW_IF_MISSING &throwIfMissing) const
nonvirtual unsigned int AddAll(ITERABLE_OF_ADDABLE &&items, AddReplaceMode addReplaceMode=AddReplaceMode::eAddReplaces)
nonvirtual void RemoveAll()
RemoveAll removes all, or all matching (predicate, iterator range, equals comparer or whatever) items...
Definition Mapping.inl:240
nonvirtual Iterable< key_type > Keys() const
Definition Mapping.inl:111
nonvirtual void RetainAll(const ITERABLE_OF_KEY_TYPE &items)
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.
EngineProperties captures the features associated with a given database engine (being talked to throu...
define a (simple) projection on a document, subsetting the fields of that document.
Definition Projection.h:32
Wrap any object with Synchronized<> and it can be used similarly to the base type,...
nonvirtual WritableReference rwget()
get a read-write smart pointer to the underlying Synchronized<> object, holding the full lock the who...
nonvirtual void Apply(const function< void(ArgByValueType< T > item)> &doToElement, Execution::SequencePolicy seq=Execution::SequencePolicy::eDEFAULT) const
Run the argument function (or lambda) on each element of the container.
static GUID GenerateNew() noexcept
Definition GUID.cpp:76