|
12 | 12 | #include <SQLiteCpp/Database.h> |
13 | 13 | #include <SQLiteCpp/Statement.h> |
14 | 14 |
|
15 | | -#include <cstdint> // for int64_t |
16 | | -#include <sqlite3.h> // for SQLITE_DONE |
| 15 | +#include <cstdint> // for int64_t |
| 16 | +#include <iterator> // for std::iterator_traits, std::input_iterator_tag |
| 17 | +#include <type_traits> // for std::is_same |
| 18 | +#include <sqlite3.h> // for SQLITE_DONE |
17 | 19 |
|
18 | 20 | #include <gtest/gtest.h> |
19 | 21 |
|
@@ -1013,6 +1015,95 @@ TEST(Statement, getColumns) |
1013 | 1015 | } |
1014 | 1016 | #endif |
1015 | 1017 |
|
| 1018 | +#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1600) |
| 1019 | + |
| 1020 | +TEST(Statement, rowIteratorTraits) |
| 1021 | +{ |
| 1022 | + using Iter = SQLite::Statement::RowIterator; |
| 1023 | + using Traits = std::iterator_traits<Iter>; |
| 1024 | + |
| 1025 | + static_assert(std::is_same<Traits::iterator_category, std::input_iterator_tag>::value, |
| 1026 | + "RowIterator must be an input iterator"); |
| 1027 | + static_assert(std::is_same<Traits::value_type, SQLite::Statement>::value, |
| 1028 | + "value_type must be Statement"); |
| 1029 | + static_assert(std::is_same<Traits::reference, SQLite::Statement&>::value, |
| 1030 | + "reference must be Statement&"); |
| 1031 | + static_assert(std::is_same<Traits::pointer, SQLite::Statement*>::value, |
| 1032 | + "pointer must be Statement*"); |
| 1033 | + static_assert(std::is_same<Traits::difference_type, std::ptrdiff_t>::value, |
| 1034 | + "difference_type must be ptrdiff_t"); |
| 1035 | +} |
| 1036 | + |
| 1037 | +TEST(Statement, rangeBasedFor) |
| 1038 | +{ |
| 1039 | + // Create a new database |
| 1040 | + SQLite::Database db(":memory:", SQLite::OPEN_READWRITE | SQLite::OPEN_CREATE); |
| 1041 | + EXPECT_EQ(0, db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, msg TEXT, val INTEGER)")); |
| 1042 | + EXPECT_EQ(1, db.exec("INSERT INTO test VALUES (1, 'first', 10)")); |
| 1043 | + EXPECT_EQ(1, db.exec("INSERT INTO test VALUES (2, 'second', 20)")); |
| 1044 | + EXPECT_EQ(1, db.exec("INSERT INTO test VALUES (3, 'third', 30)")); |
| 1045 | + |
| 1046 | + // Basic range-based for loop: iterator dereferences to the Statement itself |
| 1047 | + SQLite::Statement query(db, "SELECT id, msg, val FROM test ORDER BY id"); |
| 1048 | + int rowCount = 0; |
| 1049 | + for (SQLite::Statement& row : query) |
| 1050 | + { |
| 1051 | + ++rowCount; |
| 1052 | + EXPECT_EQ(rowCount, row.getColumn(0).getInt()); |
| 1053 | + EXPECT_EQ(rowCount * 10, row.getColumn(2).getInt()); |
| 1054 | + } |
| 1055 | + EXPECT_EQ(3, rowCount); |
| 1056 | + |
| 1057 | + // Re-iterating the same Statement must reset and start over |
| 1058 | + rowCount = 0; |
| 1059 | + for (SQLite::Statement& row : query) |
| 1060 | + { |
| 1061 | + ++rowCount; |
| 1062 | + EXPECT_EQ(rowCount, row.getColumn(0).getInt()); |
| 1063 | + } |
| 1064 | + EXPECT_EQ(3, rowCount); |
| 1065 | +} |
| 1066 | + |
| 1067 | +TEST(Statement, rangeBasedForEmpty) |
| 1068 | +{ |
| 1069 | + // Create a new database |
| 1070 | + SQLite::Database db(":memory:", SQLite::OPEN_READWRITE | SQLite::OPEN_CREATE); |
| 1071 | + EXPECT_EQ(0, db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY)")); |
| 1072 | + |
| 1073 | + // Empty table: loop body must never execute |
| 1074 | + SQLite::Statement query(db, "SELECT * FROM test"); |
| 1075 | + int rowCount = 0; |
| 1076 | + for (SQLite::Statement& row : query) |
| 1077 | + { |
| 1078 | + (void)row; |
| 1079 | + ++rowCount; |
| 1080 | + } |
| 1081 | + EXPECT_EQ(0, rowCount); |
| 1082 | +} |
| 1083 | + |
| 1084 | +TEST(Statement, rangeBasedForWithBind) |
| 1085 | +{ |
| 1086 | + // Create a new database |
| 1087 | + SQLite::Database db(":memory:", SQLite::OPEN_READWRITE | SQLite::OPEN_CREATE); |
| 1088 | + EXPECT_EQ(0, db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, val INTEGER)")); |
| 1089 | + EXPECT_EQ(1, db.exec("INSERT INTO test VALUES (1, 5)")); |
| 1090 | + EXPECT_EQ(1, db.exec("INSERT INTO test VALUES (2, 15)")); |
| 1091 | + EXPECT_EQ(1, db.exec("INSERT INTO test VALUES (3, 25)")); |
| 1092 | + |
| 1093 | + // Only rows with val > 10 should be visited |
| 1094 | + SQLite::Statement query(db, "SELECT id, val FROM test WHERE val > ? ORDER BY id"); |
| 1095 | + query.bind(1, 10); |
| 1096 | + int rowCount = 0; |
| 1097 | + for (SQLite::Statement& row : query) |
| 1098 | + { |
| 1099 | + ++rowCount; |
| 1100 | + EXPECT_GT(row.getColumn(1).getInt(), 10); |
| 1101 | + } |
| 1102 | + EXPECT_EQ(2, rowCount); |
| 1103 | +} |
| 1104 | + |
| 1105 | +#endif // C++11 |
| 1106 | + |
1016 | 1107 | TEST(Statement, getBindParameterCount) |
1017 | 1108 | { |
1018 | 1109 | // Create a new database |
|
0 commit comments