Used slightly different approach. This tab is fully build in source code using subclasses to adjust behaviour of widgets for reuse in the other tabs. Uses custom proxy model for filtering triggers for correct table and supporting out of the box sorting by QTableView. SqlCodePreview: QPlainTextEditor which sql highlighter and in readonly mode but allows copy.
180 lines
4 KiB
C++
180 lines
4 KiB
C++
#ifndef PGSQL_VALUE_H
|
|
#define PGSQL_VALUE_H
|
|
|
|
#include "Pgsql_declare.h"
|
|
#include "Pgsql_oids.h"
|
|
#include "ArrayParser.h"
|
|
#include <sstream>
|
|
#include <vector>
|
|
#include <QString>
|
|
#include <QDateTime>
|
|
#include <boost/optional.hpp>
|
|
|
|
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;
|
|
operator char() const;
|
|
|
|
bool isString() const;
|
|
|
|
/**
|
|
*
|
|
* \param insert_iter An insert_iterator which is used to add the elements of the array to a container.
|
|
*/
|
|
template <typename E, typename I>
|
|
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 for 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<E>::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 <typename E, typename I>
|
|
void getAsArray(I insert_iter, const E &value_for_nulls) const
|
|
{
|
|
if (m_val == nullptr) return;
|
|
|
|
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<E>::elem());
|
|
value_type v;
|
|
v << val;
|
|
insert_iter = v;
|
|
}
|
|
else {
|
|
insert_iter = value_for_nulls;
|
|
}
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
}
|
|
|
|
template <typename E, typename I>
|
|
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<E>::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 <typename E, typename I>
|
|
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<E>::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 <typename T>
|
|
void operator<<(boost::optional<T> &s, const Value &v)
|
|
{
|
|
if (v.null())
|
|
s = boost::optional<T>();
|
|
else
|
|
*s << v;
|
|
}
|
|
|
|
template <typename T>
|
|
void operator<<(std::vector<T> &s, const Value &v)
|
|
{
|
|
v.getAsArray(std::back_inserter(s));
|
|
}
|
|
|
|
template <typename T>
|
|
void operator<<(T &s, const Value &v)
|
|
{
|
|
s = v.operator T();
|
|
}
|
|
|
|
|
|
} // end namespace Pgsql
|
|
|
|
#endif // PGSQL_VALUE_H
|