Commit 5d1ab2c7 authored by Mateusz Łoskot's avatar Mateusz Łoskot

DB2: Switch session from SQLConnect ot SQLDriverConnect

SQLConnect is very basic, relies on DSN and is not convenient
if user wants to provide all connection parameters as command line
argument, without editing db2cli.ini, configuring DSN.

SQLDriverConnect alternative enables remote database connection
in quick and easy fashion, via complete connection string.
parent ba8b1aa2
......@@ -72,6 +72,12 @@ public:
SQLRETURN errorCode;
};
// Option allowing to specify the "driver completion" parameter of
// SQLDriverConnect(). Its possible values are the same as the allowed values
// for this parameter in the official DB2 CLI, i.e. one of SQL_DRIVER_XXX
// (in string form as all options are strings currently).
extern SOCI_DB2_DECL char const * db2_option_driver_complete;
struct db2_statement_backend;
struct SOCI_DB2_DECL db2_standard_into_type_backend : details::standard_into_type_backend
......@@ -261,9 +267,7 @@ struct db2_session_backend : details::session_backend
void parseConnectString(std::string const &);
void parseKeyVal(std::string const &);
std::string dsn;
std::string username;
std::string password;
std::string connection_string_;
bool autocommit;
bool in_transaction;
......
......@@ -10,6 +10,8 @@
#include "soci/db2/soci-db2.h"
#include "soci/connection-parameters.h"
#include <cstdio>
#ifdef _MSC_VER
#pragma warning(disable:4355)
#endif
......@@ -17,6 +19,8 @@
using namespace soci;
using namespace soci::details;
const char* soci::db2_option_driver_complete = "db2.driver_complete";
const std::string db2_soci_error::sqlState(std::string const & msg,const SQLSMALLINT htype,const SQLHANDLE hndl) {
std::ostringstream ss(msg, std::ostringstream::app);
......@@ -45,15 +49,6 @@ void db2_session_backend::parseKeyVal(std::string const & keyVal) {
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;
}
this->autocommit=true; //Default value
if (!key.compare("autocommit")) {
if (!value.compare("off")) {
......@@ -81,8 +76,10 @@ db2_session_backend::db2_session_backend(
connection_parameters const & parameters) :
in_transaction(false)
{
parseConnectString(parameters.get_connect_string());
SQLRETURN cliRC = SQL_SUCCESS;
std::string const& connectString = parameters.get_connect_string();
parseConnectString(connectString);
SQLRETURN cliRC = SQL_ERROR;
/* Prepare handles */
cliRC = SQLAllocHandle(SQL_HANDLE_ENV,SQL_NULL_HANDLE,&hEnv);
......@@ -111,15 +108,48 @@ db2_session_backend::db2_session_backend(
}
/* Connect to database */
cliRC = SQLConnect(hDbc, const_cast<SQLCHAR *>((const SQLCHAR *) dsn.c_str()), SQL_NTS,
const_cast<SQLCHAR *>((const SQLCHAR *) username.c_str()), SQL_NTS,
const_cast<SQLCHAR *>((const SQLCHAR *) password.c_str()), SQL_NTS);
// NOTE: SQLDriverConnect preparation steps below copied from ODBC backend.
SQLCHAR outConnString[1024];
SQLSMALLINT strLength;
// Prompt the user for any missing information (typically UID/PWD) in the
// connection string by default but allow overriding this using "prompt"
// option.
SQLHWND hwnd_for_prompt = NULL;
unsigned completion = SQL_DRIVER_COMPLETE;
std::string completionString;
if (parameters.get_option(db2_option_driver_complete, completionString))
{
// The value of the option is supposed to be just the integer value of
// one of SQL_DRIVER_XXX constants but don't check for the exact value in
// case more of them are added in the future, the ODBC driver will return
// an error if we pass it an invalid value anyhow.
if (std::sscanf(completionString.c_str(), "%u", &completion) != 1)
{
throw soci_error("Invalid non-numeric driver completion option value \"" +
completionString + "\".");
}
}
#ifdef _WIN32
if (completion != SQL_DRIVER_NOPROMPT)
hwnd_for_prompt = ::GetDesktopWindow();
#endif // _WIN32
cliRC = SQLDriverConnect(hDbc, hwnd_for_prompt,
reinterpret_cast<SQLCHAR*>(const_cast<char*>(connectString.c_str())),
(SQLSMALLINT)connectString.size(),
outConnString, 1024, &strLength,
static_cast<SQLUSMALLINT>(completion));
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(msg,cliRC);
}
connection_string_.assign((const char*)outConnString, strLength);
}
db2_session_backend::~db2_session_backend()
......
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