mirror of
https://github.com/pocoproject/poco.git
synced 2024-12-13 18:45:10 +01:00
Merge pull request #214 from cksmith/fix-192
Fixed GH #192: MySQL: Unsigned integer values not handled properly in result sets
This commit is contained in:
commit
1d2a95e110
@ -342,7 +342,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
bool realExtractFixed(std::size_t pos, enum_field_types type, void* buffer, std::size_t length = 0);
|
bool realExtractFixed(std::size_t pos, enum_field_types type, void* buffer, std::size_t length = 0, bool isUnsigned = false);
|
||||||
|
|
||||||
// Prevent VC8 warning "operator= could not be generated"
|
// Prevent VC8 warning "operator= could not be generated"
|
||||||
Extractor& operator=(const Extractor&);
|
Extractor& operator=(const Extractor&);
|
||||||
|
@ -62,7 +62,7 @@ bool Extractor::extract(std::size_t pos, Poco::Int8& val)
|
|||||||
|
|
||||||
bool Extractor::extract(std::size_t pos, Poco::UInt8& val)
|
bool Extractor::extract(std::size_t pos, Poco::UInt8& val)
|
||||||
{
|
{
|
||||||
return realExtractFixed(pos, MYSQL_TYPE_TINY, &val);
|
return realExtractFixed(pos, MYSQL_TYPE_TINY, &val, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -74,7 +74,7 @@ bool Extractor::extract(std::size_t pos, Poco::Int16& val)
|
|||||||
|
|
||||||
bool Extractor::extract(std::size_t pos, Poco::UInt16& val)
|
bool Extractor::extract(std::size_t pos, Poco::UInt16& val)
|
||||||
{
|
{
|
||||||
return realExtractFixed(pos, MYSQL_TYPE_SHORT, &val);
|
return realExtractFixed(pos, MYSQL_TYPE_SHORT, &val, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -86,7 +86,7 @@ bool Extractor::extract(std::size_t pos, Poco::Int32& val)
|
|||||||
|
|
||||||
bool Extractor::extract(std::size_t pos, Poco::UInt32& val)
|
bool Extractor::extract(std::size_t pos, Poco::UInt32& val)
|
||||||
{
|
{
|
||||||
return realExtractFixed(pos, MYSQL_TYPE_LONG, &val);
|
return realExtractFixed(pos, MYSQL_TYPE_LONG, &val, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -98,7 +98,7 @@ bool Extractor::extract(std::size_t pos, Poco::Int64& val)
|
|||||||
|
|
||||||
bool Extractor::extract(std::size_t pos, Poco::UInt64& val)
|
bool Extractor::extract(std::size_t pos, Poco::UInt64& val)
|
||||||
{
|
{
|
||||||
return realExtractFixed(pos, MYSQL_TYPE_LONGLONG, &val);
|
return realExtractFixed(pos, MYSQL_TYPE_LONGLONG, &val, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -111,7 +111,7 @@ bool Extractor::extract(std::size_t pos, long& val)
|
|||||||
|
|
||||||
bool Extractor::extract(std::size_t pos, unsigned long& val)
|
bool Extractor::extract(std::size_t pos, unsigned long& val)
|
||||||
{
|
{
|
||||||
return realExtractFixed(pos, MYSQL_TYPE_LONG, &val);
|
return realExtractFixed(pos, MYSQL_TYPE_LONG, &val, true);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -255,7 +255,7 @@ void Extractor::reset()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Extractor::realExtractFixed(std::size_t pos, enum_field_types type, void* buffer, std::size_t length)
|
bool Extractor::realExtractFixed(std::size_t pos, enum_field_types type, void* buffer, std::size_t length, bool isUnsigned)
|
||||||
{
|
{
|
||||||
MYSQL_BIND bind = {0};
|
MYSQL_BIND bind = {0};
|
||||||
my_bool isNull = 0;
|
my_bool isNull = 0;
|
||||||
@ -264,6 +264,7 @@ bool Extractor::realExtractFixed(std::size_t pos, enum_field_types type, void* b
|
|||||||
bind.buffer_type = type;
|
bind.buffer_type = type;
|
||||||
bind.buffer = buffer;
|
bind.buffer = buffer;
|
||||||
bind.buffer_length = static_cast<unsigned long>(length);
|
bind.buffer_length = static_cast<unsigned long>(length);
|
||||||
|
bind.is_unsigned = isUnsigned;
|
||||||
|
|
||||||
if (!_stmt.fetchColumn(pos, &bind))
|
if (!_stmt.fetchColumn(pos, &bind))
|
||||||
return false;
|
return false;
|
||||||
|
@ -217,6 +217,7 @@ void ResultMetadata::init(MYSQL_STMT* stmt)
|
|||||||
_row[i].buffer = &_buffer[0] + offset;
|
_row[i].buffer = &_buffer[0] + offset;
|
||||||
_row[i].length = &_lengths[i];
|
_row[i].length = &_lengths[i];
|
||||||
_row[i].is_null = &_isNull[i];
|
_row[i].is_null = &_isNull[i];
|
||||||
|
_row[i].is_unsigned = (fields[i].flags & UNSIGNED_FLAG) > 0;
|
||||||
|
|
||||||
offset += _row[i].buffer_length;
|
offset += _row[i].buffer_length;
|
||||||
}}
|
}}
|
||||||
|
@ -86,7 +86,7 @@ void StatementExecutor::prepare(const std::string& query)
|
|||||||
void StatementExecutor::bindParams(MYSQL_BIND* params, std::size_t count)
|
void StatementExecutor::bindParams(MYSQL_BIND* params, std::size_t count)
|
||||||
{
|
{
|
||||||
if (_state < STMT_COMPILED)
|
if (_state < STMT_COMPILED)
|
||||||
throw StatementException("Satement is not compiled yet");
|
throw StatementException("Statement is not compiled yet");
|
||||||
|
|
||||||
if (count != mysql_stmt_param_count(_pHandle))
|
if (count != mysql_stmt_param_count(_pHandle))
|
||||||
throw StatementException("wrong bind parameters count", 0, _query);
|
throw StatementException("wrong bind parameters count", 0, _query);
|
||||||
@ -101,7 +101,7 @@ void StatementExecutor::bindParams(MYSQL_BIND* params, std::size_t count)
|
|||||||
void StatementExecutor::bindResult(MYSQL_BIND* result)
|
void StatementExecutor::bindResult(MYSQL_BIND* result)
|
||||||
{
|
{
|
||||||
if (_state < STMT_COMPILED)
|
if (_state < STMT_COMPILED)
|
||||||
throw StatementException("Satement is not compiled yet");
|
throw StatementException("Statement is not compiled yet");
|
||||||
|
|
||||||
if (mysql_stmt_bind_result(_pHandle, result) != 0)
|
if (mysql_stmt_bind_result(_pHandle, result) != 0)
|
||||||
throw StatementException("mysql_stmt_bind_result error ", _pHandle, _query);
|
throw StatementException("mysql_stmt_bind_result error ", _pHandle, _query);
|
||||||
@ -111,7 +111,7 @@ void StatementExecutor::bindResult(MYSQL_BIND* result)
|
|||||||
void StatementExecutor::execute()
|
void StatementExecutor::execute()
|
||||||
{
|
{
|
||||||
if (_state < STMT_COMPILED)
|
if (_state < STMT_COMPILED)
|
||||||
throw StatementException("Satement is not compiled yet");
|
throw StatementException("Statement is not compiled yet");
|
||||||
|
|
||||||
if (mysql_stmt_execute(_pHandle) != 0)
|
if (mysql_stmt_execute(_pHandle) != 0)
|
||||||
throw StatementException("mysql_stmt_execute error", _pHandle, _query);
|
throw StatementException("mysql_stmt_execute error", _pHandle, _query);
|
||||||
@ -127,7 +127,7 @@ void StatementExecutor::execute()
|
|||||||
bool StatementExecutor::fetch()
|
bool StatementExecutor::fetch()
|
||||||
{
|
{
|
||||||
if (_state < STMT_EXECUTED)
|
if (_state < STMT_EXECUTED)
|
||||||
throw StatementException("Satement is not executed yet");
|
throw StatementException("Statement is not executed yet");
|
||||||
|
|
||||||
int res = mysql_stmt_fetch(_pHandle);
|
int res = mysql_stmt_fetch(_pHandle);
|
||||||
|
|
||||||
@ -141,7 +141,7 @@ bool StatementExecutor::fetch()
|
|||||||
bool StatementExecutor::fetchColumn(std::size_t n, MYSQL_BIND *bind)
|
bool StatementExecutor::fetchColumn(std::size_t n, MYSQL_BIND *bind)
|
||||||
{
|
{
|
||||||
if (_state < STMT_EXECUTED)
|
if (_state < STMT_EXECUTED)
|
||||||
throw StatementException("Satement is not executed yet");
|
throw StatementException("Statement is not executed yet");
|
||||||
|
|
||||||
int res = mysql_stmt_fetch_column(_pHandle, bind, static_cast<unsigned int>(n), 0);
|
int res = mysql_stmt_fetch_column(_pHandle, bind, static_cast<unsigned int>(n), 0);
|
||||||
|
|
||||||
|
@ -471,6 +471,15 @@ void MySQLTest::testBLOBStmt()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MySQLTest::testUnsignedInts()
|
||||||
|
{
|
||||||
|
if (!_pSession) fail ("Test not available.");
|
||||||
|
|
||||||
|
recreateUnsignedIntsTable();
|
||||||
|
_pExecutor->unsignedInts();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void MySQLTest::testFloat()
|
void MySQLTest::testFloat()
|
||||||
{
|
{
|
||||||
if (!_pSession) fail ("Test not available.");
|
if (!_pSession) fail ("Test not available.");
|
||||||
@ -755,6 +764,15 @@ void MySQLTest::recreateStringsTable()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MySQLTest::recreateUnsignedIntsTable()
|
||||||
|
{
|
||||||
|
dropTable("Strings");
|
||||||
|
try { *_pSession << "CREATE TABLE Strings (str INTEGER UNSIGNED)", now; }
|
||||||
|
catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail ("recreateUnsignedIntegersTable()"); }
|
||||||
|
catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail ("recreateUnsignedIntegersTable()"); }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void MySQLTest::recreateFloatsTable()
|
void MySQLTest::recreateFloatsTable()
|
||||||
{
|
{
|
||||||
dropTable("Strings");
|
dropTable("Strings");
|
||||||
@ -876,6 +894,7 @@ CppUnit::Test* MySQLTest::suite()
|
|||||||
CppUnit_addTest(pSuite, MySQLTest, testDateTime);
|
CppUnit_addTest(pSuite, MySQLTest, testDateTime);
|
||||||
//CppUnit_addTest(pSuite, MySQLTest, testBLOB);
|
//CppUnit_addTest(pSuite, MySQLTest, testBLOB);
|
||||||
CppUnit_addTest(pSuite, MySQLTest, testBLOBStmt);
|
CppUnit_addTest(pSuite, MySQLTest, testBLOBStmt);
|
||||||
|
CppUnit_addTest(pSuite, MySQLTest, testUnsignedInts);
|
||||||
CppUnit_addTest(pSuite, MySQLTest, testFloat);
|
CppUnit_addTest(pSuite, MySQLTest, testFloat);
|
||||||
CppUnit_addTest(pSuite, MySQLTest, testDouble);
|
CppUnit_addTest(pSuite, MySQLTest, testDouble);
|
||||||
CppUnit_addTest(pSuite, MySQLTest, testTuple);
|
CppUnit_addTest(pSuite, MySQLTest, testTuple);
|
||||||
|
@ -99,6 +99,7 @@ public:
|
|||||||
void testBLOB();
|
void testBLOB();
|
||||||
void testBLOBStmt();
|
void testBLOBStmt();
|
||||||
|
|
||||||
|
void testUnsignedInts();
|
||||||
void testFloat();
|
void testFloat();
|
||||||
void testDouble();
|
void testDouble();
|
||||||
|
|
||||||
@ -134,6 +135,7 @@ private:
|
|||||||
void recreatePersonTimeTable();
|
void recreatePersonTimeTable();
|
||||||
void recreateStringsTable();
|
void recreateStringsTable();
|
||||||
void recreateIntsTable();
|
void recreateIntsTable();
|
||||||
|
void recreateUnsignedIntsTable();
|
||||||
void recreateFloatsTable();
|
void recreateFloatsTable();
|
||||||
void recreateTuplesTable();
|
void recreateTuplesTable();
|
||||||
void recreateVectorsTable();
|
void recreateVectorsTable();
|
||||||
|
@ -497,6 +497,29 @@ void SQLExecutor::insertSingleBulk()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SQLExecutor::unsignedInts()
|
||||||
|
{
|
||||||
|
std::string funct = "unsignedInts()";
|
||||||
|
unsigned int data = UINT32_MAX;
|
||||||
|
unsigned int ret = 0;
|
||||||
|
|
||||||
|
try { *_pSession << "INSERT INTO Strings VALUES (?)", use(data), now; }
|
||||||
|
catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
|
||||||
|
catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
try { *_pSession << "SELECT COUNT(*) FROM Strings", into(count), now; }
|
||||||
|
catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
|
||||||
|
catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
|
||||||
|
assert (count == 1);
|
||||||
|
|
||||||
|
try { *_pSession << "SELECT str FROM Strings", into(ret), now; }
|
||||||
|
catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
|
||||||
|
catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
|
||||||
|
assert (ret == data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void SQLExecutor::floats()
|
void SQLExecutor::floats()
|
||||||
{
|
{
|
||||||
std::string funct = "floats()";
|
std::string funct = "floats()";
|
||||||
|
@ -105,6 +105,7 @@ public:
|
|||||||
void dateTime();
|
void dateTime();
|
||||||
void date();
|
void date();
|
||||||
void time();
|
void time();
|
||||||
|
void unsignedInts();
|
||||||
void floats();
|
void floats();
|
||||||
void doubles();
|
void doubles();
|
||||||
void tuples();
|
void tuples();
|
||||||
|
Loading…
Reference in New Issue
Block a user