More flexible array retrieval + *vector support.

This commit is contained in:
eelke 2017-12-17 11:27:42 +01:00
parent d9854d81fa
commit db75d9ed50
5 changed files with 119 additions and 8 deletions

View file

@ -12,10 +12,39 @@ namespace Pgsql {
{}
void reset() { col = -1; }
Pgsql::Value nextValue()
{
return row.get(++col);
}
template <typename E, typename I>
Col& getAsArray(I insert_iter, NullHandling nullhandling = NullHandling::Throw)
{
nextValue().getAsArray<E, I>(insert_iter, nullhandling);
return *this;
}
template <typename E, typename I>
void getAsArray(I insert_iter, const E &value_for_nulls) const
{
nextValue().getAsArray<E, I>(insert_iter, value_for_nulls);
return *this;
}
template <typename E, typename I>
void getAsArrayOfOptional(I insert_iter) const
{
nextValue().getAsArrayOfOptional<E, I>(insert_iter);
return *this;
}
template <typename E, typename I>
Col& getAsVector(I insert_iter)
{
nextValue().getAsVector<E, I>(insert_iter);
return *this;
}
private:
const Pgsql::Row &row;
int col = -1;
@ -28,6 +57,7 @@ namespace Pgsql {
return c;
}
} // end namespace Pgsql
#endif // PGSQL_COL_H

View file

@ -2,6 +2,7 @@
#define PGSQL_VALUE_H
#include "Pgsql_declare.h"
#include "Pgsql_oids.h"
#include "ArrayParser.h"
#include <sstream>
#include <QString>
@ -33,10 +34,6 @@ namespace Pgsql {
bool isString() const;
enum class NullHandling {
Ignore,
Throw
};
/**
*
* \param insert_iter An insert_iterator which is used to add the elements of the array to a container.
@ -51,7 +48,7 @@ namespace Pgsql {
if (res.ok) {
if (res.value) {
std::string str(res.value->data(), res.value->length());
Value val(str.c_str(), ANYOID);
Value val(str.c_str(), OidFor<E>::elem());
value_type v;
v << val;
insert_iter = v;
@ -76,7 +73,7 @@ namespace Pgsql {
if (res.ok) {
if (res.value) {
std::string str(res.value->data(), res.value->length());
Value val(str.c_str(), ANYOID);
Value val(str.c_str(), OidFor<E>::elem());
value_type v;
v << val;
insert_iter = v;
@ -100,7 +97,7 @@ namespace Pgsql {
if (res.ok) {
if (res.value) {
std::string str(res.value->data(), res.value->length());
Value val(str.c_str(), ANYOID);
Value val(str.c_str(), OidFor<E>::elem());
value_type v;
v << val;
insert_iter = v;
@ -113,6 +110,28 @@ namespace Pgsql {
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
}
}
private:
const char *m_val;
Oid m_typ;

View file

@ -102,6 +102,12 @@ namespace Pgsql {
class Value;
class Row;
enum class NullHandling {
Ignore,
Throw
};
} // END namespace Pgsql
#endif // PGSQL_DECLARE_H

View file

@ -2,6 +2,8 @@
#define PGSQL_OIDS_H
#include <libpq-fe.h>
#include <cstdint>
#include <QDateTime>
namespace Pgsql {
constexpr Oid bool_oid = 16;
@ -141,6 +143,47 @@ namespace Pgsql {
Oid ElemOidFromArrayOid(Oid oid);
Oid ArrayOidFromElemOid(Oid oid);
template <typename T>
class OidFor {
public:
static Oid elem();
static Oid array();
};
template <>
class OidFor<int16_t> {
public:
static Oid elem() { return int2_oid; }
static Oid array() { return int2_array_oid; }
};
template <>
class OidFor<int32_t> {
public:
static Oid elem() { return int4_oid; }
static Oid array() { return int4_array_oid; }
};
template <>
class OidFor<unsigned int> {
public:
static Oid elem() { return oid_oid; }
static Oid array() { return oid_array_oid; }
};
template <>
class OidFor<QDateTime> {
public:
static Oid elem() { return timestamptz_oid; }
static Oid array() { return timestamptz_array_oid; }
};
// template <>
// class OidFor<> {
// public:
// static Oid elem() { return _oid; }
// static Oid array() { return _array_oid; }
// };
} // end of namespace Pgsql
#endif // PGSQL_OIDS_H

View file

@ -68,6 +68,19 @@ TEST(Pgsql_Value, isString_varchar)
ASSERT_EQ(v.isString(), true);
}
TEST(Pgsql_Value, getAsVector_Ints)
{
Pgsql::Value v("1 2", ANYOID);
std::vector<int> r;
v.getAsVector<int>(std::back_inserter(r));
ASSERT_EQ(r.size(), 2);
ASSERT_EQ(r[0], 1);
ASSERT_EQ(r[1], 2);
}
TEST(Pgsql_Value, getAsArray_Ints)
{
Pgsql::Value v("{1,2}", TEXTARRAYOID);
@ -122,7 +135,7 @@ TEST(Pgsql_Value, getAsArray_ignore_NULL)
Pgsql::Value v("{1,NULL,2}", TEXTARRAYOID);
std::vector<int> r;
try {
v.getAsArray<int>(std::back_inserter(r), Value::NullHandling::Ignore);
v.getAsArray<int>(std::back_inserter(r), NullHandling::Ignore);
ASSERT_EQ(r.size(), 2);
ASSERT_EQ(r[0], 1);
ASSERT_EQ(r[1], 2);