Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
mloskot committed Feb 13, 2013
2 parents 662deec + 1be2d96 commit 610de78
Show file tree
Hide file tree
Showing 19 changed files with 271 additions and 76 deletions.
15 changes: 10 additions & 5 deletions src/CMakeLists.txt
Expand Up @@ -69,13 +69,18 @@ include(SociDependencies)

if(EXISTS /etc/os-release)
file(READ /etc/os-release OS_RELEASE)
string(REGEX MATCH "ID(_LIKE?)=debian" DEBIAN ${OS_RELEASE})
string(REGEX MATCH "ID(_LIKE?)=fedora" FEDORA ${OS_RELEASE})
string(REGEX MATCH "ID(_LIKE?)=ubuntu" UBUNTU ${OS_RELEASE})
string(REGEX MATCH "ID(_LIKE)?=debian" DEBIAN ${OS_RELEASE})
string(REGEX MATCH "ID(_LIKE)?=fedora" FEDORA ${OS_RELEASE})
string(REGEX MATCH "ID(_LIKE)?=ubuntu" UBUNTU ${OS_RELEASE})
elseif(EXISTS /etc/lsb-release)
file(READ /etc/lsb-release OS_RELEASE)
string(REGEX MATCH "DISTRIB_ID=[Uu]buntu" UBUNTU ${OS_RELEASE})
string(REGEX MATCH "DISTRIB_ID=[Db]ebian" DEBIAN ${OS_RELEASE})
endif()


if(DEBIAN)
if(UBUNTU)
set(SOCI_LIBDIR "lib")
elseif(DEBIAN)
execute_process(COMMAND uname -m
OUTPUT_VARIABLE SOCI_ARCH
OUTPUT_STRIP_TRAILING_WHITESPACE)
Expand Down
9 changes: 9 additions & 0 deletions src/backends/firebird/CMakeLists.txt
@@ -0,0 +1,9 @@
soci_backend(Firebird
DEPENDS Firebird
HEADERS soci-firebird.h common.h
DESCRIPTION "SOCI backend for Firebird database engine"
AUTHORS "TBD"
MAINTAINERS "TBD")

add_subdirectory(test)

91 changes: 87 additions & 4 deletions src/backends/firebird/common.cpp
Expand Up @@ -10,7 +10,9 @@
#include <ibase.h> // FireBird
#include <cstddef>
#include <cstring>
#include <cstdio>
#include <sstream>
#include <iostream>
#include <string>

namespace soci
Expand Down Expand Up @@ -82,6 +84,7 @@ void tmDecode(short type, void * src, std::tm * dst)
void setTextParam(char const * s, std::size_t size, char * buf_,
XSQLVAR * var)
{
std::cerr << "setTextParam: var->sqltype=" << var->sqltype << std::endl;
short sz = 0;
if (size < static_cast<std::size_t>(var->sqllen))
{
Expand All @@ -94,17 +97,96 @@ void setTextParam(char const * s, std::size_t size, char * buf_,

if ((var->sqltype & ~1) == SQL_VARYING)
{
memcpy(buf_, &sz, sizeof(short));
memcpy(buf_ + sizeof(short), s, sz);
std::memcpy(buf_, &sz, sizeof(short));
std::memcpy(buf_ + sizeof(short), s, sz);
}
else if ((var->sqltype & ~1) == SQL_TEXT)
{
memcpy(buf_, s, sz);
std::memcpy(buf_, s, sz);
if (sz < var->sqllen)
{
memset(buf_+sz, ' ', var->sqllen - sz);
std::memset(buf_+sz, ' ', var->sqllen - sz);
}
}
else if ((var->sqltype & ~1) == SQL_SHORT)
{
unsigned short t1;
short t2;
if (!*str2int(s, t1))
std::memcpy(buf_, &t1, sizeof(t1));
else if (!*str2int(s, t2))
std::memcpy(buf_, &t2, sizeof(t2));
else
throw soci_error("Could not parse int16 value.");
to_isc<short>(buf_, var);
}
else if ((var->sqltype & ~1) == SQL_LONG)
{
unsigned t1;
int t2;
if (!*str2int(s, t1))
std::memcpy(buf_, &t1, sizeof(t1));
else if (!*str2int(s, t2))
std::memcpy(buf_, &t2, sizeof(t2));
else
throw soci_error("Could not parse int32 value.");
to_isc<int>(buf_, var);
}
else if ((var->sqltype & ~1) == SQL_INT64)
{
unsigned long long t1;
long long t2;
if (!*str2int(s, t1))
std::memcpy(buf_, &t1, sizeof(t1));
else if (!*str2int(s, t2))
std::memcpy(buf_, &t2, sizeof(t2));
else
throw soci_error("Could not parse int64 value.");
to_isc<long long>(buf_, var);
}
else if ((var->sqltype & ~1) == SQL_TIMESTAMP
or (var->sqltype & ~1) == SQL_TYPE_DATE)
{
unsigned short year, month, day, hour, min, sec;
if (std::sscanf(s, "%hu-%hu-%hu %hu:%hu:%hu",
&year, &month, &day, &hour, &min, &sec) != 6)
{
if (std::sscanf(s, "%hu-%hu-%huT%hu:%hu:%hu",
&year, &month, &day, &hour, &min, &sec) != 6)
{
hour = min = sec = 0;
if (std::sscanf(s, "%hu-%hu-%hu", &year, &month, &day) != 3)
{
throw soci_error("Could not parse timestamp value.");
}
}
}
std::tm t;
std::memset(&t, 0, sizeof(t));
t.tm_year = year - 1900;
t.tm_mon = month - 1;
t.tm_mday = day;
t.tm_hour = hour;
t.tm_min = min;
t.tm_sec = sec;
std::memcpy(buf_, &t, sizeof(t));
tmEncode(var->sqltype, &t, buf_);
}
else if ((var->sqltype & ~1) == SQL_TYPE_TIME)
{
unsigned short hour, min, sec;
if (std::sscanf(s, "%hu:%hu:%hu", &hour, &min, &sec) != 3)
{
throw soci_error("Could not parse timestamp value.");
}
std::tm t;
std::memset(&t, 0, sizeof(t));
t.tm_hour = hour;
t.tm_min = min;
t.tm_sec = sec;
std::memcpy(buf_, &t, sizeof(t));
tmEncode(var->sqltype, &t, buf_);
}
else
{
throw soci_error("Unexpected string type.");
Expand All @@ -113,6 +195,7 @@ void setTextParam(char const * s, std::size_t size, char * buf_,

std::string getTextParam(XSQLVAR const *var)
{
std::cerr << "getTextParam: var->sqltype=" << var->sqltype << std::endl;
short size;
std::size_t offset = 0;

Expand Down
54 changes: 46 additions & 8 deletions src/backends/firebird/common.h
Expand Up @@ -37,6 +37,38 @@ void setTextParam(char const * s, std::size_t size, char * buf_,

std::string getTextParam(XSQLVAR const *var);

template <typename IntType>
const char *str2int(const char * s, IntType &out)
{
int sign = 1;
if ('+' == *s)
++s;
else if ('-' == *s)
{
sign = -1;
++s;
}
IntType res = 0;
for (out = 0; *s; ++s, out = res)
{
int d = *s - '0';
if (d < 0 || d > 9)
return s;
res = res * 10 + d * sign;
if (1 == sign)
{
if (res < out)
return s;
}
else
{
if (res > out)
return s;
}
}
return s;
}

template<typename T1>
void to_isc(void * val, XSQLVAR * var)
{
Expand Down Expand Up @@ -66,21 +98,27 @@ void to_isc(void * val, XSQLVAR * var)
break;
case SQL_LONG:
{
long tmp = static_cast<long>(value*tens);
memcpy(var->sqldata, &tmp, sizeof(long));
int tmp = static_cast<int>(value*tens);
std::memcpy(var->sqldata, &tmp, sizeof(int));
}
break;
case SQL_INT64:
{
ISC_INT64 tmp = static_cast<ISC_INT64>(value*tens);
memcpy(var->sqldata, &tmp, sizeof(ISC_INT64));
long long tmp = static_cast<long long>(value*tens);
std::memcpy(var->sqldata, &tmp, sizeof(long long));
}
break;
case SQL_FLOAT:
memcpy(var->sqldata, &value, sizeof(float));
{
float sql_value = static_cast<float>(value);
std::memcpy(var->sqldata, &sql_value, sizeof(float));
}
break;
case SQL_DOUBLE:
memcpy(var->sqldata, &value, sizeof(double));
{
double sql_value = static_cast<double>(value);
std::memcpy(var->sqldata, &sql_value, sizeof(double));
}
break;
default:
throw soci_error("Incorrect data type for numeric conversion");
Expand Down Expand Up @@ -114,9 +152,9 @@ T1 from_isc(XSQLVAR * var)
case SQL_SHORT:
return static_cast<T1>(*reinterpret_cast<short*>(var->sqldata)/tens);
case SQL_LONG:
return static_cast<T1>(*reinterpret_cast<long*>(var->sqldata)/tens);
return static_cast<T1>(*reinterpret_cast<unsigned*>(var->sqldata)/tens);
case SQL_INT64:
return static_cast<T1>(*reinterpret_cast<ISC_INT64*>(var->sqldata)/tens);
return static_cast<T1>(*reinterpret_cast<long long*>(var->sqldata)/tens);
case SQL_FLOAT:
return static_cast<T1>(*reinterpret_cast<float*>(var->sqldata));
case SQL_DOUBLE:
Expand Down
1 change: 1 addition & 0 deletions src/backends/firebird/soci-firebird.h
Expand Up @@ -209,6 +209,7 @@ struct firebird_statement_backend : details::statement_backend

protected:
int rowsFetched_;
bool endOfRowSet_;

virtual void exchangeData(bool gotData, int row);
virtual void prepareSQLDA(XSQLDA ** sqldap, int size = 10);
Expand Down
4 changes: 4 additions & 0 deletions src/backends/firebird/standard-use-type.cpp
Expand Up @@ -77,6 +77,7 @@ void firebird_standard_use_type_backend::bind_by_name(

void firebird_standard_use_type_backend::pre_use(indicator const * ind)
{
indISCHolder_ = 0;
if (ind)
{
switch (*ind)
Expand All @@ -97,6 +98,9 @@ void firebird_standard_use_type_backend::exchangeData()
{
XSQLVAR *var = statement_.sqlda2p_->sqlvar+position_;

if (0 != indISCHolder_)
return;

switch (type_)
{
case x_char:
Expand Down
9 changes: 8 additions & 1 deletion src/backends/firebird/statement.cpp
Expand Up @@ -10,14 +10,15 @@
#include "error-firebird.h"
#include <cctype>
#include <sstream>
#include <iostream>

using namespace soci;
using namespace soci::details;
using namespace soci::details::firebird;

firebird_statement_backend::firebird_statement_backend(firebird_session_backend &session)
: session_(session), stmtp_(0), sqldap_(NULL), sqlda2p_(NULL),
boundByName_(false), boundByPos_(false), rowsFetched_(0),
boundByName_(false), boundByPos_(false), rowsFetched_(0), endOfRowSet_(false),
intoType_(eStandard), useType_(eStandard), procedure_(false)
{}

Expand Down Expand Up @@ -286,6 +287,7 @@ void firebird_statement_backend::rewriteQuery(
void firebird_statement_backend::prepare(std::string const & query,
statement_type /* eType */)
{
std::cerr << "prepare: query=" << query << std::endl;
// clear named parametes
names_.clear();

Expand Down Expand Up @@ -460,6 +462,9 @@ firebird_statement_backend::execute(int number)
statement_backend::exec_fetch_result
firebird_statement_backend::fetch(int number)
{
if (endOfRowSet_)
return ef_no_data;

ISC_STATUS stat[stat_size];

for (size_t i = 0; i<static_cast<unsigned int>(sqldap_->sqld); ++i)
Expand All @@ -483,11 +488,13 @@ firebird_statement_backend::fetch(int number)
}
else if (fetch_stat == 100L)
{
endOfRowSet_ = true;
return ef_no_data;
}
else
{
// error
endOfRowSet_ = true;
throw_iscerror(stat);
return ef_no_data; // unreachable, for compiler only
}
Expand Down
5 changes: 5 additions & 0 deletions src/backends/firebird/test/CMakeLists.txt
@@ -0,0 +1,5 @@
soci_backend_test(
BACKEND Firebird
SOURCE test-firebird.cpp
CONNSTR "dummy")

0 comments on commit 610de78

Please sign in to comment.