Stroika Library 3.0d18
 
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()"};
90#endif
91 // Iterable<KeyValuePair<GUID,Document::Document>> collection = fConnectionRep_->fCollections_->LookupValue (fTableName_);
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 (not filter.has_value () or filter->Matches (d)) {
97 if (projection) {
98 d = projection->Apply (d);
99 }
100 return d;
101 }
102 return nullopt;
103 });
104 }
105 virtual void Update (const IDType& id, const Document::Document& newV, const optional<Set<String>>& onlyTheseFields) override
106 {
107#if USE_NOISY_TRACE_IN_THIS_MODULE_
108 TraceContextBumper ctx{"TrivialDocumentDB::MemoryDatabaseRep_::MyCollectionRep_::Update()"};
109#endif
110 Document::Document uploadDoc = newV;
111 if (onlyTheseFields) {
112 uploadDoc.RetainAll (*onlyTheseFields);
113 }
114 static const auto kExcept1_ = RuntimeErrorException{"no such table"};
115 static const auto kExcept_ = RuntimeErrorException{"no such id"};
116 auto rwLock = fConnectionRep_->fCollections_.rwget ();
117 CollectionRep_ collection = rwLock.cref ().LookupChecked (fTableName_, kExcept1_);
118 Document::Document d2Update = onlyTheseFields ? collection.LookupChecked (id, kExcept_) : uploadDoc;
119 // any fields listed in onlyTheseFields, but not present in newV need to be removed
120 if (onlyTheseFields) {
121 d2Update.AddAll (uploadDoc);
122 Set<String> removeMe = *onlyTheseFields - newV.Keys ();
123 d2Update.RemoveAll (removeMe);
124 }
125 collection.Add (id, d2Update);
126 rwLock.rwref ().Add (fTableName_, collection); // replace the actual collection in our master database of collections
127 }
128 virtual void Remove (const IDType& id) override
129 {
130#if USE_NOISY_TRACE_IN_THIS_MODULE_
131 TraceContextBumper ctx{"TrivialDocumentDB::MemoryDatabaseRep_::MyCollectionRep_::Remove()"};
132#endif
133 auto rwLock = fConnectionRep_->fCollections_.rwget ();
134 if (optional<CollectionRep_> oc = rwLock.cref ().Lookup (fTableName_)) {
135 CollectionRep_ c = *oc;
136 if (c.RemoveIf (id)) {
137 rwLock.rwref ().Add (fTableName_, c); // replace the actual collection in our master database of collections
138 }
139 }
140 }
141 };
142
143 struct MyTransactionRep_ final : Database::Document::Transaction::IRep {
144
145 virtual void Commit () override
146 {
147 // nothing todo
148 }
149 virtual void Rollback () override
150 {
152 }
153 virtual Disposition GetDisposition () const override
154 {
155 return Disposition::eCompleted;
156 }
157 };
158
159 MemoryDatabaseRep_ ([[maybe_unused]] const Options& options)
160 {
161 TraceContextBumper ctx{"TrivialDocumentDB::MemoryDatabaseRep_::MemoryDatabaseRep_"};
162 }
163 virtual shared_ptr<const EngineProperties> GetEngineProperties () const override
164 {
165 struct MyEngineProperties_ final : EngineProperties {
166 virtual String GetEngineName () const override
167 {
168 return "TrivialDocumentDB"sv;
169 }
170 };
171 static const shared_ptr<const EngineProperties> kProps_ = make_shared<const MyEngineProperties_> ();
172 return kProps_;
173 }
174 virtual Set<String> GetCollections () override
175 {
176 return Set<String>{fCollections_.load ().Keys ()};
177 }
178 virtual void CreateCollection (const String& name) override
179 {
180 auto rwLock = fCollections_.rwget ();
181 if (not rwLock.cref ().Lookup (name)) {
182 rwLock.rwref ().Add (name, {});
183 }
184 }
185 virtual void DropCollection (const String& name) override
186 {
187 auto rwLock = fCollections_.rwget ();
188 rwLock.rwref ().RemoveIf (name);
189 }
190 virtual Document::Collection::Ptr GetCollection (const String& name) override
191 {
193 make_shared<MyCollectionRep_> (Debug::UncheckedDynamicPointerCast<MemoryDatabaseRep_> (shared_from_this ()), name)};
194 }
195 virtual Document::Transaction mkTransaction () override
196 {
197 return Document::Transaction{make_unique<MyTransactionRep_> ()};
198 }
199 };
200
201 // TMPHACK since NYI
202 using FilesystemDatabaseRep_ = MemoryDatabaseRep_;
203}
204
205/*
206 ********************************************************************************
207 *********************** SQL::TrivialDocumentDB::New ****************************
208 ********************************************************************************
209 */
210auto Document::TrivialDocumentDB::New (const Options& options) -> Ptr
211{
212 if (get_if<Options::MemoryStorage> (&options.fStorage)) {
213 return Ptr{make_shared<MemoryDatabaseRep_> (options)};
214 }
215 else if (get_if<Options::FilesystemStorage> (&options.fStorage)) {
216 return Ptr{make_shared<FilesystemDatabaseRep_> (options)};
217 }
219 return nullptr;
220}
#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