Пример #1
0
odbc_session_backend::odbc_session_backend(
    connection_parameters const & parameters)
    : henv_(0), hdbc_(0), product_(prod_uninitialized)
{
    SQLRETURN rc;

    // Allocate environment handle
    rc = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv_);
    if (is_odbc_error(rc))
    {
        throw soci_error("Unable to get environment handle");
    }

    // Set the ODBC version environment attribute
    rc = SQLSetEnvAttr(henv_, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);
    if (is_odbc_error(rc))
    {
        throw odbc_soci_error(SQL_HANDLE_ENV, henv_, "setting ODBC version 3");
    }

    // Allocate connection handle
    rc = SQLAllocHandle(SQL_HANDLE_DBC, henv_, &hdbc_);
    if (is_odbc_error(rc))
    {
        throw odbc_soci_error(SQL_HANDLE_DBC, hdbc_,
                              "allocating connection handle");
    }

    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(odbc_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

    std::string const & connectString = parameters.get_connect_string();
    rc = SQLDriverConnect(hdbc_, hwnd_for_prompt,
                          sqlchar_cast(connectString),
                          (SQLSMALLINT)connectString.size(),
                          outConnString, 1024, &strLength,
                          static_cast<SQLUSMALLINT>(completion));

    if (is_odbc_error(rc))
    {
        throw odbc_soci_error(SQL_HANDLE_DBC, hdbc_, "connecting to database");
    }

    connection_string_.assign((const char*)outConnString, strLength);

    reset_transaction();

    configure_connection();
}
Пример #2
0
db2_session_backend::db2_session_backend(
    connection_parameters const & parameters) :
        in_transaction(false)
{
    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);
    if (cliRC != SQL_SUCCESS) {
        throw db2_soci_error("Error while allocating the enironment handle",cliRC);
    }

    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(msg,cliRC);
    }

    /* Set autocommit */
    if(this->autocommit) {
        cliRC = SQLSetConnectAttr(hDbc,SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_ON, SQL_NTS);
    } else {
        cliRC = SQLSetConnectAttr(hDbc,SQL_ATTR_AUTOCOMMIT, (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(msg,cliRC);
    }

    /* Connect to database */
    // 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);
}