Index: src/odbcappender.cpp =================================================================== RCS file: /home/cvspublic/logging-log4cxx/src/odbcappender.cpp,v retrieving revision 1.15 diff -u -r1.15 odbcappender.cpp --- src/odbcappender.cpp 4 May 2005 16:13:41 -0000 1.15 +++ src/odbcappender.cpp 8 Sep 2005 18:24:21 -0000 @@ -26,6 +26,7 @@ #include #include #include +#include #include using namespace log4cxx; @@ -35,6 +36,8 @@ IMPLEMENT_LOG4CXX_OBJECT(ODBCAppender) + + ODBCAppender::ODBCAppender() : connection(SQL_NULL_HDBC), env(SQL_NULL_HENV), bufferSize(1) { @@ -45,27 +48,27 @@ finalize(); } -void ODBCAppender::setOption(const String& option, - const String& value) +void ODBCAppender::setOption(const LogString& option, const LogString& value) { - if (StringHelper::equalsIgnoreCase(option, _T("buffersize"))) + if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("BUFFERSIZE"), LOG4CXX_STR("buffersize"))) { setBufferSize((size_t)OptionConverter::toInt(value, 1)); } - else if (StringHelper::equalsIgnoreCase(option, _T("password"))) + else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("PASSWORD"), LOG4CXX_STR("password"))) { setPassword(value); } - else if (StringHelper::equalsIgnoreCase(option, _T("sql"))) + else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("SQL"), LOG4CXX_STR("sql"))) { setSql(value); } - else if (StringHelper::equalsIgnoreCase(option, _T("url")) - || StringHelper::equalsIgnoreCase(option, _T("dns"))) + else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("URL"), LOG4CXX_STR("url")) + || StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("DSN"), LOG4CXX_STR("dsn")) + || StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("CONNECTIONSTRING"), LOG4CXX_STR("connectionstring")) ) { setURL(value); } - else if (StringHelper::equalsIgnoreCase(option, _T("user"))) + else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("USER"), LOG4CXX_STR("user"))) { setUser(value); } @@ -75,7 +78,7 @@ } } -void ODBCAppender::append(const spi::LoggingEventPtr& event) +void ODBCAppender::append(const spi::LoggingEventPtr& event, log4cxx::helpers::Pool& p) { buffer.push_back(event); @@ -83,14 +86,14 @@ flushBuffer(); } -String ODBCAppender::getLogStatement(const spi::LoggingEventPtr& event) const +LogString ODBCAppender::getLogStatement(const spi::LoggingEventPtr& event, log4cxx::helpers::Pool& p) const { - StringBuffer sbuf; - getLayout()->format(sbuf, event); - return sbuf.str(); + LogString sbuf; + getLayout()->format(sbuf, event, p); + return sbuf; } -void ODBCAppender::execute(const String& sql) +void ODBCAppender::execute(const LogString& sql) { SQLRETURN ret; SQLHDBC con = SQL_NULL_HDBC; @@ -100,21 +103,18 @@ { con = getConnection(); - ret = SQLAllocHandle(SQL_HANDLE_STMT, con, &stmt); + ret = SQLAllocHandle( SQL_HANDLE_STMT, con, &stmt); if (ret < 0) { - throw SQLException(ret); + throw SQLException( GetErrorMessage( SQL_HANDLE_DBC, con, "Failed to allocate sql handle.") ); } -#if defined(LOG4CXX_HAVE_MS_ODBC) - ret = SQLExecDirect(stmt, (SQLTCHAR *)sql.c_str(), SQL_NTS); -#else - USES_CONVERSION; - ret = SQLExecDirect(stmt, (SQLCHAR *)T2A(sql.c_str()), SQL_NTS); -#endif - if (ret < 0) + LOG4CXX_ENCODE_CHAR( strEncodedSql, sql ); + ret = SQLExecDirect(stmt, (SQLCHAR *)strEncodedSql.c_str(), SQL_NTS); + + if (ret < 0) { - throw SQLException(ret); + throw SQLException( GetErrorMessage( SQL_HANDLE_STMT, stmt, "Failed to execute sql statement.") ); } } catch (SQLException& e) @@ -123,13 +123,13 @@ { SQLFreeHandle(SQL_HANDLE_STMT, stmt); } - + throw e; } SQLFreeHandle(SQL_HANDLE_STMT, stmt); closeConnection(con); - //tcout << _T("Execute: ") << sql << std::endl; + //tcout << LOG4CXX_STR("Execute: ") << sql << std::endl; } /* The default behavior holds a single connection open until the appender @@ -138,6 +138,34 @@ { } +std::string ODBCAppender::GetErrorMessage(SQLSMALLINT fHandleType, SQLHANDLE hInput, const char* szMsg ) +{ + SQLCHAR SqlState[6]; + SQLCHAR SQLStmt[100]; + SQLCHAR Msg[SQL_MAX_MESSAGE_LENGTH]; + SQLINTEGER NativeError; + SQLSMALLINT i; + SQLSMALLINT MsgLen; + SQLRETURN rc2; + + std::string strReturn(szMsg); + strReturn += " - "; + + // Get the status records. + i = 1; + while ((rc2 = SQLGetDiagRec(fHandleType, hInput, i, SqlState, &NativeError, + Msg, sizeof(Msg), &MsgLen)) != SQL_NO_DATA) + { + strReturn += (const char*) Msg; + i++; + } + + return strReturn; +} + + + + SQLHDBC ODBCAppender::getConnection() { SQLRETURN ret; @@ -147,16 +175,18 @@ ret = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env); if (ret < 0) { + std::string strErr = GetErrorMessage(SQL_HANDLE_ENV, env, "Failed to allocate SQL handle."); env = SQL_NULL_HENV; - throw SQLException(ret); + throw SQLException( strErr ); } ret = SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC3, SQL_IS_INTEGER); if (ret < 0) { + std::string strErr = GetErrorMessage(SQL_HANDLE_ENV, env, "Failed to set odbc version."); SQLFreeHandle(SQL_HANDLE_ENV, env); env = SQL_NULL_HENV; - throw SQLException(ret); + throw SQLException( strErr ); } } @@ -165,31 +195,31 @@ ret = SQLAllocHandle(SQL_HANDLE_DBC, env, &connection); if (ret < 0) { + std::string strErr = GetErrorMessage(SQL_HANDLE_DBC, connection, "Failed to allocate sql handle."); connection = SQL_NULL_HDBC; - throw SQLException(ret); + throw SQLException( strErr ); } -#if defined(LOG4CXX_HAVE_MS_ODBC) - ret = SQLConnect(connection, - (SQLTCHAR *)databaseURL.c_str(), SQL_NTS, - (SQLTCHAR *)databaseUser.c_str(), SQL_NTS, - (SQLTCHAR *)databasePassword.c_str(), SQL_NTS); -#else - USES_CONVERSION; - std::string URL = T2A(databaseURL.c_str()); - std::string user = T2A(databaseUser.c_str()); - std::string password = T2A(databasePassword.c_str()); - ret = SQLConnect(connection, - (SQLCHAR *)URL.c_str(), SQL_NTS, - (SQLCHAR *)user.c_str(), SQL_NTS, - (SQLCHAR *)password.c_str(), SQL_NTS); -#endif - if (ret < 0) + LOG4CXX_ENCODE_CHAR( URL, databaseURL ); + LOG4CXX_ENCODE_CHAR( user, databaseUser ); + LOG4CXX_ENCODE_CHAR( password, databasePassword ); + + SQLCHAR szOutConnectionString[1024]; + SQLSMALLINT nOutConnctionLength = 0; + + ret = SQLDriverConnect( connection, NULL, + (SQLCHAR *)URL.c_str(), SQL_NTS, + szOutConnectionString, sizeof( szOutConnectionString ), + &nOutConnctionLength, SQL_DRIVER_NOPROMPT ); + + + if (ret < 0) { + std::string strErr = GetErrorMessage( SQL_HANDLE_DBC, connection, "Failed to connect to database."); SQLFreeHandle(SQL_HANDLE_DBC, connection); connection = SQL_NULL_HDBC; - throw SQLException(ret); + throw SQLException( strErr ); } } @@ -204,7 +234,7 @@ } catch (SQLException& e) { - errorHandler->error(_T("Error closing connection"), + errorHandler->error(LOG4CXX_STR("Error closing connection"), e, ErrorCode::GENERIC_FAILURE); } @@ -227,18 +257,20 @@ //Do the actual logging //removes.ensureCapacity(buffer.size()); + Pool p; + std::list::iterator i; for (i = buffer.begin(); i != buffer.end(); i++) { try { const LoggingEventPtr& logEvent = *i; - String sql = getLogStatement(logEvent); + LogString sql = getLogStatement(logEvent, p); execute(sql); } catch (SQLException& e) { - errorHandler->error(_T("Failed to excute sql"), e, + errorHandler->error(LOG4CXX_STR("Failed to excute sql"), e, ErrorCode::FLUSH_FAILURE); } } @@ -247,7 +279,7 @@ buffer.clear(); } -void ODBCAppender::setSql(const String& s) +void ODBCAppender::setSql(const LogString& s) { sqlStatement = s; if (getLayout() == 0)