diff options
Diffstat (limited to 'slicer/db')
-rw-r--r-- | slicer/db/Jamfile.jam | 35 | ||||
-rw-r--r-- | slicer/db/sqlBinder.h | 2 | ||||
-rw-r--r-- | slicer/db/sqlCommon.cpp | 11 | ||||
-rw-r--r-- | slicer/db/sqlCommon.h | 10 | ||||
-rw-r--r-- | slicer/db/sqlInsertSerializer.cpp | 32 | ||||
-rw-r--r-- | slicer/db/sqlInsertSerializer.h | 31 | ||||
-rw-r--r-- | slicer/db/sqlSelectDeserializer.cpp | 120 | ||||
-rw-r--r-- | slicer/db/sqlSelectDeserializer.h | 16 | ||||
-rw-r--r-- | slicer/db/sqlSource.cpp | 33 | ||||
-rw-r--r-- | slicer/db/sqlSource.h | 5 | ||||
-rw-r--r-- | slicer/db/sqlTablePatchSerializer.cpp | 24 | ||||
-rw-r--r-- | slicer/db/sqlTablePatchSerializer.h | 3 | ||||
-rw-r--r-- | slicer/db/sqlUpdateSerializer.cpp | 25 | ||||
-rw-r--r-- | slicer/db/sqlUpdateSerializer.h | 11 | ||||
-rw-r--r-- | slicer/db/testInsert.cpp | 1 | ||||
-rw-r--r-- | slicer/db/testMockCommon.h | 1 | ||||
-rw-r--r-- | slicer/db/testPatch.cpp | 2 | ||||
-rw-r--r-- | slicer/db/testPerf.cpp | 37 |
18 files changed, 269 insertions, 130 deletions
diff --git a/slicer/db/Jamfile.jam b/slicer/db/Jamfile.jam index 73c05e5..a304b9e 100644 --- a/slicer/db/Jamfile.jam +++ b/slicer/db/Jamfile.jam @@ -4,6 +4,7 @@ import ../test/slicer.jam ; lib dbppcore : : : : <include>/usr/include/dbpp ; lib dbpp-postgresql : : : : <include>/usr/include/dbpp-postgresql ; lib stdc++fs ; +lib benchmark ; obj sqlExceptions : sqlExceptions.ice : <use>../slicer//slicer <toolset>tidy:<checker>none ; lib slicer-db : @@ -137,6 +138,40 @@ run testUpdate.cpp testUpdate ; +run + [ obj perf : testPerf.cpp : + <slicer>pure + <use>../test//types + <implicit-dependency>../test//types + <use>benchmark + <use>stdc++fs + <use>dbpp-postgresql + <use>dbppcore + <use>..//adhocutil + <use>../test//common + <use>../slicer//slicer + <implicit-dependency>../slicer//slicer + <use>testCommon + <implicit-dependency>testCommon + <use>slicer-db + ] + : : : + <library>benchmark + <library>stdc++fs + <library>dbpp-postgresql + <library>dbppcore + <library>../test//common + <library>../test//types + <library>../slicer//slicer + <implicit-dependency>../slicer//slicer + <library>slicer-db + <library>..//adhocutil + <library>testCommon + <implicit-dependency>testCommon + <variant>profile:<testing.execute>on + <testing.execute>off + : testPerf ; + alias install : install-lib install-slice ; explicit install ; explicit install-lib ; diff --git a/slicer/db/sqlBinder.h b/slicer/db/sqlBinder.h index 4f5437c..a4a9a93 100644 --- a/slicer/db/sqlBinder.h +++ b/slicer/db/sqlBinder.h @@ -6,6 +6,7 @@ #include <memory> #include <slicer/modelParts.h> #include <string> + namespace DB { class Command; } @@ -33,7 +34,6 @@ namespace Slicer { DB::Command & command; const unsigned int idx; }; - typedef std::shared_ptr<SqlBinder> SqlBinderPtr; } #endif diff --git a/slicer/db/sqlCommon.cpp b/slicer/db/sqlCommon.cpp index 40e43f7..0516f45 100644 --- a/slicer/db/sqlCommon.cpp +++ b/slicer/db/sqlCommon.cpp @@ -11,31 +11,31 @@ namespace Slicer { constexpr std::string_view md_global_ignore {"ignore"}; bool - isPKey(const HookCommon * h) + isPKey(const HookCommon * h) noexcept { return h->GetMetadata().flagSet(md_pkey) && isBind(h); } bool - isAuto(const HookCommon * h) + isAuto(const HookCommon * h) noexcept { return h->GetMetadata().flagSet(md_auto) && isBind(h); } bool - isNotAuto(const HookCommon * h) + isNotAuto(const HookCommon * h) noexcept { return h->GetMetadata().flagNotSet(md_auto) && isBind(h); } bool - isBind(const HookCommon * h) + isBind(const HookCommon * h) noexcept { return h->GetMetadata().flagNotSet(md_global_ignore) && h->GetMetadata().flagNotSet(md_ignore); } bool - isValue(const HookCommon * h) + isValue(const HookCommon * h) noexcept { return h->GetMetadata().flagNotSet(md_auto) && h->GetMetadata().flagNotSet(md_pkey) && isBind(h); } @@ -59,6 +59,7 @@ namespace Slicer { } AdHocFormatter(UnsuitableIdFieldTypeMsg, "Unsuitable id field type [%?]"); + void UnsuitableIdFieldType::ice_print(std::ostream & s) const { diff --git a/slicer/db/sqlCommon.h b/slicer/db/sqlCommon.h index acabc51..16cefac 100644 --- a/slicer/db/sqlCommon.h +++ b/slicer/db/sqlCommon.h @@ -4,11 +4,11 @@ namespace Slicer { class HookCommon; - bool isPKey(const HookCommon *); - bool isAuto(const HookCommon *); - bool isNotAuto(const HookCommon *); - bool isBind(const HookCommon *); - bool isValue(const HookCommon *); + [[nodiscard]] bool isPKey(const HookCommon *) noexcept; + [[nodiscard]] bool isAuto(const HookCommon *) noexcept; + [[nodiscard]] bool isNotAuto(const HookCommon *) noexcept; + [[nodiscard]] bool isBind(const HookCommon *) noexcept; + [[nodiscard]] bool isValue(const HookCommon *) noexcept; } #endif diff --git a/slicer/db/sqlInsertSerializer.cpp b/slicer/db/sqlInsertSerializer.cpp index 58e30e2..0881a1b 100644 --- a/slicer/db/sqlInsertSerializer.cpp +++ b/slicer/db/sqlInsertSerializer.cpp @@ -15,15 +15,13 @@ #include <utility> namespace Slicer { - using namespace std::placeholders; - SqlInsertSerializer::SqlInsertSerializer(DB::Connection * const c, std::string t) : connection(c), tableName(std::move(t)) { } void - SqlInsertSerializer::Serialize(Slicer::ModelPartForRootPtr mp) + SqlInsertSerializer::Serialize(ModelPartForRootParam mp) { switch (mp->GetType()) { case Slicer::ModelPartType::Sequence: @@ -42,23 +40,24 @@ namespace Slicer { } void - SqlInsertSerializer::SerializeObject(const Slicer::ModelPartPtr & mp) const + SqlInsertSerializer::SerializeObject(ModelPartParam mp) const { auto ins = createInsert(mp); bindObjectAndExecute(mp, ins.get()); } void - SqlInsertSerializer::SerializeSequence(const Slicer::ModelPartPtr & mp) const + SqlInsertSerializer::SerializeSequence(ModelPartParam mp) const { - auto ins = createInsert(mp->GetContainedModelPart()); - mp->OnEachChild([&ins, this](const std::string &, const ModelPartPtr & cmp, const HookCommon *) { - bindObjectAndExecute(cmp, ins.get()); + mp->OnContained([this, mp](auto && cmp) { + mp->OnEachChild([ins = createInsert(cmp), this](auto &&, auto && chmp, auto &&) { + bindObjectAndExecute(chmp, ins.get()); + }); }); } void - SqlInsertSerializer::bindObjectAndExecute(const Slicer::ModelPartPtr & cmp, DB::ModifyCommand * ins) const + SqlInsertSerializer::bindObjectAndExecute(ModelPartParam cmp, DB::ModifyCommand * ins) const { unsigned int paramNo = 0; cmp->OnEachChild([this, ¶mNo, ins](auto &&, auto && PH2, auto && PH3) { @@ -88,6 +87,7 @@ namespace Slicer { private: DB::Connection * const connection; + template<typename T> inline void doSet([[maybe_unused]] T & v, [[maybe_unused]] const char * Tname) const @@ -102,10 +102,10 @@ namespace Slicer { }; void - SqlFetchIdInsertSerializer::bindObjectAndExecute(const Slicer::ModelPartPtr & mp, DB::ModifyCommand * ins) const + SqlFetchIdInsertSerializer::bindObjectAndExecute(ModelPartParam mp, DB::ModifyCommand * ins) const { SqlAutoIdInsertSerializer::bindObjectAndExecute(mp, ins); - mp->OnEachChild([this](const std::string &, const ModelPartPtr & cmp, const HookCommon * h) { + mp->OnEachChild([this](auto &&, auto && cmp, auto && h) { if (isAuto(h)) { cmp->SetValue(IdSave(connection)); } @@ -113,8 +113,8 @@ namespace Slicer { } void - SqlInsertSerializer::bindObjectAndExecuteField(unsigned int & paramNo, DB::ModifyCommand * ins, - const Slicer::ModelPartPtr & cmp, const HookCommon * h) const + SqlInsertSerializer::bindObjectAndExecuteField( + unsigned int & paramNo, DB::ModifyCommand * ins, ModelPartParam cmp, const HookCommon * h) const { if (isBind(h)) { if (!cmp->GetValue(SqlBinder(*ins, paramNo))) { @@ -125,8 +125,8 @@ namespace Slicer { } void - SqlAutoIdInsertSerializer::bindObjectAndExecuteField(unsigned int & paramNo, DB::ModifyCommand * ins, - const Slicer::ModelPartPtr & cmp, const HookCommon * h) const + SqlAutoIdInsertSerializer::bindObjectAndExecuteField( + unsigned int & paramNo, DB::ModifyCommand * ins, ModelPartParam cmp, const HookCommon * h) const { if (isNotAuto(h)) { SqlInsertSerializer::bindObjectAndExecuteField(paramNo, ins, cmp, h); @@ -134,7 +134,7 @@ namespace Slicer { } DB::ModifyCommandPtr - SqlInsertSerializer::createInsert(const Slicer::ModelPartPtr & mp) const + SqlInsertSerializer::createInsert(ModelPartParam mp) const { using namespace AdHoc::literals; std::stringstream insert; diff --git a/slicer/db/sqlInsertSerializer.h b/slicer/db/sqlInsertSerializer.h index b6a0d27..36ecac3 100644 --- a/slicer/db/sqlInsertSerializer.h +++ b/slicer/db/sqlInsertSerializer.h @@ -7,6 +7,7 @@ #include <slicer/serializer.h> #include <string> #include <visibility.h> + namespace DB { class Connection; class ModifyCommand; @@ -17,17 +18,17 @@ namespace Slicer { public: SqlInsertSerializer(DB::Connection * const, std::string tableName); - void Serialize(Slicer::ModelPartForRootPtr) override; + void Serialize(ModelPartForRootParam) override; protected: - void SerializeObject(const Slicer::ModelPartPtr &) const; - void SerializeSequence(const Slicer::ModelPartPtr &) const; - DB::ModifyCommandPtr createInsert(const Slicer::ModelPartPtr &) const; + void SerializeObject(ModelPartParam) const; + void SerializeSequence(ModelPartParam) const; + [[nodiscard]] DB::ModifyCommandPtr createInsert(ModelPartParam) const; virtual void createInsertField( unsigned int & fieldNo, std::ostream & insert, const std::string & name, const HookCommon * h) const; - virtual void bindObjectAndExecute(const Slicer::ModelPartPtr &, DB::ModifyCommand *) const; + virtual void bindObjectAndExecute(ModelPartParam, DB::ModifyCommand *) const; virtual void bindObjectAndExecuteField( - unsigned int & paramNo, DB::ModifyCommand *, const Slicer::ModelPartPtr &, const HookCommon *) const; + unsigned int & paramNo, DB::ModifyCommand *, ModelPartParam, const HookCommon *) const; DB::Connection * const connection; const std::string tableName; @@ -35,27 +36,21 @@ namespace Slicer { class DLL_PUBLIC SqlAutoIdInsertSerializer : public SqlInsertSerializer { public: - template<typename... P> - explicit SqlAutoIdInsertSerializer(P &&... p) : SqlInsertSerializer(std::forward<P>(p)...) - { - } + using SqlInsertSerializer::SqlInsertSerializer; protected: - virtual void createInsertField(unsigned int & fieldNo, std::ostream & insert, const std::string & name, + void createInsertField(unsigned int & fieldNo, std::ostream & insert, const std::string & name, const HookCommon * h) const override; - virtual void bindObjectAndExecuteField(unsigned int & paramNo, DB::ModifyCommand *, - const Slicer::ModelPartPtr &, const HookCommon *) const override; + void bindObjectAndExecuteField( + unsigned int & paramNo, DB::ModifyCommand *, ModelPartParam, const HookCommon *) const override; }; class DLL_PUBLIC SqlFetchIdInsertSerializer : public SqlAutoIdInsertSerializer { public: - template<typename... P> - explicit SqlFetchIdInsertSerializer(P &&... p) : SqlAutoIdInsertSerializer(std::forward<P>(p)...) - { - } + using SqlAutoIdInsertSerializer::SqlAutoIdInsertSerializer; protected: - virtual void bindObjectAndExecute(const Slicer::ModelPartPtr &, DB::ModifyCommand *) const override; + void bindObjectAndExecute(ModelPartParam, DB::ModifyCommand *) const override; }; } diff --git a/slicer/db/sqlSelectDeserializer.cpp b/slicer/db/sqlSelectDeserializer.cpp index f3f3c07..8081d76 100644 --- a/slicer/db/sqlSelectDeserializer.cpp +++ b/slicer/db/sqlSelectDeserializer.cpp @@ -5,6 +5,7 @@ #include <memory> #include <selectcommand.h> #include <slicer/common.h> +#include <slicer/hookMap.h> #include <slicer/modelParts.h> #include <utility> @@ -15,7 +16,7 @@ namespace Slicer { } void - SqlSelectDeserializer::Deserialize(Slicer::ModelPartForRootPtr mp) + SqlSelectDeserializer::Deserialize(ModelPartForRootParam mp) { cmd->execute(); columnCount = cmd->columnCount(); @@ -38,7 +39,7 @@ namespace Slicer { } void - SqlSelectDeserializer::DeserializeSimple(const Slicer::ModelPartPtr & mp) + SqlSelectDeserializer::DeserializeSimple(ModelPartParam mp) { if (!cmd->fetch()) { if (!mp->IsOptional()) { @@ -47,10 +48,11 @@ namespace Slicer { return; } if (!(*cmd)[0].isNull()) { - auto fmp = mp->GetAnonChild(); - fmp->Create(); - fmp->SetValue(SqlSource((*cmd)[0])); - fmp->Complete(); + mp->OnAnonChild([this](auto && fmp, auto &&) { + fmp->Create(); + fmp->SetValue(SqlSource((*cmd)[0])); + fmp->Complete(); + }); } if (cmd->fetch()) { throw TooManyRowsReturned(); @@ -58,16 +60,60 @@ namespace Slicer { } void - SqlSelectDeserializer::DeserializeSequence(const Slicer::ModelPartPtr & omp) + SqlSelectDeserializer::fillLowerColumnNameCache() { - auto mp = omp->GetAnonChild(); - while (cmd->fetch()) { - DeserializeRow(mp); + BOOST_ASSERT(lowerColumnNames.empty()); + lowerColumnNames.reserve(columnCount); + orderedColumns.reserve(columnCount); + for (auto col = 0U; col < columnCount; col += 1) { + const DB::Column & c = (*cmd)[col]; + lowerColumnNames.emplace_back(to_lower_copy(c.name)); + } + } + + const DB::Column * + SqlSelectDeserializer::searchOrFilleColumnCache(size_t idx, const HookCommon * hook) + { + if (idx < orderedColumns.size()) { + return orderedColumns[idx]; + } + BOOST_ASSERT(idx == orderedColumns.size()); + if (const auto itr = std::find(lowerColumnNames.begin(), lowerColumnNames.end(), hook->nameLower); + itr != lowerColumnNames.end()) { + return orderedColumns.emplace_back(&(*cmd)[static_cast<unsigned int>(itr - lowerColumnNames.begin())]); + } + else { + return orderedColumns.emplace_back(nullptr); + } + } + + namespace { + void + assignFromColumn(ModelPartParam fmp, const DB::Column & c) + { + BOOST_ASSERT(fmp); + BOOST_ASSERT(!c.isNull()); + fmp->Create(); + fmp->SetValue(SqlSource(c)); + fmp->Complete(); } } void - SqlSelectDeserializer::DeserializeObject(const Slicer::ModelPartPtr & mp) + SqlSelectDeserializer::DeserializeSequence(ModelPartParam omp) + { + omp->OnAnonChild([this](auto && mp, auto &&) { + if (!typeIdColIdx && lowerColumnNames.empty()) { + fillLowerColumnNameCache(); + } + while (cmd->fetch()) { + DeserializeRow(mp); + } + }); + } + + void + SqlSelectDeserializer::DeserializeObject(ModelPartParam mp) { if (!cmd->fetch()) { if (!mp->IsOptional()) { @@ -83,43 +129,51 @@ namespace Slicer { } void - SqlSelectDeserializer::DeserializeRow(const Slicer::ModelPartPtr & mp) + SqlSelectDeserializer::DeserializeRow(ModelPartParam mp) { - auto rmp = mp->GetAnonChild(); - if (rmp) { + mp->OnAnonChild([this](auto && rmp, auto &&) { switch (rmp->GetType()) { case Slicer::ModelPartType::Complex: { + auto apply = [this](auto && rcmp) { + rcmp->Create(); + if (typeIdColIdx || lowerColumnNames.empty()) { + for (auto col = 0U; col < columnCount; col += 1) { + const DB::Column & c = (*cmd)[col]; + if (!c.isNull()) { + rcmp->OnChild( + [&c](auto && fmp, auto &&) { + assignFromColumn(fmp, c); + }, + c.name, nullptr, false); + } + } + } + else { + rcmp->OnEachChild([idx = 0U, this](auto &&, auto && fmp, auto && hook) mutable { + if (auto c = searchOrFilleColumnCache(idx, hook); c && !c->isNull()) { + assignFromColumn(fmp, *c); + } + ++idx; + }); + } + rcmp->Complete(); + }; if (typeIdColIdx) { std::string subclass; (*cmd)[*typeIdColIdx] >> subclass; - rmp = rmp->GetSubclassModelPart(subclass); - } - rmp->Create(); - for (auto col = 0U; col < columnCount; col += 1) { - const DB::Column & c = (*cmd)[col]; - if (!c.isNull()) { - auto fmpr = rmp->GetChildRef(c.name, nullptr, false); - if (fmpr) { - auto fmp = fmpr.Child(); - fmp->Create(); - fmp->SetValue(SqlSource(c)); - fmp->Complete(); - } - } + return rmp->OnSubclass(apply, subclass); } - rmp->Complete(); + apply(rmp); } break; case Slicer::ModelPartType::Simple: { - rmp->Create(); const DB::Column & c = (*cmd)[0]; if (!c.isNull()) { - rmp->SetValue(SqlSource(c)); + assignFromColumn(rmp, c); } - rmp->Complete(); } break; default: throw UnsupportedModelType(); } - } + }); } } diff --git a/slicer/db/sqlSelectDeserializer.h b/slicer/db/sqlSelectDeserializer.h index bf2b351..b911fb1 100644 --- a/slicer/db/sqlSelectDeserializer.h +++ b/slicer/db/sqlSelectDeserializer.h @@ -6,8 +6,10 @@ #include <slicer/serializer.h> #include <string> #include <visibility.h> + namespace DB { class SelectCommand; + class Column; } namespace Slicer { @@ -16,18 +18,22 @@ namespace Slicer { explicit SqlSelectDeserializer( DB::SelectCommand *, std::optional<std::string> typeIdCol = std::optional<std::string>()); - void Deserialize(Slicer::ModelPartForRootPtr) override; + void Deserialize(ModelPartForRootParam) override; protected: - void DLL_PRIVATE DeserializeSimple(const Slicer::ModelPartPtr &); - void DLL_PRIVATE DeserializeObject(const Slicer::ModelPartPtr &); - void DLL_PRIVATE DeserializeSequence(const Slicer::ModelPartPtr &); - void DLL_PRIVATE DeserializeRow(const Slicer::ModelPartPtr &); + DLL_PRIVATE void DeserializeSimple(ModelPartParam); + DLL_PRIVATE void DeserializeObject(ModelPartParam); + DLL_PRIVATE void DeserializeSequence(ModelPartParam); + DLL_PRIVATE void DeserializeRow(ModelPartParam); + DLL_PRIVATE void fillLowerColumnNameCache(); + DLL_PRIVATE inline const DB::Column * searchOrFilleColumnCache(size_t idx, const HookCommon * hook); DB::SelectCommand * cmd; unsigned int columnCount; std::optional<std::string> typeIdColName; std::optional<unsigned int> typeIdColIdx; + std::vector<std::string> lowerColumnNames; + std::vector<const DB::Column *> orderedColumns; }; } diff --git a/slicer/db/sqlSource.cpp b/slicer/db/sqlSource.cpp index 41b9c1c..ed14b3a 100644 --- a/slicer/db/sqlSource.cpp +++ b/slicer/db/sqlSource.cpp @@ -7,6 +7,17 @@ namespace Slicer { SqlSource::SqlSource(const DB::Column & c) : column(c) { } + namespace { + template<typename C, typename T> + void + numericSet(const DB::Column & column, T & b) + { + C cb {}; + column >> cb; + b = boost::numeric_cast<T>(cb); + } + } + bool SqlSource::isNull() const { @@ -34,47 +45,37 @@ namespace Slicer { void SqlSource::set(Ice::Byte & b) const { - int64_t cb; - column >> cb; - b = boost::numeric_cast<Ice::Byte>(cb); + numericSet<int64_t>(column, b); } void SqlSource::set(Ice::Short & b) const { - int64_t cb; - column >> cb; - b = boost::numeric_cast<Ice::Short>(cb); + numericSet<int64_t>(column, b); } void SqlSource::set(Ice::Int & b) const { - int64_t cb; - column >> cb; - b = boost::numeric_cast<Ice::Int>(cb); + numericSet<int64_t>(column, b); } void SqlSource::set(Ice::Long & b) const { - int64_t cb; - column >> cb; - b = boost::numeric_cast<Ice::Long>(cb); + numericSet<int64_t>(column, b); } void SqlSource::set(Ice::Float & b) const { - double cb; - column >> cb; - b = boost::numeric_cast<Ice::Float>(cb); + numericSet<double>(column, b); } void SqlSource::set(Ice::Double & b) const { - column >> b; + numericSet<double>(column, b); } void diff --git a/slicer/db/sqlSource.h b/slicer/db/sqlSource.h index 4b76974..78d9909 100644 --- a/slicer/db/sqlSource.h +++ b/slicer/db/sqlSource.h @@ -5,9 +5,11 @@ #include <Ice/Config.h> #include <memory> #include <string> + namespace DB { class Column; } + namespace boost::posix_time { class ptime; class time_duration; @@ -21,7 +23,7 @@ namespace Slicer { public: explicit SqlSource(const DB::Column & c); - bool isNull() const; + [[nodiscard]] bool isNull() const; void set(boost::posix_time::ptime & b) const override; void set(boost::posix_time::time_duration & b) const override; void set(bool & b) const override; @@ -36,7 +38,6 @@ namespace Slicer { private: const DB::Column & column; }; - typedef std::shared_ptr<SqlSource> SqlSourcePtr; } #endif diff --git a/slicer/db/sqlTablePatchSerializer.cpp b/slicer/db/sqlTablePatchSerializer.cpp index 3b73f05..ec0e344 100644 --- a/slicer/db/sqlTablePatchSerializer.cpp +++ b/slicer/db/sqlTablePatchSerializer.cpp @@ -11,6 +11,7 @@ namespace Slicer { AdHocFormatter(ttname, "slicer_tmp_%?"); + SqlTablePatchSerializer::SqlTablePatchSerializer(DB::Connection * const d, DB::TablePatch & tp) : db(d), tablePatch(tp) { @@ -18,7 +19,7 @@ namespace Slicer { } void - SqlTablePatchSerializer::Serialize(Slicer::ModelPartForRootPtr mpr) + SqlTablePatchSerializer::Serialize(ModelPartForRootParam mpr) { tablePatch.pk.clear(); tablePatch.cols.clear(); @@ -31,22 +32,22 @@ namespace Slicer { SqlInsertSerializer ins(db, tablePatch.src); ins.Serialize(mpr); - auto mp = mpr->GetContainedModelPart(); - mp->OnEachChild([this](const auto & name, const auto &, const auto & h) { - if (isPKey(h)) { - tablePatch.pk.insert(name); - } - }); - mp->OnEachChild([this](const auto & name, const auto &, const auto & h) { - if (isBind(h)) { - tablePatch.cols.insert(name); - } + mpr->OnContained([this](auto && mp) { + mp->OnEachChild([this](const auto & name, const auto &, const auto & h) { + if (isPKey(h)) { + tablePatch.pk.insert(name); + } + if (isBind(h)) { + tablePatch.cols.insert(name); + } + }); }); db->patchTable(&tablePatch); } AdHocFormatter(createTmpTable, "CREATE TEMPORARY TABLE %? AS SELECT * FROM %? WHERE 1 = 0"); + void SqlTablePatchSerializer::createTemporaryTable() { @@ -54,6 +55,7 @@ namespace Slicer { } AdHocFormatter(dropTmpTable, "DROP TABLE %?"); + void SqlTablePatchSerializer::dropTemporaryTable() { diff --git a/slicer/db/sqlTablePatchSerializer.h b/slicer/db/sqlTablePatchSerializer.h index 21c8b3d..1da29a6 100644 --- a/slicer/db/sqlTablePatchSerializer.h +++ b/slicer/db/sqlTablePatchSerializer.h @@ -4,6 +4,7 @@ #include <slicer/modelParts.h> #include <slicer/serializer.h> #include <visibility.h> + namespace DB { class Connection; class TablePatch; @@ -14,7 +15,7 @@ namespace Slicer { public: SqlTablePatchSerializer(DB::Connection * const, DB::TablePatch &); - void Serialize(Slicer::ModelPartForRootPtr) override; + void Serialize(ModelPartForRootParam) override; private: void createTemporaryTable(); diff --git a/slicer/db/sqlUpdateSerializer.cpp b/slicer/db/sqlUpdateSerializer.cpp index 038f28e..152c923 100644 --- a/slicer/db/sqlUpdateSerializer.cpp +++ b/slicer/db/sqlUpdateSerializer.cpp @@ -21,7 +21,7 @@ namespace Slicer { } void - SqlUpdateSerializer::Serialize(Slicer::ModelPartForRootPtr mp) + SqlUpdateSerializer::Serialize(ModelPartForRootParam mp) { switch (mp->GetType()) { case Slicer::ModelPartType::Sequence: @@ -40,26 +40,27 @@ namespace Slicer { } void - SqlUpdateSerializer::SerializeObject(const Slicer::ModelPartPtr & mp) const + SqlUpdateSerializer::SerializeObject(ModelPartParam mp) const { auto ins = createUpdate(mp); bindObjectAndExecute(mp, ins.get()); } void - SqlUpdateSerializer::SerializeSequence(const Slicer::ModelPartPtr & mp) const + SqlUpdateSerializer::SerializeSequence(ModelPartParam mp) const { - auto ins = createUpdate(mp->GetContainedModelPart()); - mp->OnEachChild([&ins](const std::string &, const ModelPartPtr & cmp, const HookCommon *) { - bindObjectAndExecute(cmp, ins.get()); + mp->OnContained([this, mp](auto && cmp) { + mp->OnEachChild([upd = createUpdate(cmp)](auto &&, auto && chmp, auto &&) { + bindObjectAndExecute(chmp, upd.get()); + }); }); } void - SqlUpdateSerializer::bindObjectAndExecute(const Slicer::ModelPartPtr & mp, DB::ModifyCommand * upd) + SqlUpdateSerializer::bindObjectAndExecute(ModelPartParam mp, DB::ModifyCommand * upd) { unsigned int paramNo = 0; - mp->OnEachChild([&upd, ¶mNo](const std::string &, const ModelPartPtr & cmp, const HookCommon * h) { + mp->OnEachChild([&upd, ¶mNo](auto &&, auto && cmp, auto && h) { if (isValue(h)) { if (!cmp->GetValue(SqlBinder(*upd, paramNo))) { upd->bindNull(paramNo); @@ -67,7 +68,7 @@ namespace Slicer { paramNo++; } }); - mp->OnEachChild([&upd, ¶mNo](const std::string &, const ModelPartPtr & cmp, const HookCommon * h) { + mp->OnEachChild([&upd, ¶mNo](auto &&, auto && cmp, auto && h) { if (isPKey(h)) { cmp->GetValue(SqlBinder(*upd, paramNo++)); } @@ -78,13 +79,13 @@ namespace Slicer { } DB::ModifyCommandPtr - SqlUpdateSerializer::createUpdate(const Slicer::ModelPartPtr & mp) const + SqlUpdateSerializer::createUpdate(ModelPartParam mp) const { using namespace AdHoc::literals; std::stringstream update; "UPDATE %? SET "_fmt(update, tableName); int fieldNo = 0; - mp->OnEachChild([&update, &fieldNo](const std::string & name, const ModelPartPtr &, const HookCommon * h) { + mp->OnEachChild([&update, &fieldNo](auto && name, auto &&, auto && h) { if (isValue(h)) { if (fieldNo++) { update << ", "; @@ -94,7 +95,7 @@ namespace Slicer { }); update << " WHERE "; fieldNo = 0; - mp->OnEachChild([&update, &fieldNo](const std::string & name, const ModelPartPtr &, const HookCommon * h) { + mp->OnEachChild([&update, &fieldNo](auto && name, auto &&, auto && h) { if (isPKey(h)) { if (fieldNo++) { update << " AND "; diff --git a/slicer/db/sqlUpdateSerializer.h b/slicer/db/sqlUpdateSerializer.h index 8707988..c634ff5 100644 --- a/slicer/db/sqlUpdateSerializer.h +++ b/slicer/db/sqlUpdateSerializer.h @@ -6,6 +6,7 @@ #include <slicer/serializer.h> #include <string> #include <visibility.h> + namespace DB { class Connection; class ModifyCommand; @@ -16,13 +17,13 @@ namespace Slicer { public: SqlUpdateSerializer(DB::Connection * const, std::string tableName); - void Serialize(Slicer::ModelPartForRootPtr) override; + void Serialize(ModelPartForRootParam) override; protected: - void SerializeObject(const Slicer::ModelPartPtr &) const; - void SerializeSequence(const Slicer::ModelPartPtr &) const; - DB::ModifyCommandPtr createUpdate(const Slicer::ModelPartPtr &) const; - static void bindObjectAndExecute(const Slicer::ModelPartPtr &, DB::ModifyCommand *); + void SerializeObject(ModelPartParam) const; + void SerializeSequence(ModelPartParam) const; + [[nodiscard]] DB::ModifyCommandPtr createUpdate(ModelPartParam) const; + static void bindObjectAndExecute(ModelPartParam, DB::ModifyCommand *); DB::Connection * const connection; const std::string tableName; diff --git a/slicer/db/testInsert.cpp b/slicer/db/testInsert.cpp index a9e42f1..24cae7e 100644 --- a/slicer/db/testInsert.cpp +++ b/slicer/db/testInsert.cpp @@ -25,6 +25,7 @@ using namespace std::literals; BOOST_TEST_DONT_PRINT_LOG_VALUE(TestModule::DateTime) BOOST_TEST_DONT_PRINT_LOG_VALUE(TestModule::IsoDate) BOOST_TEST_DONT_PRINT_LOG_VALUE(TestDatabase::Timespan) + // LCOV_EXCL_STOP namespace std { diff --git a/slicer/db/testMockCommon.h b/slicer/db/testMockCommon.h index e12d2c6..891fb74 100644 --- a/slicer/db/testMockCommon.h +++ b/slicer/db/testMockCommon.h @@ -5,6 +5,7 @@ #include <mockDatabase.h> #include <pq-mock.h> #include <visibility.h> + // IWYU pragma: no_forward_declare PQ::Mock namespace DB { class Connection; diff --git a/slicer/db/testPatch.cpp b/slicer/db/testPatch.cpp index 6db440a..3e8b1e4 100644 --- a/slicer/db/testPatch.cpp +++ b/slicer/db/testPatch.cpp @@ -11,9 +11,11 @@ #include <memory> #include <string> #include <tablepatch.h> + namespace TestDatabase { class Timespan; } + namespace TestModule { struct DateTime; struct IsoDate; diff --git a/slicer/db/testPerf.cpp b/slicer/db/testPerf.cpp new file mode 100644 index 0000000..bb2a4c3 --- /dev/null +++ b/slicer/db/testPerf.cpp @@ -0,0 +1,37 @@ +#include "sqlSelectDeserializer.h" +#include "testMockCommon.h" +#include <benchmark/benchmark.h> +#include <collections.h> +#include <connection.h> +#include <definedDirs.h> +#include <slicer/slicer.h> +#include <testModels.h> + +const StandardMockDatabase db; + +class CoreFixture : public benchmark::Fixture, public ConnectionFixture { +protected: + template<typename Out> + void + do_bulk_select_complex(benchmark::State & state) + { + auto sel = db->select(R"SQL( + SELECT s mint, CAST(s AS NUMERIC(7,1)) mdouble, CAST(s as text) mstring, s % 2 = 0 mbool + FROM GENERATE_SERIES(1, 10000) s)SQL"); + for (auto _ : state) { + benchmark::DoNotOptimize(Slicer::DeserializeAny<Slicer::SqlSelectDeserializer, Out>(sel.get())); + } + } +}; + +BENCHMARK_F(CoreFixture, bulk_select_complex)(benchmark::State & state) +{ + do_bulk_select_complex<TestDatabase::BuiltInSeq>(state); +} + +BENCHMARK_F(CoreFixture, bulk_select_complex_non_optional)(benchmark::State & state) +{ + do_bulk_select_complex<TestModule::BuiltInSeq>(state); +} + +BENCHMARK_MAIN(); |