00001 // 00002 // Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton, David Courtney 00003 // Distributed under the Boost Software License, Version 1.0. 00004 // (See accompanying file LICENSE_1_0.txt or copy at 00005 // http://www.boost.org/LICENSE_1_0.txt) 00006 // 00007 00008 // 00009 #if defined(SOCI_HEADERS_BURIED) 00010 # include <soci/core/soci.h> 00011 # include <soci/backends/sqlite3/soci-sqlite3.h> 00012 # include <soci/core/test/common-tests.h> 00013 #else 00014 # include <soci.h> 00015 # include <soci-sqlite3.h> 00016 # include <test/common-tests.h> 00017 #endif 00018 // 00019 #include <iostream> 00020 #include <sstream> 00021 #include <string> 00022 #include <cassert> 00023 #include <cmath> 00024 #include <ctime> 00025 #include <cstring> 00026 00027 using namespace soci; 00028 using namespace soci::tests; 00029 00030 std::string connectString; 00031 backend_factory const &backEnd = sqlite3; 00032 00033 // ROWID test 00034 // In sqlite3 the row id can be called ROWID, _ROWID_ or oid 00035 void test1() 00036 { 00037 { 00038 session sql(backEnd, connectString); 00039 00040 try { sql << "drop table test1"; } 00041 catch (soci_error const &) {} // ignore if error 00042 00043 sql << 00044 "create table test1 (" 00045 " id integer," 00046 " name varchar(100)" 00047 ")"; 00048 00049 sql << "insert into test1(id, name) values(7, \'John\')"; 00050 00051 rowid rid(sql); 00052 sql << "select oid from test1 where id = 7", into(rid); 00053 00054 int id; 00055 std::string name; 00056 00057 sql << "select id, name from test1 where oid = :rid", 00058 into(id), into(name), use(rid); 00059 00060 assert(id == 7); 00061 assert(name == "John"); 00062 00063 sql << "drop table test1"; 00064 } 00065 00066 std::cout << "test 1 passed" << std::endl; 00067 } 00068 00069 // BLOB test 00070 struct blob_table_creator : public table_creator_base 00071 { 00072 blob_table_creator(session & sql) 00073 : table_creator_base(sql) 00074 { 00075 sql << 00076 "create table soci_test (" 00077 " id integer," 00078 " img blob" 00079 ")"; 00080 } 00081 }; 00082 00083 void test2() 00084 { 00085 { 00086 session sql(backEnd, connectString); 00087 00088 blob_table_creator tableCreator(sql); 00089 00090 char buf[] = "abcdefghijklmnopqrstuvwxyz"; 00091 00092 sql << "insert into soci_test(id, img) values(7, '')"; 00093 00094 { 00095 blob b(sql); 00096 00097 sql << "select img from soci_test where id = 7", into(b); 00098 assert(b.get_len() == 0); 00099 00100 b.write(0, buf, sizeof(buf)); 00101 assert(b.get_len() == sizeof(buf)); 00102 sql << "update soci_test set img=? where id = 7", use(b); 00103 00104 b.append(buf, sizeof(buf)); 00105 assert(b.get_len() == 2 * sizeof(buf)); 00106 sql << "insert into soci_test(id, img) values(8, ?)", use(b); 00107 } 00108 { 00109 blob b(sql); 00110 sql << "select img from soci_test where id = 8", into(b); 00111 assert(b.get_len() == 2 * sizeof(buf)); 00112 char buf2[100]; 00113 b.read(0, buf2, 10); 00114 assert(strncmp(buf2, "abcdefghij", 10) == 0); 00115 00116 sql << "select img from soci_test where id = 7", into(b); 00117 assert(b.get_len() == sizeof(buf)); 00118 00119 } 00120 } 00121 00122 std::cout << "test 2 passed" << std::endl; 00123 } 00124 00125 // This test was put in to fix a problem that occurs when there are both 00126 //into and use elements in the same query and one of them (into) binds 00127 //to a vector object. 00128 void test3() 00129 { 00130 { 00131 session sql(backEnd, connectString); 00132 00133 try { sql << "drop table test3"; } 00134 catch (soci_error const &) {} //ignore error if table doesn't exist 00135 00136 sql << "Create table test3( id integer, name varchar, subname varchar);"; 00137 00138 sql << "Insert into test3(id,name,subname) values( 1,'john','smith')"; 00139 sql << "Insert into test3(id,name,subname) values( 2,'george','vals')"; 00140 sql << "Insert into test3(id,name,subname) values( 3,'ann','smith')"; 00141 sql << "Insert into test3(id,name,subname) values( 4,'john','grey')"; 00142 sql << "Insert into test3(id,name,subname) values( 5,'anthony','wall')"; 00143 00144 std::vector<int> v(10); 00145 00146 statement s(sql.prepare << "Select id from test3 where name = :name"); 00147 00148 std::string name = "john"; 00149 00150 s.exchange(use(name, "name")); 00151 s.exchange(into(v)); 00152 00153 s.define_and_bind(); 00154 s.execute(true); 00155 00156 assert(v.size() == 2); 00157 } 00158 std::cout << "test 3 passed" << std::endl; 00159 } 00160 00161 00162 // Test case from Amnon David 11/1/2007 00163 // I've noticed that table schemas in SQLite3 can sometimes have typeless 00164 // columns. One (and only?) example is the sqlite_sequence that sqlite 00165 // creates for autoincrement . Attempting to traverse this table caused 00166 // SOCI to crash. I've made the following code change in statement.cpp to 00167 // create a workaround: 00168 void test4() 00169 { 00170 { 00171 // we need to have an table that uses autoincrement to test this. 00172 session sql(backEnd, connectString); 00173 sql << "create table nulltest (col INTEGER PRIMARY KEY AUTOINCREMENT, name char)"; 00174 sql << "insert into nulltest(name) values('john')"; 00175 sql << "insert into nulltest(name) values('james')"; 00176 00177 int key; 00178 std::string name; 00179 sql << "select * from nulltest", into(key), into(name); 00180 assert(name == "john"); 00181 00182 rowset<row> rs = (sql.prepare << "select * from sqlite_sequence"); 00183 rowset<row>::const_iterator it = rs.begin(); 00184 row const& r1 = (*it); 00185 assert(r1.get<std::string>(0) == "nulltest"); 00186 assert(r1.get<std::string>(1) == "2"); 00187 } 00188 std::cout << "test 4 passed" << std::endl; 00189 } 00190 00191 struct longlong_table_creator : table_creator_base 00192 { 00193 longlong_table_creator(session & sql) 00194 : table_creator_base(sql) 00195 { 00196 sql << "create table soci_test(val number(20))"; 00197 } 00198 }; 00199 00200 // long long test 00201 void test5() 00202 { 00203 { 00204 session sql(backEnd, connectString); 00205 00206 longlong_table_creator tableCreator(sql); 00207 00208 long long v1 = 1000000000000LL; 00209 assert(v1 / 1000000 == 1000000); 00210 00211 sql << "insert into soci_test(val) values(:val)", use(v1); 00212 00213 long long v2 = 0LL; 00214 sql << "select val from soci_test", into(v2); 00215 00216 assert(v2 == v1); 00217 } 00218 00219 // vector<long long> 00220 { 00221 session sql(backEnd, connectString); 00222 00223 longlong_table_creator tableCreator(sql); 00224 00225 std::vector<long long> v1; 00226 v1.push_back(1000000000000LL); 00227 v1.push_back(1000000000001LL); 00228 v1.push_back(1000000000002LL); 00229 v1.push_back(1000000000003LL); 00230 v1.push_back(1000000000004LL); 00231 00232 sql << "insert into soci_test(val) values(:val)", use(v1); 00233 00234 std::vector<long long> v2(10); 00235 sql << "select val from soci_test order by val desc", into(v2); 00236 00237 assert(v2.size() == 5); 00238 assert(v2[0] == 1000000000004LL); 00239 assert(v2[1] == 1000000000003LL); 00240 assert(v2[2] == 1000000000002LL); 00241 assert(v2[3] == 1000000000001LL); 00242 assert(v2[4] == 1000000000000LL); 00243 } 00244 00245 std::cout << "test 5 passed" << std::endl; 00246 } 00247 00248 // DDL Creation objects for common tests 00249 struct table_creator_one : public table_creator_base 00250 { 00251 table_creator_one(session & sql) 00252 : table_creator_base(sql) 00253 { 00254 sql << "create table soci_test(id integer, val integer, c char, " 00255 "str varchar(20), sh smallint, ul numeric(20), d float, " 00256 "tm datetime, i1 integer, i2 integer, i3 integer, " 00257 "name varchar(20))"; 00258 } 00259 }; 00260 00261 struct table_creator_two : public table_creator_base 00262 { 00263 table_creator_two(session & sql) 00264 : table_creator_base(sql) 00265 { 00266 sql << "create table soci_test(num_float float, num_int integer," 00267 " name varchar(20), sometime datetime, chr char)"; 00268 } 00269 }; 00270 00271 struct table_creator_three : public table_creator_base 00272 { 00273 table_creator_three(session & sql) 00274 : table_creator_base(sql) 00275 { 00276 sql << "create table soci_test(name varchar(100) not null, " 00277 "phone varchar(15))"; 00278 } 00279 }; 00280 00281 // 00282 // Support for SOCI Common Tests 00283 // 00284 00285 class test_context : public test_context_base 00286 { 00287 public: 00288 test_context(backend_factory const &backEnd, 00289 std::string const &connectString) 00290 : test_context_base(backEnd, connectString) {} 00291 00292 table_creator_base* table_creator_1(session& s) const 00293 { 00294 return new table_creator_one(s); 00295 } 00296 00297 table_creator_base* table_creator_2(session& s) const 00298 { 00299 return new table_creator_two(s); 00300 } 00301 00302 table_creator_base* table_creator_3(session& s) const 00303 { 00304 return new table_creator_three(s); 00305 } 00306 00307 std::string to_date_time(std::string const &datdt_string) const 00308 { 00309 return "datetime(\'" + datdt_string + "\')"; 00310 } 00311 }; 00312 00313 int main(int argc, char** argv) 00314 { 00315 00316 #ifdef _MSC_VER 00317 // Redirect errors, unrecoverable problems, and assert() failures to STDERR, 00318 // instead of debug message window. 00319 // This hack is required to run asser()-driven tests by Buildbot. 00320 // NOTE: Comment this 2 lines for debugging with Visual C++ debugger to catch assertions inside. 00321 _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE); 00322 _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR); 00323 #endif //_MSC_VER 00324 00325 if (argc == 2) 00326 { 00327 connectString = argv[1]; 00328 } 00329 else 00330 { 00331 // If no file name is specfied then work in-memory 00332 connectString = ":memory:"; 00333 } 00334 00335 try 00336 { 00337 00338 test_context tc(backEnd, connectString); 00339 common_tests tests(tc); 00340 tests.run(); 00341 00342 std::cout << "\nSOCI sqlite3 Tests:\n\n"; 00343 00344 test1(); 00345 test2(); 00346 test3(); 00347 test4(); 00348 test5(); 00349 00350 std::cout << "\nOK, all tests passed.\n\n"; 00351 } 00352 catch (soci::soci_error const & e) 00353 { 00354 std::cout << "SOCIERROR: " << e.what() << '\n'; 00355 } 00356 catch (std::exception const & e) 00357 { 00358 std::cout << "EXCEPTION: " << e.what() << '\n'; 00359 } 00360 }
Generated on Sun Oct 3 2010 17:42:17 for EXTRAS-SOCI by Doxygen 1.7.1