1 //
2 // SQLiteTest.cpp
3 //
4 // Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
5 // and Contributors.
6 //
7 // SPDX-License-Identifier:	BSL-1.0
8 //
9 
10 
11 #include "SQLiteTest.h"
12 #include "CppUnit/TestCaller.h"
13 #include "CppUnit/TestSuite.h"
14 #include "Poco/Data/Date.h"
15 #include "Poco/Data/Time.h"
16 #include "Poco/Data/LOB.h"
17 #include "Poco/Data/Statement.h"
18 #include "Poco/Data/RecordSet.h"
19 #include "Poco/Data/SQLChannel.h"
20 #include "Poco/Data/SessionFactory.h"
21 #include "Poco/Data/SQLite/Connector.h"
22 #include "Poco/Data/SQLite/Utility.h"
23 #include "Poco/Data/SQLite/Notifier.h"
24 #include "Poco/Data/SQLite/Connector.h"
25 #include "Poco/Dynamic/Var.h"
26 #include "Poco/Data/TypeHandler.h"
27 #include "Poco/Nullable.h"
28 #include "Poco/Data/Transaction.h"
29 #include "Poco/Data/DataException.h"
30 #include "Poco/Data/SQLite/SQLiteException.h"
31 #include "Poco/Tuple.h"
32 #include "Poco/Any.h"
33 #include "Poco/SharedPtr.h"
34 #include "Poco/DynamicAny.h"
35 #include "Poco/DateTime.h"
36 #include "Poco/Logger.h"
37 #include "Poco/Message.h"
38 #include "Poco/Thread.h"
39 #include "Poco/AutoPtr.h"
40 #include "Poco/Exception.h"
41 #include "Poco/RefCountedObject.h"
42 #include "Poco/Stopwatch.h"
43 #include "Poco/Delegate.h"
44 #include <iostream>
45 
46 
47 using namespace Poco::Data::Keywords;
48 using Poco::Data::Session;
49 using Poco::Data::Statement;
50 using Poco::Data::RecordSet;
51 using Poco::Data::Column;
52 using Poco::Data::Row;
53 using Poco::Data::SQLChannel;
54 using Poco::Data::LimitException;
55 using Poco::Data::ConnectionFailedException;
56 using Poco::Data::CLOB;
57 using Poco::Data::Date;
58 using Poco::Data::Time;
59 using Poco::Data::Transaction;
60 using Poco::Data::AbstractExtractionVec;
61 using Poco::Data::AbstractExtractionVecVec;
62 using Poco::Data::AbstractBindingVec;
63 using Poco::Data::NotConnectedException;
64 using Poco::Data::SQLite::Notifier;
65 using Poco::Nullable;
66 using Poco::Tuple;
67 using Poco::Any;
68 using Poco::AnyCast;
69 using Poco::DynamicAny;
70 using Poco::DateTime;
71 using Poco::Logger;
72 using Poco::Message;
73 using Poco::AutoPtr;
74 using Poco::Thread;
75 using Poco::format;
76 using Poco::InvalidAccessException;
77 using Poco::RangeException;
78 using Poco::BadCastException;
79 using Poco::NotFoundException;
80 using Poco::NullPointerException;
81 using Poco::TimeoutException;
82 using Poco::NotImplementedException;
83 using Poco::Data::SQLite::ConstraintViolationException;
84 using Poco::Data::SQLite::ParameterCountMismatchException;
85 using Poco::Int32;
86 using Poco::Int64;
87 using Poco::Dynamic::Var;
88 using Poco::Data::SQLite::Utility;
89 using Poco::delegate;
90 
91 
92 class Person
93 {
94 public:
Person()95 	Person(){_age = 0;}
Person(const std::string & ln,const std::string & fn,const std::string & adr,int a)96 	Person(const std::string& ln, const std::string& fn, const std::string& adr, int a):_lastName(ln), _firstName(fn), _address(adr), _age(a)
97 	{
98 	}
operator ==(const Person & other) const99 	bool operator==(const Person& other) const
100 	{
101 		return _lastName == other._lastName && _firstName == other._firstName && _address == other._address && _age == other._age;
102 	}
103 
operator <(const Person & p) const104 	bool operator < (const Person& p) const
105 	{
106 		if (_age < p._age)
107 			return true;
108 		if (_lastName < p._lastName)
109 			return true;
110 		if (_firstName < p._firstName)
111 			return true;
112 		return (_address < p._address);
113 	}
114 
operator ()() const115 	const std::string& operator () () const
116 		/// This method is required so we can extract data to a map!
117 	{
118 		// we choose the lastName as examplary key
119 		return _lastName;
120 	}
121 
getLastName() const122 	const std::string& getLastName() const
123 	{
124 		return _lastName;
125 	}
126 
setLastName(const std::string & lastName)127 	void setLastName(const std::string& lastName)
128 	{
129 		_lastName = lastName;
130 	}
131 
getFirstName() const132 	const std::string& getFirstName() const
133 	{
134 		return _firstName;
135 	}
136 
setFirstName(const std::string & firstName)137 	void setFirstName(const std::string& firstName)
138 	{
139 		_firstName = firstName;
140 	}
141 
getAddress() const142 	const std::string& getAddress() const
143 	{
144 		return _address;
145 	}
146 
setAddress(const std::string & address)147 	void setAddress(const std::string& address)
148 	{
149 		_address = address;
150 	}
151 
getAge() const152 	const int& getAge() const
153 	{
154 		return _age;
155 	}
156 
setAge(const int & age)157 	void setAge(const int& age)
158 	{
159 		_age = age;
160 	}
161 
162 private:
163 	std::string _lastName;
164 	std::string _firstName;
165 	std::string _address;
166 	int         _age;
167 };
168 
169 
170 namespace Poco {
171 namespace Data {
172 
173 
174 template <>
175 class TypeHandler<Person>
176 {
177 public:
bind(std::size_t pos,const Person & obj,AbstractBinder::Ptr pBinder,AbstractBinder::Direction dir)178 	static void bind(std::size_t pos, const Person& obj, AbstractBinder::Ptr pBinder, AbstractBinder::Direction dir)
179 	{
180 		// the table is defined as Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3))
181 		poco_assert_dbg (!pBinder.isNull());
182 		pBinder->bind(pos++, obj.getLastName(), dir);
183 		pBinder->bind(pos++, obj.getFirstName(), dir);
184 		pBinder->bind(pos++, obj.getAddress(), dir);
185 		pBinder->bind(pos++, obj.getAge(), dir);
186 	}
187 
prepare(std::size_t pos,const Person & obj,AbstractPreparator::Ptr pPrepare)188 	static void prepare(std::size_t pos, const Person& obj, AbstractPreparator::Ptr pPrepare)
189 	{
190 		// no-op (SQLite is prepare-less connector)
191 	}
192 
size()193 	static std::size_t size()
194 	{
195 		return 4;
196 	}
197 
extract(std::size_t pos,Person & obj,const Person & defVal,AbstractExtractor::Ptr pExt)198 	static void extract(std::size_t pos, Person& obj, const Person& defVal, AbstractExtractor::Ptr pExt)
199 	{
200 		poco_assert_dbg (!pExt.isNull());
201 		std::string lastName;
202 		std::string firstName;
203 		std::string address;
204 		int age;
205 
206 		if (pExt->extract(pos++, lastName))
207 			obj.setLastName(lastName);
208 		else
209 			obj.setLastName(defVal.getLastName());
210 
211 		if (pExt->extract(pos++, firstName))
212 			obj.setFirstName(firstName);
213 		else
214 			obj.setFirstName(defVal.getFirstName());
215 
216 		if (pExt->extract(pos++, address))
217 			obj.setAddress(address);
218 		else
219 			obj.setAddress(defVal.getAddress());
220 
221 		if (pExt->extract(pos++, age))
222 			obj.setAge(age);
223 		else
224 			obj.setAge(defVal.getAge());
225 	}
226 
227 private:
228 	TypeHandler();
229 	~TypeHandler();
230 	TypeHandler(const TypeHandler&);
231 	TypeHandler& operator=(const TypeHandler&);
232 };
233 
234 
235 } } // namespace Poco::Data
236 
237 
238 int SQLiteTest::_insertCounter;
239 int SQLiteTest::_updateCounter;
240 int SQLiteTest::_deleteCounter;
241 
242 
SQLiteTest(const std::string & name)243 SQLiteTest::SQLiteTest(const std::string& name): CppUnit::TestCase(name)
244 {
245 	Poco::Data::SQLite::Connector::registerConnector();
246 }
247 
248 
~SQLiteTest()249 SQLiteTest::~SQLiteTest()
250 {
251 	Poco::Data::SQLite::Connector::unregisterConnector();
252 }
253 
254 
testBinding()255 void SQLiteTest::testBinding()
256 {
257 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
258 	assertTrue (tmp.getConnectionTimeout() == Session::LOGIN_TIMEOUT_DEFAULT);
259 	tmp.setConnectionTimeout(5);
260 	assertTrue (tmp.getConnectionTimeout() == 5);
261 	assertTrue (tmp.isConnected());
262 	std::string tableName("Simpsons");
263 	std::string lastName("Simpson");
264 	std::string firstName("Bart");
265 	std::string address("Springfield");
266 	int age = 12;
267 
268 	std::string& rLastName(lastName);
269 	std::string& rFirstName(firstName);
270 	std::string& rAddress(address);
271 	int& rAge = age;
272 
273 	const std::string& crLastName(lastName);
274 	const std::string& crFirstName(firstName);
275 	const std::string& crAddress(address);
276 	const int& crAge = age;
277 
278 	int count = 0;
279 	std::string result;
280 
281 	tmp << "DROP TABLE IF EXISTS Simpsons", now;
282 	tmp << "CREATE TABLE IF NOT EXISTS Simpsons (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3))", now;
283 	tmp << "SELECT name FROM sqlite_master WHERE tbl_name=?", use(tableName), into(result), now;
284 	assertTrue (result == tableName);
285 
286 	// following should not compile:
287 	//tmp << "INSERT INTO Simpsons VALUES(?, ?, ?, ?)", use("Simpson"), use("Bart"), use("Springfield"), use(age), now;
288 	//tmp << "INSERT INTO Simpsons VALUES(?, ?, ?, ?)", use(lastName), use(firstName), use(address), use(12), now;
289 	//tmp << "INSERT INTO Simpsons VALUES(?, ?, ?, ?)", useRef(lastName), useRef(firstName), useRef(address), useRef(12), now;
290 
291 	tmp << "INSERT INTO Simpsons VALUES(?, ?, ?, ?)", useRef("Simpson"), useRef("Bart"), useRef("Springfield"), useRef(age), now;
292 
293 	tmp << "INSERT INTO Simpsons VALUES(?, ?, ?, ?)", use(rLastName), use(rFirstName), use(rAddress), use(rAge), now;
294 	tmp << "INSERT INTO Simpsons VALUES(?, ?, ?, ?)", useRef(crLastName), useRef(crFirstName), useRef(crAddress), useRef(crAge), now;
295 	tmp << "INSERT INTO Simpsons VALUES(?, ?, ?, ?)", bind("Simpson"), bind("Bart"), bind("Springfield"), bind(12), now;
296 	tmp << "INSERT INTO Simpsons VALUES(?, ?, ?, ?)", bind(rLastName), bind(rFirstName), bind(rAddress), bind(rAge), now;
297 	tmp << "INSERT INTO Simpsons VALUES(?, ?, ?, ?)", bind(crLastName), bind(crFirstName), bind(crAddress), bind(crAge), now;
298 
299 	tmp << "SELECT COUNT(*) FROM Simpsons", into(count), now;
300 	assertTrue (6 == count);
301 }
302 
303 
testZeroRows()304 void SQLiteTest::testZeroRows()
305 {
306 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
307 	tmp << "DROP TABLE IF EXISTS ZeroTest", now;
308 	tmp << "CREATE TABLE IF NOT EXISTS ZeroTest (zt INTEGER(3))", now;
309 	Statement stmt = (tmp << "SELECT * FROM ZeroTest");
310 	assertTrue (0 == stmt.execute());
311 }
312 
313 
testSimpleAccess()314 void SQLiteTest::testSimpleAccess()
315 {
316 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
317 	assertTrue (tmp.isConnected());
318 	std::string tableName("Person");
319 	std::string lastName("lastname");
320 	std::string firstName("firstname");
321 	std::string address("Address");
322 	int age = 133132;
323 	int count = 0;
324 	std::string result;
325 	tmp << "DROP TABLE IF EXISTS Person", now;
326 	tmp << "CREATE TABLE IF NOT EXISTS Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3))", now;
327 	tmp << "SELECT name FROM sqlite_master WHERE tbl_name=?", use(tableName), into(result), now;
328 	assertTrue (result == tableName);
329 
330 	tmp << "INSERT INTO PERSON VALUES(:ln, :fn, :ad, :age)", use(lastName), use(firstName), use(address), use(age), now;
331 	tmp << "SELECT COUNT(*) FROM PERSON", into(count), now;
332 	assertTrue (count == 1);
333 	tmp << "SELECT LastName FROM PERSON", into(result), now;
334 	assertTrue (lastName == result);
335 	tmp << "SELECT Age FROM PERSON", into(count), now;
336 	assertTrue (count == age);
337 	tmp << "UPDATE PERSON SET Age = -1", now;
338 	tmp << "SELECT Age FROM PERSON", into(age), now;
339 	assertTrue (-1 == age);
340 	tmp.close();
341 	assertTrue (!tmp.isConnected());
342 }
343 
344 
testInMemory()345 void SQLiteTest::testInMemory()
346 {
347 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
348 	assertTrue (tmp.isConnected());
349 	std::string tableName("Person");
350 	std::string lastName("lastname");
351 	std::string firstName("firstname");
352 	std::string address("Address");
353 	int age = 133132;
354 	int count = 0;
355 	std::string result;
356 	tmp << "DROP TABLE IF EXISTS Person", now;
357 	tmp << "CREATE TABLE IF NOT EXISTS Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3))", now;
358 	tmp << "SELECT name FROM sqlite_master WHERE tbl_name=?", use(tableName), into(result), now;
359 	assertTrue (result == tableName);
360 
361 	tmp << "INSERT INTO PERSON VALUES(:ln, :fn, :ad, :age)", use(lastName), use(firstName), use(address), use(age), now;
362 
363 	// load db from file to memory
364 	Session mem (Poco::Data::SQLite::Connector::KEY, ":memory:");
365 	assertTrue (Poco::Data::SQLite::Utility::fileToMemory(mem, "dummy.db"));
366 
367 	mem << "SELECT COUNT(*) FROM PERSON", into(count), now;
368 	assertTrue (count == 1);
369 	mem << "SELECT LastName FROM PERSON", into(result), now;
370 	assertTrue (lastName == result);
371 	mem << "SELECT Age FROM PERSON", into(count), now;
372 	assertTrue (count == age);
373 	mem << "UPDATE PERSON SET Age = -1", now;
374 	mem << "SELECT Age FROM PERSON", into(age), now;
375 	assertTrue (-1 == age);
376 
377 	// save db from memory to file on the disk
378 	Session dsk (Poco::Data::SQLite::Connector::KEY, "dsk.db");
379 	assertTrue (Poco::Data::SQLite::Utility::memoryToFile("dsk.db", mem));
380 
381 	dsk << "SELECT COUNT(*) FROM PERSON", into(count), now;
382 	assertTrue (count == 1);
383 	dsk << "SELECT LastName FROM PERSON", into(result), now;
384 	assertTrue (lastName == result);
385 	dsk << "SELECT Age FROM PERSON", into(count), now;
386 	assertTrue (count == age);
387 	dsk << "UPDATE PERSON SET Age = -1", now;
388 	dsk << "SELECT Age FROM PERSON", into(age), now;
389 	assertTrue (-1 == age);
390 
391 	tmp.close();
392 	mem.close();
393 	dsk.close();
394 
395 	assertTrue (!tmp.isConnected());
396 	assertTrue (!mem.isConnected());
397 	assertTrue (!dsk.isConnected());
398 }
399 
400 
testNullCharPointer()401 void SQLiteTest::testNullCharPointer()
402 {
403 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
404 	std::string lastName("lastname");
405 	int age = 100;
406 	int count = 100;
407 	std::string result;
408 	tmp << "DROP TABLE IF EXISTS Person", now;
409 	tmp << "CREATE TABLE IF NOT EXISTS Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3))", now;
410 
411 	tmp << "INSERT INTO PERSON VALUES(:ln, :fn, :ad, :age)",
412 		bind(lastName),
413 		bind("firstname"),
414 		bind("Address"),
415 		bind(0), now;
416 
417 	tmp << "SELECT COUNT(*) FROM PERSON", into(count), now;
418 	assertTrue (count == 1);
419 	tmp << "SELECT LastName FROM PERSON", into(result), now;
420 	assertTrue (lastName == result);
421 	tmp << "SELECT Age FROM PERSON", into(age), now;
422 	assertTrue (0 == age);
423 
424 	try
425 	{
426 		const char* pc = 0;
427 		tmp << "INSERT INTO PERSON VALUES(:ln, :fn, :ad, :age)",
428 			bind("lastname"),
429 			bind("firstname"),
430 			bind("Address"), bind(pc), now;
431 			fail ("must fail");
432 	} catch (NullPointerException&) { }
433 
434 	tmp << "SELECT COUNT(*) FROM PERSON", into(count), now;
435 	assertTrue (count == 1);
436 	tmp << "SELECT LastName FROM PERSON", into(result), now;
437 	assertTrue (lastName == result);
438 	tmp << "SELECT Age FROM PERSON", into(age), now;
439 	assertTrue (0 == age);
440 }
441 
442 
testInsertCharPointer()443 void SQLiteTest::testInsertCharPointer()
444 {
445 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
446 	std::string tableName("Person");
447 	std::string lastName("lastname");
448 	std::string firstName("firstname");
449 	std::string address("Address");
450 	int age = 133132;
451 	int count = 0;
452 	std::string result;
453 	tmp << "DROP TABLE IF EXISTS Person", now;
454 	tmp << "CREATE TABLE IF NOT EXISTS Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3))", now;
455 
456 	const char* pc = 0;
457 	try
458 	{
459 		tmp << "INSERT INTO PERSON VALUES(:ln, :fn, :ad, :age)", bind(pc), now;
460 		fail ("must fail");
461 	} catch (NullPointerException&)	{ }
462 
463 	pc = (const char*) std::calloc(9, sizeof(char));
464 	poco_check_ptr (pc);
465 	std::strncpy((char*) pc, "lastname", 8);
466 	Statement stmt = (tmp << "INSERT INTO PERSON VALUES(:ln, :fn, :ad, :age)",
467 		bind(pc),
468 		bind("firstname"),
469 		bind("Address"),
470 		bind(133132));
471 
472 	std::free((void*) pc); pc = 0;
473 	assertTrue (1 == stmt.execute());
474 
475 	tmp << "SELECT COUNT(*) FROM PERSON", into(count), now;
476 	assertTrue (count == 1);
477 	tmp << "SELECT LastName FROM PERSON", into(result), now;
478 	assertTrue (lastName == result);
479 	tmp << "SELECT Age FROM PERSON", into(count), now;
480 	assertTrue (count == age);
481 }
482 
483 
testInsertCharPointer2()484 void SQLiteTest::testInsertCharPointer2()
485 {
486 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
487 	std::string tableName("Person");
488 	std::string lastName("lastname");
489 	std::string firstName("firstname");
490 	std::string address("Address");
491 	int age = 133132;
492 	int count = 0;
493 	std::string result;
494 	tmp << "DROP TABLE IF EXISTS Person", now;
495 	tmp << "CREATE TABLE IF NOT EXISTS Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3))", now;
496 
497 	tmp << "INSERT INTO PERSON VALUES(:ln, :fn, :ad, :age)",
498 		bind("lastname"),
499 		bind("firstname"),
500 		bind("Address"),
501 		bind(133132), now;
502 	tmp << "SELECT COUNT(*) FROM PERSON", into(count), now;
503 	assertTrue (count == 1);
504 	Statement stmt1 = (tmp << "SELECT LastName FROM PERSON", into(result));
505 	stmt1.execute();
506 	assertTrue (lastName == result);
507 	count = 0;
508 	Statement stmt2 = (tmp << "SELECT Age FROM PERSON", into(count));
509 	stmt2.execute();
510 	assertTrue (count == age);
511 }
512 
513 
testComplexType()514 void SQLiteTest::testComplexType()
515 {
516 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
517 	Person p1("LN1", "FN1", "ADDR1", 1);
518 	Person p2("LN2", "FN2", "ADDR2", 2);
519 	tmp << "DROP TABLE IF EXISTS Person", now;
520 	tmp << "CREATE TABLE IF NOT EXISTS Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3))", now;
521 	tmp << "INSERT INTO PERSON VALUES(:ln, :fn, :ad, :age)", use(p1), now;
522 	tmp << "INSERT INTO PERSON VALUES(:ln, :fn, :ad, :age)", use(p2), now;
523 	int count = 0;
524 	tmp << "SELECT COUNT(*) FROM PERSON", into(count), now;
525 	assertTrue (count == 2);
526 
527 	Person c1;
528 	Person c2;
529 	tmp << "SELECT * FROM PERSON WHERE LASTNAME = :ln", into(c1), useRef(p1.getLastName()), now;
530 	assertTrue (c1 == p1);
531 
532 	tmp << "DROP TABLE IF EXISTS Person", now;
533 	tmp << "CREATE TABLE IF NOT EXISTS Person (LastName1 VARCHAR(30), FirstName1 VARCHAR, Address1 VARCHAR, Age1 INTEGER(3),"
534 			"LastName2 VARCHAR(30), FirstName2 VARCHAR, Address2 VARCHAR, Age2 INTEGER(3))", now;
535 
536 	Tuple<Person,Person> t(p1,p2);
537 
538 	tmp << "INSERT INTO PERSON VALUES(:ln1, :fn1, :ad1, :age1, :ln2, :fn2, :ad2, :age2)", use(t), now;
539 
540 	Tuple<Person,Person> ret;
541 	assertTrue (ret != t);
542 	tmp << "SELECT * FROM PERSON", into(ret), now;
543 	assertTrue (ret == t);
544 }
545 
546 
547 
testSimpleAccessVector()548 void SQLiteTest::testSimpleAccessVector()
549 {
550 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
551 	std::vector<std::string> lastNames;
552 	std::vector<std::string> firstNames;
553 	std::vector<std::string> addresses;
554 	std::vector<int> ages;
555 	std::string tableName("Person");
556 	lastNames.push_back("LN1");
557 	lastNames.push_back("LN2");
558 	firstNames.push_back("FN1");
559 	firstNames.push_back("FN2");
560 	addresses.push_back("ADDR1");
561 	addresses.push_back("ADDR2");
562 	ages.push_back(1);
563 	ages.push_back(2);
564 	int count = 0;
565 	std::string result;
566 	tmp << "DROP TABLE IF EXISTS Person", now;
567 	tmp << "CREATE TABLE IF NOT EXISTS Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3))", now;
568 
569 	tmp << "INSERT INTO PERSON VALUES(:ln, :fn, :ad, :age)", use(lastNames), use(firstNames), use(addresses), use(ages), now;
570 	tmp << "SELECT COUNT(*) FROM PERSON", into(count), now;
571 	assertTrue (count == 2);
572 
573 	std::vector<std::string> lastNamesR;
574 	std::vector<std::string> firstNamesR;
575 	std::vector<std::string> addressesR;
576 	std::vector<int> agesR;
577 	tmp << "SELECT * FROM PERSON", into(lastNamesR), into(firstNamesR), into(addressesR), into(agesR), now;
578 	assertTrue (ages == agesR);
579 	assertTrue (lastNames == lastNamesR);
580 	assertTrue (firstNames == firstNamesR);
581 	assertTrue (addresses == addressesR);
582 }
583 
584 
testComplexTypeVector()585 void SQLiteTest::testComplexTypeVector()
586 {
587 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
588 	std::vector<Person> people;
589 	people.push_back(Person("LN1", "FN1", "ADDR1", 1));
590 	people.push_back(Person("LN2", "FN2", "ADDR2", 2));
591 	tmp << "DROP TABLE IF EXISTS Person", now;
592 	tmp << "CREATE TABLE IF NOT EXISTS Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3))", now;
593 	tmp << "INSERT INTO PERSON VALUES(:ln, :fn, :ad, :age)", use(people), now;
594 	int count = 0;
595 	tmp << "SELECT COUNT(*) FROM PERSON", into(count), now;
596 	assertTrue (count == 2);
597 
598 	std::vector<Person> result;
599 	tmp << "SELECT * FROM PERSON", into(result), now;
600 	assertTrue (result == people);
601 }
602 
603 
testSharedPtrComplexTypeVector()604 void SQLiteTest::testSharedPtrComplexTypeVector()
605 {
606 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
607 	std::vector<Poco::SharedPtr<Person> > people;
608 	people.push_back(new Person("LN1", "FN1", "ADDR1", 1));
609 	people.push_back(new Person("LN2", "FN2", "ADDR2", 2));
610 	tmp << "DROP TABLE IF EXISTS Person", now;
611 	tmp << "CREATE TABLE IF NOT EXISTS Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3))", now;
612 	tmp << "INSERT INTO PERSON VALUES(:ln, :fn, :ad, :age)", use(people), now;
613 	int count = 0;
614 	tmp << "SELECT COUNT(*) FROM PERSON", into(count), now;
615 	assertTrue (count == 2);
616 
617 	std::vector<Poco::SharedPtr<Person> > result;
618 	tmp << "SELECT * FROM PERSON", into(result), now;
619 	assertTrue (*result[0] == *people[0]);
620 	assertTrue (*result[1] == *people[1]);
621 }
622 
623 
testInsertVector()624 void SQLiteTest::testInsertVector()
625 {
626 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
627 	std::vector<std::string> str;
628 	str.push_back("s1");
629 	str.push_back("s2");
630 	str.push_back("s3");
631 	str.push_back("s3");
632 	int count = 100;
633 	tmp << "DROP TABLE IF EXISTS Strings", now;
634 	tmp << "CREATE TABLE IF NOT EXISTS Strings (str VARCHAR(30))", now;
635 	{
636 		Statement stmt((tmp << "INSERT INTO Strings VALUES(:str)", use(str)));
637 		tmp << "SELECT COUNT(*) FROM Strings", into(count), now;
638 		assertTrue (count == 0);
639 		stmt.execute();
640 		tmp << "SELECT COUNT(*) FROM Strings", into(count), now;
641 		assertTrue (count == 4);
642 	}
643 	count = 0;
644 	tmp << "SELECT COUNT(*) FROM Strings", into(count), now;
645 	assertTrue (count == 4);
646 }
647 
648 
testInsertEmptyVector()649 void SQLiteTest::testInsertEmptyVector()
650 {
651 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
652 	std::vector<std::string> str;
653 
654 	tmp << "DROP TABLE IF EXISTS Strings", now;
655 	tmp << "CREATE TABLE IF NOT EXISTS Strings (str VARCHAR(30))", now;
656 	try
657 	{
658 		tmp << "INSERT INTO Strings VALUES(:str)", use(str), now;
659 		fail("empty collectons should not work");
660 	}
661 	catch (Poco::Exception&)
662 	{
663 	}
664 }
665 
666 
testAffectedRows()667 void SQLiteTest::testAffectedRows()
668 {
669 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
670 	std::vector<std::string> str;
671 	str.push_back("s1");
672 	str.push_back("s2");
673 	str.push_back("s3");
674 	str.push_back("s3");
675 	int count = 100;
676 	tmp << "DROP TABLE IF EXISTS Strings", now;
677 	tmp << "CREATE TABLE IF NOT EXISTS Strings (str VARCHAR(30))", now;
678 
679 	Statement stmt((tmp << "INSERT INTO Strings VALUES(:str)", use(str)));
680 	count  = -1;
681 	tmp << "SELECT COUNT(*) FROM Strings", into(count), now;
682 	assertTrue (count == 0);
683 	assertTrue (4 == stmt.execute());
684 	tmp << "SELECT COUNT(*) FROM Strings", into(count), now;
685 	assertTrue (count == 4);
686 
687 	Statement stmt0(tmp << "DELETE FROM Strings");
688 	assertTrue (4 == stmt0.execute());
689 	tmp << "SELECT COUNT(*) FROM Strings", into(count), now;
690 	assertTrue (count == 0);
691 
692 	Statement stmt1((tmp << "SELECT * FROM Strings"));
693 	tmp << "SELECT COUNT(*) FROM Strings", into(count), now;
694 	assertTrue (count == 0);
695 	assertTrue (0 == stmt1.execute());
696 
697 	Statement stmt2((tmp << "INSERT INTO Strings VALUES(:str)", use(str)));
698 	count  = -1;
699 	tmp << "SELECT COUNT(*) FROM Strings", into(count), now;
700 	assertTrue (count == 0);
701 	assertTrue (4 == stmt2.execute());
702 	tmp << "SELECT COUNT(*) FROM Strings", into(count), now;
703 	assertTrue (count == 4);
704 
705 	Statement stmt3(tmp << "UPDATE Strings SET str = 's4' WHERE str = 's3'");
706 	assertTrue (2 == stmt3.execute());
707 
708 	Statement stmt4(tmp << "DELETE FROM Strings WHERE str = 's1'");
709 	assertTrue (1 == stmt4.execute());
710 
711 	Statement stmt5(tmp << "DELETE FROM Strings WHERE str = 'bad value'");
712 	assertTrue (0 == stmt5.execute());
713 
714 	Statement stmt6(tmp << "DELETE FROM Strings");
715 	assertTrue (3 == stmt6.execute());
716 }
717 
718 
testInsertSingleBulk()719 void SQLiteTest::testInsertSingleBulk()
720 {
721 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
722 	tmp << "DROP TABLE IF EXISTS Strings", now;
723 	tmp << "CREATE TABLE IF NOT EXISTS Strings (str INTEGER(10))", now;
724 	std::size_t x = 0;
725 	Statement stmt((tmp << "INSERT INTO Strings VALUES(:str)", use(x)));
726 
727 	for (std::size_t i = 0; x < 100; ++x)
728 	{
729 		i = stmt.execute();
730 		assertTrue (1 == i);
731 	}
732 
733 	int count = 0;
734 	tmp << "SELECT COUNT(*) FROM Strings", into(count), now;
735 	assertTrue (count == 100);
736 	tmp << "SELECT SUM(str) FROM Strings", into(count), now;
737 	assertTrue (count == ((0+99)*100/2));
738 }
739 
740 
testInsertSingleBulkVec()741 void SQLiteTest::testInsertSingleBulkVec()
742 {
743 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
744 	tmp << "DROP TABLE IF EXISTS Strings", now;
745 	tmp << "CREATE TABLE IF NOT EXISTS Strings (str INTEGER(10))", now;
746 	std::vector<int> data;
747 	data.push_back(0);
748 	data.push_back(1);
749 
750 	Statement stmt((tmp << "INSERT INTO Strings VALUES(:str)", use(data)));
751 
752 	for (int x = 0; x < 100; x += 2)
753 	{
754 		data[0] = x;
755 		data[1] = x+1;
756 		stmt.execute();
757 	}
758 	int count = 0;
759 	tmp << "SELECT COUNT(*) FROM Strings", into(count), now;
760 	assertTrue (count == 100);
761 	tmp << "SELECT SUM(str) FROM Strings", into(count), now;
762 	assertTrue (count == ((0+99)*100/2));
763 }
764 
765 
testLimit()766 void SQLiteTest::testLimit()
767 {
768 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
769 	tmp << "DROP TABLE IF EXISTS Strings", now;
770 	tmp << "CREATE TABLE IF NOT EXISTS Strings (str INTEGER(10))", now;
771 	std::vector<int> data;
772 	for (int x = 0; x < 100; ++x)
773 	{
774 		data.push_back(x);
775 	}
776 
777 	tmp << "INSERT INTO Strings VALUES(:str)", use(data), now;
778 	std::vector<int> retData;
779 	tmp << "SELECT * FROM Strings", into(retData), limit(50), now;
780 	assertTrue (retData.size() == 50);
781 	for (int x = 0; x < 50; ++x)
782 	{
783 		assertTrue (data[x] == retData[x]);
784 	}
785 }
786 
787 
testLimitZero()788 void SQLiteTest::testLimitZero()
789 {
790 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
791 	tmp << "DROP TABLE IF EXISTS Strings", now;
792 	tmp << "CREATE TABLE IF NOT EXISTS Strings (str INTEGER(10))", now;
793 	std::vector<int> data;
794 	for (int x = 0; x < 100; ++x)
795 	{
796 		data.push_back(x);
797 	}
798 
799 	tmp << "INSERT INTO Strings VALUES(:str)", use(data), now;
800 	std::vector<int> retData;
801 	tmp << "SELECT * FROM Strings", into(retData), limit(0), now; // stupid test, but at least we shouldn't crash
802 	assertTrue (retData.size() == 0);
803 }
804 
805 
testLimitOnce()806 void SQLiteTest::testLimitOnce()
807 {
808 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
809 	tmp << "DROP TABLE IF EXISTS Strings", now;
810 	tmp << "CREATE TABLE IF NOT EXISTS Strings (str INTEGER(10))", now;
811 	std::vector<int> data;
812 	for (int x = 0; x < 101; ++x)
813 	{
814 		data.push_back(x);
815 	}
816 
817 	tmp << "INSERT INTO Strings VALUES(:str)", use(data), now;
818 	std::vector<int> retData;
819 	Statement stmt = (tmp << "SELECT * FROM Strings", into(retData), limit(50), now);
820 	assertTrue (!stmt.done());
821 	assertTrue (retData.size() == 50);
822 	stmt.execute();
823 	assertTrue (!stmt.done());
824 	assertTrue (retData.size() == 100);
825 	stmt.execute();
826 	assertTrue (stmt.done());
827 	assertTrue (retData.size() == 101);
828 
829 	for (int x = 0; x < 101; ++x)
830 	{
831 		assertTrue (data[x] == retData[x]);
832 	}
833 }
834 
835 
testLimitPrepare()836 void SQLiteTest::testLimitPrepare()
837 {
838 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
839 	tmp << "DROP TABLE IF EXISTS Strings", now;
840 	tmp << "CREATE TABLE IF NOT EXISTS Strings (str INTEGER(10))", now;
841 	std::vector<int> data;
842 	for (int x = 0; x < 100; ++x)
843 	{
844 		data.push_back(x);
845 	}
846 
847 	Statement stmtIns = (tmp << "INSERT INTO Strings VALUES(:str)", use(data));
848 	assertTrue (100 == stmtIns.execute());
849 
850 	std::vector<int> retData;
851 	Statement stmt = (tmp << "SELECT * FROM Strings", into(retData), limit(50));
852 	assertTrue (retData.size() == 0);
853 	assertTrue (!stmt.done());
854 	std::size_t rows = stmt.execute();
855 	assertTrue (50 == rows);
856 	assertTrue (!stmt.done());
857 	assertTrue (retData.size() == 50);
858 	rows = stmt.execute();
859 	assertTrue (50 == rows);
860 	assertTrue (stmt.done());
861 	assertTrue (retData.size() == 100);
862 	rows = stmt.execute(); // will restart execution!
863 	assertTrue (50 == rows);
864 	assertTrue (!stmt.done());
865 	assertTrue (retData.size() == 150);
866 	for (int x = 0; x < 150; ++x)
867 	{
868 		assertTrue (data[x%100] == retData[x]);
869 	}
870 }
871 
872 
873 
testPrepare()874 void SQLiteTest::testPrepare()
875 {
876 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
877 	tmp << "DROP TABLE IF EXISTS Strings", now;
878 	tmp << "CREATE TABLE IF NOT EXISTS Strings (str INTEGER(10))", now;
879 	std::vector<int> data;
880 	for (int x = 0; x < 100; x += 2)
881 	{
882 		data.push_back(x);
883 	}
884 
885 	{
886 		Statement stmt((tmp << "INSERT INTO Strings VALUES(:str)", use(data)));
887 	}
888 	// stmt should not have been executed when destroyed
889 	int count = 100;
890 	tmp << "SELECT COUNT(*) FROM Strings", into(count), now;
891 	assertTrue (count == 0);
892 }
893 
894 
testSetSimple()895 void SQLiteTest::testSetSimple()
896 {
897 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
898 	std::set<std::string> lastNames;
899 	std::set<std::string> firstNames;
900 	std::set<std::string> addresses;
901 	std::set<int> ages;
902 	std::string tableName("Person");
903 	lastNames.insert("LN1");
904 	lastNames.insert("LN2");
905 	firstNames.insert("FN1");
906 	firstNames.insert("FN2");
907 	addresses.insert("ADDR1");
908 	addresses.insert("ADDR2");
909 	ages.insert(1);
910 	ages.insert(2);
911 	int count = 0;
912 	std::string result;
913 	tmp << "DROP TABLE IF EXISTS Person", now;
914 	tmp << "CREATE TABLE IF NOT EXISTS Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3))", now;
915 
916 	tmp << "INSERT INTO PERSON VALUES(:ln, :fn, :ad, :age)", use(lastNames), use(firstNames), use(addresses), use(ages), now;
917 	tmp << "SELECT COUNT(*) FROM PERSON", into(count), now;
918 	assertTrue (count == 2);
919 
920 	std::set<std::string> lastNamesR;
921 	std::set<std::string> firstNamesR;
922 	std::set<std::string> addressesR;
923 	std::set<int> agesR;
924 	tmp << "SELECT * FROM PERSON", into(lastNamesR), into(firstNamesR), into(addressesR), into(agesR), now;
925 	assertTrue (ages == agesR);
926 	assertTrue (lastNames == lastNamesR);
927 	assertTrue (firstNames == firstNamesR);
928 	assertTrue (addresses == addressesR);
929 }
930 
931 
testSetComplex()932 void SQLiteTest::testSetComplex()
933 {
934 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
935 	std::set<Person> people;
936 	people.insert(Person("LN1", "FN1", "ADDR1", 1));
937 	people.insert(Person("LN2", "FN2", "ADDR2", 2));
938 	tmp << "DROP TABLE IF EXISTS Person", now;
939 	tmp << "CREATE TABLE IF NOT EXISTS Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3))", now;
940 	tmp << "INSERT INTO PERSON VALUES(:ln, :fn, :ad, :age)", use(people), now;
941 	int count = 0;
942 	tmp << "SELECT COUNT(*) FROM PERSON", into(count), now;
943 	assertTrue (count == 2);
944 
945 	std::set<Person> result;
946 	tmp << "SELECT * FROM PERSON", into(result), now;
947 	assertTrue (result == people);
948 }
949 
950 
testSetComplexUnique()951 void SQLiteTest::testSetComplexUnique()
952 {
953 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
954 	std::vector<Person> people;
955 	Person p1("LN1", "FN1", "ADDR1", 1);
956 	people.push_back(p1);
957 	people.push_back(p1);
958 	people.push_back(p1);
959 	people.push_back(p1);
960 	Person p2("LN2", "FN2", "ADDR2", 2);
961 	people.push_back(p2);
962 
963 	tmp << "DROP TABLE IF EXISTS Person", now;
964 	tmp << "CREATE TABLE IF NOT EXISTS Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3))", now;
965 	tmp << "INSERT INTO PERSON VALUES(:ln, :fn, :ad, :age)", use(people), now;
966 	int count = 0;
967 	tmp << "SELECT COUNT(*) FROM PERSON", into(count), now;
968 	assertTrue (count == 5);
969 
970 	std::set<Person> result;
971 	tmp << "SELECT * FROM PERSON", into(result), now;
972 	assertTrue (result.size() == 2);
973 	assertTrue (*result.begin() == p1);
974 	assertTrue (*++result.begin() == p2);
975 }
976 
testMultiSetSimple()977 void SQLiteTest::testMultiSetSimple()
978 {
979 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
980 	std::multiset<std::string> lastNames;
981 	std::multiset<std::string> firstNames;
982 	std::multiset<std::string> addresses;
983 	std::multiset<int> ages;
984 	std::string tableName("Person");
985 	lastNames.insert("LN1");
986 	lastNames.insert("LN2");
987 	firstNames.insert("FN1");
988 	firstNames.insert("FN2");
989 	addresses.insert("ADDR1");
990 	addresses.insert("ADDR2");
991 	ages.insert(1);
992 	ages.insert(2);
993 	int count = 0;
994 	std::string result;
995 	tmp << "DROP TABLE IF EXISTS Person", now;
996 	tmp << "CREATE TABLE IF NOT EXISTS Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3))", now;
997 
998 	tmp << "INSERT INTO PERSON VALUES(:ln, :fn, :ad, :age)", use(lastNames), use(firstNames), use(addresses), use(ages), now;
999 	tmp << "SELECT COUNT(*) FROM PERSON", into(count), now;
1000 	assertTrue (count == 2);
1001 
1002 	std::multiset<std::string> lastNamesR;
1003 	std::multiset<std::string> firstNamesR;
1004 	std::multiset<std::string> addressesR;
1005 	std::multiset<int> agesR;
1006 	tmp << "SELECT * FROM PERSON", into(lastNamesR), into(firstNamesR), into(addressesR), into(agesR), now;
1007 	assertTrue (ages.size() == agesR.size());
1008 	assertTrue (lastNames.size() == lastNamesR.size());
1009 	assertTrue (firstNames.size() == firstNamesR.size());
1010 	assertTrue (addresses.size() == addressesR.size());
1011 }
1012 
1013 
testMultiSetComplex()1014 void SQLiteTest::testMultiSetComplex()
1015 {
1016 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
1017 	std::multiset<Person> people;
1018 	Person p1("LN1", "FN1", "ADDR1", 1);
1019 	people.insert(p1);
1020 	people.insert(p1);
1021 	people.insert(p1);
1022 	people.insert(p1);
1023 	Person p2("LN2", "FN2", "ADDR2", 2);
1024 	people.insert(p2);
1025 
1026 	tmp << "DROP TABLE IF EXISTS Person", now;
1027 	tmp << "CREATE TABLE IF NOT EXISTS Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3))", now;
1028 	tmp << "INSERT INTO PERSON VALUES(:ln, :fn, :ad, :age)", use(people), now;
1029 	int count = 0;
1030 	tmp << "SELECT COUNT(*) FROM PERSON", into(count), now;
1031 	assertTrue (count == 5);
1032 
1033 	std::multiset<Person> result;
1034 	tmp << "SELECT * FROM PERSON", into(result), now;
1035 	assertTrue (result.size() == people.size());
1036 }
1037 
1038 
testMapComplex()1039 void SQLiteTest::testMapComplex()
1040 {
1041 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
1042 	std::map<std::string, Person> people;
1043 	Person p1("LN1", "FN1", "ADDR1", 1);
1044 	Person p2("LN2", "FN2", "ADDR2", 2);
1045 	people.insert(std::make_pair("LN1", p1));
1046 	people.insert(std::make_pair("LN2", p2));
1047 	tmp << "DROP TABLE IF EXISTS Person", now;
1048 	tmp << "CREATE TABLE IF NOT EXISTS Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3))", now;
1049 	tmp << "INSERT INTO PERSON VALUES(:ln, :fn, :ad, :age)", use(people), now;
1050 	int count = 0;
1051 	tmp << "SELECT COUNT(*) FROM PERSON", into(count), now;
1052 	assertTrue (count == 2);
1053 
1054 	std::map<std::string, Person> result;
1055 	tmp << "SELECT * FROM PERSON", into(result), now;
1056 	assertTrue (result == people);
1057 }
1058 
1059 
testMapComplexUnique()1060 void SQLiteTest::testMapComplexUnique()
1061 {
1062 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
1063 	std::multimap<std::string, Person> people;
1064 	Person p1("LN1", "FN1", "ADDR1", 1);
1065 	Person p2("LN2", "FN2", "ADDR2", 2);
1066 	people.insert(std::make_pair("LN1", p1));
1067 	people.insert(std::make_pair("LN1", p1));
1068 	people.insert(std::make_pair("LN1", p1));
1069 	people.insert(std::make_pair("LN1", p1));
1070 	people.insert(std::make_pair("LN2", p2));
1071 	tmp << "DROP TABLE IF EXISTS Person", now;
1072 	tmp << "CREATE TABLE IF NOT EXISTS Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3))", now;
1073 	tmp << "INSERT INTO PERSON VALUES(:ln, :fn, :ad, :age)", use(people), now;
1074 	int count = 0;
1075 	tmp << "SELECT COUNT(*) FROM PERSON", into(count), now;
1076 	assertTrue (count == 5);
1077 
1078 	std::map<std::string, Person> result;
1079 	tmp << "SELECT * FROM PERSON", into(result), now;
1080 	assertTrue (result.size() == 2);
1081 }
1082 
1083 
testMultiMapComplex()1084 void SQLiteTest::testMultiMapComplex()
1085 {
1086 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
1087 	std::multimap<std::string, Person> people;
1088 	Person p1("LN1", "FN1", "ADDR1", 1);
1089 	Person p2("LN2", "FN2", "ADDR2", 2);
1090 	people.insert(std::make_pair("LN1", p1));
1091 	people.insert(std::make_pair("LN1", p1));
1092 	people.insert(std::make_pair("LN1", p1));
1093 	people.insert(std::make_pair("LN1", p1));
1094 	people.insert(std::make_pair("LN2", p2));
1095 	tmp << "DROP TABLE IF EXISTS Person", now;
1096 	tmp << "CREATE TABLE IF NOT EXISTS Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3))", now;
1097 	tmp << "INSERT INTO PERSON VALUES(:ln, :fn, :ad, :age)", use(people), now;
1098 	int count = 0;
1099 	tmp << "SELECT COUNT(*) FROM PERSON", into(count), now;
1100 	assertTrue (count == 5);
1101 
1102 	std::multimap<std::string, Person> result;
1103 	tmp << "SELECT * FROM PERSON", into(result), now;
1104 	assertTrue (result.size() == people.size());
1105 }
1106 
1107 
testSelectIntoSingle()1108 void SQLiteTest::testSelectIntoSingle()
1109 {
1110 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
1111 	std::multimap<std::string, Person> people;
1112 	Person p1("LN1", "FN1", "ADDR1", 1);
1113 	Person p2("LN2", "FN2", "ADDR2", 2);
1114 	people.insert(std::make_pair("LN1", p1));
1115 	people.insert(std::make_pair("LN1", p2));
1116 	tmp << "DROP TABLE IF EXISTS Person", now;
1117 	tmp << "CREATE TABLE IF NOT EXISTS Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3))", now;
1118 	tmp << "INSERT INTO PERSON VALUES(:ln, :fn, :ad, :age)", use(people), now;
1119 	int count = 0;
1120 	tmp << "SELECT COUNT(*) FROM PERSON", into(count), now;
1121 	assertTrue (count == 2);
1122 	Person result;
1123 	tmp << "SELECT * FROM PERSON", into(result), limit(1), now; // will return 1 object into one single result
1124 	assertTrue (result == p1);
1125 }
1126 
1127 
testSelectIntoSingleStep()1128 void SQLiteTest::testSelectIntoSingleStep()
1129 {
1130 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
1131 	std::multimap<std::string, Person> people;
1132 	Person p1("LN1", "FN1", "ADDR1", 1);
1133 	Person p2("LN2", "FN2", "ADDR2", 2);
1134 	people.insert(std::make_pair("LN1", p1));
1135 	people.insert(std::make_pair("LN1", p2));
1136 	tmp << "DROP TABLE IF EXISTS Person", now;
1137 	tmp << "CREATE TABLE IF NOT EXISTS Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3))", now;
1138 	tmp << "INSERT INTO PERSON VALUES(:ln, :fn, :ad, :age)", use(people), now;
1139 	int count = 0;
1140 	tmp << "SELECT COUNT(*) FROM PERSON", into(count), now;
1141 	assertTrue (count == 2);
1142 	Person result;
1143 	Statement stmt = (tmp << "SELECT * FROM PERSON", into(result), limit(1));
1144 	stmt.execute();
1145 	assertTrue (result == p1);
1146 	assertTrue (!stmt.done());
1147 	stmt.execute();
1148 	assertTrue (result == p2);
1149 	assertTrue (stmt.done());
1150 }
1151 
1152 
testSelectIntoSingleFail()1153 void SQLiteTest::testSelectIntoSingleFail()
1154 {
1155 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
1156 	std::multimap<std::string, Person> people;
1157 	Person p1("LN1", "FN1", "ADDR1", 1);
1158 	Person p2("LN2", "FN2", "ADDR2", 2);
1159 	people.insert(std::make_pair("LN1", p1));
1160 	people.insert(std::make_pair("LN1", p2));
1161 	tmp << "DROP TABLE IF EXISTS Person", now;
1162 	tmp << "CREATE TABLE IF NOT EXISTS Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3))", now;
1163 	tmp << "INSERT INTO PERSON VALUES(:ln, :fn, :ad, :age)", use(people), now;
1164 	int count = 0;
1165 	tmp << "SELECT COUNT(*) FROM PERSON", into(count), limit(2, true), now;
1166 	assertTrue (count == 2);
1167 	Person result;
1168 	try
1169 	{
1170 		tmp << "SELECT * FROM PERSON", into(result), limit(1, true), now; // will fail now
1171 		fail("hardLimit is set: must fail");
1172 	}
1173 	catch(Poco::Data::LimitException&)
1174 	{
1175 	}
1176 }
1177 
1178 
testLowerLimitOk()1179 void SQLiteTest::testLowerLimitOk()
1180 {
1181 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
1182 	std::multimap<std::string, Person> people;
1183 	Person p1("LN1", "FN1", "ADDR1", 1);
1184 	Person p2("LN2", "FN2", "ADDR2", 2);
1185 	people.insert(std::make_pair("LN1", p1));
1186 	people.insert(std::make_pair("LN1", p2));
1187 	tmp << "DROP TABLE IF EXISTS Person", now;
1188 	tmp << "CREATE TABLE IF NOT EXISTS Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3))", now;
1189 	tmp << "INSERT INTO PERSON VALUES(:ln, :fn, :ad, :age)", use(people), now;
1190 	int count = 0;
1191 	tmp << "SELECT COUNT(*) FROM PERSON", into(count), now;
1192 	assertTrue (count == 2);
1193 	Person result;
1194 	try
1195 	{
1196 		tmp << "SELECT * FROM PERSON", into(result), lowerLimit(2), now; // will return 2 objects into one single result but only room for one!
1197 		fail("Not enough space for results");
1198 	}
1199 	catch(Poco::Exception&)
1200 	{
1201 	}
1202 }
1203 
1204 
testSingleSelect()1205 void SQLiteTest::testSingleSelect()
1206 {
1207 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
1208 	std::multimap<std::string, Person> people;
1209 	Person p1("LN1", "FN1", "ADDR1", 1);
1210 	Person p2("LN2", "FN2", "ADDR2", 2);
1211 	people.insert(std::make_pair("LN1", p1));
1212 	people.insert(std::make_pair("LN1", p2));
1213 	tmp << "DROP TABLE IF EXISTS Person", now;
1214 	tmp << "CREATE TABLE IF NOT EXISTS Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3))", now;
1215 	tmp << "INSERT INTO PERSON VALUES(:ln, :fn, :ad, :age)", use(people), now;
1216 	int count = 0;
1217 	tmp << "SELECT COUNT(*) FROM PERSON", into(count), now;
1218 	assertTrue (count == 2);
1219 	Person result;
1220 	Statement stmt = (tmp << "SELECT * FROM PERSON", into(result), limit(1));
1221 	stmt.execute();
1222 	assertTrue (result == p1);
1223 	assertTrue (!stmt.done());
1224 	stmt.execute();
1225 	assertTrue (result == p2);
1226 	assertTrue (stmt.done());
1227 }
1228 
1229 
testLowerLimitFail()1230 void SQLiteTest::testLowerLimitFail()
1231 {
1232 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
1233 	std::multimap<std::string, Person> people;
1234 	Person p1("LN1", "FN1", "ADDR1", 1);
1235 	Person p2("LN2", "FN2", "ADDR2", 2);
1236 	people.insert(std::make_pair("LN1", p1));
1237 	people.insert(std::make_pair("LN1", p2));
1238 	tmp << "DROP TABLE IF EXISTS Person", now;
1239 	tmp << "CREATE TABLE IF NOT EXISTS Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3))", now;
1240 	tmp << "INSERT INTO PERSON VALUES(:ln, :fn, :ad, :age)", use(people), now;
1241 	int count = 0;
1242 	tmp << "SELECT COUNT(*) FROM PERSON", into(count), now;
1243 	assertTrue (count == 2);
1244 	Person result;
1245 	try
1246 	{
1247 		tmp << "SELECT * FROM PERSON", into(result), lowerLimit(3), now; // will fail
1248 		fail("should fail. not enough data");
1249 	}
1250 	catch(Poco::Exception&)
1251 	{
1252 	}
1253 }
1254 
1255 
testCombinedLimits()1256 void SQLiteTest::testCombinedLimits()
1257 {
1258 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
1259 	std::multimap<std::string, Person> people;
1260 	Person p1("LN1", "FN1", "ADDR1", 1);
1261 	Person p2("LN2", "FN2", "ADDR2", 2);
1262 	people.insert(std::make_pair("LN1", p1));
1263 	people.insert(std::make_pair("LN1", p2));
1264 	tmp << "DROP TABLE IF EXISTS Person", now;
1265 	tmp << "CREATE TABLE IF NOT EXISTS Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3))", now;
1266 	tmp << "INSERT INTO PERSON VALUES(:ln, :fn, :ad, :age)", use(people), now;
1267 
1268 	std::string a, b, c;
1269 	Statement stmt = (tmp << "SELECT LastName, FirstName, Address FROM Person WHERE Address = 'invalid value'",
1270 		into(a), into(b), into(c), limit(1));
1271 	assertTrue (!stmt.done() && stmt.execute() == 0);
1272 
1273 	int count = 0;
1274 	tmp << "SELECT COUNT(*) FROM PERSON", into(count), now;
1275 	assertTrue (count == 2);
1276 	std::vector <Person> result;
1277 	tmp << "SELECT * FROM PERSON", into(result), lowerLimit(2), upperLimit(2), now; // will return 2 objects
1278 	assertTrue (result.size() == 2);
1279 	assertTrue (result[0] == p1);
1280 	assertTrue (result[1] == p2);
1281 }
1282 
1283 
1284 
testRange()1285 void SQLiteTest::testRange()
1286 {
1287 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
1288 	std::multimap<std::string, Person> people;
1289 	Person p1("LN1", "FN1", "ADDR1", 1);
1290 	Person p2("LN2", "FN2", "ADDR2", 2);
1291 	people.insert(std::make_pair("LN1", p1));
1292 	people.insert(std::make_pair("LN1", p2));
1293 	tmp << "DROP TABLE IF EXISTS Person", now;
1294 	tmp << "CREATE TABLE IF NOT EXISTS Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3))", now;
1295 	tmp << "INSERT INTO PERSON VALUES(:ln, :fn, :ad, :age)", use(people), now;
1296 	int count = 0;
1297 	tmp << "SELECT COUNT(*) FROM PERSON", into(count), now;
1298 	assertTrue (count == 2);
1299 	std::vector <Person> result;
1300 	tmp << "SELECT * FROM PERSON", into(result), range(2, 2), now; // will return 2 objects
1301 	assertTrue (result.size() == 2);
1302 	assertTrue (result[0] == p1);
1303 	assertTrue (result[1] == p2);
1304 }
1305 
1306 
testCombinedIllegalLimits()1307 void SQLiteTest::testCombinedIllegalLimits()
1308 {
1309 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
1310 	std::multimap<std::string, Person> people;
1311 	Person p1("LN1", "FN1", "ADDR1", 1);
1312 	Person p2("LN2", "FN2", "ADDR2", 2);
1313 	people.insert(std::make_pair("LN1", p1));
1314 	people.insert(std::make_pair("LN1", p2));
1315 	tmp << "DROP TABLE IF EXISTS Person", now;
1316 	tmp << "CREATE TABLE IF NOT EXISTS Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3))", now;
1317 	tmp << "INSERT INTO PERSON VALUES(:ln, :fn, :ad, :age)", use(people), now;
1318 	int count = 0;
1319 	tmp << "SELECT COUNT(*) FROM PERSON", into(count), now;
1320 	assertTrue (count == 2);
1321 	Person result;
1322 	try
1323 	{
1324 		tmp << "SELECT * FROM PERSON", into(result), lowerLimit(3), upperLimit(2), now;
1325 		fail("lower > upper is not allowed");
1326 	}
1327 	catch(LimitException&)
1328 	{
1329 	}
1330 }
1331 
1332 
1333 
testIllegalRange()1334 void SQLiteTest::testIllegalRange()
1335 {
1336 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
1337 	std::multimap<std::string, Person> people;
1338 	Person p1("LN1", "FN1", "ADDR1", 1);
1339 	Person p2("LN2", "FN2", "ADDR2", 2);
1340 	people.insert(std::make_pair("LN1", p1));
1341 	people.insert(std::make_pair("LN1", p2));
1342 	tmp << "DROP TABLE IF EXISTS Person", now;
1343 	tmp << "CREATE TABLE IF NOT EXISTS Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3))", now;
1344 	tmp << "INSERT INTO PERSON VALUES(:ln, :fn, :ad, :age)", use(people), now;
1345 	int count = 0;
1346 	tmp << "SELECT COUNT(*) FROM PERSON", into(count), now;
1347 	assertTrue (count == 2);
1348 	Person result;
1349 	try
1350 	{
1351 		tmp << "SELECT * FROM PERSON", into(result), range(3, 2), now;
1352 		fail("lower > upper is not allowed");
1353 	}
1354 	catch(LimitException&)
1355 	{
1356 	}
1357 }
1358 
1359 
testEmptyDB()1360 void SQLiteTest::testEmptyDB()
1361 {
1362 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
1363 
1364 	tmp << "DROP TABLE IF EXISTS Person", now;
1365 	tmp << "CREATE TABLE IF NOT EXISTS Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3))", now;
1366 	int count = 0;
1367 	tmp << "SELECT COUNT(*) FROM PERSON", into(count), now;
1368 	assertTrue (count == 0);
1369 	Person result;
1370 	Statement stmt = (tmp << "SELECT * FROM PERSON", into(result), limit(1));
1371 	stmt.execute();
1372 	assertTrue (result.getFirstName().empty());
1373 	assertTrue (stmt.done());
1374 }
1375 
1376 
testCLOB()1377 void SQLiteTest::testCLOB()
1378 {
1379 	std::string lastName("lastname");
1380 	std::string firstName("firstname");
1381 	std::string address("Address");
1382 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
1383 	tmp << "DROP TABLE IF EXISTS Person", now;
1384 	tmp << "CREATE TABLE IF NOT EXISTS Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Image BLOB)", now;
1385 	CLOB img("0123456789", 10);
1386 	int count = 0;
1387 	tmp << "INSERT INTO PERSON VALUES(:ln, :fn, :ad, :img)", use(lastName), use(firstName), use(address), use(img), now;
1388 	tmp << "SELECT COUNT(*) FROM PERSON", into(count), now;
1389 	assertTrue (count == 1);
1390 	CLOB res;
1391 	poco_assert (res.size() == 0);
1392 
1393 	tmp << "SELECT Image FROM Person WHERE LastName == :ln", bind("lastname"), into(res), now;
1394 	poco_assert (res == img);
1395 
1396 	tmp << "DROP TABLE IF EXISTS BlobTest", now;
1397 	std::vector<CLOB> resVec;
1398 	const int arrSize = 10;
1399 	char val[arrSize];
1400 	for (int i = 0; i < arrSize; ++i)
1401 	{
1402 		val[i] = (char) (0x30 + i);
1403 	}
1404 
1405 	for (int i = 0; i < arrSize; ++i)
1406 	{
1407 		tmp << "CREATE TABLE IF NOT EXISTS BlobTest (idx INTEGER(2), Image BLOB)", now;
1408 		val[0] = (char) (0x30 + i);
1409 		img.assignRaw(val, arrSize);
1410 		tmp << "INSERT INTO BlobTest VALUES(?, ?)", use(i), use(img), now;
1411 	}
1412 	tmp << "SELECT Image FROM BlobTest", into(resVec), now;
1413 	poco_assert (resVec.size() == arrSize);
1414 	for (int i = 0; i < arrSize; ++i)
1415 	{
1416 		poco_assert (*resVec[i].begin() == (char) (0x30 + i));
1417 	}
1418 }
1419 
1420 
testTuple10()1421 void SQLiteTest::testTuple10()
1422 {
1423 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
1424 	tmp << "DROP TABLE IF EXISTS Tuples", now;
1425 	tmp << "CREATE TABLE Tuples "
1426 		"(int0 INTEGER, int1 INTEGER, int2 INTEGER, int3 INTEGER, int4 INTEGER, int5 INTEGER, int6 INTEGER, "
1427 		"int7 INTEGER, int8 INTEGER, int9 INTEGER)", now;
1428 
1429 	Tuple<int,int,int,int,int,int,int,int,int,int> t(0,1,2,3,4,5,6,7,8,9);
1430 
1431 	tmp << "INSERT INTO Tuples VALUES (?,?,?,?,?,?,?,?,?,?)", use(t), now;
1432 
1433 	Tuple<int,int,int,int,int,int,int,int,int,int> ret(-10,-11,-12,-13,-14,-15,-16,-17,-18,-19);
1434 	assertTrue (ret != t);
1435 	tmp << "SELECT * FROM Tuples", into(ret), now;
1436 	assertTrue (ret == t);
1437 }
1438 
1439 
testTupleVector10()1440 void SQLiteTest::testTupleVector10()
1441 {
1442 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
1443 	tmp << "DROP TABLE IF EXISTS Tuples", now;
1444 	tmp << "CREATE TABLE Tuples "
1445 		"(int0 INTEGER, int1 INTEGER, int2 INTEGER, int3 INTEGER, int4 INTEGER, int5 INTEGER, int6 INTEGER, "
1446 		"int7 INTEGER, int8 INTEGER, int9 INTEGER)", now;
1447 
1448 	Tuple<int,int,int,int,int,int,int,int,int,int> t(0,1,2,3,4,5,6,7,8,9);
1449 	Tuple<int,int,int,int,int,int,int,int,int,int> t10(10,11,12,13,14,15,16,17,18,19);
1450 	Tuple<int,int,int,int,int,int,int,int,int,int> t100(100,101,102,103,104,105,106,107,108,109);
1451 	std::vector<Tuple<int,int,int,int,int,int,int,int,int,int> > v;
1452 	v.push_back(t);
1453 	v.push_back(t10);
1454 	v.push_back(t100);
1455 
1456 	tmp << "INSERT INTO Tuples VALUES (?,?,?,?,?,?,?,?,?,?)", use(v), now;
1457 
1458 	int count = 0;
1459 	tmp << "SELECT COUNT(*) FROM Tuples", into(count), now;
1460 	assertTrue (v.size() == count);
1461 
1462 	std::vector<Tuple<int,int,int,int,int,int,int,int,int,int> > ret;
1463 	assertTrue (ret != v);
1464 	tmp << "SELECT * FROM Tuples", into(ret), now;
1465 	assertTrue (ret == v);
1466 }
1467 
1468 
testTuple9()1469 void SQLiteTest::testTuple9()
1470 {
1471 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
1472 	tmp << "DROP TABLE IF EXISTS Tuples", now;
1473 	tmp << "CREATE TABLE Tuples "
1474 		"(int0 INTEGER, int1 INTEGER, int2 INTEGER, int3 INTEGER, int4 INTEGER, int5 INTEGER, int6 INTEGER, "
1475 		"int7 INTEGER, int8 INTEGER)", now;
1476 
1477 	Tuple<int,int,int,int,int,int,int,int,int> t(0,1,2,3,4,5,6,7,8);
1478 
1479 	tmp << "INSERT INTO Tuples VALUES (?,?,?,?,?,?,?,?,?)", use(t), now;
1480 
1481 	Tuple<int,int,int,int,int,int,int,int,int> ret(-10,-11,-12,-13,-14,-15,-16,-17,-18);
1482 	assertTrue (ret != t);
1483 	tmp << "SELECT * FROM Tuples", into(ret), now;
1484 	assertTrue (ret == t);
1485 }
1486 
1487 
testTupleVector9()1488 void SQLiteTest::testTupleVector9()
1489 {
1490 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
1491 	tmp << "DROP TABLE IF EXISTS Tuples", now;
1492 	tmp << "CREATE TABLE Tuples "
1493 		"(int0 INTEGER, int1 INTEGER, int2 INTEGER, int3 INTEGER, int4 INTEGER, int5 INTEGER, int6 INTEGER, "
1494 		"int7 INTEGER, int8 INTEGER)", now;
1495 
1496 	Tuple<int,int,int,int,int,int,int,int,int> t(0,1,2,3,4,5,6,7,8);
1497 	Tuple<int,int,int,int,int,int,int,int,int> t10(10,11,12,13,14,15,16,17,18);
1498 	Tuple<int,int,int,int,int,int,int,int,int> t100(100,101,102,103,104,105,106,107,108);
1499 	std::vector<Tuple<int,int,int,int,int,int,int,int,int> > v;
1500 	v.push_back(t);
1501 	v.push_back(t10);
1502 	v.push_back(t100);
1503 
1504 	tmp << "INSERT INTO Tuples VALUES (?,?,?,?,?,?,?,?,?)", use(v), now;
1505 
1506 	int count = 0;
1507 	tmp << "SELECT COUNT(*) FROM Tuples", into(count), now;
1508 	assertTrue (v.size() == count);
1509 
1510 	std::vector<Tuple<int,int,int,int,int,int,int,int,int> > ret;
1511 	assertTrue (ret != v);
1512 	tmp << "SELECT * FROM Tuples", into(ret), now;
1513 	assertTrue (ret == v);
1514 }
1515 
1516 
testTuple8()1517 void SQLiteTest::testTuple8()
1518 {
1519 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
1520 	tmp << "DROP TABLE IF EXISTS Tuples", now;
1521 	tmp << "CREATE TABLE Tuples "
1522 		"(int0 INTEGER, int1 INTEGER, int2 INTEGER, int3 INTEGER, int4 INTEGER, int5 INTEGER, int6 INTEGER, "
1523 		"int7 INTEGER)", now;
1524 
1525 	Tuple<int,int,int,int,int,int,int,int> t(0,1,2,3,4,5,6,7);
1526 
1527 	tmp << "INSERT INTO Tuples VALUES (?,?,?,?,?,?,?,?)", use(t), now;
1528 
1529 	Tuple<int,int,int,int,int,int,int,int> ret(-10,-11,-12,-13,-14,-15,-16,-17);
1530 	assertTrue (ret != t);
1531 	tmp << "SELECT * FROM Tuples", into(ret), now;
1532 	assertTrue (ret == t);
1533 }
1534 
1535 
testTupleVector8()1536 void SQLiteTest::testTupleVector8()
1537 {
1538 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
1539 	tmp << "DROP TABLE IF EXISTS Tuples", now;
1540 	tmp << "CREATE TABLE Tuples "
1541 		"(int0 INTEGER, int1 INTEGER, int2 INTEGER, int3 INTEGER, int4 INTEGER, int5 INTEGER, int6 INTEGER, "
1542 		"int7 INTEGER)", now;
1543 
1544 	Tuple<int,int,int,int,int,int,int,int> t(0,1,2,3,4,5,6,7);
1545 	Tuple<int,int,int,int,int,int,int,int> t10(10,11,12,13,14,15,16,17);
1546 	Tuple<int,int,int,int,int,int,int,int> t100(100,101,102,103,104,105,106,107);
1547 	std::vector<Tuple<int,int,int,int,int,int,int,int> > v;
1548 	v.push_back(t);
1549 	v.push_back(t10);
1550 	v.push_back(t100);
1551 
1552 	tmp << "INSERT INTO Tuples VALUES (?,?,?,?,?,?,?,?)", use(v), now;
1553 
1554 	int count = 0;
1555 	tmp << "SELECT COUNT(*) FROM Tuples", into(count), now;
1556 	assertTrue (v.size() == count);
1557 
1558 	std::vector<Tuple<int,int,int,int,int,int,int,int> > ret;
1559 	assertTrue (ret != v);
1560 	tmp << "SELECT * FROM Tuples", into(ret), now;
1561 	assertTrue (ret == v);
1562 }
1563 
1564 
testTuple7()1565 void SQLiteTest::testTuple7()
1566 {
1567 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
1568 	tmp << "DROP TABLE IF EXISTS Tuples", now;
1569 	tmp << "CREATE TABLE Tuples "
1570 		"(int0 INTEGER, int1 INTEGER, int2 INTEGER, int3 INTEGER, int4 INTEGER, int5 INTEGER, int6 INTEGER)", now;
1571 
1572 	Tuple<int,int,int,int,int,int,int> t(0,1,2,3,4,5,6);
1573 
1574 	tmp << "INSERT INTO Tuples VALUES (?,?,?,?,?,?,?)", use(t), now;
1575 
1576 	Tuple<int,int,int,int,int,int,int> ret(-10,-11,-12,-13,-14,-15,-16);
1577 	assertTrue (ret != t);
1578 	tmp << "SELECT * FROM Tuples", into(ret), now;
1579 	assertTrue (ret == t);
1580 }
1581 
1582 
testTupleVector7()1583 void SQLiteTest::testTupleVector7()
1584 {
1585 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
1586 	tmp << "DROP TABLE IF EXISTS Tuples", now;
1587 	tmp << "CREATE TABLE Tuples "
1588 		"(int0 INTEGER, int1 INTEGER, int2 INTEGER, int3 INTEGER, int4 INTEGER, int5 INTEGER, int6 INTEGER)", now;
1589 
1590 	Tuple<int,int,int,int,int,int,int> t(0,1,2,3,4,5,6);
1591 	Tuple<int,int,int,int,int,int,int> t10(10,11,12,13,14,15,16);
1592 	Tuple<int,int,int,int,int,int,int> t100(100,101,102,103,104,105,106);
1593 	std::vector<Tuple<int,int,int,int,int,int,int> > v;
1594 	v.push_back(t);
1595 	v.push_back(t10);
1596 	v.push_back(t100);
1597 
1598 	tmp << "INSERT INTO Tuples VALUES (?,?,?,?,?,?,?)", use(v), now;
1599 
1600 	int count = 0;
1601 	tmp << "SELECT COUNT(*) FROM Tuples", into(count), now;
1602 	assertTrue (v.size() == count);
1603 
1604 	std::vector<Tuple<int,int,int,int,int,int,int> > ret;
1605 	assertTrue (ret != v);
1606 	tmp << "SELECT * FROM Tuples", into(ret), now;
1607 	assertTrue (ret == v);
1608 }
1609 
1610 
testTuple6()1611 void SQLiteTest::testTuple6()
1612 {
1613 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
1614 	tmp << "DROP TABLE IF EXISTS Tuples", now;
1615 	tmp << "CREATE TABLE Tuples "
1616 		"(int0 INTEGER, int1 INTEGER, int2 INTEGER, int3 INTEGER, int4 INTEGER, int5 INTEGER)", now;
1617 
1618 	Tuple<int,int,int,int,int,int> t(0,1,2,3,4,5);
1619 
1620 	tmp << "INSERT INTO Tuples VALUES (?,?,?,?,?,?)", use(t), now;
1621 
1622 	Tuple<int,int,int,int,int,int> ret(-10,-11,-12,-13,-14,-15);
1623 	assertTrue (ret != t);
1624 	tmp << "SELECT * FROM Tuples", into(ret), now;
1625 	assertTrue (ret == t);
1626 }
1627 
1628 
testTupleVector6()1629 void SQLiteTest::testTupleVector6()
1630 {
1631 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
1632 	tmp << "DROP TABLE IF EXISTS Tuples", now;
1633 	tmp << "CREATE TABLE Tuples "
1634 		"(int0 INTEGER, int1 INTEGER, int2 INTEGER, int3 INTEGER, int4 INTEGER, int5 INTEGER)", now;
1635 
1636 	Tuple<int,int,int,int,int,int> t(0,1,2,3,4,5);
1637 	Tuple<int,int,int,int,int,int> t10(10,11,12,13,14,15);
1638 	Tuple<int,int,int,int,int,int> t100(100,101,102,103,104,105);
1639 	std::vector<Tuple<int,int,int,int,int,int> > v;
1640 	v.push_back(t);
1641 	v.push_back(t10);
1642 	v.push_back(t100);
1643 
1644 	tmp << "INSERT INTO Tuples VALUES (?,?,?,?,?,?)", use(v), now;
1645 
1646 	int count = 0;
1647 	tmp << "SELECT COUNT(*) FROM Tuples", into(count), now;
1648 	assertTrue (v.size() == count);
1649 
1650 	std::vector<Tuple<int,int,int,int,int,int> > ret;
1651 	assertTrue (ret != v);
1652 	tmp << "SELECT * FROM Tuples", into(ret), now;
1653 	assertTrue (ret == v);
1654 }
1655 
1656 
testTuple5()1657 void SQLiteTest::testTuple5()
1658 {
1659 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
1660 	tmp << "DROP TABLE IF EXISTS Tuples", now;
1661 	tmp << "CREATE TABLE Tuples "
1662 		"(int0 INTEGER, int1 INTEGER, int2 INTEGER, int3 INTEGER, int4 INTEGER)", now;
1663 
1664 	Tuple<int,int,int,int,int> t(0,1,2,3,4);
1665 
1666 	tmp << "INSERT INTO Tuples VALUES (?,?,?,?,?)", use(t), now;
1667 
1668 	Tuple<int,int,int,int,int> ret(-10,-11,-12,-13,-14);
1669 	assertTrue (ret != t);
1670 	tmp << "SELECT * FROM Tuples", into(ret), now;
1671 	assertTrue (ret == t);
1672 }
1673 
1674 
testTupleVector5()1675 void SQLiteTest::testTupleVector5()
1676 {
1677 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
1678 	tmp << "DROP TABLE IF EXISTS Tuples", now;
1679 	tmp << "CREATE TABLE Tuples "
1680 		"(int0 INTEGER, int1 INTEGER, int2 INTEGER, int3 INTEGER, int4 INTEGER)", now;
1681 
1682 	Tuple<int,int,int,int,int> t(0,1,2,3,4);
1683 	Tuple<int,int,int,int,int> t10(10,11,12,13,14);
1684 	Tuple<int,int,int,int,int> t100(100,101,102,103,104);
1685 	std::vector<Tuple<int,int,int,int,int> > v;
1686 	v.push_back(t);
1687 	v.push_back(t10);
1688 	v.push_back(t100);
1689 
1690 	tmp << "INSERT INTO Tuples VALUES (?,?,?,?,?)", use(v), now;
1691 
1692 	int count = 0;
1693 	tmp << "SELECT COUNT(*) FROM Tuples", into(count), now;
1694 	assertTrue (v.size() == count);
1695 
1696 	std::vector<Tuple<int,int,int,int,int> > ret;
1697 	assertTrue (ret != v);
1698 	tmp << "SELECT * FROM Tuples", into(ret), now;
1699 	assertTrue (ret == v);
1700 }
1701 
1702 
testTuple4()1703 void SQLiteTest::testTuple4()
1704 {
1705 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
1706 	tmp << "DROP TABLE IF EXISTS Tuples", now;
1707 	tmp << "CREATE TABLE Tuples "
1708 		"(int0 INTEGER, int1 INTEGER, int2 INTEGER, int3 INTEGER)", now;
1709 
1710 	Tuple<int,int,int,int> t(0,1,2,3);
1711 
1712 	tmp << "INSERT INTO Tuples VALUES (?,?,?,?)", use(t), now;
1713 
1714 	Tuple<int,int,int,int> ret(-10,-11,-12,-13);
1715 	assertTrue (ret != t);
1716 	tmp << "SELECT * FROM Tuples", into(ret), now;
1717 	assertTrue (ret == t);
1718 }
1719 
1720 
testTupleVector4()1721 void SQLiteTest::testTupleVector4()
1722 {
1723 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
1724 	tmp << "DROP TABLE IF EXISTS Tuples", now;
1725 	tmp << "CREATE TABLE Tuples "
1726 		"(int0 INTEGER, int1 INTEGER, int2 INTEGER, int3 INTEGER)", now;
1727 
1728 	Tuple<int,int,int,int> t(0,1,2,3);
1729 	Tuple<int,int,int,int> t10(10,11,12,13);
1730 	Tuple<int,int,int,int> t100(100,101,102,103);
1731 	std::vector<Tuple<int,int,int,int> > v;
1732 	v.push_back(t);
1733 	v.push_back(t10);
1734 	v.push_back(t100);
1735 
1736 	tmp << "INSERT INTO Tuples VALUES (?,?,?,?)", use(v), now;
1737 
1738 	int count = 0;
1739 	tmp << "SELECT COUNT(*) FROM Tuples", into(count), now;
1740 	assertTrue (v.size() == count);
1741 
1742 	std::vector<Tuple<int,int,int,int> > ret;
1743 	assertTrue (ret != v);
1744 	tmp << "SELECT * FROM Tuples", into(ret), now;
1745 	assertTrue (ret == v);
1746 }
1747 
1748 
testTuple3()1749 void SQLiteTest::testTuple3()
1750 {
1751 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
1752 	tmp << "DROP TABLE IF EXISTS Tuples", now;
1753 	tmp << "CREATE TABLE Tuples "
1754 		"(int0 INTEGER, int1 INTEGER, int2 INTEGER)", now;
1755 
1756 	Tuple<int,int,int> t(0,1,2);
1757 
1758 	tmp << "INSERT INTO Tuples VALUES (?,?,?)", use(t), now;
1759 
1760 	Tuple<int,int,int> ret(-10,-11,-12);
1761 	assertTrue (ret != t);
1762 	tmp << "SELECT * FROM Tuples", into(ret), now;
1763 	assertTrue (ret == t);
1764 }
1765 
1766 
testTupleVector3()1767 void SQLiteTest::testTupleVector3()
1768 {
1769 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
1770 	tmp << "DROP TABLE IF EXISTS Tuples", now;
1771 	tmp << "CREATE TABLE Tuples "
1772 		"(int0 INTEGER, int1 INTEGER, int2 INTEGER)", now;
1773 
1774 	Tuple<int,int,int> t(0,1,2);
1775 	Tuple<int,int,int> t10(10,11,12);
1776 	Tuple<int,int,int> t100(100,101,102);
1777 	std::vector<Tuple<int,int,int> > v;
1778 	v.push_back(t);
1779 	v.push_back(t10);
1780 	v.push_back(t100);
1781 
1782 	tmp << "INSERT INTO Tuples VALUES (?,?,?)", use(v), now;
1783 
1784 	int count = 0;
1785 	tmp << "SELECT COUNT(*) FROM Tuples", into(count), now;
1786 	assertTrue (v.size() == count);
1787 
1788 	std::vector<Tuple<int,int,int> > ret;
1789 	assertTrue (ret != v);
1790 	tmp << "SELECT * FROM Tuples", into(ret), now;
1791 	assertTrue (ret == v);
1792 }
1793 
1794 
testTuple2()1795 void SQLiteTest::testTuple2()
1796 {
1797 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
1798 	tmp << "DROP TABLE IF EXISTS Tuples", now;
1799 	tmp << "CREATE TABLE Tuples (int0 INTEGER, int1 INTEGER)", now;
1800 
1801 	Tuple<int,int> t(0,1);
1802 
1803 	tmp << "INSERT INTO Tuples VALUES (?,?)", use(t), now;
1804 
1805 	Tuple<int,int> ret(-10,-11);
1806 	assertTrue (ret != t);
1807 	tmp << "SELECT * FROM Tuples", into(ret), now;
1808 	assertTrue (ret == t);
1809 }
1810 
1811 
testTupleVector2()1812 void SQLiteTest::testTupleVector2()
1813 {
1814 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
1815 	tmp << "DROP TABLE IF EXISTS Tuples", now;
1816 	tmp << "CREATE TABLE Tuples (int0 INTEGER, int1 INTEGER)", now;
1817 
1818 	Tuple<int,int> t(0,1);
1819 	Tuple<int,int> t10(10,11);
1820 	Tuple<int,int> t100(100,101);
1821 	std::vector<Tuple<int,int> > v;
1822 	v.push_back(t);
1823 	v.push_back(t10);
1824 	v.push_back(t100);
1825 
1826 	tmp << "INSERT INTO Tuples VALUES (?,?)", use(v), now;
1827 
1828 	int count = 0;
1829 	tmp << "SELECT COUNT(*) FROM Tuples", into(count), now;
1830 	assertTrue (v.size() == count);
1831 
1832 	std::vector<Tuple<int,int> > ret;
1833 	assertTrue (ret != v);
1834 	tmp << "SELECT * FROM Tuples", into(ret), now;
1835 	assertTrue (ret == v);
1836 }
1837 
1838 
testTuple1()1839 void SQLiteTest::testTuple1()
1840 {
1841 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
1842 	tmp << "DROP TABLE IF EXISTS Tuples", now;
1843 	tmp << "CREATE TABLE Tuples (int0 INTEGER)", now;
1844 
1845 	Tuple<int> t(0);
1846 
1847 	tmp << "INSERT INTO Tuples VALUES (?)", use(t), now;
1848 
1849 	Tuple<int> ret(-10);
1850 	assertTrue (ret != t);
1851 	tmp << "SELECT * FROM Tuples", into(ret), now;
1852 	assertTrue (ret == t);
1853 }
1854 
1855 
testTupleVector1()1856 void SQLiteTest::testTupleVector1()
1857 {
1858 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
1859 	tmp << "DROP TABLE IF EXISTS Tuples", now;
1860 	tmp << "CREATE TABLE Tuples (int0 INTEGER)", now;
1861 
1862 	Tuple<int> t(0);
1863 	Tuple<int> t10(10);
1864 	Tuple<int> t100(100);
1865 	std::vector<Tuple<int> > v;
1866 	v.push_back(t);
1867 	v.push_back(t10);
1868 	v.push_back(t100);
1869 
1870 	tmp << "INSERT INTO Tuples VALUES (?)", use(v), now;
1871 
1872 	int count = 0;
1873 	tmp << "SELECT COUNT(*) FROM Tuples", into(count), now;
1874 	assertTrue (v.size() == count);
1875 
1876 	std::vector<Tuple<int> > ret;
1877 	assertTrue (ret != v);
1878 	tmp << "SELECT * FROM Tuples", into(ret), now;
1879 	assertTrue (ret == v);
1880 }
1881 
1882 
testDateTime()1883 void SQLiteTest::testDateTime()
1884 {
1885 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
1886 	tmp << "DROP TABLE IF EXISTS DateTimes", now;
1887 	tmp << "CREATE TABLE DateTimes (dt0 DATE)", now;
1888 
1889 	DateTime dt(1965, 6, 18, 5, 35, 1);
1890 	tmp << "INSERT INTO DateTimes VALUES (?)", use(dt), now;
1891 
1892 	DateTime rdt;
1893 	assertTrue (rdt != dt);
1894 	tmp << "SELECT * FROM DateTimes", into(rdt), now;
1895 	assertTrue (rdt == dt);
1896 
1897 	tmp << "DELETE FROM DateTimes", now;
1898 
1899 	Date d(dt);
1900 	tmp << "INSERT INTO DateTimes VALUES (?)", use(d), now;
1901 
1902 	Date rd;
1903 	assertTrue (rd != d);
1904 	tmp << "SELECT * FROM DateTimes", into(rd), now;
1905 	assertTrue (rd == d);
1906 
1907 	tmp << "DELETE FROM DateTimes", now;
1908 
1909 	Time t(dt);
1910 	tmp << "INSERT INTO DateTimes VALUES (?)", use(t), now;
1911 
1912 	Time rt;
1913 	assertTrue (rt != t);
1914 	tmp << "SELECT * FROM DateTimes", into(rt), now;
1915 	assertTrue (rt == t);
1916 }
1917 
1918 
testInternalExtraction()1919 void SQLiteTest::testInternalExtraction()
1920 {
1921 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
1922 	tmp << "DROP TABLE IF EXISTS Vectors", now;
1923 	tmp << "CREATE TABLE Vectors (int0 INTEGER, flt0 REAL, str0 VARCHAR)", now;
1924 
1925 	std::vector<Tuple<int, double, std::string> > v;
1926 	v.push_back(Tuple<int, double, std::string>(1, 1.5, "3"));
1927 	v.push_back(Tuple<int, double, std::string>(2, 2.5, "4"));
1928 	v.push_back(Tuple<int, double, std::string>(3, 3.5, "5"));
1929 	v.push_back(Tuple<int, double, std::string>(4, 4.5, "6"));
1930 
1931 	tmp << "INSERT INTO Vectors VALUES (?,?,?)", use(v), now;
1932 
1933 	Statement stmt = (tmp << "SELECT * FROM Vectors", now);
1934 	RecordSet rset(stmt);
1935 	assertTrue (3 == rset.columnCount());
1936 	assertTrue (4 == rset.rowCount());
1937 
1938 	RecordSet rset2(rset);
1939 	assertTrue (3 == rset2.columnCount());
1940 	assertTrue (4 == rset2.rowCount());
1941 
1942 	Int32 a = static_cast<Int32>(rset.value<Int64>(0,2));
1943 	assertTrue (3 == a);
1944 
1945 	int c = rset2.value(0);
1946 	assertTrue (1 == c);
1947 
1948 	Int32 b = static_cast<Int32>(rset2.value<Int64>("InT0",2));
1949 	assertTrue (3 == b);
1950 
1951 	double d = rset.value<double>(1,0);
1952 	assertTrue (1.5 == d);
1953 
1954 	std::string s = rset.value<std::string>(2,1);
1955 	assertTrue ("4" == s);
1956 
1957 	typedef std::deque<Int64> IntDeq;
1958 
1959 	const Column<IntDeq>& col = rset.column<IntDeq>(0);
1960 	assertTrue (col[0] == 1);
1961 
1962 	try { rset.column<IntDeq>(100); fail ("must fail"); }
1963 	catch (RangeException&) { }
1964 
1965 	const Column<IntDeq>& col1 = rset.column<IntDeq>(0);
1966 	assertTrue ("int0" == col1.name());
1967 	Column<IntDeq>::Iterator it = col1.begin();
1968 	Column<IntDeq>::Iterator itEnd = col1.end();
1969 	int counter = 1;
1970 	for (; it != itEnd; ++it, ++counter)
1971 		assertTrue (counter == *it);
1972 
1973 	rset = (tmp << "SELECT COUNT(*) FROM Vectors", now);
1974 	s = rset.value<std::string>(0,0);
1975 	assertTrue ("4" == s);
1976 
1977 	stmt = (tmp << "DELETE FROM Vectors", now);
1978 	rset = stmt;
1979 
1980 	try { rset.column<IntDeq>(0); fail ("must fail"); }
1981 	catch (RangeException&) { }
1982 }
1983 
1984 
testPrimaryKeyConstraint()1985 void SQLiteTest::testPrimaryKeyConstraint()
1986 {
1987 	Session ses (Poco::Data::SQLite::Connector::KEY, "dummy.db");
1988 	ses << "DROP TABLE IF EXISTS LogTest", now;
1989 	ses << "CREATE TABLE LogTest (Id INTEGER PRIMARY KEY, Time INTEGER, Value INTEGER)", now;
1990 	const double value = -200000000000.0;
1991 	const Poco::Int64 timeIn = static_cast<Poco::Int64>(22329988776655.0);
1992 	int id = 1;
1993 
1994 	ses.begin();
1995 
1996 	for(int i = 0; i < 10; i++)
1997 	{
1998 		try
1999 		{
2000 			ses << "INSERT INTO LogTest (Id, [Time], Value) VALUES (:id, :time, :value)", use(id), bind(timeIn), bind(value), now; //lint !e1058
2001 			if (i > 0)
2002 				fail("must fail");
2003 		}
2004 		catch(Poco::Exception&)
2005 		{
2006 			if (i == 0) // the very first insert must work
2007 				throw;
2008 		}
2009 	}
2010 
2011 	ses.commit();
2012 }
2013 
2014 
testNullable()2015 void SQLiteTest::testNullable()
2016 {
2017 	Session ses (Poco::Data::SQLite::Connector::KEY, "dummy.db");
2018 	ses << "DROP TABLE IF EXISTS NullableTest", now;
2019 
2020 	ses << "CREATE TABLE NullableTest (i INTEGER, r REAL, s VARCHAR, d DATETIME)", now;
2021 
2022 	ses << "INSERT INTO NullableTest VALUES(:i, :r, :s, :d)", use(null), use(null), use(null), use(null), now;
2023 
2024 	Nullable<int> i = 1;
2025 	Nullable<double> f = 1.5;
2026 	Nullable<std::string> s = std::string("abc");
2027 	Nullable<DateTime> d = DateTime();
2028 
2029 	assertTrue (!i.isNull());
2030 	assertTrue (!f.isNull());
2031 	assertTrue (!s.isNull());
2032 	assertTrue (!d.isNull());
2033 
2034 	ses << "SELECT i, r, s, d FROM NullableTest", into(i), into(f), into(s), into(d), now;
2035 
2036 	assertTrue (i.isNull());
2037 	assertTrue (f.isNull());
2038 	assertTrue (s.isNull());
2039 	assertTrue (d.isNull());
2040 
2041 	RecordSet rs(ses, "SELECT * FROM NullableTest");
2042 
2043 	rs.moveFirst();
2044 	assertTrue (rs.isNull("i"));
2045 	assertTrue (rs.isNull("r"));
2046 	assertTrue (rs.isNull("s"));
2047 	assertTrue (rs.isNull("d"));
2048 
2049 	Var di = 1;
2050 	Var df = 1.5;
2051 	Var ds = "abc";
2052 	Var dd = DateTime();
2053 
2054 	assertTrue (!di.isEmpty());
2055 	assertTrue (!df.isEmpty());
2056 	assertTrue (!ds.isEmpty());
2057 	assertTrue (!dd.isEmpty());
2058 
2059 	ses << "SELECT i, r, s, d FROM NullableTest", into(di), into(df), into(ds), into(dd), now;
2060 
2061 	assertTrue (di.isEmpty());
2062 	assertTrue (df.isEmpty());
2063 	assertTrue (ds.isEmpty());
2064 	assertTrue (dd.isEmpty());
2065 }
2066 
2067 
testNulls()2068 void SQLiteTest::testNulls()
2069 {
2070 	Session ses (Poco::Data::SQLite::Connector::KEY, "dummy.db");
2071 	ses << "DROP TABLE IF EXISTS NullTest", now;
2072 
2073 	ses << "CREATE TABLE NullTest (i INTEGER NOT NULL)", now;
2074 
2075 	try
2076 	{
2077 		ses << "INSERT INTO NullTest VALUES(:i)", use(null), now;
2078 		fail ("must fail");
2079 	}catch (ConstraintViolationException&) { }
2080 
2081 	ses << "DROP TABLE IF EXISTS NullTest", now;
2082 	ses << "CREATE TABLE NullTest (i INTEGER, r REAL, v VARCHAR)", now;
2083 
2084 	ses << "INSERT INTO NullTest VALUES(:i, :r, :v)", use(null), use(null), use(null), now;
2085 
2086 	RecordSet rs(ses, "SELECT i, r, v, null as e FROM NullTest");
2087 	rs.moveFirst();
2088 	assertTrue (rs.isNull("i"));
2089 	assertTrue (rs["i"].isEmpty());
2090 	assertTrue (rs.isNull("r"));
2091 	assertTrue (rs.isNull("v"));
2092 	assertTrue (rs["v"].isEmpty());
2093 	assertTrue (rs["e"].isEmpty());
2094 
2095 	assertTrue (rs[0].isEmpty());
2096 	assertTrue (rs[1].isEmpty());
2097 	assertTrue (rs[2].isEmpty());
2098 	assertTrue (rs[3].isEmpty());
2099 
2100 	ses << "DROP TABLE IF EXISTS NullTest", now;
2101 	ses << "CREATE TABLE NullTest (i INTEGER, r REAL, v VARCHAR)", now;
2102 	int i = 1;
2103 	double f = 1.2;
2104 	std::string s = "123";
2105 
2106 	ses << "INSERT INTO NullTest (i, r, v) VALUES (:i, :r, :v)", use(i), use(f), use(s), now;
2107 	rs = (ses << "SELECT * FROM NullTest", now);
2108 	rs.moveFirst();
2109 	assertTrue (!rs.isNull("i"));
2110 	assertTrue (rs["i"] == 1);
2111 	assertTrue (!rs.isNull("v"));
2112 	assertTrue (!rs.isNull("r"));
2113 	assertTrue (rs["v"] == "123");
2114 
2115 	ses << "UPDATE NullTest SET v = :n WHERE i == :i", use(null), use(i), now;
2116 	i = 2;
2117 	f = 3.4;
2118 	ses << "INSERT INTO NullTest (i, r, v) VALUES (:i, :r, :v)", use(i), use(null), use(null), now;
2119 	rs = (ses << "SELECT i, r, v FROM NullTest ORDER BY i ASC", now);
2120 	rs.moveFirst();
2121 	assertTrue (!rs.isNull("i"));
2122 	assertTrue (rs["i"] == 1);
2123 	assertTrue (!rs.isNull("r"));
2124 	assertTrue (rs.isNull("v"));
2125 	assertTrue (rs["v"].isEmpty());
2126 
2127 	assertTrue (rs.moveNext());
2128 	assertTrue (!rs.isNull("i"));
2129 	assertTrue (rs["i"] == 2);
2130 	Poco::Int64 i64 = 0;
2131 	assertTrue (rs.nvl("i", i64) == 2);
2132 	assertTrue (rs.nvl("i", 123) == 2);
2133 
2134 	assertTrue (rs.isNull("r"));
2135 	assertTrue (rs.nvl("r", 123) == 123);
2136 	assertTrue (rs.nvl("r", 1.5) == 1.5);
2137 
2138 	assertTrue (rs.isNull("v"));
2139 	assertTrue (rs["v"].isEmpty());
2140 	assertTrue (rs.nvl("v", s) == "123");
2141 }
2142 
2143 
testRowIterator()2144 void SQLiteTest::testRowIterator()
2145 {
2146 	Session ses (Poco::Data::SQLite::Connector::KEY, "dummy.db");
2147 	ses << "DROP TABLE IF EXISTS Vectors", now;
2148 	ses << "CREATE TABLE Vectors (int0 INTEGER, flt0 REAL, str0 VARCHAR)", now;
2149 
2150 	std::vector<Tuple<int, double, std::string> > v;
2151 	v.push_back(Tuple<int, double, std::string>(1, 1.5f, "3"));
2152 	v.push_back(Tuple<int, double, std::string>(2, 2.5f, "4"));
2153 	v.push_back(Tuple<int, double, std::string>(3, 3.5f, "5"));
2154 	v.push_back(Tuple<int, double, std::string>(4, 4.5f, "6"));
2155 
2156 	ses << "INSERT INTO Vectors VALUES (?,?,?)", use(v), now;
2157 
2158 	RecordSet rset(ses, "SELECT * FROM Vectors");
2159 
2160 	std::ostringstream osLoop;
2161 	RecordSet::ConstIterator it = rset.begin();
2162 	RecordSet::ConstIterator end = rset.end();
2163 	for (int i = 1; it != end; ++it, ++i)
2164 	{
2165 		assertTrue (it->get(0) == i);
2166 		osLoop << *it;
2167 	}
2168 	assertTrue (!osLoop.str().empty());
2169 
2170 	std::ostringstream osCopy;
2171 	std::copy(rset.begin(), rset.end(), std::ostream_iterator<Row>(osCopy));
2172 	assertTrue (osLoop.str() == osCopy.str());
2173 }
2174 
2175 
testAsync()2176 void SQLiteTest::testAsync()
2177 {
2178 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
2179 	tmp << "DROP TABLE IF EXISTS Strings", now;
2180 	tmp << "CREATE TABLE IF NOT EXISTS Strings (str INTEGER(10))", now;
2181 
2182 	int rowCount = 500;
2183 	std::vector<int> data(rowCount);
2184 	Statement stmt = (tmp << "INSERT INTO Strings VALUES(:str)", use(data));
2185 	Statement::Result result = stmt.executeAsync();
2186 	assertTrue (!stmt.isAsync());
2187 	result.wait();
2188 	assertTrue (500 == result.data());
2189 
2190 	Statement stmt1 = (tmp << "SELECT * FROM Strings", into(data), async, now);
2191 	assertTrue (stmt1.isAsync());
2192 	assertTrue (stmt1.wait() == rowCount);
2193 
2194 	stmt1.execute();
2195 	try
2196 	{
2197 		stmt1.execute();
2198 		fail ("must fail");
2199 	}
2200 	catch (InvalidAccessException&)
2201 	{
2202 		stmt1.wait();
2203 		stmt1.execute();
2204 		stmt1.wait();
2205 	}
2206 
2207 	stmt = tmp << "SELECT * FROM Strings", into(data), async, now;
2208 	assertTrue (stmt.isAsync());
2209 	stmt.wait();
2210 
2211 	assertTrue (stmt.execute() == 0);
2212 	assertTrue (stmt.isAsync());
2213 	try
2214 	{
2215 		result = stmt.executeAsync();
2216 		fail ("must fail");
2217 	}
2218 	catch (InvalidAccessException&)
2219 	{
2220 		stmt.wait();
2221 		result = stmt.executeAsync();
2222 	}
2223 
2224 	assertTrue (stmt.wait() == rowCount);
2225 	assertTrue (result.data() == rowCount);
2226 	stmt.setAsync(false);
2227 	assertTrue (!stmt.isAsync());
2228 	assertTrue (stmt.execute() == rowCount);
2229 
2230 	stmt = tmp << "SELECT * FROM Strings", into(data), sync, now;
2231 	assertTrue (!stmt.isAsync());
2232 	assertTrue (stmt.wait() == 0);
2233 	assertTrue (stmt.execute() == rowCount);
2234 	result = stmt.executeAsync();
2235 	assertTrue (!stmt.isAsync());
2236 	result.wait();
2237 	assertTrue (result.data() == rowCount);
2238 
2239 	assertTrue (0 == rowCount % 10);
2240 	int step = (int) (rowCount/10);
2241 	data.clear();
2242 	Statement stmt2 = (tmp << "SELECT * FROM Strings", into(data), async, limit(step));
2243 	assertTrue (data.size() == 0);
2244 	assertTrue (!stmt2.done());
2245 	std::size_t rows = 0;
2246 
2247 	for (int i = 0; !stmt2.done(); i += step)
2248 	{
2249 		stmt2.execute();
2250 		rows = stmt2.wait();
2251 		assertTrue (step == rows);
2252 		assertTrue (step + i == data.size());
2253 	}
2254 	assertTrue (stmt2.done());
2255 	assertTrue (rowCount == data.size());
2256 
2257 	stmt2 = tmp << "SELECT * FROM Strings", reset;
2258 	assertTrue (!stmt2.isAsync());
2259 	assertTrue ("deque" == stmt2.getStorage());
2260 	assertTrue (stmt2.execute() == rowCount);
2261 }
2262 
2263 
testAny()2264 void SQLiteTest::testAny()
2265 {
2266 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
2267 	tmp << "DROP TABLE IF EXISTS Anys", now;
2268 	tmp << "CREATE TABLE Anys (int0 INTEGER, flt0 REAL, str0 VARCHAR)", now;
2269 
2270 	Any i = Int32(42);
2271 	Any f = double(42.5);
2272 	Any s = std::string("42");
2273 
2274 	tmp << "INSERT INTO Anys VALUES (?, ?, ?)", use(i), use(f), use(s), now;
2275 
2276 	int count = 0;
2277 	tmp << "SELECT COUNT(*) FROM Anys", into(count), now;
2278 	assertTrue (1 == count);
2279 
2280 	i = 0;
2281 	f = 0.0;
2282 	s = std::string("");
2283 	tmp << "SELECT * FROM Anys", into(i), into(f), into(s), now;
2284 	assertTrue (AnyCast<Int64>(i) == 42);
2285 	assertTrue (AnyCast<double>(f) == 42.5);
2286 	assertTrue (AnyCast<std::string>(s) == "42");
2287 }
2288 
2289 
testDynamicAny()2290 void SQLiteTest::testDynamicAny()
2291 {
2292 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
2293 	tmp << "DROP TABLE IF EXISTS Anys", now;
2294 	tmp << "CREATE TABLE Anys (int0 INTEGER, flt0 REAL, str0 VARCHAR, empty INTEGER)", now;
2295 
2296 	DynamicAny i = Int32(42);
2297 	DynamicAny f = double(42.5);
2298 	DynamicAny s = std::string("42");
2299 	DynamicAny e;
2300 	assertTrue (e.isEmpty());
2301 
2302 	tmp << "INSERT INTO Anys VALUES (?, ?, ?, null)", use(i), use(f), use(s), now;
2303 
2304 	int count = 0;
2305 	tmp << "SELECT COUNT(*) FROM Anys", into(count), now;
2306 	assertTrue (1 == count);
2307 
2308 	i = 0;
2309 	f = 0.0;
2310 	s = std::string("");
2311 	e = 1;
2312 	assertTrue (!e.isEmpty());
2313 	tmp << "SELECT * FROM Anys", into(i), into(f), into(s), into(e), now;
2314 	assertTrue (42 == i);
2315 	assertTrue (42.5 == f);
2316 	assertTrue ("42" == s);
2317 	assertTrue (e.isEmpty());
2318 }
2319 
2320 
testPair()2321 void SQLiteTest::testPair()
2322 {
2323 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
2324 	assertTrue (tmp.isConnected());
2325 	std::string tableName("Simpsons");
2326 	std::pair<std::string, int> junior = std::make_pair("Junior", 12);
2327 	std::pair<std::string, int> senior = std::make_pair("Senior", 99);
2328 
2329 	int count = 0;
2330 	std::string result;
2331 
2332 	tmp << "DROP TABLE IF EXISTS Simpsons", now;
2333 	tmp << "CREATE TABLE IF NOT EXISTS Simpsons (LastName VARCHAR(30), Age INTEGER(3))", now;
2334 	tmp << "SELECT name FROM sqlite_master WHERE tbl_name=?", use(tableName), into(result), now;
2335 	assertTrue (result == tableName);
2336 
2337 	// these are fine
2338 	tmp << "INSERT INTO Simpsons VALUES(?, ?)", use(junior), now;
2339 	tmp << "INSERT INTO Simpsons VALUES(?, ?)", useRef(senior), now;
2340 
2341 	tmp << "SELECT COUNT(*) FROM Simpsons", into(count), now;
2342 	assertTrue (2 == count);
2343 
2344 	std::vector<std::pair<std::string, int> > ret;
2345 	tmp << "SELECT * FROM Simpsons", into(ret), range(2,2), now;
2346 	assertTrue (ret[0].second == 12 || ret[1].second == 12);
2347 	assertTrue (ret[0].second == 99 || ret[1].second == 99);
2348 	assertTrue (ret[0].first == "Junior" || ret[1].first == "Junior");
2349 	assertTrue (ret[0].first == "Senior" || ret[1].first == "Senior");
2350 }
2351 
2352 
testSQLChannel()2353 void SQLiteTest::testSQLChannel()
2354 {
2355 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
2356 	tmp << "DROP TABLE IF EXISTS T_POCO_LOG", now;
2357 	tmp << "CREATE TABLE T_POCO_LOG (Source VARCHAR,"
2358 		"Name VARCHAR,"
2359 		"ProcessId INTEGER,"
2360 		"Thread VARCHAR, "
2361 		"ThreadId INTEGER,"
2362 		"Priority INTEGER,"
2363 		"Text VARCHAR,"
2364 		"DateTime DATE)", now;
2365 
2366 	tmp << "DROP TABLE IF EXISTS T_POCO_LOG_ARCHIVE", now;
2367 	tmp << "CREATE TABLE T_POCO_LOG_ARCHIVE (Source VARCHAR,"
2368 		"Name VARCHAR,"
2369 		"ProcessId INTEGER,"
2370 		"Thread VARCHAR, "
2371 		"ThreadId INTEGER,"
2372 		"Priority INTEGER,"
2373 		"Text VARCHAR,"
2374 		"DateTime DATE)", now;
2375 
2376 	AutoPtr<SQLChannel> pChannel = new SQLChannel(Poco::Data::SQLite::Connector::KEY, "dummy.db", "TestSQLChannel");
2377 	pChannel->setProperty("keep", "2 seconds");
2378 
2379 	Message msgInf("InformationSource", "a Informational async message", Message::PRIO_INFORMATION);
2380 	pChannel->log(msgInf);
2381 	Message msgWarn("WarningSource", "b Warning async message", Message::PRIO_WARNING);
2382 	pChannel->log(msgWarn);
2383 	pChannel->wait();
2384 
2385 	pChannel->setProperty("async", "false");
2386 	Message msgInfS("InformationSource", "c Informational sync message", Message::PRIO_INFORMATION);
2387 	pChannel->log(msgInfS);
2388 	Message msgWarnS("WarningSource", "d Warning sync message", Message::PRIO_WARNING);
2389 	pChannel->log(msgWarnS);
2390 
2391 	RecordSet rs(tmp, "SELECT * FROM T_POCO_LOG ORDER by Text");
2392 	assertTrue (4 == rs.rowCount());
2393 	assertTrue ("InformationSource" == rs["Source"]);
2394 	assertTrue ("a Informational async message" == rs["Text"]);
2395 	rs.moveNext();
2396 	assertTrue ("WarningSource" == rs["Source"]);
2397 	assertTrue ("b Warning async message" == rs["Text"]);
2398 	rs.moveNext();
2399 	assertTrue ("InformationSource" == rs["Source"]);
2400 	assertTrue ("c Informational sync message" == rs["Text"]);
2401 	rs.moveNext();
2402 	assertTrue ("WarningSource" == rs["Source"]);
2403 	assertTrue ("d Warning sync message" == rs["Text"]);
2404 
2405 	Thread::sleep(3000);
2406 
2407 	Message msgInfA("InformationSource", "e Informational sync message", Message::PRIO_INFORMATION);
2408 	pChannel->log(msgInfA);
2409 	Message msgWarnA("WarningSource", "f Warning sync message", Message::PRIO_WARNING);
2410 	pChannel->log(msgWarnA);
2411 
2412 	RecordSet rs1(tmp, "SELECT * FROM T_POCO_LOG_ARCHIVE");
2413 	assertTrue (4 == rs1.rowCount());
2414 
2415 	pChannel->setProperty("keep", "");
2416 	assertTrue ("forever" == pChannel->getProperty("keep"));
2417 	RecordSet rs2(tmp, "SELECT * FROM T_POCO_LOG ORDER by Text");
2418 	assertTrue (2 == rs2.rowCount());
2419 	assertTrue ("InformationSource" == rs2["Source"]);
2420 	assertTrue ("e Informational sync message" == rs2["Text"]);
2421 	rs2.moveNext();
2422 	assertTrue ("WarningSource" == rs2["Source"]);
2423 	assertTrue ("f Warning sync message" == rs2["Text"]);
2424 }
2425 
2426 
testSQLLogger()2427 void SQLiteTest::testSQLLogger()
2428 {
2429 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
2430 	tmp << "DROP TABLE IF EXISTS T_POCO_LOG", now;
2431 	tmp << "CREATE TABLE T_POCO_LOG (Source VARCHAR,"
2432 		"Name VARCHAR,"
2433 		"ProcessId INTEGER,"
2434 		"Thread VARCHAR, "
2435 		"ThreadId INTEGER,"
2436 		"Priority INTEGER,"
2437 		"Text VARCHAR,"
2438 		"DateTime DATE)", now;
2439 
2440 	{
2441 		AutoPtr<SQLChannel> pChannel = new SQLChannel(Poco::Data::SQLite::Connector::KEY, "dummy.db", "TestSQLChannel");
2442 		Logger& root = Logger::root();
2443 		root.setChannel(pChannel);
2444 		root.setLevel(Message::PRIO_INFORMATION);
2445 
2446 		root.information("Informational message");
2447 		root.warning("Warning message");
2448 		root.debug("Debug message");
2449 	}
2450 
2451 	Thread::sleep(100);
2452 	RecordSet rs(tmp, "SELECT * FROM T_POCO_LOG ORDER by DateTime");
2453 	assertTrue (2 == rs.rowCount());
2454 	assertTrue ("TestSQLChannel" == rs["Source"]);
2455 	assertTrue ("Informational message" == rs["Text"]);
2456 	rs.moveNext();
2457 	assertTrue ("TestSQLChannel" == rs["Source"]);
2458 	assertTrue ("Warning message" == rs["Text"]);
2459 }
2460 
2461 
testExternalBindingAndExtraction()2462 void SQLiteTest::testExternalBindingAndExtraction()
2463 {
2464 	AbstractExtractionVecVec extractionVec;
2465 	AbstractExtractionVec extraction;
2466 	AbstractBindingVec binding;
2467 
2468 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
2469 
2470 	tmp << "DROP TABLE IF EXISTS Ints", now;
2471 	tmp << "CREATE TABLE Ints (int0 INTEGER, int1 INTEGER, int2 INTEGER)", now;
2472 
2473 	int x = 1, y = 2, z = 3;
2474 	binding.push_back(use(x));
2475 	binding.push_back(use(y));
2476 	binding.push_back(use(z));
2477 
2478 	tmp << "INSERT INTO Ints VALUES (?,?,?)", use(binding), now;
2479 
2480 	Poco::Int64 a = 0, b = 0, c = 0;
2481 	extraction.push_back(into(a));
2482 	extraction.push_back(into(b));
2483 	extraction.push_back(into(c));
2484 	tmp << "SELECT * FROM Ints", into(extraction), now;
2485 	assertTrue (a == x);
2486 	assertTrue (b == y);
2487 	assertTrue (c == z);
2488 
2489 	a = 0, b = 0, c = 0;
2490 	extractionVec.push_back(extraction);
2491 	tmp << "SELECT * FROM Ints", into(extractionVec), now;
2492 	assertTrue (a == x);
2493 	assertTrue (b == y);
2494 	assertTrue (c == z);
2495 }
2496 
2497 
testBindingCount()2498 void SQLiteTest::testBindingCount()
2499 {
2500 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
2501 
2502 	tmp << "DROP TABLE IF EXISTS Ints", now;
2503 	tmp << "CREATE TABLE Ints (int0 INTEGER)", now;
2504 
2505 	int i = 42;
2506 	try { tmp << "INSERT INTO Ints VALUES (?)", now; fail("must fail"); }
2507 	catch (ParameterCountMismatchException&) { }
2508 	tmp << "INSERT INTO Ints VALUES (?)", use(i), now;
2509 
2510 	i = 0;
2511 	try { tmp << "SELECT int0 from Ints where int0 = ?", into(i), now; fail("must fail"); }
2512 	catch (ParameterCountMismatchException&) { }
2513 	tmp << "SELECT int0 from Ints where int0 = ?", bind(42), into(i), now;
2514 	assertTrue (42 == i);
2515 
2516 	tmp << "DROP TABLE IF EXISTS Ints", now;
2517 	tmp << "CREATE TABLE Ints (int0 INTEGER, int1 INTEGER, int2 INTEGER)", now;
2518 
2519 	try { tmp << "INSERT INTO Ints VALUES (?,?,?)", bind(42), bind(42), now; fail("must fail"); }
2520 	catch (ParameterCountMismatchException&) { }
2521 }
2522 
2523 
testMultipleResults()2524 void SQLiteTest::testMultipleResults()
2525 {
2526 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
2527 
2528 	tmp << "DROP TABLE IF EXISTS Person", now;
2529 	tmp << "CREATE TABLE Person (LastName VARCHAR(30),"
2530 		"FirstName VARCHAR(30),"
2531 		"Address VARCHAR(30),"
2532 		"Age INTEGER)", now;
2533 
2534 	typedef Tuple<std::string, std::string, std::string, Poco::UInt32> Person;
2535 	std::vector<Person> people, people2;
2536 	people.push_back(Person("Simpson", "Homer", "Springfield", 42));
2537 	people.push_back(Person("Simpson", "Bart", "Springfield", 12));
2538 	people.push_back(Person("Simpson", "Lisa", "Springfield", 10));
2539 
2540 	Person pHomer;
2541 	int aHomer = 42, aLisa = 10;
2542 	Poco::UInt32 aBart = 0;
2543 
2544 	Poco::UInt32 pos1 = 1;
2545 	int pos2 = 2;
2546 
2547 	Statement stmt(tmp);
2548 	stmt << "INSERT INTO Person VALUES (?, ?, ?, ?);"
2549 		"SELECT * FROM Person WHERE Age = ?; "
2550 		"SELECT Age FROM Person WHERE FirstName = 'Bart'; "
2551 		"SELECT * FROM Person WHERE Age = ? OR Age = ? ORDER BY Age;"
2552 		, use(people)
2553 		, into(pHomer, from(0)), use(aHomer)
2554 		, into(aBart, pos1)
2555 		, into(people2, from(pos2)), use(aLisa), use(aHomer);
2556 
2557 	assertTrue (7 == stmt.execute());
2558 	assertTrue (Person("Simpson", "Homer", "Springfield", 42) == pHomer);
2559 	assertTrue (12 == aBart);
2560 	assertTrue (2 == people2.size());
2561 	assertTrue (Person("Simpson", "Lisa", "Springfield", 10) == people2[0]);
2562 	assertTrue (Person("Simpson", "Homer", "Springfield", 42) == people2[1]);
2563 }
2564 
2565 
testReconnect()2566 void SQLiteTest::testReconnect()
2567 {
2568 	Session session (Poco::Data::SQLite::Connector::KEY, "dummy.db");
2569 
2570 	session << "DROP TABLE IF EXISTS Person", now;
2571 	session << "CREATE TABLE Person (LastName VARCHAR(30),"
2572 		"FirstName VARCHAR(30),"
2573 		"Address VARCHAR(30),"
2574 		"Age INTEGER)", now;
2575 
2576 	std::string lastName = "lastName";
2577 	std::string firstName("firstName");
2578 	std::string address("Address");
2579 	int age = 133132;
2580 	int count = 0;
2581 	std::string result;
2582 
2583 	session << "INSERT INTO PERSON VALUES (?,?,?,?)", use(lastName), use(firstName), use(address), use(age), now;
2584 
2585 	count = 0;
2586 	session << "SELECT COUNT(*) FROM PERSON", into(count), now;
2587 	assertTrue (count == 1);
2588 
2589 	assertTrue (session.isConnected());
2590 	session.close();
2591 	assertTrue (!session.isConnected());
2592 	try
2593 	{
2594 		session << "SELECT LastName FROM PERSON", into(result), now;
2595 		fail ("must fail");
2596 	}
2597 	catch(NotConnectedException&){ }
2598 	assertTrue (!session.isConnected());
2599 
2600 	session.open();
2601 	assertTrue (session.isConnected());
2602 	session << "SELECT Age FROM PERSON", into(count), now;
2603 	assertTrue (count == age);
2604 	assertTrue (session.isConnected());
2605 }
2606 
2607 
testThreadModes()2608 void SQLiteTest::testThreadModes()
2609 {
2610 	using namespace Poco::Data::SQLite;
2611 	typedef std::vector<int> ModeVec;
2612 
2613 	assertTrue (Utility::isThreadSafe());
2614 	assertTrue (Utility::getThreadMode() == Utility::THREAD_MODE_SERIAL);
2615 
2616 	const int datasize = 100;
2617 	ModeVec mode;
2618 	mode.push_back(Utility::THREAD_MODE_SINGLE);
2619 	mode.push_back(Utility::THREAD_MODE_MULTI);
2620 	mode.push_back(Utility::THREAD_MODE_SERIAL);
2621 
2622 	Poco::Stopwatch sw;
2623 	ModeVec::iterator it = mode.begin();
2624 	ModeVec::iterator end = mode.end();
2625 	for (; it != end; ++it)
2626 	{
2627 		sw.restart();
2628 		assertTrue (Utility::setThreadMode(*it));
2629 		{
2630 			Session tmp (Connector::KEY, "dummy.db");
2631 			std::vector<int> iv(datasize);
2632 			int count = 0;
2633 
2634 			tmp << "DROP TABLE IF EXISTS Ints", now;
2635 			tmp << "CREATE TABLE IF NOT EXISTS Ints (theInt INTEGER)", now;
2636 			Statement stmt((tmp << "INSERT INTO Ints VALUES(?)", use(iv)));
2637 			tmp << "SELECT COUNT(*) FROM Ints", into(count), now;
2638 			assertTrue (count == 0);
2639 			stmt.execute();
2640 			tmp << "SELECT COUNT(*) FROM Ints", into(count), now;
2641 			assertTrue (count == datasize);
2642 			count = 0;
2643 			tmp << "SELECT COUNT(*) FROM Ints", into(count), now;
2644 			assertTrue (count == datasize);
2645 		}
2646 		sw.stop();
2647 		std::cout << "Mode: " << ((*it == Utility::THREAD_MODE_SINGLE) ? "single,"
2648                                 :(*it == Utility::THREAD_MODE_MULTI) ? "multi,"
2649                                 :(*it == Utility::THREAD_MODE_SERIAL) ? "serial,"
2650                                 : "unknown,") << " Time: " << sw.elapsed() / 1000.0 << " [ms]" << std::endl;
2651 	}
2652 
2653 	assertTrue (Utility::setThreadMode(Utility::THREAD_MODE_SERIAL));
2654 	assertTrue (Utility::isThreadSafe());
2655 	assertTrue (Utility::getThreadMode() == Utility::THREAD_MODE_SERIAL);
2656 }
2657 
2658 
sqliteUpdateCallbackFn(void * pVal,int opCode,const char * pDB,const char * pTable,Poco::Int64 row)2659 void SQLiteTest::sqliteUpdateCallbackFn(void* pVal, int opCode, const char* pDB, const char* pTable, Poco::Int64 row)
2660 {
2661 	poco_check_ptr(pVal);
2662 	Poco::Int64* pV = reinterpret_cast<Poco::Int64*>(pVal);
2663 	if (opCode == Utility::OPERATION_INSERT)
2664 	{
2665 		poco_assert (*pV == 2);
2666 		poco_assert (row == 1);
2667 		std::cout << "Inserted " << pDB << '.' << pTable << ", RowID=" << row << std::endl;
2668 		++_insertCounter;
2669 	}
2670 	else if (opCode == Utility::OPERATION_UPDATE)
2671 	{
2672 		poco_assert (*pV == 3);
2673 		poco_assert (row == 1);
2674 		std::cout << "Updated " << pDB << '.' << pTable << ", RowID=" << row << std::endl;
2675 		++_updateCounter;
2676 	}
2677 	else if (opCode == Utility::OPERATION_DELETE)
2678 	{
2679 		poco_assert (*pV == 4);
2680 		poco_assert (row == 1);
2681 		std::cout << "Deleted " << pDB << '.' << pTable << ", RowID=" << row << std::endl;
2682 		++_deleteCounter;
2683 	}
2684 }
2685 
2686 
testUpdateCallback()2687 void SQLiteTest::testUpdateCallback()
2688 {
2689 	// will be updated by callback
2690 	_insertCounter = 0;
2691 	_updateCounter = 0;
2692 	_deleteCounter = 0;
2693 
2694 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
2695 	assertTrue (tmp.isConnected());
2696 	Poco::Int64 val = 1;
2697 	assertTrue (Utility::registerUpdateHandler(tmp, &sqliteUpdateCallbackFn, &val));
2698 
2699 	std::string tableName("Person");
2700 	std::string lastName("lastname");
2701 	std::string firstName("firstname");
2702 	std::string address("Address");
2703 	int age = 133132;
2704 	int count = 0;
2705 	std::string result;
2706 	tmp << "DROP TABLE IF EXISTS Person", now;
2707 	tmp << "CREATE TABLE IF NOT EXISTS Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3))", now;
2708 	tmp << "SELECT name FROM sqlite_master WHERE tbl_name=?", use(tableName), into(result), now;
2709 	assertTrue (result == tableName);
2710 
2711 	// insert
2712 	val = 2;
2713 	tmp << "INSERT INTO PERSON VALUES(:ln, :fn, :ad, :age)", use(lastName), use(firstName), use(address), use(age), now;
2714 	tmp << "SELECT COUNT(*) FROM PERSON", into(count), now;
2715 	assertTrue (count == 1);
2716 	assertTrue (_insertCounter == 1);
2717 	tmp << "SELECT LastName FROM PERSON", into(result), now;
2718 	assertTrue (lastName == result);
2719 	tmp << "SELECT Age FROM PERSON", into(count), now;
2720 	assertTrue (count == age);
2721 
2722 	// update
2723 	val = 3;
2724 	tmp << "UPDATE PERSON SET Age = -1", now;
2725 	tmp << "SELECT Age FROM PERSON", into(age), now;
2726 	assertTrue (-1 == age);
2727 	assertTrue (_updateCounter == 1);
2728 
2729 	// delete
2730 	val =4;
2731 	tmp << "DELETE FROM Person WHERE Age = -1", now;
2732 	tmp << "SELECT COUNT(*) FROM PERSON", into(count), now;
2733 	assertTrue (count == 0);
2734 	assertTrue (_deleteCounter == 1);
2735 
2736 	// disarm callback and do the same drill
2737 	assertTrue (Utility::registerUpdateHandler(tmp, (Utility::UpdateCallbackType) 0, &val));
2738 
2739 	tmp << "DROP TABLE IF EXISTS Person", now;
2740 	tmp << "CREATE TABLE IF NOT EXISTS Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3))", now;
2741 	tmp << "SELECT name FROM sqlite_master WHERE tbl_name=?", use(tableName), into(result), now;
2742 	assertTrue (result == tableName);
2743 
2744 	// must remain zero now
2745 	_insertCounter = 0;
2746 	_updateCounter = 0;
2747 	_deleteCounter = 0;
2748 
2749 	// insert
2750 	tmp << "INSERT INTO PERSON VALUES(:ln, :fn, :ad, :age)", use(lastName), use(firstName), use(address), use(age), now;
2751 	tmp << "SELECT COUNT(*) FROM PERSON", into(count), now;
2752 	assertTrue (count == 1);
2753 	assertTrue (_insertCounter == 0);
2754 	tmp << "SELECT LastName FROM PERSON", into(result), now;
2755 	assertTrue (lastName == result);
2756 	tmp << "SELECT Age FROM PERSON", into(count), now;
2757 	assertTrue (count == age);
2758 
2759 	// update
2760 	tmp << "UPDATE PERSON SET Age = -1", now;
2761 	tmp << "SELECT Age FROM PERSON", into(age), now;
2762 	assertTrue (-1 == age);
2763 	assertTrue (_updateCounter == 0);
2764 
2765 	// delete
2766 	tmp << "DELETE FROM Person WHERE Age = -1", now;
2767 	tmp << "SELECT COUNT(*) FROM PERSON", into(count), now;
2768 	assertTrue (count == 0);
2769 	assertTrue (_deleteCounter == 0);
2770 
2771 	tmp.close();
2772 	assertTrue (!tmp.isConnected());
2773 }
2774 
2775 
sqliteCommitCallbackFn(void * pVal)2776 int SQLiteTest::sqliteCommitCallbackFn(void* pVal)
2777 {
2778 	poco_check_ptr(pVal);
2779 	Poco::Int64* pV = reinterpret_cast<Poco::Int64*>(pVal);
2780 	poco_assert ((*pV) == 1);
2781 	++(*pV);
2782 	return 0;
2783 }
2784 
2785 
testCommitCallback()2786 void SQLiteTest::testCommitCallback()
2787 {
2788 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
2789 	assertTrue (tmp.isConnected());
2790 	Poco::Int64 val = 1;
2791 	assertTrue (Utility::registerUpdateHandler(tmp, &sqliteCommitCallbackFn, &val));
2792 
2793 	std::string tableName("Person");
2794 	std::string lastName("lastname");
2795 	std::string firstName("firstname");
2796 	std::string address("Address");
2797 	int age = 133132;
2798 	std::string result;
2799 	tmp.begin();
2800 	tmp << "DROP TABLE IF EXISTS Person", now;
2801 	tmp << "CREATE TABLE IF NOT EXISTS Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3))", now;
2802 	tmp << "INSERT INTO PERSON VALUES(:ln, :fn, :ad, :age)", use(lastName), use(firstName), use(address), use(age), now;
2803 	tmp.commit();
2804 	assertTrue (val == 2);
2805 
2806 	assertTrue (Utility::registerUpdateHandler(tmp, (Utility::CommitCallbackType) 0, &val));
2807 	val = 0;
2808 	tmp.begin();
2809 	tmp << "DROP TABLE IF EXISTS Person", now;
2810 	tmp << "CREATE TABLE IF NOT EXISTS Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3))", now;
2811 	tmp << "INSERT INTO PERSON VALUES(:ln, :fn, :ad, :age)", use(lastName), use(firstName), use(address), use(age), now;
2812 	tmp.commit();
2813 	assertTrue (val == 0);
2814 
2815 }
2816 
2817 
sqliteRollbackCallbackFn(void * pVal)2818 void SQLiteTest::sqliteRollbackCallbackFn(void* pVal)
2819 {
2820 	poco_check_ptr(pVal);
2821 	Poco::Int64* pV = reinterpret_cast<Poco::Int64*>(pVal);
2822 	poco_assert ((*pV) == 1);
2823 	++(*pV);
2824 }
2825 
2826 
testRollbackCallback()2827 void SQLiteTest::testRollbackCallback()
2828 {
2829 	Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
2830 	assertTrue (tmp.isConnected());
2831 	Poco::Int64 val = 1;
2832 	assertTrue (Utility::registerUpdateHandler(tmp, &sqliteRollbackCallbackFn, &val));
2833 
2834 	std::string tableName("Person");
2835 	std::string lastName("lastname");
2836 	std::string firstName("firstname");
2837 	std::string address("Address");
2838 	int age = 133132;
2839 	std::string result;
2840 	tmp.begin();
2841 	tmp << "DROP TABLE IF EXISTS Person", now;
2842 	tmp << "CREATE TABLE IF NOT EXISTS Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3))", now;
2843 	tmp << "INSERT INTO PERSON VALUES(:ln, :fn, :ad, :age)", use(lastName), use(firstName), use(address), use(age), now;
2844 	tmp.rollback();
2845 	assertTrue (val == 2);
2846 
2847 	assertTrue (Utility::registerUpdateHandler(tmp, (Utility::RollbackCallbackType) 0, &val));
2848 	val = 0;
2849 	tmp.begin();
2850 	tmp << "DROP TABLE IF EXISTS Person", now;
2851 	tmp << "CREATE TABLE IF NOT EXISTS Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3))", now;
2852 	tmp << "INSERT INTO PERSON VALUES(:ln, :fn, :ad, :age)", use(lastName), use(firstName), use(address), use(age), now;
2853 	tmp.rollback();
2854 	assertTrue (val == 0);
2855 }
2856 
2857 
testNotifier()2858 void SQLiteTest::testNotifier()
2859 {
2860 	Session session (Poco::Data::SQLite::Connector::KEY, "dummy.db");
2861 	assertTrue (session.isConnected());
2862 	session << "DROP TABLE IF EXISTS Person", now;
2863 	session << "CREATE TABLE IF NOT EXISTS Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3))", now;
2864 
2865 	Notifier notifier(session);
2866 	notifier.insert += delegate(this, &SQLiteTest::onInsert);
2867 	notifier.update += delegate(this, &SQLiteTest::onUpdate);
2868 	notifier.erase += delegate(this, &SQLiteTest::onDelete);
2869 
2870 	_insertCounter = 0;
2871 	_updateCounter = 0;
2872 	_deleteCounter = 0;
2873 
2874 	session << "INSERT INTO PERSON VALUES('Simpson', 'Bart', 'Springfield', 12)", now;
2875 	assertTrue (_insertCounter == 1);
2876 	assertTrue (notifier.getRow() == 1);
2877 	session << "INSERT INTO PERSON VALUES('Simpson', 'Lisa', 'Springfield', 10)", now;
2878 	assertTrue (_insertCounter == 2);
2879 	assertTrue (notifier.getRow() == 2);
2880 	session << "INSERT INTO PERSON VALUES('Simpson', 'Homer', 'Springfield', 42)", now;
2881 	assertTrue (_insertCounter == 3);
2882 	assertTrue (notifier.getRow() == 3);
2883 	assertTrue (notifier.getTable() == "Person");
2884 
2885 	session << "UPDATE PERSON SET Age = 11 WHERE FirstName = 'Bart'", now;
2886 	assertTrue (_updateCounter == 1);
2887 	assertTrue (notifier.getRow() == 1);
2888 	session << "UPDATE PERSON SET Age = 9 WHERE FirstName = 'Lisa'", now;
2889 	assertTrue (_updateCounter == 2);
2890 	assertTrue (notifier.getRow() == 2);
2891 	session << "UPDATE PERSON SET Age = 41 WHERE FirstName = 'Homer'", now;
2892 	assertTrue (_updateCounter == 3);
2893 	assertTrue (notifier.getRow() == 3);
2894 
2895 	notifier.setRow(0);
2896 	// SQLite optimizes DELETE so here we must have
2897 	// the WHERE clause to trigger per-row notifications
2898 	session << "DELETE FROM PERSON WHERE 1=1", now;
2899 	assertTrue (_deleteCounter == 3);
2900 	assertTrue (notifier.getRow() == 3);
2901 
2902 	notifier.insert -= delegate(this, &SQLiteTest::onInsert);
2903 	notifier.update -= delegate(this, &SQLiteTest::onUpdate);
2904 	notifier.erase -= delegate(this, &SQLiteTest::onDelete);
2905 
2906 	notifier.disableUpdate();
2907 
2908 	notifier.setRow(0);
2909 	_commitCounter = 0;
2910 	notifier.commit += delegate(this, &SQLiteTest::onCommit);
2911 	session.begin();
2912 	session << "INSERT INTO PERSON VALUES('Simpson', 'Bart', 'Springfield', 12)", now;
2913 	session << "INSERT INTO PERSON VALUES('Simpson', 'Lisa', 'Springfield', 10)", now;
2914 	session << "INSERT INTO PERSON VALUES('Simpson', 'Homer', 'Springfield', 42)", now;
2915 	session.commit();
2916 	assertTrue (_commitCounter == 1);
2917 	assertTrue (notifier.getRow() == 0);
2918 	notifier.commit -= delegate(this, &SQLiteTest::onCommit);
2919 
2920 	session << "DELETE FROM PERSON", now;
2921 
2922 	notifier.setRow(0);
2923 	_rollbackCounter = 0;
2924 	notifier.rollback += delegate(this, &SQLiteTest::onRollback);
2925 	session.begin();
2926 	session << "INSERT INTO PERSON VALUES('Simpson', 'Bart', 'Springfield', 12)", now;
2927 	session << "INSERT INTO PERSON VALUES('Simpson', 'Lisa', 'Springfield', 10)", now;
2928 	session << "INSERT INTO PERSON VALUES('Simpson', 'Homer', 'Springfield', 42)", now;
2929 	session.rollback();
2930 	assertTrue (_rollbackCounter == 1);
2931 	assertTrue (notifier.getRow() == 0);
2932 	notifier.rollback -= delegate(this, &SQLiteTest::onRollback);
2933 }
2934 
2935 
onInsert(const void * pSender)2936 void SQLiteTest::onInsert(const void* pSender)
2937 {
2938 	Notifier* pN = reinterpret_cast<Notifier*>(const_cast<void*>(pSender));
2939 	std::cout << "onInsert, table:" << pN->getTable() << ", row:" << pN->getRow() << std::endl;
2940 	++_insertCounter;
2941 }
2942 
2943 
onUpdate(const void * pSender)2944 void SQLiteTest::onUpdate(const void* pSender)
2945 {
2946 	Notifier* pN = reinterpret_cast<Notifier*>(const_cast<void*>(pSender));
2947 	std::cout << "onUpdate, table:" << pN->getTable() << ", row:" << pN->getRow() << std::endl;
2948 	++_updateCounter;
2949 }
2950 
2951 
onDelete(const void * pSender)2952 void SQLiteTest::onDelete(const void* pSender)
2953 {
2954 	Notifier* pN = reinterpret_cast<Notifier*>(const_cast<void*>(pSender));
2955 	std::cout << "onDelete, table:" << pN->getTable() << ", row:" << pN->getRow() << std::endl;
2956 	++_deleteCounter;
2957 }
2958 
2959 
onCommit(const void * pSender)2960 void SQLiteTest::onCommit(const void* pSender)
2961 {
2962 	Notifier* pN = reinterpret_cast<Notifier*>(const_cast<void*>(pSender));
2963 	std::cout << "onCommit, table:" << pN->getTable() << ", row:" << pN->getRow() << std::endl;
2964 	++_commitCounter;
2965 }
2966 
2967 
onRollback(const void * pSender)2968 void SQLiteTest::onRollback(const void* pSender)
2969 {
2970 	Notifier* pN = reinterpret_cast<Notifier*>(const_cast<void*>(pSender));
2971 	std::cout << "onRollback, table:" << pN->getTable() << ", row:" << pN->getRow() << std::endl;
2972 	++_rollbackCounter;
2973 }
2974 
2975 
setTransactionIsolation(Session & session,Poco::UInt32 ti)2976 void SQLiteTest::setTransactionIsolation(Session& session, Poco::UInt32 ti)
2977 {
2978 	if (session.hasTransactionIsolation(ti))
2979 	{
2980 		std::string funct = "setTransactionIsolation()";
2981 
2982 		try
2983 		{
2984 			Transaction t(session, false);
2985 			t.setIsolation(ti);
2986 
2987 			assertTrue (ti == t.getIsolation());
2988 			assertTrue (t.isIsolation(ti));
2989 
2990 			assertTrue (ti == session.getTransactionIsolation());
2991 			assertTrue (session.isTransactionIsolation(ti));
2992 		}
2993 		catch(Poco::Exception& e){ std::cout << funct << ':' << e.displayText() << std::endl;}
2994 	}
2995 	else
2996 	{
2997 		std::cerr << '[' << name() << ']' << " Warning, transaction isolation not supported: ";
2998 		switch (ti)
2999 		{
3000 		case Session::TRANSACTION_READ_COMMITTED:
3001 			std::cerr << "READ COMMITTED"; break;
3002 		case Session::TRANSACTION_READ_UNCOMMITTED:
3003 			std::cerr << "READ UNCOMMITTED"; break;
3004 		case Session::TRANSACTION_REPEATABLE_READ:
3005 			std::cerr << "REPEATABLE READ"; break;
3006 		case Session::TRANSACTION_SERIALIZABLE:
3007 			std::cerr << "SERIALIZABLE"; break;
3008 		default:
3009 			std::cerr << "UNKNOWN"; break;
3010 		}
3011 		std::cerr << std::endl;
3012 	}
3013 }
3014 
3015 
testSessionTransaction()3016 void SQLiteTest::testSessionTransaction()
3017 {
3018 	Session session (Poco::Data::SQLite::Connector::KEY, "dummy.db");
3019 	assertTrue (session.isConnected());
3020 
3021 	session << "DROP TABLE IF EXISTS Person", now;
3022 	session << "CREATE TABLE IF NOT EXISTS Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3))", now;
3023 
3024 	if (!session.canTransact())
3025 	{
3026 		std::cout << "Session not capable of transactions." << std::endl;
3027 		return;
3028 	}
3029 
3030 	Session local (Poco::Data::SQLite::Connector::KEY, "dummy.db");
3031 	assertTrue (local.isConnected());
3032 
3033 	try
3034 	{
3035 		local.setFeature("autoCommit", true);
3036 		fail ("Setting SQLite auto-commit explicitly must fail!");
3037 	}
3038 	catch (NotImplementedException&) { }
3039 	assertTrue (local.getFeature("autoCommit"));
3040 
3041 	std::string funct = "transaction()";
3042 	std::vector<std::string> lastNames;
3043 	std::vector<std::string> firstNames;
3044 	std::vector<std::string> addresses;
3045 	std::vector<int> ages;
3046 	std::string tableName("Person");
3047 	lastNames.push_back("LN1");
3048 	lastNames.push_back("LN2");
3049 	firstNames.push_back("FN1");
3050 	firstNames.push_back("FN2");
3051 	addresses.push_back("ADDR1");
3052 	addresses.push_back("ADDR2");
3053 	ages.push_back(1);
3054 	ages.push_back(2);
3055 	int count = 0, locCount = 0;
3056 	std::string result;
3057 
3058 	setTransactionIsolation(session, Session::TRANSACTION_READ_COMMITTED);
3059 
3060 	session.begin();
3061 	assertTrue (!session.getFeature("autoCommit"));
3062 	assertTrue (session.isTransaction());
3063 	session << "INSERT INTO Person VALUES (?,?,?,?)", use(lastNames), use(firstNames), use(addresses), use(ages), now;
3064 	assertTrue (session.isTransaction());
3065 
3066 	Statement stmt = (local << "SELECT COUNT(*) FROM Person", into(locCount), async, now);
3067 
3068 	session << "SELECT COUNT(*) FROM Person", into(count), now;
3069 	assertTrue (2 == count);
3070 	assertTrue (session.isTransaction());
3071 	session.rollback();
3072 	assertTrue (!session.isTransaction());
3073 	assertTrue (session.getFeature("autoCommit"));
3074 
3075 	stmt.wait();
3076 	assertTrue (0 == locCount);
3077 
3078 	session << "SELECT count(*) FROM Person", into(count), now;
3079 	assertTrue (0 == count);
3080 	assertTrue (!session.isTransaction());
3081 
3082 	session.begin();
3083 	session << "INSERT INTO Person VALUES (?,?,?,?)", use(lastNames), use(firstNames), use(addresses), use(ages), now;
3084 	assertTrue (session.isTransaction());
3085 	assertTrue (!session.getFeature("autoCommit"));
3086 
3087 	Statement stmt1 = (local << "SELECT COUNT(*) FROM Person", into(locCount), now);
3088 	assertTrue (0 == locCount);
3089 
3090 	session << "SELECT count(*) FROM Person", into(count), now;
3091 	assertTrue (2 == count);
3092 
3093 	session.commit();
3094 	assertTrue (!session.isTransaction());
3095 	assertTrue (session.getFeature("autoCommit"));
3096 
3097 	session << "SELECT count(*) FROM Person", into(count), now;
3098 	assertTrue (2 == count);
3099 
3100 	/* TODO: see http://www.sqlite.org/pragma.html#pragma_read_uncommitted
3101 	setTransactionIsolation(session, Session::TRANSACTION_READ_UNCOMMITTED);
3102 	*/
3103 
3104 	session.close();
3105 	assertTrue (!session.isConnected());
3106 
3107 	local.close();
3108 	assertTrue (!local.isConnected());
3109 }
3110 
3111 
testTransaction()3112 void SQLiteTest::testTransaction()
3113 {
3114 	Session session (Poco::Data::SQLite::Connector::KEY, "dummy.db");
3115 	assertTrue (session.isConnected());
3116 
3117 	session << "DROP TABLE IF EXISTS Person", now;
3118 	session << "CREATE TABLE IF NOT EXISTS Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3))", now;
3119 
3120 	if (!session.canTransact())
3121 	{
3122 		std::cout << "Session not transaction-capable." << std::endl;
3123 		return;
3124 	}
3125 
3126 	Session local(Poco::Data::SQLite::Connector::KEY, "dummy.db");
3127 
3128 	setTransactionIsolation(session, Session::TRANSACTION_READ_COMMITTED);
3129 
3130 	std::string funct = "transaction()";
3131 	std::vector<std::string> lastNames;
3132 	std::vector<std::string> firstNames;
3133 	std::vector<std::string> addresses;
3134 	std::vector<int> ages;
3135 	std::string tableName("Person");
3136 	lastNames.push_back("LN1");
3137 	lastNames.push_back("LN2");
3138 	firstNames.push_back("FN1");
3139 	firstNames.push_back("FN2");
3140 	addresses.push_back("ADDR1");
3141 	addresses.push_back("ADDR2");
3142 	ages.push_back(1);
3143 	ages.push_back(2);
3144 	int count = 0, locCount = 0;
3145 	std::string result;
3146 
3147 	session.setTransactionIsolation(Session::TRANSACTION_READ_COMMITTED);
3148 
3149 	{
3150 		Transaction trans(session);
3151 		assertTrue (trans.isActive());
3152 		assertTrue (session.isTransaction());
3153 
3154 		session << "INSERT INTO Person VALUES (?,?,?,?)", use(lastNames), use(firstNames), use(addresses), use(ages), now;
3155 
3156 		assertTrue (session.isTransaction());
3157 		assertTrue (trans.isActive());
3158 
3159 		session << "SELECT COUNT(*) FROM Person", into(count), now;
3160 		assertTrue (2 == count);
3161 		assertTrue (session.isTransaction());
3162 		assertTrue (trans.isActive());
3163 		// no explicit commit, so transaction RAII must roll back here
3164 	}
3165 	assertTrue (!session.isTransaction());
3166 
3167 	session << "SELECT count(*) FROM Person", into(count), now;
3168 	assertTrue (0 == count);
3169 	assertTrue (!session.isTransaction());
3170 
3171 	{
3172 		Transaction trans(session);
3173 		session << "INSERT INTO Person VALUES (?,?,?,?)", use(lastNames), use(firstNames), use(addresses), use(ages), now;
3174 
3175 		Statement stmt1 = (local << "SELECT COUNT(*) FROM Person", into(locCount), now);
3176 
3177 		assertTrue (session.isTransaction());
3178 		assertTrue (trans.isActive());
3179 		trans.commit();
3180 		assertTrue (!session.isTransaction());
3181 		assertTrue (!trans.isActive());
3182 		assertTrue (0 == locCount);
3183 	}
3184 
3185 	session << "SELECT count(*) FROM Person", into(count), now;
3186 	assertTrue (2 == count);
3187 	local << "SELECT count(*) FROM Person", into(count), now;
3188 	assertTrue (2 == count);
3189 
3190 	session << "DELETE FROM Person", now;
3191 
3192 	std::string sql1 = format("INSERT INTO Person VALUES ('%s','%s','%s',%d)", lastNames[0], firstNames[0], addresses[0], ages[0]);
3193 	std::string sql2 = format("INSERT INTO Person VALUES ('%s','%s','%s',%d)", lastNames[1], firstNames[1], addresses[1], ages[1]);
3194 	std::vector<std::string> sql;
3195 	sql.push_back(sql1);
3196 	sql.push_back(sql2);
3197 
3198 	Transaction trans(session);
3199 
3200 	trans.execute(sql1, false);
3201 	session << "SELECT count(*) FROM Person", into(count), now;
3202 	assertTrue (1 == count);
3203 	trans.execute(sql2, false);
3204 	session << "SELECT count(*) FROM Person", into(count), now;
3205 	assertTrue (2 == count);
3206 
3207 	Statement stmt2 = (local << "SELECT COUNT(*) FROM Person", into(locCount), now);
3208 	assertTrue (0 == locCount);
3209 
3210 	trans.rollback();
3211 
3212 	session << "SELECT count(*) FROM Person", into(count), now;
3213 	assertTrue (0 == count);
3214 
3215 	trans.execute(sql);
3216 
3217 	Statement stmt3 = (local << "SELECT COUNT(*) FROM Person", into(locCount), now);
3218 	assertTrue (2 == locCount);
3219 
3220 	session << "SELECT count(*) FROM Person", into(count), now;
3221 	assertTrue (2 == count);
3222 
3223 	session.close();
3224 	assertTrue (!session.isConnected());
3225 
3226 	local.close();
3227 	assertTrue (!local.isConnected());
3228 }
3229 
3230 
3231 struct TestCommitTransactor
3232 {
operator ()TestCommitTransactor3233 	void operator () (Session& session) const
3234 	{
3235 		session << "INSERT INTO Person VALUES ('lastName','firstName','address',10)", now;
3236 	}
3237 };
3238 
3239 
3240 struct TestRollbackTransactor
3241 {
operator ()TestRollbackTransactor3242 	void operator () (Session& session) const
3243 	{
3244 		session << "INSERT INTO Person VALUES ('lastName','firstName','address',10)", now;
3245 		throw Poco::Exception("test");
3246 	}
3247 };
3248 
3249 
testTransactor()3250 void SQLiteTest::testTransactor()
3251 {
3252 	Session session (Poco::Data::SQLite::Connector::KEY, "dummy.db");
3253 	assertTrue (session.isConnected());
3254 
3255 	session << "DROP TABLE IF EXISTS Person", now;
3256 	session << "CREATE TABLE IF NOT EXISTS Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3))", now;
3257 
3258 	std::string funct = "transaction()";
3259 	int count = 0;
3260 
3261 	assertTrue (session.getFeature("autoCommit"));
3262 	session.setTransactionIsolation(Session::TRANSACTION_READ_COMMITTED);
3263 
3264 	TestCommitTransactor ct;
3265 	Transaction t1(session, ct);
3266 
3267 	session << "SELECT count(*) FROM Person", into(count), now;
3268 	assertTrue (1 == count);
3269 
3270 	session << "DELETE FROM Person", now;
3271 	session << "SELECT count(*) FROM Person", into(count), now;
3272 	assertTrue (0 == count);
3273 
3274 	try
3275 	{
3276 		TestRollbackTransactor rt;
3277 		Transaction t(session, rt);
3278 		fail ("must fail");
3279 	} catch (Poco::Exception&) { }
3280 
3281 	session << "SELECT count(*) FROM Person", into(count), now;
3282 	assertTrue (0 == count);
3283 
3284 	try
3285 	{
3286 		TestRollbackTransactor rt;
3287 		Transaction t(session);
3288 		t.transact(rt);
3289 		fail ("must fail");
3290 	} catch (Poco::Exception&) { }
3291 
3292 	session << "SELECT count(*) FROM Person", into(count), now;
3293 	assertTrue (0 == count);
3294 
3295 	try
3296 	{
3297 		TestRollbackTransactor rt;
3298 		Transaction t(session, false);
3299 		t.transact(rt);
3300 		fail ("must fail");
3301 	} catch (Poco::Exception&) { }
3302 
3303 	session << "SELECT count(*) FROM Person", into(count), now;
3304 	assertTrue (0 == count);
3305 
3306 	try
3307 	{
3308 		TestRollbackTransactor rt;
3309 		Transaction t(session, true);
3310 		t.transact(rt);
3311 		fail ("must fail");
3312 	} catch (Poco::Exception&) { }
3313 
3314 	session << "SELECT count(*) FROM Person", into(count), now;
3315 	assertTrue (0 == count);
3316 
3317 	session.close();
3318 	assertTrue (!session.isConnected());
3319 }
3320 
3321 
testFTS3()3322 void SQLiteTest::testFTS3()
3323 {
3324 #ifdef SQLITE_ENABLE_FTS3
3325 	Session session(Poco::Data::SQLite::Connector::KEY, "dummy.db");
3326 	assertTrue (session.isConnected());
3327 
3328 	session << "DROP TABLE IF EXISTS docs", now;
3329 	session << "CREATE VIRTUAL TABLE docs USING fts3()", now;
3330 
3331 	session << "INSERT INTO docs(docid, content) VALUES(1, 'a database is a software system')", now;
3332 	session << "INSERT INTO docs(docid, content) VALUES(2, 'sqlite is a software system')", now;
3333 	session << "INSERT INTO docs(docid, content) VALUES(3, 'sqlite is a database')", now;
3334 
3335 	int docid = 0;
3336 	session << "SELECT docid FROM docs WHERE docs MATCH 'sqlite AND database'", into(docid), now;
3337 	assertTrue (docid == 3);
3338 
3339 	docid = 0;
3340 	session << "SELECT docid FROM docs WHERE docs MATCH 'database sqlite'", into(docid), now;
3341 	assertTrue (docid == 3);
3342 
3343 	std::vector<int> docids;
3344 	session << "SELECT docid FROM docs WHERE docs MATCH 'sqlite OR database' ORDER BY docid",
3345 		into(docids), now;
3346 	assertTrue (docids.size() == 3);
3347 	assertTrue (docids[0] == 1);
3348 	assertTrue (docids[1] == 2);
3349 	assertTrue (docids[2] == 3);
3350 
3351 	std::string content;
3352 	docid = 0;
3353 	session << "SELECT docid, content FROM docs WHERE docs MATCH 'database NOT sqlite'",
3354 		into(docid), into(content), now;
3355 	assertTrue (docid == 1);
3356 	assertTrue (content == "a database is a software system");
3357 
3358 	docid = 0;
3359 	session << "SELECT count(*) FROM docs WHERE docs MATCH 'database and sqlite'", into(docid), now;
3360 	assertTrue (docid == 0);
3361 #else
3362 	std::cout << "SQLite FTS not enabled, test not executed." << std::endl;
3363 #endif // SQLITE_ENABLE_FTS3
3364 }
3365 
3366 
testIllegalFilePath()3367 void SQLiteTest::testIllegalFilePath()
3368 {
3369 	try
3370 	{
3371 		Session tmp(Poco::Data::SQLite::Connector::KEY, "\\/some\\/illegal\\/path\\/dummy.db", 1);
3372 		fail("must fail");
3373 	}
3374 	catch (ConnectionFailedException&)
3375 	{
3376 	}
3377 }
3378 
3379 
setUp()3380 void SQLiteTest::setUp()
3381 {
3382 }
3383 
3384 
tearDown()3385 void SQLiteTest::tearDown()
3386 {
3387 }
3388 
3389 
suite()3390 CppUnit::Test* SQLiteTest::suite()
3391 {
3392 	CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("SQLiteTest");
3393 
3394 	CppUnit_addTest(pSuite, SQLiteTest, testBinding);
3395 	CppUnit_addTest(pSuite, SQLiteTest, testZeroRows);
3396 	CppUnit_addTest(pSuite, SQLiteTest, testSimpleAccess);
3397 	CppUnit_addTest(pSuite, SQLiteTest, testInMemory);
3398 	CppUnit_addTest(pSuite, SQLiteTest, testNullCharPointer);
3399 	CppUnit_addTest(pSuite, SQLiteTest, testInsertCharPointer);
3400 	CppUnit_addTest(pSuite, SQLiteTest, testInsertCharPointer2);
3401 	CppUnit_addTest(pSuite, SQLiteTest, testComplexType);
3402 	CppUnit_addTest(pSuite, SQLiteTest, testSimpleAccessVector);
3403 	CppUnit_addTest(pSuite, SQLiteTest, testComplexTypeVector);
3404 	CppUnit_addTest(pSuite, SQLiteTest, testSharedPtrComplexTypeVector);
3405 	CppUnit_addTest(pSuite, SQLiteTest, testInsertVector);
3406 	CppUnit_addTest(pSuite, SQLiteTest, testInsertEmptyVector);
3407 	CppUnit_addTest(pSuite, SQLiteTest, testAffectedRows);
3408 	CppUnit_addTest(pSuite, SQLiteTest, testInsertSingleBulk);
3409 	CppUnit_addTest(pSuite, SQLiteTest, testInsertSingleBulkVec);
3410 	CppUnit_addTest(pSuite, SQLiteTest, testLimit);
3411 	CppUnit_addTest(pSuite, SQLiteTest, testLimitOnce);
3412 	CppUnit_addTest(pSuite, SQLiteTest, testLimitPrepare);
3413 	CppUnit_addTest(pSuite, SQLiteTest, testLimitZero);
3414 	CppUnit_addTest(pSuite, SQLiteTest, testPrepare);
3415 	CppUnit_addTest(pSuite, SQLiteTest, testSetSimple);
3416 	CppUnit_addTest(pSuite, SQLiteTest, testSetComplex);
3417 	CppUnit_addTest(pSuite, SQLiteTest, testSetComplexUnique);
3418 	CppUnit_addTest(pSuite, SQLiteTest, testMultiSetSimple);
3419 	CppUnit_addTest(pSuite, SQLiteTest, testMultiSetComplex);
3420 	CppUnit_addTest(pSuite, SQLiteTest, testMapComplex);
3421 	CppUnit_addTest(pSuite, SQLiteTest, testMapComplexUnique);
3422 	CppUnit_addTest(pSuite, SQLiteTest, testMultiMapComplex);
3423 	CppUnit_addTest(pSuite, SQLiteTest, testSelectIntoSingle);
3424 	CppUnit_addTest(pSuite, SQLiteTest, testSelectIntoSingleStep);
3425 	CppUnit_addTest(pSuite, SQLiteTest, testSelectIntoSingleFail);
3426 	CppUnit_addTest(pSuite, SQLiteTest, testLowerLimitOk);
3427 	CppUnit_addTest(pSuite, SQLiteTest, testLowerLimitFail);
3428 	CppUnit_addTest(pSuite, SQLiteTest, testCombinedLimits);
3429 	CppUnit_addTest(pSuite, SQLiteTest, testCombinedIllegalLimits);
3430 	CppUnit_addTest(pSuite, SQLiteTest, testRange);
3431 	CppUnit_addTest(pSuite, SQLiteTest, testIllegalRange);
3432 	CppUnit_addTest(pSuite, SQLiteTest, testSingleSelect);
3433 	CppUnit_addTest(pSuite, SQLiteTest, testEmptyDB);
3434 	CppUnit_addTest(pSuite, SQLiteTest, testCLOB);
3435 	CppUnit_addTest(pSuite, SQLiteTest, testTuple10);
3436 	CppUnit_addTest(pSuite, SQLiteTest, testTupleVector10);
3437 	CppUnit_addTest(pSuite, SQLiteTest, testTuple9);
3438 	CppUnit_addTest(pSuite, SQLiteTest, testTupleVector9);
3439 	CppUnit_addTest(pSuite, SQLiteTest, testTuple8);
3440 	CppUnit_addTest(pSuite, SQLiteTest, testTupleVector8);
3441 	CppUnit_addTest(pSuite, SQLiteTest, testTuple7);
3442 	CppUnit_addTest(pSuite, SQLiteTest, testTupleVector7);
3443 	CppUnit_addTest(pSuite, SQLiteTest, testTuple6);
3444 	CppUnit_addTest(pSuite, SQLiteTest, testTupleVector6);
3445 	CppUnit_addTest(pSuite, SQLiteTest, testTuple5);
3446 	CppUnit_addTest(pSuite, SQLiteTest, testTupleVector5);
3447 	CppUnit_addTest(pSuite, SQLiteTest, testTuple4);
3448 	CppUnit_addTest(pSuite, SQLiteTest, testTupleVector4);
3449 	CppUnit_addTest(pSuite, SQLiteTest, testTuple3);
3450 	CppUnit_addTest(pSuite, SQLiteTest, testTupleVector3);
3451 	CppUnit_addTest(pSuite, SQLiteTest, testTuple2);
3452 	CppUnit_addTest(pSuite, SQLiteTest, testTupleVector2);
3453 	CppUnit_addTest(pSuite, SQLiteTest, testTuple1);
3454 	CppUnit_addTest(pSuite, SQLiteTest, testTupleVector1);
3455 	CppUnit_addTest(pSuite, SQLiteTest, testDateTime);
3456 	CppUnit_addTest(pSuite, SQLiteTest, testInternalExtraction);
3457 	CppUnit_addTest(pSuite, SQLiteTest, testPrimaryKeyConstraint);
3458 	CppUnit_addTest(pSuite, SQLiteTest, testNullable);
3459 	CppUnit_addTest(pSuite, SQLiteTest, testNulls);
3460 	CppUnit_addTest(pSuite, SQLiteTest, testRowIterator);
3461 	CppUnit_addTest(pSuite, SQLiteTest, testAsync);
3462 	CppUnit_addTest(pSuite, SQLiteTest, testAny);
3463 	CppUnit_addTest(pSuite, SQLiteTest, testDynamicAny);
3464 	CppUnit_addTest(pSuite, SQLiteTest, testSQLChannel);
3465 	CppUnit_addTest(pSuite, SQLiteTest, testSQLLogger);
3466 	CppUnit_addTest(pSuite, SQLiteTest, testExternalBindingAndExtraction);
3467 	CppUnit_addTest(pSuite, SQLiteTest, testBindingCount);
3468 	CppUnit_addTest(pSuite, SQLiteTest, testMultipleResults);
3469 	CppUnit_addTest(pSuite, SQLiteTest, testPair);
3470 	CppUnit_addTest(pSuite, SQLiteTest, testReconnect);
3471 	CppUnit_addTest(pSuite, SQLiteTest, testThreadModes);
3472 	CppUnit_addTest(pSuite, SQLiteTest, testUpdateCallback);
3473 	CppUnit_addTest(pSuite, SQLiteTest, testCommitCallback);
3474 	CppUnit_addTest(pSuite, SQLiteTest, testRollbackCallback);
3475 	CppUnit_addTest(pSuite, SQLiteTest, testNotifier);
3476 	CppUnit_addTest(pSuite, SQLiteTest, testSessionTransaction);
3477 	CppUnit_addTest(pSuite, SQLiteTest, testTransaction);
3478 	CppUnit_addTest(pSuite, SQLiteTest, testTransactor);
3479 	CppUnit_addTest(pSuite, SQLiteTest, testFTS3);
3480 	CppUnit_addTest(pSuite, SQLiteTest, testIllegalFilePath);
3481 
3482 	return pSuite;
3483 }
3484