From 6e09ec2fbd89fc0fa92b8853da29b2a79923e258 Mon Sep 17 00:00:00 2001 From: Aleksandar Fabijanic Date: Wed, 16 Oct 2024 12:26:08 +0200 Subject: [PATCH] chore(ODBC): add SQLServer big string vector test case #4324 --- Data/ODBC/include/Poco/Data/ODBC/Binder.h | 10 ++- Data/ODBC/include/Poco/Data/ODBC/ODBC.h | 16 +++-- Data/ODBC/testsuite/src/ODBCSQLServerTest.cpp | 64 +++++++++++++++++++ Data/ODBC/testsuite/src/ODBCSQLServerTest.h | 1 + 4 files changed, 86 insertions(+), 5 deletions(-) diff --git a/Data/ODBC/include/Poco/Data/ODBC/Binder.h b/Data/ODBC/include/Poco/Data/ODBC/Binder.h index ebcba15692..ece5708ca9 100644 --- a/Data/ODBC/include/Poco/Data/ODBC/Binder.h +++ b/Data/ODBC/include/Poco/Data/ODBC/Binder.h @@ -616,7 +616,11 @@ class ODBC_API Binder: public Poco::Data::AbstractBinder toODBCDirection(dir), SQL_C_CHAR, Utility::sqlDataType(SQL_C_CHAR), - (SQLUINTEGER) size - 1, +#if defined(POCO_DATA_ODBC_HAVE_SQL_SERVER_EXT) && POCO_DATA_SQL_SERVER_BIG_STRINGS + SQL_SS_LENGTH_UNLIMITED, +#else + (SQLUINTEGER)size - 1, +#endif 0, _charPtrs[pos], (SQLINTEGER) size, @@ -683,7 +687,11 @@ class ODBC_API Binder: public Poco::Data::AbstractBinder toODBCDirection(dir), SQL_C_WCHAR, Utility::sqlDataType(SQL_C_WCHAR), +#if defined(POCO_DATA_ODBC_HAVE_SQL_SERVER_EXT) && POCO_DATA_SQL_SERVER_BIG_STRINGS + SQL_SS_LENGTH_UNLIMITED, +#else (SQLUINTEGER)size - 1, +#endif 0, _utf16CharPtrs[pos], (SQLINTEGER)size, diff --git a/Data/ODBC/include/Poco/Data/ODBC/ODBC.h b/Data/ODBC/include/Poco/Data/ODBC/ODBC.h index 9217ba121a..289ce5aff4 100644 --- a/Data/ODBC/include/Poco/Data/ODBC/ODBC.h +++ b/Data/ODBC/include/Poco/Data/ODBC/ODBC.h @@ -59,10 +59,18 @@ #include #define POCO_DATA_ODBC_HAVE_SQL_SERVER_EXT - // To disable varchar(max) > 8000 bytes, set to 0. - // Note that this setting works in conjunction with - // the session "maxFieldSize" property, which ultimately - // determines the max string length available. + // To enable varchar(max) > 8000 bytes, set to 1. + // + // Notes: + // + // - this setting works in conjunction with + // the session "maxFieldSize" property, which + // ultimately determines the max string length. + // + // - increasing the "maxFieldSize" property may + // affect performance (more memory preallocated + // for prepared statements in order to safely + // accomodate data returned at execution) #define POCO_DATA_SQL_SERVER_BIG_STRINGS 1 #endif #endif diff --git a/Data/ODBC/testsuite/src/ODBCSQLServerTest.cpp b/Data/ODBC/testsuite/src/ODBCSQLServerTest.cpp index d433b322e7..d9ce9e581d 100644 --- a/Data/ODBC/testsuite/src/ODBCSQLServerTest.cpp +++ b/Data/ODBC/testsuite/src/ODBCSQLServerTest.cpp @@ -269,6 +269,69 @@ void ODBCSQLServerTest::testBigString() } +void ODBCSQLServerTest::testBigStringVector() +{ +#if defined(POCO_DATA_ODBC_HAVE_SQL_SERVER_EXT) && POCO_DATA_SQL_SERVER_BIG_STRINGS + const int limitSize = 8000, overLimitSize = 16002, entries = 10; + std::string lastName(overLimitSize, 'l'); + std::vector lastNameVec(entries, lastName); + std::string firstName(limitSize, 'f'); + std::vector firstNameVec(entries, firstName); + std::string address("Address"); + std::vector addressVec(entries, address); + int age = 42; + std::vector ageVec(10, age); + + for (int i = 0; i < 8;) + { + recreatePersonBigStringTable(); + session().setFeature("autoBind", bindValue(i)); + session().setFeature("autoExtract", bindValue(i + 1)); + session().setProperty("maxFieldSize", overLimitSize + 1); + try + { + session() << "DELETE FROM Person"s, now; + session() << "INSERT INTO Person VALUES (?,?,?,?)"s, + use(lastNameVec), use(firstNameVec), use(addressVec), use(ageVec), now; + lastNameVec.clear(); + firstNameVec.clear(); + addressVec.clear(); + ageVec.clear(); + + assertEqual(lastNameVec.size(), 0); + assertEqual(firstNameVec.size(), 0); + assertEqual(addressVec.size(), 0); + assertEqual(ageVec.size(), 0); + + session() << "SELECT LastName /*VARCHAR(MAX)*/, FirstName /*VARCHAR(8000)*/, Address /*VARCHAR(30)*/, Age FROM Person"s, + into(lastNameVec), into(firstNameVec), into(addressVec), into(ageVec), now; + + assertEqual(lastNameVec.size(), entries); + assertEqual(firstNameVec.size(), entries); + assertEqual(addressVec.size(), entries); + assertEqual(ageVec.size(), entries); + + for (int i = 0; i < entries; ++i) + { + assertEqual(lastNameVec[i], std::string(overLimitSize, 'l')); + assertEqual(firstNameVec[i], std::string(limitSize, 'f')); + assertEqual(addressVec[i], "Address"s); + assertEqual(ageVec[i], 42); + } + } + catch (DataException& ce) + { + std::cout << ce.displayText() << std::endl; + failmsg(__func__); + } + i += 2; + } +#else + std::cout << "SQL Server extensions not enabled."; +#endif // POCO_DATA_ODBC_HAVE_SQL_SERVER_EXT && POCO_DATA_SQL_SERVER_BIG_STRINGS +} + + void ODBCSQLServerTest::testBigBatch() { const std::string query("INSERT INTO Person VALUES('L', 'N', 'A', %d);"); @@ -1045,6 +1108,7 @@ CppUnit::Test* ODBCSQLServerTest::suite() CppUnit_addTest(pSuite, ODBCSQLServerTest, testEmptyDB); CppUnit_addTest(pSuite, ODBCSQLServerTest, testBLOB); CppUnit_addTest(pSuite, ODBCSQLServerTest, testBigString); + CppUnit_addTest(pSuite, ODBCSQLServerTest, testBigStringVector); CppUnit_addTest(pSuite, ODBCSQLServerTest, testBigBatch); CppUnit_addTest(pSuite, ODBCSQLServerTest, testBLOBContainer); CppUnit_addTest(pSuite, ODBCSQLServerTest, testBLOBStmt); diff --git a/Data/ODBC/testsuite/src/ODBCSQLServerTest.h b/Data/ODBC/testsuite/src/ODBCSQLServerTest.h index 61f95be9b1..d1557a1711 100644 --- a/Data/ODBC/testsuite/src/ODBCSQLServerTest.h +++ b/Data/ODBC/testsuite/src/ODBCSQLServerTest.h @@ -48,6 +48,7 @@ class ODBCSQLServerTest: public ODBCTest void testBLOB() override; void testBigString(); + void testBigStringVector(); void testBigBatch(); void testNull() override; void testBulk() override;