Ser/De: Arrays POC.

This commit is contained in:
lganzzzo 2021-02-10 01:19:03 +02:00
parent c5f81d5e64
commit d1bcba1380
5 changed files with 361 additions and 102 deletions

View File

@ -113,7 +113,7 @@ private:
return nullptr;
}
auto ndim = (v_int32) htonl(*((p_int32)data.data));
auto ndim = (v_int32) ntohl(*((p_int32)data.data));
switch (ndim) {
@ -218,7 +218,7 @@ private:
return oatpp::Void(nullptr, type);
}
auto ndim = (v_int32) htonl(*((p_int32)data.data));
auto ndim = (v_int32) ntohl(*((p_int32)data.data));
if(ndim == 0) {
auto polymorphicDispatcher = static_cast<const typename Collection::Class::PolymorphicDispatcher*>(type->polymorphicDispatcher);
return polymorphicDispatcher->createObject(); // empty array
@ -229,10 +229,10 @@ private:
meta.data = &data;
meta.arrayHeader = *((PgArrayHeader*) data.data);
meta.arrayHeader.ndim = (v_int32) htonl(meta.arrayHeader.ndim);
meta.arrayHeader.size = (v_int32) htonl(meta.arrayHeader.size);
meta.arrayHeader.oid = (v_int32) htonl(meta.arrayHeader.oid);
meta.arrayHeader.index = (v_int32) htonl(meta.arrayHeader.index);
meta.arrayHeader.ndim = (v_int32) ntohl(meta.arrayHeader.ndim);
meta.arrayHeader.size = (v_int32) ntohl(meta.arrayHeader.size);
meta.arrayHeader.oid = (v_int32) ntohl(meta.arrayHeader.oid);
meta.arrayHeader.index = (v_int32) ntohl(meta.arrayHeader.index);
meta.dimensions = {meta.arrayHeader.size};
@ -240,16 +240,12 @@ private:
meta.payload = (p_char8) &data.data[sizeof(PgArrayHeader)];
} else {
for(v_int32 i = 0; i < meta.arrayHeader.ndim - 1; i ++) {
v_int32 dsize = htonl( * ((p_int32) &data.data[sizeof(PgArrayHeader) + i * sizeof(v_int32) * 2]));
v_int32 dsize = ntohl( * ((p_int32) &data.data[sizeof(PgArrayHeader) + i * sizeof(v_int32) * 2]));
meta.dimensions.push_back(dsize);
}
meta.payload = (p_char8) &data.data[sizeof(PgArrayHeader) + sizeof(v_int32) * (meta.arrayHeader.ndim - 1) * 2];
}
// for(v_int32 d : meta.dimensions) {
// OATPP_LOGD("Array", "D=%d", d);
// }
return deserializeSubArray(type, meta, 0);
}

View File

@ -65,40 +65,65 @@ void Serializer::setSerializerMethods() {
setSerializerMethod(data::mapping::type::__class::AbstractEnum::CLASS_ID, &Serializer::serializeEnum);
setSerializerMethod(data::mapping::type::__class::AbstractVector::CLASS_ID, &Serializer::serializeArray2<oatpp::AbstractVector>);
setSerializerMethod(data::mapping::type::__class::AbstractList::CLASS_ID, &Serializer::serializeArray2<oatpp::AbstractList>);
setSerializerMethod(data::mapping::type::__class::AbstractUnorderedSet::CLASS_ID, &Serializer::serializeArray2<oatpp::AbstractUnorderedSet>);
////
setSerializerMethod(postgresql::mapping::type::__class::Uuid::CLASS_ID, &Serializer::serializeUuid);
setSerializerMethod(data::mapping::type::__class::AbstractVector::CLASS_ID, &Serializer::serializeArray);
}
void Serializer::setTypeOidMethods() {
m_typeOidMethods.resize(data::mapping::type::ClassId::getClassCount(), nullptr);
m_arrayTypeOidMethods.resize(data::mapping::type::ClassId::getClassCount(), nullptr);
setTypeOidMethod(data::mapping::type::__class::String::CLASS_ID, &Serializer::getTypeOid<TEXTOID>);
setArrayTypeOidMethod(data::mapping::type::__class::String::CLASS_ID, &Serializer::getTypeOid<TEXTARRAYOID>);
setTypeOidMethod(data::mapping::type::__class::Int8::CLASS_ID, &Serializer::getTypeOid<INT2OID>);
setArrayTypeOidMethod(data::mapping::type::__class::Int8::CLASS_ID, &Serializer::getTypeOid<INT2ARRAYOID>);
setTypeOidMethod(data::mapping::type::__class::UInt8::CLASS_ID, &Serializer::getTypeOid<INT2OID>);
setArrayTypeOidMethod(data::mapping::type::__class::UInt8::CLASS_ID, &Serializer::getTypeOid<INT2ARRAYOID>);
setTypeOidMethod(data::mapping::type::__class::Int16::CLASS_ID, &Serializer::getTypeOid<INT2OID>);
setArrayTypeOidMethod(data::mapping::type::__class::Int16::CLASS_ID, &Serializer::getTypeOid<INT2ARRAYOID>);
setTypeOidMethod(data::mapping::type::__class::UInt16::CLASS_ID, &Serializer::getTypeOid<INT4OID>);
setArrayTypeOidMethod(data::mapping::type::__class::UInt16::CLASS_ID, &Serializer::getTypeOid<INT4ARRAYOID>);
setTypeOidMethod(data::mapping::type::__class::Int32::CLASS_ID, &Serializer::getTypeOid<INT4OID>);
setArrayTypeOidMethod(data::mapping::type::__class::Int32::CLASS_ID, &Serializer::getTypeOid<INT4ARRAYOID>);
setTypeOidMethod(data::mapping::type::__class::UInt32::CLASS_ID, &Serializer::getTypeOid<INT8OID>);
setArrayTypeOidMethod(data::mapping::type::__class::UInt32::CLASS_ID, &Serializer::getTypeOid<INT8ARRAYOID>);
setTypeOidMethod(data::mapping::type::__class::Int64::CLASS_ID, &Serializer::getTypeOid<INT8OID>);
setArrayTypeOidMethod(data::mapping::type::__class::Int64::CLASS_ID, &Serializer::getTypeOid<INT8ARRAYOID>);
setTypeOidMethod(data::mapping::type::__class::Float32::CLASS_ID, &Serializer::getTypeOid<FLOAT4OID>);
setTypeOidMethod(data::mapping::type::__class::Float64::CLASS_ID, &Serializer::getTypeOid<FLOAT8OID>);
setTypeOidMethod(data::mapping::type::__class::Boolean::CLASS_ID, &Serializer::getTypeOid<BOOLOID>);
setArrayTypeOidMethod(data::mapping::type::__class::Float32::CLASS_ID, &Serializer::getTypeOid<FLOAT4ARRAYOID>);
setTypeOidMethod(data::mapping::type::__class::AbstractVector::CLASS_ID, &Serializer::getTypeOid<FLOAT8ARRAYOID>);
setTypeOidMethod(data::mapping::type::__class::Float64::CLASS_ID, &Serializer::getTypeOid<FLOAT8OID>);
setArrayTypeOidMethod(data::mapping::type::__class::Float64::CLASS_ID, &Serializer::getTypeOid<FLOAT8ARRAYOID>);
setTypeOidMethod(data::mapping::type::__class::Boolean::CLASS_ID, &Serializer::getTypeOid<BOOLOID>);
setArrayTypeOidMethod(data::mapping::type::__class::Boolean::CLASS_ID, &Serializer::getTypeOid<BOOLARRAYOID>);
setTypeOidMethod(data::mapping::type::__class::AbstractVector::CLASS_ID, &Serializer::get1DCollectionOid);
setTypeOidMethod(data::mapping::type::__class::AbstractList::CLASS_ID, &Serializer::get1DCollectionOid);
setTypeOidMethod(data::mapping::type::__class::AbstractUnorderedSet::CLASS_ID, &Serializer::get1DCollectionOid);
setTypeOidMethod(data::mapping::type::__class::AbstractEnum::CLASS_ID, &Serializer::getEnumTypeOid);
setArrayTypeOidMethod(data::mapping::type::__class::AbstractEnum::CLASS_ID, &Serializer::getEnumArrayTypeOid);
////
setTypeOidMethod(postgresql::mapping::type::__class::Uuid::CLASS_ID, &Serializer::getTypeOid<UUIDOID>);
setTypeOidMethod(data::mapping::type::__class::AbstractEnum::CLASS_ID, &Serializer::getEnumTypeOid);
setArrayTypeOidMethod(postgresql::mapping::type::__class::Uuid::CLASS_ID, &Serializer::getTypeOid<UUIDARRAYOID>);
}
@ -113,13 +138,22 @@ void Serializer::setSerializerMethod(const data::mapping::type::ClassId& classId
void Serializer::setTypeOidMethod(const data::mapping::type::ClassId& classId, TypeOidMethod method) {
const v_uint32 id = classId.id;
if(id < m_methods.size()) {
if(id < m_typeOidMethods.size()) {
m_typeOidMethods[id] = method;
} else {
throw std::runtime_error("[oatpp::postgresql::mapping::Serializer::setTypeOidMethod()]: Error. Unknown classId");
}
}
void Serializer::setArrayTypeOidMethod(const data::mapping::type::ClassId& classId, TypeOidMethod method) {
const v_uint32 id = classId.id;
if(id < m_arrayTypeOidMethods.size()) {
m_arrayTypeOidMethods[id] = method;
} else {
throw std::runtime_error("[oatpp::postgresql::mapping::Serializer::setArrayTypeOidMethod()]: Error. Unknown classId");
}
}
void Serializer::serialize(OutputData& outData, const oatpp::Void& polymorph) const {
auto id = polymorph.valueType->classId.id;
auto& method = m_methods[id];
@ -146,13 +180,27 @@ Oid Serializer::getTypeOid(const oatpp::Type* type) const {
}
Oid Serializer::getArrayTypeOid(const oatpp::Type* type) const {
auto id = type->classId.id;
auto& method = m_arrayTypeOidMethods[id];
if(method) {
return (*method)(this, type);
}
throw std::runtime_error("[oatpp::postgresql::mapping::Serializer::getArrayTypeOid()]: "
"Error. Can't derive OID for type '" + std::string(type->classId.name) +
"'");
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Serializer utility functions
void Serializer::serNull(OutputData& outData) {
outData.dataBuffer.reset();
outData.data = nullptr;
outData.dataSize = 0;
outData.dataSize = -1;
outData.dataFormat = 1;
}
@ -377,6 +425,30 @@ Oid Serializer::getEnumTypeOid(const Serializer* _this, const oatpp::Type* type)
}
Oid Serializer::getEnumArrayTypeOid(const Serializer* _this, const oatpp::Type* type) {
auto polymorphicDispatcher = static_cast<const data::mapping::type::__class::AbstractEnum::PolymorphicDispatcher*>(
type->polymorphicDispatcher
);
const oatpp::Type* enumInterType = polymorphicDispatcher->getInterpretationType();
return _this->getArrayTypeOid(enumInterType);
}
Oid Serializer::get1DCollectionOid(const Serializer* _this, const oatpp::Type* type) {
while(type->classId.id == oatpp::AbstractVector::Class::CLASS_ID.id ||
type->classId.id == oatpp::AbstractList::Class::CLASS_ID.id ||
type->classId.id == oatpp::AbstractUnorderedSet::Class::CLASS_ID.id)
{
type = *type->params.begin();
}
return _this->getArrayTypeOid(type);
}
void Serializer::serializeUuid(const Serializer* _this, OutputData& outData, const oatpp::Void& polymorph) {
(void) _this;
@ -392,46 +464,106 @@ void Serializer::serializeUuid(const Serializer* _this, OutputData& outData, con
}
}
void Serializer::serializeArray(const Serializer* _this, OutputData& outData, const oatpp::Void& polymorph) {
const oatpp::Type* Serializer::getArrayItemTypeAndDimensions(const oatpp::Void& polymorph, std::vector<v_int32>& dimensions) {
(void) _this;
void* currObj = polymorph.get();
const oatpp::Type* currType = polymorph.valueType;
if(polymorph) {
auto v = polymorph.staticCast<oatpp::Vector<Float64>>();
while(currType->classId.id == oatpp::AbstractVector::Class::CLASS_ID.id ||
currType->classId.id == oatpp::AbstractList::Class::CLASS_ID.id ||
currType->classId.id == oatpp::AbstractUnorderedSet::Class::CLASS_ID.id)
{
// get size of header + vector size * sizeof each element (size + data)
auto dataSize = sizeof(PgArrayHeader) + v->size() * (sizeof(PgElem) + sizeof(v_float64));
outData.dataBuffer.reset(new char[dataSize]);
outData.dataSize = dataSize;
outData.dataFormat = 1;
outData.oid = FLOAT8ARRAYOID;
outData.data = outData.dataBuffer.get();
auto buffer = outData.data;
// load the data in to the pgArray
auto *pgArray = reinterpret_cast<PgArray *>(buffer);
// only support 1d float8 arrays for now
pgArray->header.ndim = htonl(1);
pgArray->header._ign = 0;
pgArray->header.oid = htonl(FLOAT8OID);
pgArray->header.size = htonl(v->size());
pgArray->header.index = htonl(1); // postgres arrays are indexed 1..N by default
// stuff in the elements in network order
auto *elemBuff = reinterpret_cast<p_uint8>(pgArray->elem);
for (int i=0; i < v->size(); i++) {
*reinterpret_cast<p_uint32>(elemBuff) = htonl(sizeof(v_float64));
elemBuff += sizeof(v_int32);
v_float64 fValue = v->at(i);
auto pVal = reinterpret_cast<p_int64>(&fValue);
*reinterpret_cast<p_uint32>(elemBuff) = htonl(*pVal >> 32);
elemBuff += sizeof(v_int32);
*reinterpret_cast<p_uint32>(elemBuff) = htonl(*pVal & 0xFFFFFFFF);
elemBuff += sizeof(v_int32);
}
} else{
serNull(outData);
if(currObj == nullptr) {
throw std::runtime_error("[oatpp::postgresql::mapping::Serializer::getArrayItemTypeAndDimensions()]: Error. "
"The nested container can't be null.");
}
if(currType->classId.id == oatpp::AbstractVector::Class::CLASS_ID.id) {
auto c = static_cast<std::vector<oatpp::Void>*>(currObj);
dimensions.push_back(c->size());
currObj = (c->size() > 0) ? (*c)[0].get() : nullptr;
} else if(currType->classId.id == oatpp::AbstractList::Class::CLASS_ID.id) {
auto c = static_cast<std::list<oatpp::Void>*>(currObj);
dimensions.push_back(c->size());
currObj = (c->size() > 0) ? c->front().get() : nullptr;
} else if(currType->classId.id == oatpp::AbstractUnorderedSet::Class::CLASS_ID.id) {
auto c = static_cast<std::unordered_set<oatpp::Void>*>(currObj);
dimensions.push_back(c->size());
currObj = (c->size() > 0) ? c->begin()->get() : nullptr;
}
currType = *currType->params.begin();
}
return currType;
}
void Serializer::writeArrayHeader(data::stream::ConsistentOutputStream* stream,
Oid itemOid,
const std::vector<v_int32>& dimensions)
{
// num dimensions
v_int32 v = htonl(dimensions.size());
stream->writeSimple(&v, sizeof(v_int32));
// ignore
v = 0;
stream->writeSimple(&v, sizeof(v_int32));
// oid
v = htonl(itemOid);
stream->writeSimple(&v, sizeof(v_int32));
// size
v = htonl(dimensions[0]);
stream->writeSimple(&v, sizeof(v_int32));
// index
v = htonl(1);
stream->writeSimple(&v, sizeof(v_int32));
for(v_uint32 i = 1; i < dimensions.size(); i++) {
v_int32 size = htonl(dimensions[i]);
v_int32 index = htonl(1);
stream->writeSimple(&size, sizeof(v_int32));
stream->writeSimple(&index, sizeof(v_int32));
}
}
void Serializer::serializeSubArray(data::stream::ConsistentOutputStream* stream,
const oatpp::Void& polymorph,
ArraySerializationMeta& meta,
v_int32 dimension)
{
const oatpp::Type* type = polymorph.valueType;
if(data::mapping::type::__class::AbstractVector::CLASS_ID.id == type->classId.id) {
return serializeSubArray<oatpp::AbstractVector>(stream, polymorph, meta, dimension);
} else if(data::mapping::type::__class::AbstractList::CLASS_ID.id == type->classId.id) {
return serializeSubArray<oatpp::AbstractList>(stream, polymorph, meta, dimension);
} else if(data::mapping::type::__class::AbstractUnorderedSet::CLASS_ID.id == type->classId.id) {
return serializeSubArray<oatpp::AbstractUnorderedSet>(stream, polymorph, meta, dimension);
}
throw std::runtime_error("[oatpp::postgresql::mapping::Serializer::serializeSubArray()]: "
"Error. Unknown 1D collection type.");
}
}}}

View File

@ -25,6 +25,7 @@
#ifndef oatpp_postgresql_mapping_Serializer_hpp
#define oatpp_postgresql_mapping_Serializer_hpp
#include "oatpp/core/data/stream/BufferStream.hpp"
#include "oatpp/core/Types.hpp"
#include <libpq-fe.h>
@ -38,11 +39,11 @@ class Serializer {
public:
struct OutputData {
Oid oid;
Oid oid = InvalidOid;
std::unique_ptr<char[]> dataBuffer;
char* data;
int dataSize;
int dataFormat;
char* data = nullptr;
int dataSize = -1;
int dataFormat = 1;
};
public:
@ -63,16 +64,19 @@ private:
private:
std::vector<SerializerMethod> m_methods;
std::vector<TypeOidMethod> m_typeOidMethods;
std::vector<TypeOidMethod> m_arrayTypeOidMethods;
public:
Serializer();
void setSerializerMethod(const data::mapping::type::ClassId& classId, SerializerMethod method);
void setTypeOidMethod(const data::mapping::type::ClassId& classId, TypeOidMethod method);
void setArrayTypeOidMethod(const data::mapping::type::ClassId& classId, TypeOidMethod method);
void serialize(OutputData& outData, const oatpp::Void& polymorph) const;
Oid getTypeOid(const oatpp::Type* type) const;
Oid getArrayTypeOid(const oatpp::Type* type) const;
private:
@ -99,7 +103,105 @@ private:
static void serializeUuid(const Serializer* _this, OutputData& outData, const oatpp::Void& polymorph);
static void serializeArray(const Serializer* _this, OutputData& outData, const oatpp::Void& polymorph);
struct ArraySerializationMeta {
const Serializer* _this;
std::vector<v_int32> dimensions;
};
static const oatpp::Type* getArrayItemTypeAndDimensions(const oatpp::Void& polymorph, std::vector<v_int32>& dimensions);
static void writeArrayHeader(data::stream::ConsistentOutputStream* stream, Oid itemOid, const std::vector<v_int32>& dimensions);
static void serializeSubArray(data::stream::ConsistentOutputStream* stream,
const oatpp::Void& polymorph,
ArraySerializationMeta& meta,
v_int32 dimension);
template<class Collection>
static void serializeSubArray(data::stream::ConsistentOutputStream* stream,
const oatpp::Void& polymorph,
ArraySerializationMeta& meta,
v_int32 dimension)
{
const oatpp::Type* type = polymorph.valueType;
const oatpp::Type* itemType = *type->params.begin();
if(dimension < meta.dimensions.size() - 1) {
auto size = meta.dimensions[dimension];
auto arr = polymorph.template staticCast<Collection>();
if(arr->size() != size) {
throw std::runtime_error("[oatpp::postgresql::mapping::Serializer::serializeSubArray()]. Error. "
"All nested arrays must be of the same size.");
}
for(auto& item : *arr) {
serializeSubArray(stream, item, meta, dimension + 1);
}
} else if(dimension == meta.dimensions.size() - 1) {
auto size = meta.dimensions[dimension];
auto arr = polymorph.template staticCast<Collection>();
if(arr->size() != size) {
throw std::runtime_error("[oatpp::postgresql::mapping::Serializer::serializeSubArray()]. Error. "
"All nested arrays must be of the same size.");
}
for(auto& item : *arr) {
OutputData data;
meta._this->serialize(data, item);
v_int32 itemSize = htonl(data.dataSize);
stream->writeSimple(&itemSize, sizeof(v_int32));
if(data.data != nullptr) {
stream->writeSimple(data.data, data.dataSize);
}
}
}
}
template<class Collection>
static void serializeArray2(const Serializer* _this, OutputData& outData, const oatpp::Void& polymorph) {
if(!polymorph) {
serNull(outData);
}
ArraySerializationMeta meta;
meta._this = _this;
const oatpp::Type* itemType = getArrayItemTypeAndDimensions(polymorph, meta.dimensions);
if(meta.dimensions.empty()) {
throw std::runtime_error("[oatpp::postgresql::mapping::Serializer::serializeArray2()]: Error. "
"Invalid array.");
}
data::stream::BufferOutputStream stream;
writeArrayHeader(&stream, _this->getTypeOid(itemType), meta.dimensions);
serializeSubArray(&stream, polymorph, meta, 0);
outData.oid = _this->getArrayTypeOid(itemType);
outData.dataSize = stream.getCurrentPosition();
outData.dataBuffer.template reset(new char[outData.dataSize]);
outData.data = outData.dataBuffer.get();
outData.dataFormat = 1;
std::memcpy(outData.data, stream.getData(), outData.dataSize);
}
private:
template<Oid OID>
@ -111,6 +213,10 @@ private:
static Oid getEnumTypeOid(const Serializer* _this, const oatpp::Type* type);
static Oid getEnumArrayTypeOid(const Serializer* _this, const oatpp::Type* type);
static Oid get1DCollectionOid(const Serializer* _this, const oatpp::Type* type);
};
}}}

View File

@ -24,43 +24,43 @@ CREATE TABLE test_arrays2 (
f_text text[][]
);
INSERT INTO test_arrays1
(f_real, f_double, f_int16, f_int32, f_int64, f_bool, f_text)
VALUES
(null, null, null, null, null, null, null);
INSERT INTO test_arrays1
(f_real, f_double, f_int16, f_int32, f_int64, f_bool, f_text)
VALUES
('{}', '{}', '{}', '{}', '{}', '{}', '{}');
INSERT INTO test_arrays1
(f_real, f_double, f_int16, f_int32, f_int64, f_bool, f_text)
VALUES
('{null, null}', '{null, null}', '{null, null}', '{null, null}', '{null, null}', '{null, null}', '{null, null}');
INSERT INTO test_arrays1
(f_real, f_double, f_int16, f_int32, f_int64, f_bool, f_text)
VALUES
('{0}', '{0}', '{0}', '{0}', '{0}', '{false}', '{"", ""}');
INSERT INTO test_arrays1
(f_real, f_double, f_int16, f_int32, f_int64, f_bool, f_text)
VALUES
('{1}', '{1}', '{1}', '{1}', '{1}', '{true}', '{"hello"}');
INSERT INTO test_arrays2
(f_real, f_double, f_int16, f_int32, f_int64, f_bool, f_text)
VALUES
(null, null, null, null, null, null, null);
INSERT INTO test_arrays2
(f_real, f_double, f_int16, f_int32, f_int64, f_bool, f_text)
VALUES
('{}', '{}', '{}', '{}', '{}', '{}', '{}');
--
-- INSERT INTO test_arrays1
-- (f_real, f_double, f_int16, f_int32, f_int64, f_bool, f_text)
-- VALUES
-- (null, null, null, null, null, null, null);
--
-- INSERT INTO test_arrays1
-- (f_real, f_double, f_int16, f_int32, f_int64, f_bool, f_text)
-- VALUES
-- ('{}', '{}', '{}', '{}', '{}', '{}', '{}');
--
-- INSERT INTO test_arrays1
-- (f_real, f_double, f_int16, f_int32, f_int64, f_bool, f_text)
-- VALUES
-- ('{null, null}', '{null, null}', '{null, null}', '{null, null}', '{null, null}', '{null, null}', '{null, null}');
--
-- INSERT INTO test_arrays1
-- (f_real, f_double, f_int16, f_int32, f_int64, f_bool, f_text)
-- VALUES
-- ('{0}', '{0}', '{0}', '{0}', '{0}', '{false}', '{"", ""}');
--
-- INSERT INTO test_arrays1
-- (f_real, f_double, f_int16, f_int32, f_int64, f_bool, f_text)
-- VALUES
-- ('{1}', '{1}', '{1}', '{1}', '{1}', '{true}', '{"hello"}');
--
--
-- INSERT INTO test_arrays2
-- (f_real, f_double, f_int16, f_int32, f_int64, f_bool, f_text)
-- VALUES
-- (null, null, null, null, null, null, null);
--
-- INSERT INTO test_arrays2
-- (f_real, f_double, f_int16, f_int32, f_int64, f_bool, f_text)
-- VALUES
-- ('{}', '{}', '{}', '{}', '{}', '{}', '{}');
--
INSERT INTO test_arrays2
(f_real, f_double, f_int16, f_int32, f_int64, f_bool, f_text)
VALUES

View File

@ -41,8 +41,13 @@ class Row : public oatpp::DTO {
DTO_INIT(Row, DTO);
DTO_FIELD(Float32, f_real);
DTO_FIELD(Float64, f_double);
DTO_FIELD(Vector<Float32>, f_real);
DTO_FIELD(Vector<Float64>, f_double);
DTO_FIELD(Vector<Int16>, f_int16);
DTO_FIELD(Vector<Int32>, f_int32);
DTO_FIELD(Vector<Int64>, f_int64);
DTO_FIELD(Vector<Boolean> , f_bool);
DTO_FIELD(Vector<String> , f_text);
};
@ -69,16 +74,16 @@ public:
}
QUERY(insertValues,
"INSERT INTO test_floats "
"(f_real, f_double) "
"INSERT INTO test_arrays1 "
"(f_real, f_double, f_int16, f_int32, f_int64, f_bool, f_text) "
"VALUES "
"(:row.f_real, :row.f_double);",
"(:row.f_real, :row.f_double, :row.f_int16, :row.f_int32, :row.f_int64, :row.f_bool, :row.f_text);",
PARAM(oatpp::Object<Row>, row), PREPARE(true))
QUERY(deleteValues,
"DELETE FROM test_floats;")
QUERY(selectValues, "SELECT * FROM test_arrays2;")
QUERY(selectValues, "SELECT * FROM test_arrays1;")
};
@ -95,6 +100,26 @@ void ArrayTest::onRun() {
auto client = MyClient(executor);
{
auto row = Row::createShared();
row->f_real = {nullptr, v_float32(0), 0.32};
row->f_double = {nullptr, v_float64 (0), 0.64};
row->f_int16 = {nullptr, v_int16(0), 16};
row->f_int32 = {nullptr, v_int16(0), 32};
row->f_int64 = {nullptr, v_int16(0), 64};
row->f_bool = {nullptr, true, false};
row->f_text = {nullptr, "", "Hello", "World!"};
auto res = client.insertValues(row);
if(res->isSuccess()) {
OATPP_LOGD(TAG, "OK, knownCount=%d, hasMore=%d", res->getKnownCount(), res->hasMoreToFetch());
} else {
auto message = res->getErrorMessage();
OATPP_LOGD(TAG, "Error, message=%s", message->c_str());
}
}
{
auto res = client.selectValues();
if(res->isSuccess()) {