diff options
author | Lionel Elie Mamane <lionel@mamane.lu> | 2011-09-06 23:04:57 +0200 |
---|---|---|
committer | Lionel Elie Mamane <lionel@mamane.lu> | 2011-11-17 21:15:27 +0100 |
commit | 1ed8d09f679c321870c94cc18b171a4267fd2197 (patch) | |
tree | 593614ba0900aee8c1ba21bfa3cd9803d6b084ed /connectivity | |
parent | 4934930529c096d83aed091f6c8932cc7e4c367b (diff) |
pq_connect: wrap C values in exception-safe containers
Diffstat (limited to 'connectivity')
-rw-r--r-- | connectivity/source/drivers/postgresql/pq_connection.cxx | 75 |
1 files changed, 49 insertions, 26 deletions
diff --git a/connectivity/source/drivers/postgresql/pq_connection.cxx b/connectivity/source/drivers/postgresql/pq_connection.cxx index 5d75a599fe97..9669a531de9f 100644 --- a/connectivity/source/drivers/postgresql/pq_connection.cxx +++ b/connectivity/source/drivers/postgresql/pq_connection.cxx @@ -66,6 +66,8 @@ #include <time.h> #include <string.h> +#include <boost/shared_ptr.hpp> + #include "pq_connection.hxx" #include "pq_statement.hxx" #include "pq_preparedstatement.hxx" @@ -451,11 +453,40 @@ void Connection::clearWarnings( ) throw (SQLException, RuntimeException) { } +class cstr_vector +{ + std::vector<char*> values; + std::vector<bool> acquired; +public: + cstr_vector () : values(), acquired() { values.reserve(8); acquired.reserve(8); } + ~cstr_vector () + { + OSL_ENSURE(values.size() == acquired.size(), "pq_connection: cstr_vector values and acquired size mismatch"); + std::vector<char*>::iterator pv = values.begin(); + std::vector<bool>::iterator pa = acquired.begin(); + const std::vector<char*>::iterator pve = values.end(); + for( ; pv < pve ; ++pv, ++pa ) + if (*pa) + free(*pv); + } + void push_back(const char* s, __sal_NoAcquire) + { + values.push_back(const_cast<char*>(s)); + acquired.push_back(false); + } + void push_back(char* s) + { + values.push_back(s); + acquired.push_back(true); + } + char const** c_array() const { return const_cast <const char**>(&values[0]); } +}; + static void properties2arrays( const Sequence< PropertyValue > & args, const Reference< XTypeConverter> &tc, rtl_TextEncoding enc, - std::vector<const char*> &keywords, - std::vector<char*> &values) + cstr_vector &keywords, + cstr_vector &values) { // LEM TODO: can we just blindly take all properties? // I.e. they are prefiltered to have only relevant ones? @@ -466,31 +497,31 @@ static void properties2arrays( const Sequence< PropertyValue > & args, bool append = true; if( args[i].Name.matchIgnoreAsciiCaseAsciiL( RTL_CONSTASCII_STRINGPARAM( "password" ) ) ) { - keywords.push_back( "password" ); + keywords.push_back( "password", SAL_NO_ACQUIRE ); } else if( args[i].Name.matchIgnoreAsciiCaseAsciiL( RTL_CONSTASCII_STRINGPARAM( "user" ) ) ) { - keywords.push_back( "user" ); + keywords.push_back( "user", SAL_NO_ACQUIRE ); } else if( args[i].Name.matchIgnoreAsciiCaseAsciiL( RTL_CONSTASCII_STRINGPARAM( "port" ) ) ) { - keywords.push_back( "port" ); + keywords.push_back( "port", SAL_NO_ACQUIRE ); } else if( args[i].Name.matchIgnoreAsciiCaseAsciiL( RTL_CONSTASCII_STRINGPARAM( "dbname" ) ) ) { - keywords.push_back( "dbname" ); + keywords.push_back( "dbname", SAL_NO_ACQUIRE ); } else if( args[i].Name.matchIgnoreAsciiCaseAsciiL( RTL_CONSTASCII_STRINGPARAM( "connect_timeout" ) ) ) { - keywords.push_back( "connect_timeout" ); + keywords.push_back( "connect_timeout", SAL_NO_ACQUIRE ); } else if( args[i].Name.matchIgnoreAsciiCaseAsciiL( RTL_CONSTASCII_STRINGPARAM( "options" ) ) ) { - keywords.push_back( "options" ); + keywords.push_back( "options", SAL_NO_ACQUIRE ); } else if( args[i].Name.matchIgnoreAsciiCaseAsciiL( RTL_CONSTASCII_STRINGPARAM( "requiressl" ) ) ) { - keywords.push_back( "requiressl" ); + keywords.push_back( "requiressl", SAL_NO_ACQUIRE ); } else { @@ -552,15 +583,14 @@ void Connection::initialize( const Sequence< Any >& aArguments ) } } { - std::vector<const char*> keywords; - std::vector<char*> values; + cstr_vector keywords; + cstr_vector values; - PQconninfoOption *oOpts = NULL; if ( o.getLength() > 0 ) { char *err; - oOpts = PQconninfoParse(o.getStr(), &err); - if ( oOpts == NULL ) + boost::shared_ptr<PQconninfoOption> oOpts(PQconninfoParse(o.getStr(), &err), PQconninfoFree); + if ( oOpts.get() == NULL ) { OUString errorMessage; if ( err != NULL) @@ -580,27 +610,20 @@ void Connection::initialize( const Sequence< Any >& aArguments ) throw SQLException( buf.makeStringAndClear(), *this, OUString(RTL_CONSTASCII_USTRINGPARAM("HY092")), 5, Any() ); } - for ( PQconninfoOption * opt = oOpts; opt->keyword != NULL; ++opt) + for ( PQconninfoOption * opt = oOpts.get(); opt->keyword != NULL; ++opt) { if ( opt->val != NULL ) { - keywords.push_back(opt->keyword); + keywords.push_back(strdup(opt->keyword)); values.push_back(strdup(opt->val)); } } } properties2arrays( args , tc, m_settings.encoding, keywords, values ); - keywords.push_back(NULL); - values.push_back(NULL); - - m_settings.pConnection = PQconnectdbParams( &keywords[0], const_cast <const char**>(&values[0]), 0 ); + keywords.push_back(NULL, SAL_NO_ACQUIRE); + values.push_back(NULL, SAL_NO_ACQUIRE); - if ( oOpts != NULL ) - PQconninfoFree(oOpts); - std::vector<char*>::iterator p = values.begin(); - const std::vector<char*>::iterator pe = values.end(); - for( ; p < pe ; ++p ) - free(*p); + m_settings.pConnection = PQconnectdbParams( keywords.c_array(), values.c_array(), 0 ); } if( ! m_settings.pConnection ) throw RuntimeException( OUString( RTL_CONSTASCII_USTRINGPARAM( "pq_driver: out of memory" ) ), |