Open croja opened 3 years ago
#pragma once
#include <ozo/pg/definitions.h>
#include <ozo/io/send.h>
#include <ozo/io/recv.h>
#include <boost/asio.hpp>
namespace ozo {
// NOT TESTED!!!
template <>
struct send_impl<boost::asio::ip::network_v4> {
template <typename OidMap>
static ostream& apply(ostream& out, const OidMap&, const boost::asio::ip::network_v4& in) {
std::uint8_t size_of_mask = sizeof(std::uint16_t);
std::uint16_t mask = in.netmask().to_uint();
write(out, size_of_mask);
write(out, htons(mask));
std::uint8_t size_of_address = sizeof(std::uint32_t);
std::uint32_t address = in.address().to_uint();
write(out, size_of_address);
return write(out, address);
}
};
template <>
struct recv_impl<boost::asio::ip::network_v4> {
template <typename OidMap>
static istream& apply(istream& in, size_type, const OidMap&, boost::asio::ip::network_v4& out) {
std::uint8_t size_of_mask = 0;
read(in, size_of_mask);
assert(size_of_mask == sizeof(std::uint16_t));
std::uint16_t mask = 0;
read(in, mask);
mask = ntohs(mask);
std::uint8_t size_of_address = 0;
read(in, size_of_address);
assert(size_of_address == sizeof(std::uint32_t));
std::uint32_t address = 0;
read(in, address);
out = boost::asio::ip::network_v4(boost::asio::ip::address_v4(address), mask);
return in;
}
};
}
OZO_PG_BIND_TYPE(boost::asio::ip::network_v4, "inet")
Found some examples in source code and tried to implement support for "inet". recv_impl
seems to work (binary representation explored experimentally, not sure where I can find it's description)
Unfortunately I don't know how to test send_impl
, failed to write INSERT query using boost::asio::ip::network_v4
variable.
Hi!
Thanks for trying to implement the IO. Yes, this is very close to the proper implementation. A good description for the binary representation may be found here. Since the type has a dynamic size of the binary representation, the ozo::size_of_impl
specialization is needed too. The ozo::size_of
should return a size of binary representation for the type. So this is the reason for send
failure.
I spent some time last night implementing a more general solution. So feel free to use your solution for a while until the out-of-the-box solution is on the way.
Thank you very much! It is great.
p.s. About send
- I meant I don't know how to construct INSERT query passing network_v4
variables. All INSERT queries I found in sources contain hardcoded values. Maybe you can provide example how to construct insert query using variables?
I tried concatenate variable (analogous to SELECT example from documentation), but this doesn't compile:
using namespace boost::asio;
const ip::network_v4 net(ip::make_address_v4("127.0.0.0"), 8);
const auto query_insert = "INSERT INTO tbl (network) VALUES ('"_SQL + net + "') RETURNING network"_SQL;
Maybe there other ways to trigger send_impl::apply()
execution?
Could you please share the compilation error?
Also, in the case of inet
type of the network
column, you do not need to quote variables, since they are transferred via the binary protocol, and all the type information being preserved.
Sorry! As you said, compilation error is related to missing ozo::size_of
.
I had to check it again more carefully after your response.
Implemented size_of
and error is gone.
p.s. Thank you for the library! I use boost::asio
hard, and for me it is really enjoying to asynchronously access Postgres with little to no efforts, reusing io_context
from my applications.
Which C++ type should I use if I want to read column of type "inet"? Is it as simple as using std::string for "text"? Which actions must be performed to be able to read column value into variable of type
boost::asio::ip::network_v4
?