diff --git a/include/soci/firebird/soci-firebird.h b/include/soci/firebird/soci-firebird.h index 89a6c92d7..b1a3e7c6e 100644 --- a/include/soci/firebird/soci-firebird.h +++ b/include/soci/firebird/soci-firebird.h @@ -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 diff --git a/src/backends/firebird/standard-into-type.cpp b/src/backends/firebird/standard-into-type.cpp index 30e754ded..36b0eaac6 100644 --- a/src/backends/firebird/standard-into-type.cpp +++ b/src/backends/firebird/standard-into-type.cpp @@ -11,6 +11,8 @@ #include "firebird/common.h" #include "soci/soci.h" +#include + 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(buf_)); } break; + + case x_longstring: + { + long_string* const dst = static_cast(data_); + + firebird_blob_backend blob(statement_.session_); + blob.assign(*reinterpret_cast(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 diff --git a/src/backends/firebird/standard-use-type.cpp b/src/backends/firebird/standard-use-type.cpp index 5b216fa82..f2bb4acb8 100644 --- a/src/backends/firebird/standard-use-type.cpp +++ b/src/backends/firebird/standard-use-type.cpp @@ -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(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::iterator it = std::find(statement_.uses_.begin(), statement_.uses_.end(), this); if (it != statement_.uses_.end()) diff --git a/tests/firebird/test-firebird.cpp b/tests/firebird/test-firebird.cpp index 0e8804c7c..0daffd5d5 100644 --- a/tests/firebird/test-firebird.cpp +++ b/tests/firebird/test-firebird.cpp @@ -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 + "'";