Commit e5d8124e authored by Mateusz Loskot's avatar Mateusz Loskot

Experimental support of unsigned long long in core and postgresql backend.

parent 6da1388f
......@@ -119,6 +119,12 @@ void postgresql_standard_into_type_backend::post_fetch(
*dest = string_to_integer<long long>(buf);
}
break;
case x_unsigned_long_long:
{
unsigned long long * dest = static_cast<unsigned long long *>(data_);
*dest = string_to_unsigned_integer<unsigned long long>(buf);
}
break;
case x_double:
{
double * dest = static_cast<double *>(data_);
......
......@@ -113,6 +113,15 @@ void postgresql_standard_use_type_backend::pre_use(indicator const * ind)
*static_cast<long long *>(data_));
}
break;
case x_unsigned_long_long:
{
std::size_t const bufSize
= std::numeric_limits<unsigned long long>::digits10 + 3;
buf_ = new char[bufSize];
snprintf(buf_, bufSize, "%llu",
*static_cast<unsigned long long *>(data_));
}
break;
case x_double:
{
// no need to overengineer it (KISS)...
......
......@@ -291,6 +291,26 @@ void test4()
std::cout << "test 4 passed" << std::endl;
}
// unsigned long long test
void test4ul()
{
{
session sql(backEnd, connectString);
longlong_table_creator tableCreator(sql);
unsigned long long v1 = 1000000000000ULL;
assert(v1 / 1000000 == 1000000);
sql << "insert into soci_test(val) values(:val)", use(v1);
unsigned long long v2 = 0ULL;
sql << "select val from soci_test", into(v2);
assert(v2 == v1);
}
}
struct boolean_table_creator : table_creator_base
{
boolean_table_creator(session & sql)
......@@ -587,11 +607,11 @@ int main(int argc, char** argv)
tests.run();
std::cout << "\nSOCI Postgres Tests:\n\n";
test1();
test2();
test3();
test4();
test4ul();
test5();
// test6();
......
......@@ -9,6 +9,7 @@
#include "soci-postgresql.h"
#include "common.h"
#include <libpq/libpq-fs.h> // libpq
#include <cassert>
#include <cctype>
#include <cstdio>
#include <cstring>
......@@ -125,6 +126,13 @@ void postgresql_vector_into_type_backend::post_fetch(bool gotData, indicator * i
set_invector_(data_, i, val);
}
break;
case x_unsigned_long_long:
{
unsigned long long const val =
string_to_unsigned_integer<unsigned long long>(buf);
set_invector_(data_, i, val);
}
break;
case x_double:
{
double const val = string_to_double(buf);
......@@ -166,18 +174,38 @@ void resizevector_(void * p, std::size_t sz)
void postgresql_vector_into_type_backend::resize(std::size_t sz)
{
assert(sz < std::numeric_limits<unsigned short>::max()); // Not a strong constraint, for debugging only
switch (type_)
{
// simple cases
case x_char: resizevector_<char> (data_, sz); break;
case x_short: resizevector_<short> (data_, sz); break;
case x_integer: resizevector_<int> (data_, sz); break;
case x_unsigned_long: resizevector_<unsigned long>(data_, sz); break;
case x_long_long: resizevector_<long long> (data_, sz); break;
case x_double: resizevector_<double> (data_, sz); break;
case x_stdstring: resizevector_<std::string> (data_, sz); break;
case x_stdtm: resizevector_<std::tm> (data_, sz); break;
// simple cases
case x_char:
resizevector_<char>(data_, sz);
break;
case x_short:
resizevector_<short>(data_, sz);
break;
case x_integer:
resizevector_<int>(data_, sz);
break;
case x_unsigned_long:
resizevector_<unsigned long>(data_, sz);
break;
case x_long_long:
resizevector_<long long>(data_, sz);
break;
case x_unsigned_long_long:
resizevector_<unsigned long long>(data_, sz);
break;
case x_double:
resizevector_<double>(data_, sz);
break;
case x_stdstring:
resizevector_<std::string>(data_, sz);
break;
case x_stdtm:
resizevector_<std::tm>(data_, sz);
break;
default:
throw soci_error("Into vector element used with non-supported type.");
}
......@@ -188,16 +216,34 @@ std::size_t postgresql_vector_into_type_backend::size()
std::size_t sz = 0; // dummy initialization to please the compiler
switch (type_)
{
// simple cases
case x_char: sz = get_vector_size<char> (data_); break;
case x_short: sz = get_vector_size<short> (data_); break;
case x_integer: sz = get_vector_size<int> (data_); break;
case x_unsigned_long: sz = get_vector_size<unsigned long>(data_); break;
case x_long_long: sz = get_vector_size<long long> (data_); break;
case x_double: sz = get_vector_size<double> (data_); break;
case x_stdstring: sz = get_vector_size<std::string> (data_); break;
case x_stdtm: sz = get_vector_size<std::tm> (data_); break;
// simple cases
case x_char:
sz = get_vector_size<char>(data_);
break;
case x_short:
sz = get_vector_size<short>(data_);
break;
case x_integer:
sz = get_vector_size<int>(data_);
break;
case x_unsigned_long:
sz = get_vector_size<unsigned long>(data_);
break;
case x_long_long:
sz = get_vector_size<long long>(data_);
break;
case x_unsigned_long_long:
sz = get_vector_size<unsigned long long>(data_);
break;
case x_double:
sz = get_vector_size<double>(data_);
break;
case x_stdstring:
sz = get_vector_size<std::string>(data_);
break;
case x_stdtm:
sz = get_vector_size<std::tm>(data_);
break;
default:
throw soci_error("Into vector element used with non-supported type.");
}
......
......@@ -122,9 +122,9 @@ void postgresql_vector_use_type_backend::pre_use(indicator const * ind)
break;
case x_long_long:
{
std::vector<long long> * pv
= static_cast<std::vector<long long> *>(data_);
std::vector<long long> & v = *pv;
std::vector<long long>* pv
= static_cast<std::vector<long long>*>(data_);
std::vector<long long>& v = *pv;
std::size_t const bufSize
= std::numeric_limits<long long>::digits10 + 3;
......@@ -132,6 +132,18 @@ void postgresql_vector_use_type_backend::pre_use(indicator const * ind)
snprintf(buf, bufSize, "%lld", v[i]);
}
break;
case x_unsigned_long_long:
{
std::vector<unsigned long long>* pv
= static_cast<std::vector<unsigned long long>*>(data_);
std::vector<unsigned long long>& v = *pv;
std::size_t const bufSize
= std::numeric_limits<unsigned long long>::digits10 + 2;
buf = new char[bufSize];
snprintf(buf, bufSize, "%llu", v[i]);
}
break;
case x_double:
{
// no need to overengineer it (KISS)...
......@@ -187,16 +199,34 @@ std::size_t postgresql_vector_use_type_backend::size()
std::size_t sz = 0; // dummy initialization to please the compiler
switch (type_)
{
// simple cases
case x_char: sz = get_vector_size<char> (data_); break;
case x_short: sz = get_vector_size<short> (data_); break;
case x_integer: sz = get_vector_size<int> (data_); break;
case x_unsigned_long: sz = get_vector_size<unsigned long>(data_); break;
case x_long_long: sz = get_vector_size<long long> (data_); break;
case x_double: sz = get_vector_size<double> (data_); break;
case x_stdstring: sz = get_vector_size<std::string> (data_); break;
case x_stdtm: sz = get_vector_size<std::tm> (data_); break;
// simple cases
case x_char:
sz = get_vector_size<char>(data_);
break;
case x_short:
sz = get_vector_size<short>(data_);
break;
case x_integer:
sz = get_vector_size<int>(data_);
break;
case x_unsigned_long:
sz = get_vector_size<unsigned long>(data_);
break;
case x_long_long:
sz = get_vector_size<long long>(data_);
break;
case x_unsigned_long_long:
sz = get_vector_size<unsigned long long>(data_);
break;
case x_double:
sz = get_vector_size<double>(data_);
break;
case x_stdstring:
sz = get_vector_size<std::string>(data_);
break;
case x_stdtm:
sz = get_vector_size<std::tm>(data_);
break;
default:
throw soci_error("Use vector element used with non-supported type.");
}
......
......@@ -34,7 +34,10 @@ struct exchange_traits
enum // anonymous
{
x_type =
exchange_traits<typename type_conversion<T>::base_type>::x_type
exchange_traits
<
typename type_conversion<T>::base_type
>::x_type
};
};
......@@ -73,6 +76,13 @@ struct exchange_traits<long long>
enum { x_type = x_long_long };
};
template <>
struct exchange_traits<unsigned long long>
{
typedef basic_type_tag type_family;
enum { x_type = x_unsigned_long_long };
};
#if defined (__LP64__) || ( __WORDSIZE == 64 )
template <>
struct exchange_traits<long int>
......@@ -80,6 +90,12 @@ struct exchange_traits<long int>
typedef basic_type_tag type_family;
enum { x_type = x_long_long };
};
template <>
struct exchange_traits<unsigned long int>
{
typedef basic_type_tag type_family;
enum { x_type = x_unsigned_long_long };
};
#endif // #if defined (__LP64__) || ( __WORDSIZE == 64 )
template <>
......
......@@ -33,13 +33,19 @@ namespace details
// data types, as used to describe exchange format
enum exchange_type
{
x_char, x_stdstring, x_short, x_integer,
x_unsigned_long, x_long_long, x_double, x_stdtm, x_statement,
x_char, x_stdstring,
x_short, x_integer,
x_unsigned_long, x_long_long, x_unsigned_long_long,
x_double, x_stdtm, x_statement,
x_rowid, x_blob
};
// type of statement (used for optimizing statement preparation)
enum statement_type { st_one_time_query, st_repeatable_query };
enum statement_type
{
st_one_time_query,
st_repeatable_query
};
// polymorphic into type backend
......
......@@ -168,7 +168,15 @@ public:
private:
void drop()
{
try { msession << "drop table soci_test"; } catch (soci_error&) {}
try
{
msession << "drop table soci_test";
}
catch (soci_error const& e)
{
//std::cerr << e.what() << std::endl;
e.what();
}
}
session& msession;
};
......
......@@ -40,26 +40,38 @@ typedef type_ptr<use_type_base> use_type_ptr;
class SOCI_DECL standard_use_type : public use_type_base
{
public:
standard_use_type(void * data, exchange_type type, bool readOnly,
std::string const & name = std::string())
: data_(data), type_(type), ind_(NULL)
, readOnly_(readOnly), name_(name), backEnd_(NULL)
standard_use_type(void* data, exchange_type type,
bool readOnly, std::string const& name = std::string())
: data_(data)
, type_(type)
, ind_(NULL)
, readOnly_(readOnly)
, name_(name)
, backEnd_(NULL)
{
convert_to_base();
// FIXME: This was added with Ilia's patch
// http://soci.git.sourceforge.net/git/gitweb.cgi?p=soci/soci;a=blobdiff;f=src/core/use-type.h;h=3510ac95fe7530f977bf9e78d74fd502164a4071;hp=b6d9ba9c27aef3640b8edac4b8e44a620b1b5294;hb=c166625a28f7c907318134f625ff5acea7d9a1f8;hpb=ec19564b2f0994b3960acf891643d92fc224b453
// but it seems to be a troublemaker, causing duplicated conversions
//convert_to_base();
}
standard_use_type(void * data, exchange_type type, indicator & ind,
bool readOnly, std::string const & name = std::string())
: data_(data), type_(type), ind_(&ind)
, readOnly_(readOnly), name_(name), backEnd_(NULL)
standard_use_type(void* data, exchange_type type, indicator& ind,
bool readOnly, std::string const& name = std::string())
: data_(data)
, type_(type)
, ind_(&ind)
, readOnly_(readOnly)
, name_(name)
, backEnd_(NULL)
{
convert_to_base();
// FIXME
//convert_to_base();
}
virtual ~standard_use_type();
virtual void bind(statement_impl & st, int & position);
std::string get_name() const {return name_;}
virtual void * get_data() {return data_;}
std::string get_name() const { return name_; }
virtual void * get_data() { return data_; }
// conversion hook (from arbitrary user type to base type)
virtual void convert_to_base() {}
......@@ -73,41 +85,49 @@ private:
virtual void clean_up();
virtual std::size_t size() const { return 1; }
void * data_;
void* data_;
exchange_type type_;
indicator * ind_;
indicator* ind_;
bool readOnly_;
std::string name_;
standard_use_type_backend * backEnd_;
standard_use_type_backend* backEnd_;
};
class SOCI_DECL vector_use_type : public use_type_base
{
public:
vector_use_type(void * data, exchange_type type,
std::string const & name = std::string())
: data_(data), type_(type), ind_(NULL),
name_(name), backEnd_(NULL) {}
vector_use_type(void * data, exchange_type type,
std::vector<indicator> const & ind,
std::string const & name = std::string())
: data_(data), type_(type), ind_(&ind),
name_(name), backEnd_(NULL) {}
vector_use_type(void* data, exchange_type type,
std::string const& name = std::string())
: data_(data)
, type_(type)
, ind_(NULL)
, name_(name)
, backEnd_(NULL)
{}
vector_use_type(void* data, exchange_type type,
std::vector<indicator> const& ind,
std::string const& name = std::string())
: data_(data)
, type_(type)
, ind_(&ind)
, name_(name)
, backEnd_(NULL)
{}
~vector_use_type();
private:
virtual void bind(statement_impl & st, int & position);
virtual void bind(statement_impl& st, int & position);
virtual void pre_use();
virtual void post_use(bool) { /* nothing to do */ }
virtual void clean_up();
virtual std::size_t size() const;
void * data_;
void* data_;
exchange_type type_;
std::vector<indicator> const * ind_;
std::vector<indicator> const* ind_;
std::string name_;
vector_use_type_backend * backEnd_;
......@@ -122,46 +142,52 @@ template <typename T>
class use_type : public standard_use_type
{
public:
use_type(T & t, std::string const & name = std::string())
use_type(T& t, std::string const& name = std::string())
: standard_use_type(&t,
static_cast<exchange_type>(exchange_traits<T>::x_type),
false, name) {}
use_type(T const & t, std::string const & name = std::string())
: standard_use_type(const_cast<T *>(&t),
static_cast<exchange_type>(exchange_traits<T>::x_type),
true, name) {}
use_type(T & t, indicator & ind,
std::string const & name = std::string())
static_cast<exchange_type>(exchange_traits<T>::x_type), false, name)
{}
use_type(T const& t, std::string const& name = std::string())
: standard_use_type(const_cast<T*>(&t),
static_cast<exchange_type>(exchange_traits<T>::x_type), true, name)
{}
use_type(T& t, indicator& ind, std::string const& name = std::string())
: standard_use_type(&t,
static_cast<exchange_type>(exchange_traits<T>::x_type),
ind, false, name) {}
use_type(T const & t, indicator & ind,
std::string const & name = std::string())
: standard_use_type(const_cast<T *>(&t),
static_cast<exchange_type>(exchange_traits<T>::x_type),
ind, false, name) {}
static_cast<exchange_type>(exchange_traits<T>::x_type), ind, false, name)
{}
use_type(T const& t, indicator& ind, std::string const& name = std::string())
: standard_use_type(const_cast<T*>(&t),
static_cast<exchange_type>(exchange_traits<T>::x_type), ind, false, name)
{}
};
template <typename T>
class use_type<std::vector<T> > : public vector_use_type
{
public:
use_type(std::vector<T> & v, std::string const & name = std::string())
use_type(std::vector<T>& v, std::string const& name = std::string())
: vector_use_type(&v,
static_cast<exchange_type>(exchange_traits<T>::x_type), name) {}
use_type(std::vector<T> const & v, std::string const & name = std::string())
: vector_use_type(const_cast<std::vector<T> *>(&v),
static_cast<exchange_type>(exchange_traits<T>::x_type), name) {}
use_type(std::vector<T> & v, std::vector<indicator> const & ind,
std::string const & name = std::string())
static_cast<exchange_type>(exchange_traits<T>::x_type), name)
{}
use_type(std::vector<T> const& v, std::string const& name = std::string())
: vector_use_type(const_cast<std::vector<T>*>(&v),
static_cast<exchange_type>(exchange_traits<T>::x_type), name)
{}
use_type(std::vector<T>& v, std::vector<indicator> const& ind,
std::string const& name = std::string())
: vector_use_type(&v,
static_cast<exchange_type>(exchange_traits<T>::x_type),
ind, name) {}
use_type(std::vector<T> const & v, std::vector<indicator> const & ind,
std::string const & name = std::string())
static_cast<exchange_type>(exchange_traits<T>::x_type), ind, name)
{}
use_type(std::vector<T> const& v, std::vector<indicator> const& ind,
std::string const& name = std::string())
: vector_use_type(const_cast<std::vector<T> *>(&v),
static_cast<exchange_type>(exchange_traits<T>::x_type),
ind, name) {}
static_cast<exchange_type>(exchange_traits<T>::x_type), ind, name)
{}
};
// helper dispatchers for basic types
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment