More flexible array retrieval + *vector support.
This commit is contained in:
parent
d9854d81fa
commit
db75d9ed50
5 changed files with 119 additions and 8 deletions
|
|
@ -12,10 +12,39 @@ namespace Pgsql {
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void reset() { col = -1; }
|
void reset() { col = -1; }
|
||||||
|
|
||||||
Pgsql::Value nextValue()
|
Pgsql::Value nextValue()
|
||||||
{
|
{
|
||||||
return row.get(++col);
|
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:
|
private:
|
||||||
const Pgsql::Row &row;
|
const Pgsql::Row &row;
|
||||||
int col = -1;
|
int col = -1;
|
||||||
|
|
@ -28,6 +57,7 @@ namespace Pgsql {
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} // end namespace Pgsql
|
} // end namespace Pgsql
|
||||||
|
|
||||||
#endif // PGSQL_COL_H
|
#endif // PGSQL_COL_H
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
#define PGSQL_VALUE_H
|
#define PGSQL_VALUE_H
|
||||||
|
|
||||||
#include "Pgsql_declare.h"
|
#include "Pgsql_declare.h"
|
||||||
|
#include "Pgsql_oids.h"
|
||||||
#include "ArrayParser.h"
|
#include "ArrayParser.h"
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
@ -33,10 +34,6 @@ namespace Pgsql {
|
||||||
|
|
||||||
bool isString() const;
|
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.
|
* \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.ok) {
|
||||||
if (res.value) {
|
if (res.value) {
|
||||||
std::string str(res.value->data(), res.value->length());
|
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;
|
value_type v;
|
||||||
v << val;
|
v << val;
|
||||||
insert_iter = v;
|
insert_iter = v;
|
||||||
|
|
@ -76,7 +73,7 @@ namespace Pgsql {
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
if (res.value) {
|
if (res.value) {
|
||||||
std::string str(res.value->data(), res.value->length());
|
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;
|
value_type v;
|
||||||
v << val;
|
v << val;
|
||||||
insert_iter = v;
|
insert_iter = v;
|
||||||
|
|
@ -100,7 +97,7 @@ namespace Pgsql {
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
if (res.value) {
|
if (res.value) {
|
||||||
std::string str(res.value->data(), res.value->length());
|
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;
|
value_type v;
|
||||||
v << val;
|
v << val;
|
||||||
insert_iter = v;
|
insert_iter = v;
|
||||||
|
|
@ -113,6 +110,28 @@ namespace Pgsql {
|
||||||
break;
|
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:
|
private:
|
||||||
const char *m_val;
|
const char *m_val;
|
||||||
Oid m_typ;
|
Oid m_typ;
|
||||||
|
|
|
||||||
|
|
@ -102,6 +102,12 @@ namespace Pgsql {
|
||||||
class Value;
|
class Value;
|
||||||
class Row;
|
class Row;
|
||||||
|
|
||||||
|
enum class NullHandling {
|
||||||
|
Ignore,
|
||||||
|
Throw
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
} // END namespace Pgsql
|
} // END namespace Pgsql
|
||||||
|
|
||||||
#endif // PGSQL_DECLARE_H
|
#endif // PGSQL_DECLARE_H
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@
|
||||||
#define PGSQL_OIDS_H
|
#define PGSQL_OIDS_H
|
||||||
|
|
||||||
#include <libpq-fe.h>
|
#include <libpq-fe.h>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <QDateTime>
|
||||||
|
|
||||||
namespace Pgsql {
|
namespace Pgsql {
|
||||||
constexpr Oid bool_oid = 16;
|
constexpr Oid bool_oid = 16;
|
||||||
|
|
@ -141,6 +143,47 @@ namespace Pgsql {
|
||||||
Oid ElemOidFromArrayOid(Oid oid);
|
Oid ElemOidFromArrayOid(Oid oid);
|
||||||
Oid ArrayOidFromElemOid(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
|
} // end of namespace Pgsql
|
||||||
|
|
||||||
#endif // PGSQL_OIDS_H
|
#endif // PGSQL_OIDS_H
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,19 @@ TEST(Pgsql_Value, isString_varchar)
|
||||||
ASSERT_EQ(v.isString(), true);
|
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)
|
TEST(Pgsql_Value, getAsArray_Ints)
|
||||||
{
|
{
|
||||||
Pgsql::Value v("{1,2}", TEXTARRAYOID);
|
Pgsql::Value v("{1,2}", TEXTARRAYOID);
|
||||||
|
|
@ -122,7 +135,7 @@ TEST(Pgsql_Value, getAsArray_ignore_NULL)
|
||||||
Pgsql::Value v("{1,NULL,2}", TEXTARRAYOID);
|
Pgsql::Value v("{1,NULL,2}", TEXTARRAYOID);
|
||||||
std::vector<int> r;
|
std::vector<int> r;
|
||||||
try {
|
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.size(), 2);
|
||||||
ASSERT_EQ(r[0], 1);
|
ASSERT_EQ(r[0], 1);
|
||||||
ASSERT_EQ(r[1], 2);
|
ASSERT_EQ(r[1], 2);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue