Stroika Library 3.0d20
 
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"
14
15#include "TrivialDocumentDB.h"
16
17using namespace Stroika::Foundation;
18
19using namespace Characters;
20using namespace Containers;
21using namespace Debug;
22using namespace DataExchange;
23using namespace Database;
24using namespace Database::Document::TrivialDocumentDB;
25using namespace Execution;
26using namespace Time;
27
32
33// Comment this in to turn on aggressive noisy DbgTrace in this module
34// #define USE_NOISY_TRACE_IN_THIS_MODULE_ 1
35
36using Common::GUID;
38
39namespace {
40
41 /*
42 * Store collections entirely in RAM.
43 * \note \em Thread-Safety <a href='#Internally-Synchronized-Thread-Safety'>Internally-Synchronized-Thread-Safety</a>
44 */
45 struct MemoryDatabaseRep_ final : Database::Document::Connection::IRep {
46
47 using CollectionRep_ = Mapping<GUID, Document::Document>;
48
50
51 struct MyCollectionRep_ final : Document::Collection::IRep {
52 const shared_ptr<MemoryDatabaseRep_> fConnectionRep_; // save to bump reference count
53 const String fTableName_;
54
55 MyCollectionRep_ (const shared_ptr<MemoryDatabaseRep_>& connectionRep, const String& collectionName)
56 : fConnectionRep_{connectionRep}
57 , fTableName_{collectionName}
58 {
59 }
60 virtual IDType Add (const Document::Document& v) override
61 {
62#if USE_NOISY_TRACE_IN_THIS_MODULE_
63 TraceContextBumper ctx{"TrivialDocumentDB::MemoryDatabaseRep_::MyCollectionRep_::Add()"};
64#endif
65 auto rwLock = fConnectionRep_->fCollections_.rwget ();
66 CollectionRep_ collection = rwLock.cref ().LookupValue (fTableName_);
67 GUID id = GUID::GenerateNew ();
68 collection.Add (id, v);
69 rwLock.rwref ().Add (fTableName_, collection);
70 return id.ToString ();
71 }
72 virtual optional<Document::Document> GetOne (const IDType& id, const optional<Projection>& projection) override
73 {
74#if USE_NOISY_TRACE_IN_THIS_MODULE_
75 TraceContextBumper ctx{"TrivialDocumentDB::MemoryDatabaseRep_::MyCollectionRep_::GetOne()"};
76#endif
77 auto r = fConnectionRep_->fCollections_->LookupValue (fTableName_).Lookup (GUID{id});
78 if (r) {
79 r->Add (Document::kID, id);
80 }
81 if (projection && r) {
82 r = projection->Apply (*r);
83 }
84 return r;
85 }
86 virtual Sequence<Document::Document> GetAll (const optional<Filter>& filter, const optional<Projection>& projection) override
87 {
88#if USE_NOISY_TRACE_IN_THIS_MODULE_
89 TraceContextBumper ctx{"TrivialDocumentDB::MemoryDatabaseRep_::MyCollectionRep_::GetAll()", "filter={}, projection={}"_f,
90 filter, projection};
91#endif
92 return fConnectionRep_->fCollections_->LookupValue (fTableName_)
93 .Map<Sequence<Document::Document>> ([&] (const KeyValuePair<GUID, Document::Document>& kvp) -> optional<Document::Document> {
94 Document::Document d = kvp.fValue;
95 d.Add (Document::kID, kvp.fKey.ToString ());
96 if (filter and not filter->Matches (d)) {
97 return nullopt; // skip cuz didn't match filter
98 }
99 else {
100 if (projection) {
101 d = projection->Apply (d);
102 }
103 return d;
104 }
105 });
106 }
107 virtual void Update (const IDType& id, const Document::Document& newV, const optional<Set<String>>& onlyTheseFields) override
108 {
109#if USE_NOISY_TRACE_IN_THIS_MODULE_
110 TraceContextBumper ctx{"TrivialDocumentDB::MemoryDatabaseRep_::MyCollectionRep_::Update()"};
111#endif
112 Document::Document uploadDoc = newV;
113 if (onlyTheseFields) {
114 uploadDoc.RetainAll (*onlyTheseFields);
115 }
116 static const auto kExcept1_ = RuntimeErrorException{"no such table"};
117 static const auto kExcept_ = RuntimeErrorException{"no such id"};
118 auto rwLock = fConnectionRep_->fCollections_.rwget ();
119 CollectionRep_ collection = rwLock.cref ().LookupChecked (fTableName_, kExcept1_);
120 Document::Document d2Update = onlyTheseFields ? collection.LookupChecked (id, kExcept_) : uploadDoc;
121 // any fields listed in onlyTheseFields, but not present in newV need to be removed
122 if (onlyTheseFields) {
123 d2Update.AddAll (uploadDoc);
124 Set<String> removeMe = *onlyTheseFields - newV.Keys ();
125 d2Update.RemoveAll (removeMe);
126 }
127 collection.Add (id, d2Update);
128 rwLock.rwref ().Add (fTableName_, collection); // replace the actual collection in our master database of collections
129 }
130 virtual void Remove (const IDType& id) override
131 {
132#if USE_NOISY_TRACE_IN_THIS_MODULE_
133 TraceContextBumper ctx{"TrivialDocumentDB::MemoryDatabaseRep_::MyCollectionRep_::Remove()"};
134#endif
135 auto rwLock = fConnectionRep_->fCollections_.rwget ();
136 if (optional<CollectionRep_> oc = rwLock.cref ().Lookup (fTableName_)) {
137 CollectionRep_ c = *oc;
138 if (c.RemoveIf (id)) {
139 rwLock.rwref ().Add (fTableName_, c); // replace the actual collection in our master database of collections
140 }
141 }
142 }
143 };
144
145 struct MyTransactionRep_ final : Database::Document::Transaction::IRep {
146
147 virtual void Commit () override
148 {
149 // nothing todo
150 }
151 virtual void Rollback () override
152 {
154 }
155 virtual Disposition GetDisposition () const override
156 {
157 return Disposition::eCompleted;
158 }
159 };
160
161 MemoryDatabaseRep_ ([[maybe_unused]] const Options& options)
162 {
163 TraceContextBumper ctx{"TrivialDocumentDB::MemoryDatabaseRep_::MemoryDatabaseRep_"};
164 }
165 virtual shared_ptr<const EngineProperties> GetEngineProperties () const override
166 {
167 struct MyEngineProperties_ final : EngineProperties {
168 virtual String GetEngineName () const override
169 {
170 return "TrivialDocumentDB"sv;
171 }
172 };
173 static const shared_ptr<const EngineProperties> kProps_ = make_shared<const MyEngineProperties_> ();
174 return kProps_;
175 }
176 virtual Set<String> GetCollections () override
177 {
178 return Set<String>{fCollections_.load ().Keys ()};
179 }
180 virtual void CreateCollection (const String& name) override
181 {
182 auto rwLock = fCollections_.rwget ();
183 if (not rwLock.cref ().Lookup (name)) {
184 rwLock.rwref ().Add (name, {});
185 }
186 }
187 virtual void DropCollection (const String& name) override
188 {
189 auto rwLock = fCollections_.rwget ();
190 rwLock.rwref ().RemoveIf (name);
191 }
192 virtual Document::Collection::Ptr GetCollection (const String& name) override
193 {
195 make_shared<MyCollectionRep_> (Debug::UncheckedDynamicPointerCast<MemoryDatabaseRep_> (shared_from_this ()), name)};
196 }
197 virtual Document::Transaction mkTransaction () override
198 {
199 return Document::Transaction{make_unique<MyTransactionRep_> ()};
200 }
201 };
202
203 // TMPHACK since NYI
204 using FilesystemDatabaseRep_ = MemoryDatabaseRep_;
205}
206
207/*
208 ********************************************************************************
209 *********************** SQL::TrivialDocumentDB::New ****************************
210 ********************************************************************************
211 */
212auto Document::TrivialDocumentDB::New (const Options& options) -> Ptr
213{
214 if (get_if<Options::MemoryStorage> (&options.fStorage)) {
215 return Ptr{make_shared<MemoryDatabaseRep_> (options)};
216 }
217 else if (get_if<Options::FilesystemStorage> (&options.fStorage)) {
218 return Ptr{make_shared<FilesystemDatabaseRep_> (options)};
219 }
221 return nullptr;
222}
#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