4#include "Stroika/Foundation/StroikaPreComp.h"
6#if qStroika_HasComponent_mongocxxdriver
8#if defined(__clang_major__) and (16 < __clang_major__ && __clang_major__ < 21)
9DISABLE_COMPILER_CLANG_WARNING_START (
"clang diagnostic ignored \"-Wdeprecated-literal-operator\"");
11#include <bsoncxx/builder/basic/document.hpp>
12#include <bsoncxx/document/value.hpp>
13#include <bsoncxx/json.hpp>
14#include <bsoncxx/string/to_string.hpp>
15#include <bsoncxx/types.hpp>
16#include <bsoncxx/types/bson_value/value.hpp>
17#include <bsoncxx/types/bson_value/view.hpp>
18#include <bsoncxx/view_or_value.hpp>
19#include <mongocxx/client.hpp>
20#include <mongocxx/collection.hpp>
21#include <mongocxx/exception/exception.hpp>
22#include <mongocxx/exception/operation_exception.hpp>
23#include <mongocxx/instance.hpp>
24#include <mongocxx/pool.hpp>
25#include <mongocxx/uri.hpp>
26#if defined(__clang_major__) and (16 < __clang_major__ && __clang_major__ < 21)
27DISABLE_COMPILER_CLANG_WARNING_END (
"clang diagnostic ignored \"-Wdeprecated-literal-operator\"");
29DISABLE_COMPILER_MSC_WARNING_END (4166)
34#include "Stroika/Foundation/Containers/Concrete/Mapping_HashTable.h"
38#include "Stroika/Foundation/Database/Exception.h"
39#include "Stroika/Foundation/Debug/Main.h"
41#include "Stroika/Foundation/Memory/Common.h"
43#include "MongoDBClient.h"
48using namespace Stroika::Foundation::Database;
49using namespace Stroika::Foundation::Database::Document::MongoDBClient;
51using namespace Stroika::Foundation::Debug;
53using namespace Stroika::Foundation::Memory;
72#if qStroika_HasComponent_mongocxxdriver
74using bsoncxx::builder::basic::kvp;
75using bsoncxx::builder::basic::make_array;
76using bsoncxx::builder::basic::make_document;
77using bsoncxx::builder::basic::sub_array;
78using bsoncxx::builder::basic::sub_document;
81 const String kMongoID_ =
"_id"sv;
85 atomic<unsigned int> sActivatorLiveCnt_{0};
89 auto ConnectionString2MongoURI_ (
const String& connectionString)
91 return mongocxx::uri{connectionString.
AsUTF8<
string> ()};
96 bsoncxx::types::bson_value::value ToBSONId_ (
const string_view& s)
98 if (s.length () == 24) {
100 return bsoncxx::types::b_oid{bsoncxx::oid{s}};
103 return bsoncxx::types::bson_value::value{s};
109 String cvt2String_ (
const bsoncxx::stdx::string_view& bs)
111 return String::FromUTF8 (SpanBytesCast<span<const char8_t>> (span{bs}));
113 String cvt2String_ (
const bsoncxx::types::b_string& bs)
115 return String::FromUTF8 (SpanBytesCast<span<const char8_t>> (span{bs.value}));
120 [[noreturn]]
void DoReThrow_ ()
132 String ID_2_string_ (
const bsoncxx::types::bson_value::view& value)
134 switch (value.type ()) {
135 case bsoncxx::type::k_oid:
136 return String{value.get_oid ().value.to_string ()};
137 case bsoncxx::type::k_string:
138 return cvt2String_ (value.get_string ());
144 template <Common::IAnyOf<bsoncxx::types::bson_value::view, bsoncxx::document::element, bsoncxx::document::value, bsoncxx::array::element> T>
147 switch (value.type ()) {
148 case bsoncxx::type::k_double:
149 return value.get_double ().value;
150 case bsoncxx::type::k_string:
151 return cvt2String_ (value.get_string ());
152 case bsoncxx::type::k_document: {
154 const bsoncxx::types::b_document& thisDoc = value.get_document ();
155 for (
auto di : thisDoc.value) {
156 vvResult.
Add (String::FromUTF8 (span{di.key ()}), BSON2VV_ (di));
160 case bsoncxx::type::k_array: {
161 vector<VariantValue> vvResult;
162 const bsoncxx::types::b_array& thisArray = value.get_array ();
163 vvResult.reserve (distance (thisArray.value.begin (), thisArray.value.end ()));
164 for (
auto ai : thisArray.value) {
165 vvResult.push_back (BSON2VV_ (ai));
169 case bsoncxx::type::k_binary:
170 return Memory::BLOB{span{value.get_binary ().bytes,
static_cast<size_t> (value.get_binary ().size)}};
171 case bsoncxx::type::k_undefined:
173 case bsoncxx::type::k_oid:
174 return String{value.get_oid ().value.to_string ()};
175 case bsoncxx::type::k_bool:
176 return static_cast<bool> (value.get_bool ());
177 case bsoncxx::type::k_date:
179 return Time::DateTime{chrono::time_point<chrono::system_clock>{value.get_date ().value}};
180 case bsoncxx::type::k_null:
182 case bsoncxx::type::k_regex:
183 return cvt2String_ (value.get_string ());
184 case bsoncxx::type::k_dbpointer:
187 case bsoncxx::type::k_code:
190 case bsoncxx::type::k_symbol:
193 case bsoncxx::type::k_codewscope:
196 case bsoncxx::type::k_int32:
197 return value.get_int32 ().value;
198 case bsoncxx::type::k_timestamp:
201 case bsoncxx::type::k_int64:
202 return value.get_int64 ().value;
203 case bsoncxx::type::k_decimal128:
206 case bsoncxx::type::k_maxkey:
207 case bsoncxx::type::k_minkey:
215 bsoncxx::types::bson_value::value VV2BSONV_ (
const VariantValue& vv)
217 using namespace std::chrono;
219 switch (vv.GetType ()) {
220 case VariantValue::Type::eNull:
221 return bsoncxx::types::bson_value::value{
nullptr};
222 case VariantValue::Type::eBLOB:
223 return bsoncxx::types::bson_value::value{vv.
As<
Memory::BLOB> ().As<vector<uint8_t>> ()};
224 case VariantValue::Type::eBoolean:
225 return bsoncxx::types::bson_value::value{vv.
As<
bool> ()};
226 case VariantValue::Type::eInteger:
227 return bsoncxx::types::bson_value::value{vv.
As<int64_t> ()};
228 case VariantValue::Type::eUnsignedInteger:
229 return bsoncxx::types::bson_value::value{
static_cast<int64_t
> (vv.
As<uint64_t> ())};
230 case VariantValue::Type::eFloat:
231 return bsoncxx::types::bson_value::value{vv.
As<
double> ()};
232 case VariantValue::Type::eDate:
240 case VariantValue::Type::eDateTime:
248 return vv.
As<DateTime> ().AsUTC ().Format (DateTime::kISO8601Format).AsUTF8<
string> ();
249 case VariantValue::Type::eString:
250 return bsoncxx::types::bson_value::value{vv.
As<
String> ().AsUTF8<string> ()};
251 case VariantValue::Type::eArray: {
252 bsoncxx::builder::basic::array bsonArr;
254 bsonArr.append (VV2BSONV_ (ai));
256 return bsoncxx::types::bson_value::value{bsonArr};
258 case VariantValue::Type::eMap: {
259 bsoncxx::builder::basic::document bsonDoc;
261 bsonDoc.append (kvp (ai.fKey.AsUTF8<
string> (), VV2BSONV_ (ai.fValue)));
263 return bsoncxx::types::bson_value::value{bsonDoc};
267 return bsoncxx::types::bson_value::value{
nullptr};
273 for (
const bsoncxx::document::element& di : b.view ()) {
274 result.
Add (String::FromUTF8 (span{di.key ()}), BSON2VV_ (di));
279 result.
Remove (kMongoID_);
280 result.
Add (Database::Document::kID, idValue);
291 auto idValue = vv[Database::Document::kID];
292 newDoc.
Remove (Database::Document::kID);
293 id = idValue.
As<
String> ().AsUTF8<string> ();
295 bsoncxx::builder::basic::document bsonDoc;
297 bsonDoc.append (kvp (ai.fKey.AsUTF8<
string> (), VV2BSONV_ (ai.fValue)));
300 bsonDoc.append (kvp (
"_id", ToBSONId_ (*
id)));
302 return bsonDoc.extract ();
313 tuple<optional<bsoncxx::document::value>, optional<Filter>> Partition_ (
const optional<Filter>& filter)
323 bsoncxx::builder::basic::document filterDoc;
324 bool anyTransfers =
false;
326 bool transferred =
false;
327 if (
const Document::FilterElements::Equals* eqOp = get_if<Document::FilterElements::Equals> (&op)) {
328 String useFieldName = eqOp->fLHS == Database::Document::kID ? kMongoID_ : eqOp->fLHS;
331 if (useFieldName == kMongoID_) {
333 filterDoc.append (kvp (
"_id", ToBSONId_ (rhsValue->As<
String> ().
AsUTF8<
string> ())));
336 filterDoc.append (kvp (useFieldName.
AsUTF8<
string> (), VV2BSONV_ (*rhsValue)));
342 if (not transferred) {
348 return make_tuple (filterDoc.extract (), clientSideOps.
empty () ? optional<Filter>{} : make_optional (
Filter{clientSideOps}));
351 return make_tuple (nullopt, filter);
353 return make_tuple (nullopt, nullopt);
366 tuple<optional<bsoncxx::document::value>, optional<Projection>> Partition_ (
const optional<Projection>& p)
372 tuple<Document::Projection::Flag, Set<String>> fields = p->GetFields ();
373 Require (get<1> (fields).size () >= 1);
374 bsoncxx::builder::basic::document projectionDoc;
375 for (
String f : get<1> (fields)) {
376 String mongoFieldName = f;
377 if (mongoFieldName == Database::Document::kID) {
378 mongoFieldName = kMongoID_;
380 projectionDoc.append (kvp (mongoFieldName.
AsUTF8<
string> (), get<0> (fields) == Document::Projection::Flag::eInclude ? 1 : 0));
382 return make_tuple (projectionDoc.extract (), nullopt);
384 return make_tuple (nullopt, nullopt);
389 template <InternallySynchronized SYNC_STYLE>
391 conditional_t<SYNC_STYLE == InternallySynchronized::eNotKnownInternallySynchronized, Debug::AssertExternallySynchronizedMutex, recursive_mutex>;
392 static_assert (Common::StdCompat::BasicLockable<MyMaybeLock_<InternallySynchronized::eNotKnownInternallySynchronized>>);
393 static_assert (Common::StdCompat::BasicLockable<MyMaybeLock_<InternallySynchronized::eInternallySynchronized>>);
397 template <Execution::InternallySynchronized SYNC_STYLE>
398 struct AdminRep_ final : Stroika::Foundation::Database::Document::MongoDBClient::AdminConnection::IRep {
403 variant<mongocxx::client, mongocxx::pool::entry> fClientStorage_;
404 mongocxx::client* fClientPtr_;
406 AdminRep_ (
const AdminRep_&) =
delete;
407 AdminRep_ (
const AdminConnection::Options& options)
410 if (
auto os = get_if<String> (&options.fConnectionTarget)) {
411 fClientStorage_ = mongocxx::client{ConnectionString2MongoURI_ (*os)};
412 fClientPtr_ = get_if<mongocxx::client> (&fClientStorage_);
414 else if (
auto op = get_if<ConnectionPool> (&options.fConnectionTarget)) {
415 fClientStorage_ = op->PeekPool ().acquire ();
416 fClientPtr_ = get<mongocxx::pool::entry> (fClientStorage_).operator->();
420 ~AdminRep_ () =
default;
424 virtual mongocxx::client& GetClientRef ()
override
430#if USE_NOISY_TRACE_IN_THIS_MODULE_
433 scoped_lock critSec{fMaybeLock_};
435 return FromBSON_ (fClientPtr_->database (
"admin").run_command (ToBSON_ (v)));
443 scoped_lock critSec{fMaybeLock_};
445 vector<string> n = fClientPtr_->list_database_names ();
452 virtual void DropDatabase (
const String& dbName)
override
454 scoped_lock critSec{fMaybeLock_};
456 mongocxx::database{fClientPtr_->database (dbName.
AsUTF8<
string> ())}.drop ();
462 virtual void CreateDatabase (
const String& dbName)
override
464 scoped_lock critSec{fMaybeLock_};
467 mongocxx::database d{fClientPtr_->database (dbName.
AsUTF8<
string> ())};
468 d.create_collection (
"_junk_");
469 d.collection (
"_junk_").drop ();
479 template <Execution::InternallySynchronized SYNC_STYLE>
480 struct ConnectionRep_ final : Stroika::Foundation::Database::Document::MongoDBClient::Connection::IRep {
482 shared_ptr<ConnectionRep_> fConnectionRep_;
483 mongocxx::collection fCollection_;
485 CollectionRep_ (
const shared_ptr<ConnectionRep_>& connectionRep,
const String& collectionName)
486 : fConnectionRep_{connectionRep}
487 , fCollection_{connectionRep->fDatabase_.collection (collectionName.AsUTF8<string> ())}
490 virtual String GetName ()
const override
492 return cvt2String_ (fCollection_.name ());
496#if USE_NOISY_TRACE_IN_THIS_MODULE_
499 Require (not v.
ContainsKey (Database::Document::kID) or fConnectionRep_->fOptions_.fAddAllowsExternallySpecifiedIDs);
500 scoped_lock declareContext{fConnectionRep_->fMaybeLock_};
501 return fConnectionRep_->WrapExecute_ (
505 if (
auto insert_one_result = fCollection_.insert_one (ToBSON_ (v))) {
506 return ID_2_string_ (insert_one_result->inserted_id ());
514 cvt2String_ (fCollection_.name ()),
true);
516 virtual optional<Document::Document> Get (
const IDType&
id,
const optional<Projection>& projection)
override
518#if USE_NOISY_TRACE_IN_THIS_MODULE_
521 scoped_lock declareContext{fConnectionRep_->fMaybeLock_};
522 return fConnectionRep_->WrapExecute_ (
523 [&] () -> optional<Document::Document> {
525 bsoncxx::builder::basic::document filterDoc;
526 filterDoc.append (kvp (
"_id", ToBSONId_ (
id.AsUTF8<string> ())));
527 auto [mongoProjection, myProjection] = Partition_ (projection);
528 mongocxx::options::find o;
529 if (mongoProjection) {
530 o.projection (mongoProjection->view ());
532 auto result = fCollection_.find_one (filterDoc.view (), o);
534 auto rr = FromBSON_ (bsoncxx::document::view_or_value{*result});
536 rr = myProjection->
Apply (rr);
546 cvt2String_ (fCollection_.name ()),
false);
550#if USE_NOISY_TRACE_IN_THIS_MODULE_
551 TraceContextBumper ctx{
"MongoDBClient::CollectionRep_::GetAll",
"filter={}, projection={}"_f, filter, projection};
553 scoped_lock declareContext{fConnectionRep_->fMaybeLock_};
554 return fConnectionRep_->WrapExecute_ (
556 auto [mongoFilter, myFilter] = Partition_ (filter);
559 auto [mongoProjection, myProjection] = myFilter == nullopt ? Partition_ (projection) : make_tuple (nullopt, projection);
560#if USE_NOISY_TRACE_IN_THIS_MODULE_
561 DbgTrace (
"myFilter={}"_f, myFilter);
567 mongocxx::options::find o;
568 if (mongoProjection) {
569 o.projection (mongoProjection->view ());
572 auto cursor = fCollection_.find (mongoFilter ? mongoFilter->view () : bsoncxx::builder::basic::document{}.view (), o);
573 for (
auto&& doc : cursor) {
574 auto rr = FromBSON_ (doc);
576 rr = myProjection->Apply (rr);
578 if (not myFilter or myFilter->Matches (rr)) {
588 cvt2String_ (fCollection_.name ()),
false);
592#if USE_NOISY_TRACE_IN_THIS_MODULE_
595 scoped_lock declareContext{fConnectionRep_->fMaybeLock_};
596 fConnectionRep_->WrapExecute_ (
600 if (onlyTheseFields) {
603 uploadDoc.
RemoveIf (Database::Document::kID);
605 bsoncxx::document::value bsonDoc = ToBSON_ (uploadDoc);
606 if (onlyTheseFields) {
607 if (
auto o = fCollection_.update_one (make_document (kvp (
"_id", ToBSONId_ (
id.AsUTF8<string> ()))),
608 make_document (kvp (
"$set", bsonDoc.view ())))) {
609 if (o->modified_count () == 0) {
620 if (
auto o = fCollection_.replace_one (make_document (kvp (
"_id", ToBSONId_ (
id.AsUTF8<string> ()))),
622 if (o->modified_count () == 0) {
637 cvt2String_ (fCollection_.name ()),
true);
639 virtual void Remove (
const IDType&
id)
override
641#if USE_NOISY_TRACE_IN_THIS_MODULE_
644 scoped_lock declareContext{fConnectionRep_->fMaybeLock_};
645 fConnectionRep_->WrapExecute_ (
648 bsoncxx::builder::basic::document filterDoc;
649 filterDoc.append (kvp (
"_id", ToBSONId_ (
id.AsUTF8<string> ())));
650 auto result = fCollection_.delete_one (filterDoc.view ());
651 if (result && result->deleted_count () == 0) {
659 cvt2String_ (fCollection_.name ()),
true);
667 variant<mongocxx::client, mongocxx::pool::entry> fClientStorage_;
668 mongocxx::database fDatabase_;
669 const Connection::Options fOptions_;
671 ConnectionRep_ (
const Connection::Options& options)
676 if (
auto os = get_if<String> (&options.fConnectionTarget)) {
677 fClientStorage_ = mongocxx::client{ConnectionString2MongoURI_ (*os)};
678 fDatabase_ = get<mongocxx::client> (fClientStorage_).database (options.fDatabase.AsUTF8<
string> ());
680 else if (
auto op = get_if<ConnectionPool> (&options.fConnectionTarget)) {
681 fClientStorage_ = op->PeekPool ().acquire ();
682 fDatabase_ = get<mongocxx::pool::entry> (fClientStorage_)->database (options.fDatabase.AsUTF8<
string> ());
690 ~ConnectionRep_ () =
default;
694 virtual shared_ptr<const EngineProperties> GetEngineProperties ()
const override
697 virtual String GetEngineName ()
const override
699 return "mongo-cxx-driver"sv;
702 return Memory::MakeSharedPtr<const MyEngineProperties_> ();
704 virtual Document::Connection::Options GetOptions ()
const override
708 virtual uintmax_t GetSpaceConsumed ()
const override
710 bsoncxx::builder::basic::document db_stats_cmd_builder;
711 db_stats_cmd_builder.append (bsoncxx::builder::basic::kvp (
"dbStats", 1));
712 bsoncxx::document::value command_result = mongocxx::database{fDatabase_}.run_command (db_stats_cmd_builder.view ());
713 bsoncxx::document::view result_view = command_result.view ();
715 if (
auto oStorageSize = result_view[
"storageSize"]) {
716 if (oStorageSize.type () == bsoncxx::types::b_int64::type_id) {
717 return oStorageSize.get_int64 ();
719 else if (oStorageSize.type () == bsoncxx::types::b_double::type_id) {
720 return static_cast<uintmax_t
> (oStorageSize.get_double ());
723 DbgTrace (
"dbStats result_view[storageSize].type ()={}"_f, oStorageSize.type ());
731 scoped_lock declareContext{fMaybeLock_};
732 return WrapExecute_ (
735 vector<string> n = fDatabase_.list_collection_names ();
738 catch (
const mongocxx::v_noabi::operation_exception& e) {
740 if (e.raw_server_error ()) {
741 DbgTrace (
"e.raw={}"_f, FromBSON_ (e.raw_server_error ()->view ()));
754#if USE_NOISY_TRACE_IN_THIS_MODULE_
757 scoped_lock declareContext{fMaybeLock_};
758 return WrapExecute_ (
760 fDatabase_.create_collection (name.
AsUTF8<
string> ());
761 return GetCollection (name);
765 virtual void DropCollection (
const String& name)
override
767#if USE_NOISY_TRACE_IN_THIS_MODULE_
770 scoped_lock declareContext{fMaybeLock_};
774 fDatabase_.collection (name.
AsUTF8<
string> ()).drop ();
784 scoped_lock declareContext{fMaybeLock_};
785 Require (GetCollections ().Contains (name));
788 Memory::MakeSharedPtr<CollectionRep_> (Debug::UncheckedDynamicPointerCast<ConnectionRep_> (shared_from_this ()), name)};
796 scoped_lock declareContext{fMaybeLock_};
808 virtual mongocxx::client& GetClientRef ()
override
810 if (
auto oc = get_if<mongocxx::client> (&fClientStorage_)) {
813 else if (
auto oe = get_if<mongocxx::pool::entry> (&fClientStorage_)) {
814 return *oe->operator->();
818 static mongocxx::client x;
824 template <
typename FUN>
825 inline auto WrapExecute_ (FUN&& f,
const optional<String>& collectionName,
bool write) -> invoke_result_t<FUN>
827 return Document::Connection::Private_::WrapLoggingExecuteHelper_ (forward<FUN> (f),
this, fOptions_, collectionName, write);
837unique_ptr<mongocxx::instance> Document::MongoDBClient::Activator::sMongoInstance_;
839Document::MongoDBClient::Activator::Activator ()
840 : fAllowReactivation_{false}
842 Require (Debug::AppearsDuringMainLifetime ());
843 if (sActivatorLiveCnt_.fetch_add (1) == 0) {
844 if (not sMongoInstance_) {
845 sMongoInstance_ = make_unique<mongocxx::instance> ();
850Document::MongoDBClient::Activator::Activator (AllowReactivateFlag)
853 fAllowReactivation_ =
true;
856Document::MongoDBClient::Activator::~Activator ()
858 Require (Debug::AppearsDuringMainLifetime ());
859 Require (sActivatorLiveCnt_ > 0);
860 if (sActivatorLiveCnt_.fetch_sub (1) == 0 and not fAllowReactivation_) {
861 sMongoInstance_.reset ();
870ConnectionPool::ConnectionPool (shared_ptr<mongocxx::pool>&& poolRep)
871 : fPool_{move (poolRep)}
874ConnectionPool::ConnectionPool (
const String& connectionString)
875 : ConnectionPool{Memory::
MakeSharedPtr<mongocxx::pool> (ConnectionString2MongoURI_ (connectionString))}
879mongocxx::pool& ConnectionPool::PeekPool ()
const
890Document::MongoDBClient::Connection::Ptr::Ptr (
const shared_ptr<IRep>& src)
900auto Document::MongoDBClient::AdminConnection::New (
const AdminConnection::Options& options) -> Ptr
902#if qStroika_Foundation_Debug_AssertionsChecked
903 Require (sActivatorLiveCnt_ > 0);
905 switch (options.fInternallySynchronizedLetter) {
906 case Execution::eInternallySynchronized:
907 return Ptr{Memory::MakeSharedPtr<AdminRep_<Execution::eInternallySynchronized>> (options)};
908 case Execution::eNotKnownInternallySynchronized:
909 return Ptr{Memory::MakeSharedPtr<AdminRep_<Execution::eNotKnownInternallySynchronized>> (options)};
921auto Document::MongoDBClient::Connection::New (
const Connection::Options& options) -> Ptr
923#if qStroika_Foundation_Debug_AssertionsChecked
924 Require (sActivatorLiveCnt_ > 0);
926 switch (options.fInternallySynchronizedLetter) {
927 case Execution::eInternallySynchronized:
928 return Ptr{Memory::MakeSharedPtr<ConnectionRep_<Execution::eInternallySynchronized>> (options)};
929 case Execution::eNotKnownInternallySynchronized:
930 return Ptr{Memory::MakeSharedPtr<ConnectionRep_<Execution::eNotKnownInternallySynchronized>> (options)};
942struct Transaction::MyRep_ :
public MongoDBClient::Transaction::IRep {
944 : fConnectionPtr_{db}
948 virtual void Commit ()
override
950 Require (not fCompleted_);
954 virtual void Rollback ()
override
956 Require (not fCompleted_);
960 virtual Disposition GetDisposition ()
const override
963 return fCompleted_ ? Disposition::eCompleted : Disposition::eNone;
966 bool fCompleted_{
false};
969 : inherited{make_unique<MyRep_> (db)}
#define WeakAssertNotReached()
#define AssertNotImplemented()
#define RequireNotReached()
#define AssertNotReached()
auto MakeSharedPtr(ARGS_TYPE &&... args) -> shared_ptr< T >
same as make_shared, but if type T has block allocation, then use block allocation for the 'shared pa...
variant< Equals > Operation
#define qStroika_ATTRIBUTE_NO_UNIQUE_ADDRESS_VCBUGGY
qStroika_ATTRIBUTE_NO_UNIQUE_ADDRESS_VCBUGGY same as qStroika_ATTRIBUTE_NO_UNIQUE_ADDRESS
String is like std::u32string, except it is much easier to use, often much more space efficient,...
nonvirtual T AsUTF8() const
Mapping_HashTable<KEY_TYPE, MAPPED_VALUE_TYPE, TRAITS> is a HashTable based concrete implementation o...
Sequence_stdvector<T> is an std::vector-based concrete implementation of the Sequence<T> container pa...
nonvirtual bool Add(ArgByValueType< key_type > key, ArgByValueType< mapped_type > newElt, AddReplaceMode addReplaceMode=AddReplaceMode::eAddReplaces)
nonvirtual bool ContainsKey(ArgByValueType< key_type > key) const
nonvirtual bool RemoveIf(ArgByValueType< key_type > key)
Remove the given item, if it exists. Return true if found and removed.
nonvirtual void Remove(ArgByValueType< key_type > key)
Remove the given item (which must exist).
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.
Simple variant-value (case variant union) object, with (variant) basic types analogous to a value in ...
nonvirtual RETURNTYPE As() const
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.
NestedException contains a new higher level error message (typically based on argument basedOnExcepti...
static constexpr string_view kISO8601Format
Y-M-D format - locale independent, and ISO-8601 date format standard.
Iterable<T> is a base class for containers which easily produce an Iterator<T> to traverse them.
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.
nonvirtual RESULT_CONTAINER Map(ELEMENT_MAPPER &&elementMapper) const
functional API which iterates over all members of an Iterable, applies a map function to each element...
nonvirtual bool empty() const
Returns true iff size() == 0.
DISABLE_COMPILER_MSC_WARNING_START(4996)
void Throw(T &&e2Throw)
identical to builtin C++ 'throw' except that it does helpful, type dependent DbgTrace() messages firs...
bool AnyCurrentActivities()
Checks if CaptureCurrentActivities() would produce a non-empty stack (but faster)