Last active
December 17, 2015 16:09
-
-
Save wichert/5636906 to your computer and use it in GitHub Desktop.
Minimal uuid and HSTORE support for pqxx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <boost/algorithm/string/join.hpp> | |
#include <boost/format.hpp> | |
#include <boost/regex.hpp> | |
#include <boost/uuid/uuid_generators.hpp> | |
#include <boost/uuid/uuid_io.hpp> | |
#include <stylist/private/pqxx.hh> | |
using namespace std; | |
namespace { | |
boost::uuids::nil_generator nil_gen; | |
boost::uuids::string_generator parse_uuid; | |
const boost::regex regexp_kv( | |
// A quoted key | |
"\"(.*?)(?!\\\\)\"" | |
// assignment, possibly with extra whitespace | |
"\\s*=>\\s*" | |
// NULL or quoted value | |
"(NULL|\"(.*?)(?!\\\\)\")"); | |
} | |
namespace stylist { | |
namespace pg { | |
string escape(const string &value) { | |
string result; | |
result.reserve(value.length()+5); | |
for (auto chr : value) { | |
if (chr=='\\' || chr=='"') | |
result+='\\'; | |
result+=chr; | |
} | |
return result; | |
} | |
string unescape(const string &value) { | |
string result; | |
result.reserve(value.length()); | |
for (string::const_iterator it=value.begin(); it!=value.end(); it++) { | |
if (*it=='\\') { | |
it++; | |
if (it==value.end()) | |
break; | |
} | |
result.push_back(*it); | |
} | |
return result; | |
} | |
} | |
} | |
namespace pqxx { | |
boost::uuids::uuid string_traits<boost::uuids::uuid>::null() { | |
return nil_gen(); | |
} | |
void string_traits<boost::uuids::uuid>::from_string(const char str[], value_type &uuid) { | |
uuid=parse_uuid(str); | |
} | |
std::string string_traits<boost::uuids::uuid>::to_string(const value_type &uuid) { | |
return boost::uuids::to_string(uuid); | |
} | |
void string_traits<map<string, string>>::from_string(const char str[], value_type &output) { | |
string input(str); | |
boost::sregex_iterator begin(input.begin(), input.end(), regexp_kv); | |
boost::sregex_iterator end; | |
output.clear(); | |
for (auto match=begin; match!=end; match++) { | |
string key(stylist::pg::unescape(match->str(1))); | |
int hits = match->size(); | |
string v(match->str(2)); | |
string value(stylist::pg::unescape(match->str(3))); | |
output[key]=value; | |
} | |
} | |
string string_traits<map<string, string>>::to_string(const value_type &obj) { | |
list<string> parts; | |
for (auto i : obj) { | |
string key(stylist::pg::escape(i.first)); | |
string value(stylist::pg::escape(i.second)); | |
parts.push_back((boost::format("\"%s\"=>\"%s\"") % key % value).str()); | |
} | |
return boost::algorithm::join(parts, ", "); | |
} | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef _STYLIST_PRIVATE_PQXX_INCLUDED_ | |
#define _STYLIST_PRIVATE_PQXX_INCLUDED_ | |
#include <map> | |
#include <string> | |
#include <boost/uuid/uuid.hpp> | |
#include <pqxx/pqxx> | |
namespace stylist { | |
namespace pg { | |
std::string escape(const std::string &value); | |
std::string unescape(const std::string &value); | |
} | |
} | |
namespace pqxx { | |
template<> | |
struct string_traits<boost::uuids::uuid> { | |
typedef boost::uuids::uuid value_type; | |
static const char *name() { | |
return "UUID"; | |
} | |
static bool has_null() { | |
return true; | |
} | |
static bool is_null(const value_type &uuid) { | |
return uuid.is_nil(); | |
} | |
static boost::uuids::uuid null(); | |
static void from_string(const char str[], value_type &uuid); | |
static std::string to_string(const value_type &uuid); | |
}; | |
template<> | |
struct string_traits<std::map<std::string, std::string>> { | |
typedef std::map<std::string, std::string> value_type; | |
static const char *name() { | |
return "map<string, string>"; | |
} | |
static bool has_null() { | |
return true; | |
} | |
static bool is_null(const value_type& value) { | |
return value.empty(); | |
} | |
static value_type null() { | |
return value_type(); | |
} | |
static void from_string(const char str[], value_type &output); | |
static std::string to_string(const value_type &obj); | |
}; | |
} | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment