Commit 059faf5d authored by Vadim Zeitlin's avatar Vadim Zeitlin

Add CLOB support to Firebird backend

Reuse the existing BLOB support, however we now need to allocate a BLOB
inside firebird_standard_use_type_backend objects as, unlike when using
soci::blob objects, we don't have any way to associate backend-specific
data with the parameter otherwise.

This difference between CLOB and BLOB support is not ideal, but there
doesn't seem to be any way to avoid it.
parent 85159db6
......@@ -59,6 +59,7 @@ enum BuffersType
eStandard, eVector
};
struct firebird_blob_backend;
struct firebird_statement_backend;
struct firebird_standard_into_type_backend : details::standard_into_type_backend
{
......@@ -117,7 +118,8 @@ struct firebird_vector_into_type_backend : details::vector_into_type_backend
struct firebird_standard_use_type_backend : details::standard_use_type_backend
{
firebird_standard_use_type_backend(firebird_statement_backend &st)
: statement_(st), data_(NULL), type_(), position_(0), buf_(NULL), indISCHolder_(0)
: statement_(st), data_(NULL), type_(), position_(0), buf_(NULL), indISCHolder_(0),
blob_(NULL)
{}
virtual void bind_by_pos(int &position,
......@@ -139,6 +141,9 @@ struct firebird_standard_use_type_backend : details::standard_use_type_backend
char *buf_;
short indISCHolder_;
// This is used for types mapping to CLOB.
firebird_blob_backend* blob_;
};
struct firebird_vector_use_type_backend : details::vector_use_type_backend
......
......@@ -11,6 +11,8 @@
#include "firebird/common.h"
#include "soci/soci.h"
#include <sstream>
using namespace soci;
using namespace soci::details;
using namespace soci::details::firebird;
......@@ -119,6 +121,28 @@ void firebird_standard_into_type_backend::exchangeData()
blob->assign(*reinterpret_cast<ISC_QUAD*>(buf_));
}
break;
case x_longstring:
{
long_string* const dst = static_cast<long_string*>(data_);
firebird_blob_backend blob(statement_.session_);
blob.assign(*reinterpret_cast<ISC_QUAD*>(buf_));
std::size_t const len_total = blob.get_len();
dst->value.resize(len_total);
std::size_t len_read = blob.read(0, &dst->value[0], len_total);
if (len_read != len_total)
{
std::ostringstream os;
os << "Read " << len_read << " bytes instead of expected "
<< len_total << " from Firebird text blob object";
throw soci_error(os.str());
}
}
break;
default:
throw soci_error("Into element used with non-supported type.");
} // switch
......
......@@ -147,6 +147,18 @@ void firebird_standard_use_type_backend::exchangeData()
memcpy(buf_, &blob->bid_, var->sqllen);
}
break;
case x_longstring:
{
long_string const* const src = static_cast<long_string*>(data_);
blob_ = new firebird_blob_backend(statement_.session_);
blob_->append(src->value.c_str(), src->value.length());
blob_->save();
memcpy(buf_, &blob_->bid_, var->sqllen);
}
break;
default:
throw soci_error("Use element used with non-supported type.");
} // switch
......@@ -175,6 +187,13 @@ void firebird_standard_use_type_backend::clean_up()
delete [] buf_;
buf_ = NULL;
}
if (blob_)
{
delete blob_;
blob_ = NULL;
}
std::vector<void*>::iterator it =
std::find(statement_.uses_.begin(), statement_.uses_.end(), this);
if (it != statement_.uses_.end())
......
......@@ -1274,6 +1274,17 @@ struct TableCreator4 : public tests::table_creator_base
}
};
struct TableCreatorCLOB : public tests::table_creator_base
{
TableCreatorCLOB(soci::session & sql)
: tests::table_creator_base(sql)
{
sql << "create table soci_test(id integer, s blob sub_type text)";
sql.commit();
sql.begin();
}
};
class test_context : public tests::test_context_base
{
public:
......@@ -1302,6 +1313,11 @@ class test_context : public tests::test_context_base
return new TableCreator4(s);
}
tests::table_creator_base* table_creator_clob(soci::session& s) const
{
return new TableCreatorCLOB(s);
}
std::string to_date_time(std::string const &datdt_string) const
{
return "'" + datdt_string + "'";
......
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