case-insensitivity for SessionPool

This commit is contained in:
Aleksandar Fabijanic
2013-04-21 21:38:55 -05:00
parent fe5c4098e5
commit 225401743f
11 changed files with 96 additions and 44 deletions

View File

@@ -35,6 +35,7 @@
#include "Poco/Data/ODBC/ODBC.h" #include "Poco/Data/ODBC/ODBC.h"
#include "Poco/Data/ODBC/Utility.h"
#include "Poco/Data/ODBC/Unicode_WIN32.h" #include "Poco/Data/ODBC/Unicode_WIN32.h"
#include "Poco/Buffer.h" #include "Poco/Buffer.h"
#include "Poco/Exception.h" #include "Poco/Exception.h"
@@ -612,6 +613,7 @@ SQLRETURN SQLDriverConnect(SQLHDBC hdbc,
pcbConnStrOut, pcbConnStrOut,
fDriverCompletion); fDriverCompletion);
if (!Utility::isError(rc))
makeUTF8(bufOut, *pcbConnStrOut * sizeof(wchar_t), szConnStrOut, cbConnStrOutMax); makeUTF8(bufOut, *pcbConnStrOut * sizeof(wchar_t), szConnStrOut, cbConnStrOutMax);
return rc; return rc;

View File

@@ -58,20 +58,22 @@ using Poco::DateTime;
#ifdef POCO_ODBC_USE_MAMMOTH_NG #ifdef POCO_ODBC_USE_MAMMOTH_NG
#define POSTGRESQL_ODBC_DRIVER "Mammoth ODBCng Beta" #define POSTGRESQL_ODBC_DRIVER "Mammoth ODBCng Beta"
#elif defined (POCO_ODBC_UNICODE) #elif defined (POCO_ODBC_UNICODE)
#define POSTGRESQL_ODBC_DRIVER "PostgreSQL Unicode" #define POSTGRESQL_ODBC_DRIVER "PostgreSQL ODBC Driver(UNICODE)"
#define POSTGRESQL_DSN "PocoDataPgSQLTestW"
#else #else
#define POSTGRESQL_ODBC_DRIVER "PostgreSQL ANSI" #define POSTGRESQL_ODBC_DRIVER "PostgreSQL ODBC Driver(ANSI)"
#define POSTGRESQL_DSN "PocoDataPgSQLTest"
#endif #endif
#define POSTGRESQL_DSN "PocoDataPgSQLTest"
#define POSTGRESQL_SERVER POCO_ODBC_TEST_DATABASE_SERVER #define POSTGRESQL_SERVER POCO_ODBC_TEST_DATABASE_SERVER
#define POSTGRESQL_PORT "5432" #define POSTGRESQL_PORT "5432"
#define POSTGRESQL_DB "postgres" #define POSTGRESQL_DB "postgres"
#define POSTGRESQL_UID "postgres" #define POSTGRESQL_UID "postgres"
#define POSTGRESQL_PWD "postgres" #define POSTGRESQL_PWD "postgres"
#define POSTGRESQL_VERSION "9.2"
#ifdef POCO_OS_FAMILY_WINDOWS #ifdef POCO_OS_FAMILY_WINDOWS
const std::string ODBCPostgreSQLTest::_libDir = "C:\\\\Program Files\\\\PostgreSQL\\\\8.2\\\\lib\\\\"; const std::string ODBCPostgreSQLTest::_libDir = "C:\\\\Program Files\\\\PostgreSQL\\\\" POSTGRESQL_VERSION "\\\\lib\\\\";
#else #else
const std::string ODBCPostgreSQLTest::_libDir = "/usr/local/pgsql/lib/"; const std::string ODBCPostgreSQLTest::_libDir = "/usr/local/pgsql/lib/";
#endif #endif

View File

@@ -109,15 +109,7 @@ private:
SessionInfo(Connector* pSI); SessionInfo(Connector* pSI);
}; };
struct ILT typedef std::map<std::string, SessionInfo, Poco::CILess> Connectors;
{
bool operator() (const std::string& s1, const std::string& s2) const
{
return Poco::icompare(s1, s2) < 0;
}
};
typedef std::map<std::string, SessionInfo, ILT> Connectors;
Connectors _connectors; Connectors _connectors;
Poco::FastMutex _mutex; Poco::FastMutex _mutex;
}; };

View File

@@ -43,7 +43,7 @@
#include "Poco/Data/Data.h" #include "Poco/Data/Data.h"
#include "Poco/Data/Session.h" #include "Poco/Data/Session.h"
#include "Poco/Data/SessionPool.h" #include "Poco/Data/SessionPool.h"
#include "Poco/HashMap.h" #include "Poco/String.h"
#include "Poco/Mutex.h" #include "Poco/Mutex.h"
@@ -92,7 +92,7 @@ public:
/// Shuts down all the held pools. /// Shuts down all the held pools.
private: private:
typedef HashMap<std::string, AutoPtr<SessionPool> > SessionPoolMap; typedef std::map<std::string, AutoPtr<SessionPool>, Poco::CILess> SessionPoolMap;
SessionPoolContainer(const SessionPoolContainer&); SessionPoolContainer(const SessionPoolContainer&);
SessionPoolContainer& operator = (const SessionPoolContainer&); SessionPoolContainer& operator = (const SessionPoolContainer&);

View File

@@ -69,7 +69,7 @@ void SessionPoolContainer::add(SessionPool* pPool)
throw SessionPoolExistsException("Session pool already exists: " + pPool->name()); throw SessionPoolExistsException("Session pool already exists: " + pPool->name());
pPool->duplicate(); pPool->duplicate();
_sessionPools.insert(SessionPoolMap::ValueType(pPool->name(), pPool)); _sessionPools.insert(SessionPoolMap::value_type(pPool->name(), pPool));
} }
@@ -82,7 +82,7 @@ Session SessionPoolContainer::add(const std::string& sessionKey,
std::string name = SessionPool::name(sessionKey, connectionString); std::string name = SessionPool::name(sessionKey, connectionString);
FastMutex::ScopedLock lock(_mutex); FastMutex::ScopedLock lock(_mutex);
SessionPoolMap::Iterator it = _sessionPools.find(name); SessionPoolMap::iterator it = _sessionPools.find(name);
// pool already exists, silently return a session from it // pool already exists, silently return a session from it
if (it != _sessionPools.end()) return it->second->get(); if (it != _sessionPools.end()) return it->second->get();
@@ -90,8 +90,8 @@ Session SessionPoolContainer::add(const std::string& sessionKey,
SessionPool* pSP = SessionPool* pSP =
new SessionPool(sessionKey, connectionString, minSessions, maxSessions, idleTime); new SessionPool(sessionKey, connectionString, minSessions, maxSessions, idleTime);
std::pair<SessionPoolMap::Iterator, bool> ins = std::pair<SessionPoolMap::iterator, bool> ins =
_sessionPools.insert(SessionPoolMap::ValueType(name, pSP)); _sessionPools.insert(SessionPoolMap::value_type(name, pSP));
return ins.first->second->get(); return ins.first->second->get();
} }
@@ -111,7 +111,7 @@ SessionPool& SessionPoolContainer::getPool(const std::string& name)
std::string n = Session::uri(uri.getScheme(), path.substr(1)); std::string n = Session::uri(uri.getScheme(), path.substr(1));
FastMutex::ScopedLock lock(_mutex); FastMutex::ScopedLock lock(_mutex);
SessionPoolMap::Iterator it = _sessionPools.find(n); SessionPoolMap::iterator it = _sessionPools.find(n);
if (_sessionPools.end() == it) throw NotFoundException(n); if (_sessionPools.end() == it) throw NotFoundException(n);
return *it->second; return *it->second;
} }
@@ -119,8 +119,8 @@ SessionPool& SessionPoolContainer::getPool(const std::string& name)
void SessionPoolContainer::shutdown() void SessionPoolContainer::shutdown()
{ {
SessionPoolMap::Iterator it = _sessionPools.begin(); SessionPoolMap::iterator it = _sessionPools.begin();
SessionPoolMap::Iterator end = _sessionPools.end(); SessionPoolMap::iterator end = _sessionPools.end();
for (; it != end; ++it) it->second->shutdown(); for (; it != end; ++it) it->second->shutdown();
} }

View File

@@ -234,9 +234,15 @@ void SessionPoolTest::testSessionPool()
void SessionPoolTest::testSessionPoolContainer() void SessionPoolTest::testSessionPoolContainer()
{ {
SessionPoolContainer spc; SessionPoolContainer spc;
AutoPtr<SessionPool> pPool = new SessionPool("test", "cs"); AutoPtr<SessionPool> pPool = new SessionPool("TeSt", "Cs");
spc.add(pPool); spc.add(pPool);
assert (1 == spc.count()); assert (1 == spc.count());
Poco::Data::Session sess = spc.get("test:///cs");
assert ("test" == sess.impl()->connectorName());
assert ("Cs" == sess.impl()->connectionString());
assert ("test:///Cs" == sess.uri());
try { spc.add(pPool); fail ("must fail"); } try { spc.add(pPool); fail ("must fail"); }
catch (SessionPoolExistsException&) { } catch (SessionPoolExistsException&) { }
spc.remove(pPool->name()); spc.remove(pPool->name());
@@ -244,10 +250,10 @@ void SessionPoolTest::testSessionPoolContainer()
try { spc.get("test"); fail ("must fail"); } try { spc.get("test"); fail ("must fail"); }
catch (NotFoundException&) { } catch (NotFoundException&) { }
spc.add("test", "cs"); spc.add("tEsT", "cs");
spc.add("test", "cs");//duplicate request, must be silently ignored spc.add("TeSt", "cs");//duplicate request, must be silently ignored
assert (1 == spc.count()); assert (1 == spc.count());
spc.remove("test:///cs"); spc.remove("TesT:///cs");
assert (0 == spc.count()); assert (0 == spc.count());
try { spc.get("test"); fail ("must fail"); } try { spc.get("test"); fail ("must fail"); }
catch (NotFoundException&) { } catch (NotFoundException&) { }

View File

@@ -652,17 +652,17 @@ S cat(const S& delim, const It& begin, const It& end)
template <typename charT> template <typename charT>
struct i_char_traits : public std::char_traits<charT> struct i_char_traits : public std::char_traits<charT>
{ {
static bool eq(charT c1, charT c2) inline static bool eq(charT c1, charT c2)
{ {
return Ascii::toLower(c1) == Ascii::toLower(c2); return Ascii::toLower(c1) == Ascii::toLower(c2);
} }
static bool ne(charT c1, charT c2) inline static bool ne(charT c1, charT c2)
{ {
return !eq(c1, c2); return !eq(c1, c2);
} }
static bool lt(charT c1, charT c2) inline static bool lt(charT c1, charT c2)
{ {
return Ascii::toLower(c1) < Ascii::toLower(c2); return Ascii::toLower(c1) < Ascii::toLower(c2);
} }
@@ -688,10 +688,13 @@ struct i_char_traits : public std::char_traits<charT>
typedef std::basic_string<char, i_char_traits<char> > istring; typedef std::basic_string<char, i_char_traits<char> > istring;
/// Case-insensitive std::string counterpart.
template<typename T> template<typename T>
std::size_t isubstr(const T& str, const T& sought) std::size_t isubstr(const T& str, const T& sought)
/// Case-insensitive substring; searches for a substring
/// without regards to case.
{ {
typename T::const_iterator it = std::search(str.begin(), str.end(), typename T::const_iterator it = std::search(str.begin(), str.end(),
sought.begin(), sought.end(), sought.begin(), sought.end(),
@@ -702,6 +705,18 @@ std::size_t isubstr(const T& str, const T& sought)
} }
struct CILess
/// Case-insensitive less-than functor; useful for standard maps
/// and sets with std::strings keys and case-insensitive ordering
/// requirement.
{
inline bool operator() (const std::string& s1, const std::string& s2) const
{
return icompare(s1, s2) < 0;
}
};
} // namespace Poco } // namespace Poco

View File

@@ -123,15 +123,7 @@ private:
TextEncodingManager(const TextEncodingManager&); TextEncodingManager(const TextEncodingManager&);
TextEncodingManager& operator = (const TextEncodingManager&); TextEncodingManager& operator = (const TextEncodingManager&);
struct ILT typedef std::map<std::string, TextEncoding::Ptr, CILess> EncodingMap;
{
bool operator() (const std::string& s1, const std::string& s2) const
{
return Poco::icompare(s1, s2) < 0;
}
};
typedef std::map<std::string, TextEncoding::Ptr, ILT> EncodingMap;
EncodingMap _encodings; EncodingMap _encodings;
mutable RWLock _lock; mutable RWLock _lock;

View File

@@ -41,6 +41,8 @@
#include <iostream> #include <iostream>
#include <iomanip> #include <iomanip>
#include <cstdio> #include <cstdio>
#include <map>
#include <set>
using Poco::trimLeft; using Poco::trimLeft;
@@ -73,6 +75,7 @@ using Poco::doubleToStr;
using Poco::thousandSeparator; using Poco::thousandSeparator;
using Poco::decimalSeparator; using Poco::decimalSeparator;
using Poco::format; using Poco::format;
using Poco::CILess;
using Poco::MemoryInputStream; using Poco::MemoryInputStream;
using Poco::Stopwatch; using Poco::Stopwatch;
using Poco::RangeException; using Poco::RangeException;
@@ -305,6 +308,39 @@ void StringTest::testIcompare()
} }
void StringTest::testCILessThan()
{
typedef std::map<std::string, int, CILess> CIMapType;
CIMapType ciMap;
ciMap["z"] = 1;
ciMap["b"] = 2;
ciMap["A"] = 3;
ciMap["Z"] = 4;
assert (ciMap.size() == 3);
CIMapType::iterator it = ciMap.begin();
assert (it->first == "A"); ++it;
assert (it->first == "b"); ++it;
assert (it->first == "z");
assert (it->second == 4);
typedef std::set<std::string, CILess> CISetType;
CISetType ciSet;
ciSet.insert("z");
ciSet.insert("b");
ciSet.insert("A");
ciSet.insert("Z");
assert (ciSet.size() == 3);
CISetType::iterator sIt = ciSet.begin();
assert (*sIt == "A"); ++sIt;
assert (*sIt == "b"); ++sIt;
assert (*sIt == "z");
}
void StringTest::testTranslate() void StringTest::testTranslate()
{ {
std::string s = "aabbccdd"; std::string s = "aabbccdd";
@@ -1080,6 +1116,7 @@ CppUnit::Test* StringTest::suite()
CppUnit_addTest(pSuite, StringTest, testToLower); CppUnit_addTest(pSuite, StringTest, testToLower);
CppUnit_addTest(pSuite, StringTest, testIstring); CppUnit_addTest(pSuite, StringTest, testIstring);
CppUnit_addTest(pSuite, StringTest, testIcompare); CppUnit_addTest(pSuite, StringTest, testIcompare);
CppUnit_addTest(pSuite, StringTest, testCILessThan);
CppUnit_addTest(pSuite, StringTest, testTranslate); CppUnit_addTest(pSuite, StringTest, testTranslate);
CppUnit_addTest(pSuite, StringTest, testTranslateInPlace); CppUnit_addTest(pSuite, StringTest, testTranslateInPlace);
CppUnit_addTest(pSuite, StringTest, testReplace); CppUnit_addTest(pSuite, StringTest, testReplace);

View File

@@ -58,6 +58,7 @@ public:
void testToLower(); void testToLower();
void testIstring(); void testIstring();
void testIcompare(); void testIcompare();
void testCILessThan();
void testTranslate(); void testTranslate();
void testTranslateInPlace(); void testTranslateInPlace();
void testReplace(); void testReplace();

View File

@@ -40,6 +40,7 @@
#include "Poco/Windows1250Encoding.h" #include "Poco/Windows1250Encoding.h"
#include "Poco/Windows1251Encoding.h" #include "Poco/Windows1251Encoding.h"
#include "Poco/Windows1252Encoding.h" #include "Poco/Windows1252Encoding.h"
#include "Poco/UTF8Encoding.h"
using namespace Poco; using namespace Poco;
@@ -105,6 +106,10 @@ void TextEncodingTest::testTextEncoding()
TextEncoding::global(new Windows1252Encoding); TextEncoding::global(new Windows1252Encoding);
TextEncoding& glob7 = TextEncoding::global(); TextEncoding& glob7 = TextEncoding::global();
assert (std::string("Windows-1252") == glob7.canonicalName()); assert (std::string("Windows-1252") == glob7.canonicalName());
TextEncoding::global(new UTF8Encoding);
TextEncoding& glob8 = TextEncoding::global();
assert (std::string("UTF-8") == glob8.canonicalName());
} }