Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Added DB2 backend
  • Loading branch information
Denis Chapligin committed Feb 20, 2013
1 parent c5135ee commit 48650b3
Show file tree
Hide file tree
Showing 13 changed files with 1,836 additions and 61 deletions.
2 changes: 1 addition & 1 deletion src/backends/db2/CMakeLists.txt
@@ -1,7 +1,7 @@
soci_backend(DB2
DEPENDS DB2
HEADERS soci-db2.h
DESCRIPTION "SOCI backend for DB2 Ubiversal Database"
DESCRIPTION "SOCI backend for DB2 Universal Database"
AUTHORS "Denis Chapligin"
MAINTAINERS "Denis Chapligin")

Expand Down
62 changes: 62 additions & 0 deletions src/backends/db2/blob.cpp
@@ -0,0 +1,62 @@
//
// Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton
// Copyright (C) 2011 Denis Chapligin
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//

#define SOCI_DB2_SOURCE
#include "soci-db2.h"

#ifdef _MSC_VER
#pragma warning(disable:4355)
#endif

using namespace soci;
using namespace soci::details;


db2_blob_backend::db2_blob_backend(db2_session_backend &session)
: session_(session)
{
// ...
}

db2_blob_backend::~db2_blob_backend()
{
// ...
}

std::size_t db2_blob_backend::get_len()
{
// ...
return 0;
}

std::size_t db2_blob_backend::read(
std::size_t /* offset */, char * /* buf */, std::size_t /* toRead */)
{
// ...
return 0;
}

std::size_t db2_blob_backend::write(
std::size_t /* offset */, char const * /* buf */,
std::size_t /* toWrite */)
{
// ...
return 0;
}

std::size_t db2_blob_backend::append(
char const * /* buf */, std::size_t /* toWrite */)
{
// ...
return 0;
}

void db2_blob_backend::trim(std::size_t /* newLen */)
{
// ...
}
40 changes: 40 additions & 0 deletions src/backends/db2/factory.cpp
@@ -0,0 +1,40 @@
//
// Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton, David Courtney
// Copyright (C) 2011 Denis Chapligin
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//

#define SOCI_DB2_SOURCE
#include "soci-db2.h"
#include <backend-loader.h>

using namespace soci;
using namespace soci::details;


// concrete factory for ODBC concrete strategies
db2_session_backend * db2_backend_factory::make_session(
std::string const &connectString) const
{
return new db2_session_backend(connectString);
}

db2_backend_factory const soci::db2;

extern "C"
{

// for dynamic backend loading
SOCI_DB2_DECL backend_factory const * factory_db2()
{
return &soci::db2;
}

SOCI_DB2_DECL void register_factory_db2()
{
soci::dynamic_backends::register_backend("db2", soci::db2);
}

} // extern "C"
28 changes: 28 additions & 0 deletions src/backends/db2/row-id.cpp
@@ -0,0 +1,28 @@
//
// Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton
// Copyright (C) 2011 Denis Chapligin
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//

#define SOCI_DB2_SOURCE
#include "soci-db2.h"

#ifdef _MSC_VER
#pragma warning(disable:4355)
#endif

using namespace soci;
using namespace soci::details;


db2_rowid_backend::db2_rowid_backend(db2_session_backend & /* session */)
{
// ...
}

db2_rowid_backend::~db2_rowid_backend()
{
// ...
}
71 changes: 67 additions & 4 deletions src/backends/db2/session.cpp
Expand Up @@ -16,10 +16,70 @@
using namespace soci;
using namespace soci::details;

const std::string db2_soci_error::sqlState(std::string const & msg,const SQLSMALLINT htype,const SQLHANDLE hndl) {
std::stringstream ss(msg);


SQLCHAR message[SQL_MAX_MESSAGE_LENGTH + 1];
SQLCHAR sqlstate[SQL_SQLSTATE_SIZE + 1];
SQLINTEGER sqlcode;
SQLSMALLINT length;

if ( SQLGetDiagRec(htype,
hndl,
1,
sqlstate,
&sqlcode,
message,
SQL_MAX_MESSAGE_LENGTH + 1,
&length) == SQL_SUCCESS ) {
ss<<" SQLMESSAGE: ";
ss<<message;
}
return ss.str();
}

void db2_session_backend::parseKeyVal(std::string const & keyVal) {
size_t delimiter=keyVal.find_first_of("=");
std::string key=keyVal.substr(0,delimiter);
std::string value=keyVal.substr(delimiter+1,keyVal.length());

if (!key.compare("Dsn")) {
this->dsn=value;
}
if (!key.compare("Uid")) {
this->username=value;
}
if (!key.compare("Pwd")) {
this->password=value;
}
if (!key.compare("autocommit")) {
if (!value.compare("off")) {
this->autocommit=false;
} else {
this->autocommit=true;
}
}
}

void db2_session_backend::parseConnectString(std::string const & connectString) {
std::string processingString(connectString);
size_t delimiter=processingString.find_first_of(";");
while(delimiter!=std::string::npos) {
std::string keyVal=processingString.substr(0,delimiter);
parseKeyVal(keyVal);
processingString=processingString.erase(0,delimiter+1);
delimiter=processingString.find_first_of(";");
}
if (!processingString.empty()) {
parseKeyVal(processingString);
}
}

db2_session_backend::db2_session_backend(
std::string const & connectString /* DSN=SAMPLE;Uid=db2inst1;Pwd=db2inst1;AutoCommit=off */)
{
parseConnectString(connectString);
SQLRETURN cliRC = SQL_SUCCESS;

/* Prepare handles */
Expand All @@ -30,24 +90,27 @@ db2_session_backend::db2_session_backend(

cliRC = SQLAllocHandle(SQL_HANDLE_DBC, hEnv, &hDbc);
if (cliRC != SQL_SUCCESS) {
std::string msg=db2_soci_error::sqlState("Error while allocating the connection handle",SQL_HANDLE_ENV,hEnv);
SQLFreeHandle(SQL_HANDLE_ENV,hEnv);
throw db2_soci_error("Error while allocating the connection handle",cliRC);
throw db2_soci_error(msg,cliRC);
}

/* Set autocommit */
cliRC = SQLSetConnectAttr(hDbc,SQL_ATTR_AUTOCOMMIT, this->autocommit ? (SQLPOINTER)SQL_AUTOCOMMIT_ON : (SQLPOINTER)SQL_AUTOCOMMIT_OFF, SQL_NTS);
if (cliRC != SQL_SUCCESS) {
std::string msg=db2_soci_error::sqlState("Error while setting autocommit attribute",SQL_HANDLE_DBC,hDbc);
SQLFreeHandle(SQL_HANDLE_DBC,hDbc);
SQLFreeHandle(SQL_HANDLE_ENV,hEnv);
throw db2_soci_error("Error while setting autocommit attribute",cliRC);
throw db2_soci_error(msg,cliRC);
}

/* Connect to database */
cliRC = SQLConnect(hDbc,(SQLCHAR*)connectString.c_str(),SQL_NTS,(SQLCHAR*)username.c_str(),SQL_NTS,(SQLCHAR*)password.c_str(),SQL_NTS);
cliRC = SQLConnect(hDbc,(SQLCHAR*)dsn.c_str(),SQL_NTS,(SQLCHAR*)username.c_str(),SQL_NTS,(SQLCHAR*)password.c_str(),SQL_NTS);
if (cliRC != SQL_SUCCESS) {
std::string msg=db2_soci_error::sqlState("Error connecting to database",SQL_HANDLE_DBC,hDbc);
SQLFreeHandle(SQL_HANDLE_DBC,hDbc);
SQLFreeHandle(SQL_HANDLE_ENV,hEnv);
throw db2_soci_error("Error connecting to database",cliRC);
throw db2_soci_error(msg,cliRC);
}
}

Expand Down
67 changes: 62 additions & 5 deletions src/backends/db2/soci-db2.h
Expand Up @@ -28,16 +28,25 @@

#include <cstddef>
#include <string>
#include <vector>
#include <iostream>
#include <sstream>
#include <cstring>

#include <sqlcli1.h>

namespace soci
{

static const std::size_t maxBuffer = 1024 * 1024 * 1024; //CLI limit is about 3 GB, but 1GB should be enough
class db2_soci_error : public soci_error {
public:
db2_soci_error(std::string const & msg, SQLRETURN rc) : soci_error(msg),errorCode(rc) {};

~db2_soci_error() throw() { };

//We have to extract error information before exception throwing, cause CLI handles could be broken at the construction time
static const std::string sqlState(std::string const & msg,const SQLSMALLINT htype,const SQLHANDLE hndl);

SQLRETURN errorCode;
};

Expand All @@ -46,7 +55,7 @@ struct db2_statement_backend;
struct SOCI_DB2_DECL db2_standard_into_type_backend : details::standard_into_type_backend
{
db2_standard_into_type_backend(db2_statement_backend &st)
: statement_(st)
: statement_(st),buf(NULL)
{}

void define_by_pos(int& position, void* data, details::exchange_type type);
Expand All @@ -57,12 +66,19 @@ struct SOCI_DB2_DECL db2_standard_into_type_backend : details::standard_into_typ
void clean_up();

db2_statement_backend& statement_;

char* buf;
void *data;
details::exchange_type type;
int position;
SQLSMALLINT cType;
SQLLEN valueLen;
};

struct SOCI_DB2_DECL db2_vector_into_type_backend : details::vector_into_type_backend
{
db2_vector_into_type_backend(db2_statement_backend &st)
: statement_(st)
: statement_(st),buf(NULL)
{}

void define_by_pos(int& position, void* data, details::exchange_type type);
Expand All @@ -76,12 +92,22 @@ struct SOCI_DB2_DECL db2_vector_into_type_backend : details::vector_into_type_ba
void clean_up();

db2_statement_backend& statement_;

void prepare_indicators(std::size_t size);

SQLLEN *indptr;
std::vector<SQLLEN> indVec;
void *data;
char *buf;
details::exchange_type type;
SQLSMALLINT cType;
std::size_t colSize;
};

struct SOCI_DB2_DECL db2_standard_use_type_backend : details::standard_use_type_backend
{
db2_standard_use_type_backend(db2_statement_backend &st)
: statement_(st)
: statement_(st),buf(NULL)
{}

void bind_by_pos(int& position, void* data, details::exchange_type type, bool readOnly);
Expand All @@ -93,12 +119,22 @@ struct SOCI_DB2_DECL db2_standard_use_type_backend : details::standard_use_type_
void clean_up();

db2_statement_backend& statement_;

void prepare_for_bind(void *&data, SQLLEN &size, SQLSMALLINT &sqlType, SQLSMALLINT &cType);
void bind_helper(int &position, void *data, details::exchange_type type);

void *data;
details::exchange_type type;
int position;
std::string name;
char* buf;
SQLLEN indptr;
};

struct SOCI_DB2_DECL db2_vector_use_type_backend : details::vector_use_type_backend
{
db2_vector_use_type_backend(db2_statement_backend &st)
: statement_(st) {}
: statement_(st),buf(NULL) {}

void bind_by_pos(int& position, void* data, details::exchange_type type);
void bind_by_name(std::string const& name, void* data, details::exchange_type type);
Expand All @@ -110,6 +146,17 @@ struct SOCI_DB2_DECL db2_vector_use_type_backend : details::vector_use_type_back
void clean_up();

db2_statement_backend& statement_;

void prepare_indicators(std::size_t size);
void prepare_for_bind(void *&data, SQLUINTEGER &size,SQLSMALLINT &sqlType, SQLSMALLINT &cType);
void bind_helper(int &position, void *data, details::exchange_type type);

SQLLEN *indptr;
std::vector<SQLLEN> indVec;
void *data;
char *buf;
details::exchange_type type;
std::size_t colSize;
};

struct db2_session_backend;
Expand All @@ -131,13 +178,20 @@ struct SOCI_DB2_DECL db2_statement_backend : details::statement_backend

int prepare_for_describe();
void describe_column(int colNum, data_type& dtype, std::string& columnName);
std::size_t column_size(int col);

db2_standard_into_type_backend* make_into_type_backend();
db2_standard_use_type_backend* make_use_type_backend();
db2_vector_into_type_backend* make_vector_into_type_backend();
db2_vector_use_type_backend* make_vector_use_type_backend();

db2_session_backend& session_;

SQLHANDLE hStmt;
std::string query_;
std::vector<std::string> names;
bool hasVectorUseElements;
SQLUINTEGER numRowsFetched;
};

struct db2_rowid_backend : details::rowid_backend
Expand Down Expand Up @@ -180,6 +234,9 @@ struct db2_session_backend : details::session_backend
db2_rowid_backend* make_rowid_backend();
db2_blob_backend* make_blob_backend();

void parseConnectString(std::string const &);
void parseKeyVal(std::string const &);

std::string dsn;
std::string username;
std::string password;
Expand Down

0 comments on commit 48650b3

Please sign in to comment.