summaryrefslogtreecommitdiff
path: root/p2pvr/daemon/sqlSelectDeserializer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'p2pvr/daemon/sqlSelectDeserializer.cpp')
-rw-r--r--p2pvr/daemon/sqlSelectDeserializer.cpp176
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();
+ }
+}
+