Skip to content

Commit a41629f

Browse files
committed
Fix SRombauts#155 Statement::bind truncates long integer to 32 bits on x86_64 Linux
Reproduced the problem with a dedicated unit test, then fixed the bug. Thanks @tszypenbejl for the clear analysis and the fix.
1 parent d15a84e commit a41629f

File tree

3 files changed

+23
-8
lines changed

3 files changed

+23
-8
lines changed

include/SQLiteCpp/Column.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
#include <SQLiteCpp/Exception.h>
1515

1616
#include <string>
17-
#include <limits.h>
17+
#include <climits> // For INT_MAX
1818

1919

2020
namespace SQLite
@@ -76,7 +76,7 @@ class Column
7676
#ifdef SQLITE_ENABLE_COLUMN_METADATA
7777
/**
7878
* @brief Return a pointer to the table column name that is the origin of this result column
79-
*
79+
*
8080
* Require definition of the SQLITE_ENABLE_COLUMN_METADATA preprocessor macro :
8181
* - when building the SQLite library itself (which is the case for the Debian libsqlite3 binary for instance),
8282
* - and also when compiling this wrapper.
@@ -187,7 +187,7 @@ class Column
187187
{
188188
return getUInt();
189189
}
190-
#else
190+
#else // sizeof(long)==8 means the data model of the system is LLP64 (64bits Linux)
191191
/// Inline cast operator to 64bits long when the data model of the system is ILP64 (Linux 64 bits...)
192192
inline operator long() const
193193
{

include/SQLiteCpp/Statement.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
#include <string>
1616
#include <map>
17+
#include <climits> // For INT_MAX
1718

1819
// Forward declarations to avoid inclusion of <sqlite3.h> in a header
1920
struct sqlite3;
@@ -123,7 +124,7 @@ class Statement
123124
{
124125
bind(aIndex, static_cast<int>(aValue));
125126
}
126-
#else
127+
#else // sizeof(long)==8 means the data model of the system is LLP64 (64bits Linux)
127128
/**
128129
* @brief Bind a 64bits long value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
129130
*/
@@ -205,7 +206,7 @@ class Statement
205206
{
206207
bind(apName, static_cast<int>(aValue));
207208
}
208-
#else
209+
#else // sizeof(long)==8 means the data model of the system is LLP64 (64bits Linux)
209210
/**
210211
* @brief Bind a 64bits long value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
211212
*/
@@ -293,7 +294,7 @@ class Statement
293294
{
294295
bind(aName.c_str(), static_cast<int>(aValue));
295296
}
296-
#else
297+
#else // sizeof(long)==8 means the data model of the system is LLP64 (64bits Linux)
297298
/**
298299
* @brief Bind a 64bits long value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
299300
*/
@@ -408,7 +409,7 @@ class Statement
408409
/**
409410
* @brief Try to execute a step of the prepared query to fetch one row of results, returning the sqlite result code.
410411
*
411-
*
412+
*
412413
*
413414
* @see exec() execute a one-step prepared statement with no expected result
414415
* @see executeStep() execute a step of the prepared query to fetch one row of results

tests/Statement_test.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <cstdio>
2020
#include <stdint.h>
2121

22+
#include <climits> // For INT_MAX
2223

2324
TEST(Statement, invalid) {
2425
// Create a new database
@@ -751,7 +752,7 @@ TEST(Statement, getColumns) {
751752
EXPECT_EQ("first", testStruct.msg);
752753
EXPECT_EQ(123, testStruct.integer);
753754
EXPECT_EQ(0.123, testStruct.real);
754-
755+
755756
// Get only the first 2 columns
756757
auto testStruct2 = query.getColumns<GetRowTestStruct, 2>();
757758
EXPECT_EQ(1, testStruct2.id);
@@ -761,3 +762,16 @@ TEST(Statement, getColumns) {
761762
}
762763
#endif
763764

765+
#if (LONG_MAX > INT_MAX) // sizeof(long)==8 means the data model of the system is LLP64 (64bits Linux)
766+
TEST(Statement, bind64bitsLong) {
767+
// Create a new database
768+
SQLite::Database db(":memory:", SQLite::OPEN_READWRITE|SQLite::OPEN_CREATE);
769+
EXPECT_EQ(SQLite::OK, db.getErrorCode());
770+
EXPECT_EQ(SQLite::OK, db.getExtendedErrorCode());
771+
772+
SQLite::Statement query(db, "SELECT ?");
773+
query.bind(1, 4294967297L);
774+
query.executeStep();
775+
EXPECT_EQ(4294967297L, query.getColumn(0).getInt64());
776+
}
777+
#endif

0 commit comments

Comments
 (0)