#ifndef PGSQL_VALUE_H #define PGSQL_VALUE_H #include "Pgsql_declare.h" #include "Pgsql_oids.h" #include "ArrayParser.h" #include #include #include #include namespace Pgsql { /** \brief Class that is returned as value of a cell to facilitate auto conversion. */ class Value { public: const char *empty_str = ""; Value(const char *val, Oid typ); QString asQString() const; bool null() const { return m_val == nullptr; } const char* c_str() const { return m_val == nullptr ? empty_str : m_val; } operator QString() const; operator QDateTime() const; operator QDate() const; operator QTime() const; operator std::string() const; operator int16_t() const; operator int32_t() const; operator Oid() const; operator int64_t() const; operator bool() const; operator float() const; operator double() const; bool isString() const; /** * * \param insert_iter An insert_iterator which is used to add the elements of the array to a container. */ template void getAsArray(I insert_iter, NullHandling nullhandling = NullHandling::Throw) const { if (m_val == nullptr) { if (nullhandling == NullHandling::Throw) throw std::runtime_error("Unexpected NULL value in array"); } else { using value_type = E; ArrayParser parser(m_val); for (;;) { auto res = parser.GetNextElem(); if (res.ok) { if (res.value) { std::string str(res.value->data(), res.value->length()); Value val(str.c_str(), OidFor::elem()); value_type v; v << val; insert_iter = v; } else { if (nullhandling == NullHandling::Throw) throw std::runtime_error("Unexpected NULL value in array"); } } else break; } } } template void getAsArray(I insert_iter, const E &value_for_nulls) const { using value_type = E; ArrayParser parser(m_val); for (;;) { auto res = parser.GetNextElem(); if (res.ok) { if (res.value) { std::string str(res.value->data(), res.value->length()); Value val(str.c_str(), OidFor::elem()); value_type v; v << val; insert_iter = v; } else { insert_iter = value_for_nulls; } } else break; } } template void getAsArrayOfOptional(I insert_iter) const { using value_type = E; ArrayParser parser(m_val); for (;;) { auto res = parser.GetNextElem(); if (res.ok) { if (res.value) { std::string str(res.value->data(), res.value->length()); Value val(str.c_str(), OidFor::elem()); value_type v; v << val; insert_iter = v; } else { insert_iter = std::nullopt; } } else break; } } /** De catalog uses vector types which are similar to array * but uses spaces as seperators. AFAIK there are only integral * vector types so this implementation is only tested for those */ template void getAsVector(I insert_iter) const { const char * pos = m_val; const char * start = pos; for (;;) { while (*pos != 0 && *pos != ' ') ++pos; std::string str(start, pos-start); Value val(str.c_str(), OidFor::elem()); E v; v << val; insert_iter = v; if (*pos == 0) break; start = ++pos; // skip space and set new start to match } } inline Oid getOid() const { return m_typ; } private: const char *m_val; Oid m_typ; }; template void operator<<(T &s, const Value &v) { //s = static_cast(v); s = v.operator T(); } } // end namespace Pgsql #endif // PGSQL_VALUE_H