diff options
Diffstat (limited to 'p2pvr/daemon/sqlSelectDeserializer.cpp')
-rw-r--r-- | p2pvr/daemon/sqlSelectDeserializer.cpp | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/p2pvr/daemon/sqlSelectDeserializer.cpp b/p2pvr/daemon/sqlSelectDeserializer.cpp new file mode 100644 index 0000000..5a59e3a --- /dev/null +++ b/p2pvr/daemon/sqlSelectDeserializer.cpp @@ -0,0 +1,176 @@ +#include "sqlSelectDeserializer.h" +#include <sqlHandleAsVariableType.h> +#include <logger.h> +#include <boost/algorithm/string/predicate.hpp> +#include <stdexcept> + +VariableType +operator/(DB::SelectCommand & cmd, unsigned int col) +{ + HandleAsVariableType vt; + cmd[col].apply(vt); + return vt.variable; +} + +class SqlSource : public DB::HandleField, public Slicer::ValueSource, + public Slicer::TValueSource<boost::posix_time::time_duration>, + public Slicer::TValueSource<boost::posix_time::ptime> { + public: + bool isNull() const + { + return vt.isNull(); + } + + void interval(const boost::posix_time::time_duration & d) override + { + vt = d; + } + void null() override + { + vt = Null(); + } + void string(const char * s, size_t l) override + { + vt = std::string(s, l); + } + void integer(int64_t i) override + { + vt = i; + } + void floatingpoint(double fp) override + { + vt = fp; + } + void timestamp(const boost::posix_time::ptime & t) + { + vt = t; + } + void boolean(bool b) override + { + vt = b; + } +#define SET(Type) \ + void set(Type & b) const override { \ + b = vt.as<Type>(); \ + } +#define SETNCONV(Type, CType) \ + void set(Type & b) const override { \ + b = boost::numeric_cast<Type>(vt.as<CType>()); \ + } + SET(bool); + SET(std::string); + SETNCONV(Ice::Byte, int64_t); + SETNCONV(Ice::Short, int64_t); + SET(Ice::Int); + SET(Ice::Long); + SETNCONV(Ice::Float, double); + SET(Ice::Double); + SET(boost::posix_time::ptime); + SET(boost::posix_time::time_duration); + + private: + VariableType vt; +}; +typedef IceUtil::Handle<SqlSource> SqlSourcePtr; + +SqlSelectDeserializer::SqlSelectDeserializer(DB::SelectCommand & c, IceUtil::Optional<std::string> tc) : + cmd(c), + typeIdColName(tc) +{ +} + +void +SqlSelectDeserializer::Deserialize(Slicer::ModelPartPtr mp) +{ + cmd.execute(); + columnCount = cmd.columnCount(); + if (typeIdColName) { + typeIdColIdx = cmd.getOrdinal(*typeIdColName); + } + switch (mp->GetType()) { + case Slicer::mpt_Sequence: + DeserializeSequence(mp); + return; + case Slicer::mpt_Complex: + DeserializeObject(mp); + return; + case Slicer::mpt_Simple: + DeserializeSimple(mp); + return; + default: + throw std::invalid_argument("Unspported model type"); + } +} + +void +SqlSelectDeserializer::DeserializeSimple(Slicer::ModelPartPtr mp) +{ + auto fmp = mp->GetAnonChild(); + if (!cmd.fetch()) { + throw NoRowsReturned(); + } + SqlSourcePtr h = new SqlSource(); + const DB::Column & c = cmd[0]; + c.apply(*h); + if (!h->isNull()) { + fmp->Create(); + fmp->SetValue(h); + fmp->Complete(); + } + if (cmd.fetch()) { + throw std::invalid_argument("Too many rows returned"); + } +} + +void +SqlSelectDeserializer::DeserializeSequence(Slicer::ModelPartPtr mp) +{ + mp = mp->GetAnonChild(); + SqlSourcePtr h = new SqlSource(); + while (cmd.fetch()) { + DeserializeRow(mp); + } +} + +void +SqlSelectDeserializer::DeserializeObject(Slicer::ModelPartPtr mp) +{ + if (!cmd.fetch()) { + throw NoRowsReturned(); + } + DeserializeRow(mp); + if (cmd.fetch()) { + while (cmd.fetch()) ; + throw std::invalid_argument("Too many rows returned"); + } +} + +void +SqlSelectDeserializer::DeserializeRow(Slicer::ModelPartPtr mp) +{ + SqlSourcePtr h = new SqlSource(); + auto rmp = mp->GetAnonChild(); + if (rmp) { + if (typeIdColIdx) { + rmp = rmp->GetSubclassModelPart(cmd / *typeIdColIdx); + } + rmp->Create(); + for (auto col = 0u; col < columnCount; col += 1) { + const DB::Column & c = cmd[col]; + auto fmpr = rmp->GetAnonChildRef([&c](Slicer::HookCommonPtr h) { + return boost::iequals(c.name.raw(), h->PartName()); + }); + if (fmpr) { + auto fmp = fmpr->Child(); + c.apply(*h); + if (!h->isNull()) { + fmp->Create(); + fmp->SetValue(h); + fmp->Complete(); + } + } + } + rmp->Complete(); + } +} + |