Author: carnold Date: Mon Mar 10 13:53:41 2008 New Revision: 635687 URL: http://svn.apache.org/viewvc?rev=635687&view=rev Log: LOGCXX-248: ODBCAppender has Unicode issues
Modified: logging/log4cxx/trunk/src/changes/changes.xml logging/log4cxx/trunk/src/main/cpp/exception.cpp logging/log4cxx/trunk/src/main/cpp/odbcappender.cpp logging/log4cxx/trunk/src/main/include/log4cxx/db/odbcappender.h logging/log4cxx/trunk/src/main/include/log4cxx/helpers/exception.h Modified: logging/log4cxx/trunk/src/changes/changes.xml URL: http://svn.apache.org/viewvc/logging/log4cxx/trunk/src/changes/changes.xml?rev=635687&r1=635686&r2=635687&view=diff ============================================================================== --- logging/log4cxx/trunk/src/changes/changes.xml (original) +++ logging/log4cxx/trunk/src/changes/changes.xml Mon Mar 10 13:53:41 2008 @@ -22,7 +22,7 @@ <title>Apache log4cxx</title> </properties> <body> -<release version="0.10.0" date="2008-02-29" description="First Apache release"> +<release version="0.10.0" date="2008-03-17" description="First Apache release"> <action issue="LOGCXX-2">logger.h includes config.h</action> <action issue="LOGCXX-3">Missing #else</action> <action issue="LOGCXX-4">initialization not working on many OS's</action> @@ -217,6 +217,7 @@ <action issue="LOGCXX-242">Eliminate log4cxx proxies for APR types</action> <action issue="LOGCXX-243">Problem Compile in Doxy</action> <action issue="LOGCXX-247">MSVC project has wrong additional include directories</action> +<action issue="LOGCXX-248">ODBCAppender has unicode issues</action> </release> <release version="0.9.7" date="2004-05-10"> <action type="fix">Fixed examples source code in the "Short introduction to log4cxx".</action> Modified: logging/log4cxx/trunk/src/main/cpp/exception.cpp URL: http://svn.apache.org/viewvc/logging/log4cxx/trunk/src/main/cpp/exception.cpp?rev=635687&r1=635686&r2=635687&view=diff ============================================================================== --- logging/log4cxx/trunk/src/main/cpp/exception.cpp (original) +++ logging/log4cxx/trunk/src/main/cpp/exception.cpp Mon Mar 10 13:53:41 2008 @@ -41,6 +41,20 @@ msg[len] = 0; } +Exception::Exception(const std::string& m) { + size_t len = m.size(); + if (len > MSG_SIZE) { + len = MSG_SIZE; + } +#if defined(__STDC_LIB_EXT1__) || defined(__STDC_SECURE_LIB__) + memcpy_s(msg, sizeof msg, m.data(), len); +#else + memcpy(msg, m.data(), len); +#endif + msg[len] = 0; +} + + Exception::Exception(const Exception& src) : std::exception() { #if defined(__STDC_LIB_EXT1__) || defined(__STDC_SECURE_LIB__) strcpy_s(msg, sizeof msg, src.msg); Modified: logging/log4cxx/trunk/src/main/cpp/odbcappender.cpp URL: http://svn.apache.org/viewvc/logging/log4cxx/trunk/src/main/cpp/odbcappender.cpp?rev=635687&r1=635686&r2=635687&view=diff ============================================================================== --- logging/log4cxx/trunk/src/main/cpp/odbcappender.cpp (original) +++ logging/log4cxx/trunk/src/main/cpp/odbcappender.cpp Mon Mar 10 13:53:41 2008 @@ -38,6 +38,48 @@ using namespace log4cxx::db; using namespace log4cxx::spi; +SQLException::SQLException(short fHandleType, + void* hInput, const char* prolog) + : Exception(formatMessage(fHandleType, hInput, prolog)) { +} + + +SQLException::SQLException(const std::string& msg) + : Exception(msg) { +} + +SQLException::SQLException(const SQLException& src) + : Exception(src) { +} + +std::string SQLException::formatMessage(short fHandleType, + void* hInput, const char* prolog) { + std::string strReturn(prolog); + strReturn.append(" - "); +#if LOG4CXX_HAVE_ODBC + SQLCHAR SqlState[6]; + SQLCHAR Msg[SQL_MAX_MESSAGE_LENGTH]; + SQLINTEGER NativeError; + SQLSMALLINT i; + SQLSMALLINT MsgLen; + SQLRETURN rc2; + + // Get the status records. + i = 1; + while ((rc2 = SQLGetDiagRecA(fHandleType, hInput, i, SqlState, &NativeError, + Msg, sizeof(Msg), &MsgLen)) != SQL_NO_DATA) + { + strReturn.append((char*) Msg); + i++; + } +#else + strReturn.append("log4cxx built without ODBC support"); +#endif + + return strReturn; +} + + IMPLEMENT_LOG4CXX_OBJECT(ODBCAppender) @@ -89,13 +131,13 @@ } -void ODBCAppender::append(const spi::LoggingEventPtr& event, log4cxx::helpers::Pool& /* p */) +void ODBCAppender::append(const spi::LoggingEventPtr& event, log4cxx::helpers::Pool& p) { #if LOG4CXX_HAVE_ODBC buffer.push_back(event); if (buffer.size() >= bufferSize) - flushBuffer(); + flushBuffer(p); #endif } @@ -106,7 +148,7 @@ return sbuf; } -void ODBCAppender::execute(const LogString& sql) +void ODBCAppender::execute(const LogString& sql, log4cxx::helpers::Pool& p) { #if LOG4CXX_HAVE_ODBC SQLRETURN ret; @@ -115,22 +157,20 @@ try { - con = getConnection(); + con = getConnection(p); ret = SQLAllocHandle( SQL_HANDLE_STMT, con, &stmt); if (ret < 0) { - LOG4CXX_DECODE_CHAR(msg, GetErrorMessage( SQL_HANDLE_DBC, con, "Failed to allocate sql handle.")); - throw SQLException( msg ); + throw SQLException( SQL_HANDLE_DBC, con, "Failed to allocate sql handle."); } - LOG4CXX_ENCODE_CHAR( strEncodedSql, sql ); - ret = SQLExecDirect(stmt, (SQLCHAR *)strEncodedSql.c_str(), SQL_NTS); + SQLWCHAR* wsql = Transcoder::wencode(sql, p); + ret = SQLExecDirectW(stmt, wsql, SQL_NTS); if (ret < 0) { - LOG4CXX_DECODE_CHAR(msg, GetErrorMessage( SQL_HANDLE_STMT, stmt, "Failed to execute sql statement.")); - throw SQLException( msg ); + throw SQLException(SQL_HANDLE_STMT, stmt, "Failed to execute sql statement."); } } catch (SQLException& e) @@ -145,7 +185,7 @@ SQLFreeHandle(SQL_HANDLE_STMT, stmt); closeConnection(con); #else - throw SQLException(LOG4CXX_STR("log4cxx build without ODBC support")); + throw SQLException("log4cxx build without ODBC support"); #endif } @@ -155,39 +195,11 @@ { } -std::string ODBCAppender::GetErrorMessage(ODBCAppender::SQLSMALLINT fHandleType, - ODBCAppender::SQLHANDLE hInput, const char* szMsg ) -{ -#if LOG4CXX_HAVE_ODBC - SQLCHAR SqlState[6]; - 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; -#else - return "log4cxx built without ODBC support"; -#endif -} -ODBCAppender::SQLHDBC ODBCAppender::getConnection() +ODBCAppender::SQLHDBC ODBCAppender::getConnection(log4cxx::helpers::Pool& p) { #if LOG4CXX_HAVE_ODBC SQLRETURN ret; @@ -197,18 +209,18 @@ ret = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env); if (ret < 0) { - LOG4CXX_DECODE_CHAR(strErr, GetErrorMessage(SQL_HANDLE_ENV, env, "Failed to allocate SQL handle.")); + SQLException ex(SQL_HANDLE_ENV, env, "Failed to allocate SQL handle."); env = SQL_NULL_HENV; - throw SQLException( strErr ); + throw ex; } ret = SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC3, SQL_IS_INTEGER); if (ret < 0) { - LOG4CXX_DECODE_CHAR(strErr, GetErrorMessage(SQL_HANDLE_ENV, env, "Failed to set odbc version.")); + SQLException ex(SQL_HANDLE_ENV, env, "Failed to set odbc version."); SQLFreeHandle(SQL_HANDLE_ENV, env); env = SQL_NULL_HENV; - throw SQLException( strErr ); + throw ex; } } @@ -217,31 +229,29 @@ ret = SQLAllocHandle(SQL_HANDLE_DBC, env, &connection); if (ret < 0) { - LOG4CXX_DECODE_CHAR(strErr, GetErrorMessage(SQL_HANDLE_DBC, connection, "Failed to allocate sql handle.")); + SQLException ex(SQL_HANDLE_DBC, connection, "Failed to allocate sql handle."); connection = SQL_NULL_HDBC; - throw SQLException( strErr ); + throw ex; } - LOG4CXX_ENCODE_CHAR( URL, databaseURL ); - LOG4CXX_ENCODE_CHAR( user, databaseUser ); - LOG4CXX_ENCODE_CHAR( password, databasePassword ); + SQLWCHAR* wURL = Transcoder::wencode(databaseURL, p); - SQLCHAR szOutConnectionString[1024]; + wchar_t szOutConnectionString[1024]; SQLSMALLINT nOutConnctionLength = 0; - ret = SQLDriverConnect( connection, NULL, - (SQLCHAR *)URL.c_str(), SQL_NTS, + ret = SQLDriverConnectW( connection, NULL, + wURL, SQL_NTS, szOutConnectionString, sizeof( szOutConnectionString ), &nOutConnctionLength, SQL_DRIVER_NOPROMPT ); if (ret < 0) { - LOG4CXX_DECODE_CHAR(strErr, GetErrorMessage( SQL_HANDLE_DBC, connection, "Failed to connect to database.")); + SQLException ex(SQL_HANDLE_DBC, connection, "Failed to connect to database."); SQLFreeHandle(SQL_HANDLE_DBC, connection); connection = SQL_NULL_HDBC; - throw SQLException( strErr ); + throw ex; } } @@ -256,9 +266,10 @@ if (closed) { return; } + Pool p; try { - flushBuffer(); + flushBuffer(p); } catch (SQLException& e) { @@ -280,13 +291,8 @@ this->closed = true; } -void ODBCAppender::flushBuffer() +void ODBCAppender::flushBuffer(Pool& p) { - //Do the actual logging - //removes.ensureCapacity(buffer.size()); - - Pool p; - std::list<spi::LoggingEventPtr>::iterator i; for (i = buffer.begin(); i != buffer.end(); i++) { @@ -294,7 +300,7 @@ { const LoggingEventPtr& logEvent = *i; LogString sql = getLogStatement(logEvent, p); - execute(sql); + execute(sql, p); } catch (SQLException& e) { Modified: logging/log4cxx/trunk/src/main/include/log4cxx/db/odbcappender.h URL: http://svn.apache.org/viewvc/logging/log4cxx/trunk/src/main/include/log4cxx/db/odbcappender.h?rev=635687&r1=635686&r2=635687&view=diff ============================================================================== --- logging/log4cxx/trunk/src/main/include/log4cxx/db/odbcappender.h (original) +++ logging/log4cxx/trunk/src/main/include/log4cxx/db/odbcappender.h Mon Mar 10 13:53:41 2008 @@ -35,19 +35,16 @@ { namespace db { - class LOG4CXX_EXPORT SQLException : public log4cxx::helpers::Exception - { - public: - SQLException(const LogString& msg) : log4cxx::helpers::Exception(msg) { - } - SQLException(const SQLException& src) : log4cxx::helpers::Exception(src) { - } - - private: - SQLException& operator=(const SQLException&); - }; - - class ODBCAppender; + class LOG4CXX_EXPORT SQLException : public log4cxx::helpers::Exception { + public: + SQLException(short fHandleType, + void* hInput, const char* prolog); + SQLException(const std::string& msg); + SQLException(const SQLException& src); + private: + std::string formatMessage(short fHandleType, + void* hInput, const char* prolog); + }; /** <p><b>WARNING: This version of ODBCAppender @@ -195,7 +192,8 @@ * end. I use a connection pool outside of ODBCAppender which is * accessed in an override of this method. * */ - virtual void execute(const LogString& sql) /*throw(SQLException)*/; + virtual void execute(const LogString& sql, + log4cxx::helpers::Pool& p) /*throw(SQLException)*/; /** * Override this to return the connection to a pool, or to clean up the @@ -206,15 +204,13 @@ */ virtual void closeConnection(SQLHDBC con); - virtual std::string GetErrorMessage( SQLSMALLINT fHandleType, SQLHANDLE hInput, const char* szMsg ); - /** * Override this to link with your connection pooling system. * * By default this creates a single connection which is held open * until the object is garbage collected. */ - virtual SQLHDBC getConnection() /*throw(SQLException)*/; + virtual SQLHDBC getConnection(log4cxx::helpers::Pool& p) /*throw(SQLException)*/; /** * Closes the appender, flushing the buffer first then closing the default @@ -230,7 +226,7 @@ * * If a statement fails the LoggingEvent stays in the buffer! */ - virtual void flushBuffer(); + virtual void flushBuffer(log4cxx::helpers::Pool& p); /** * ODBCAppender requires a layout. Modified: logging/log4cxx/trunk/src/main/include/log4cxx/helpers/exception.h URL: http://svn.apache.org/viewvc/logging/log4cxx/trunk/src/main/include/log4cxx/helpers/exception.h?rev=635687&r1=635686&r2=635687&view=diff ============================================================================== --- logging/log4cxx/trunk/src/main/include/log4cxx/helpers/exception.h (original) +++ logging/log4cxx/trunk/src/main/include/log4cxx/helpers/exception.h Mon Mar 10 13:53:41 2008 @@ -32,6 +32,7 @@ class LOG4CXX_EXPORT Exception : public ::std::exception { public: + Exception(const std::string& msg); Exception(const LogString& msg); Exception(const Exception& src); Exception& operator=(const Exception& src);