DboTest.C 61 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442
  1. /*
  2. * Copyright (C) 2009 Emweb bvba, Kessel-Lo, Belgium.
  3. *
  4. * See the LICENSE file for terms of use.
  5. */
  6. #include <boost/test/unit_test.hpp>
  7. #include <Wt/Dbo/Dbo>
  8. #include <Wt/Dbo/FixedSqlConnectionPool>
  9. #include <Wt/WDate>
  10. #include <Wt/WDateTime>
  11. #include <Wt/WTime>
  12. #include <Wt/Dbo/WtSqlTraits>
  13. #include <Wt/Dbo/ptr_tuple>
  14. #include <Wt/Dbo/QueryModel>
  15. #include <boost/date_time/posix_time/posix_time.hpp>
  16. #include <boost/date_time/gregorian/gregorian.hpp>
  17. #include "DboFixture.h"
  18. //#define SCHEMA "test."
  19. #define SCHEMA ""
  20. #define DEBUG(x) x
  21. //#define DEBUG(x)
  22. namespace dbo = Wt::Dbo;
  23. class A;
  24. class B;
  25. class C;
  26. class D;
  27. class E;
  28. class F;
  29. bool fractionalSeconds = true;
  30. struct Coordinate {
  31. int x, y;
  32. Coordinate()
  33. : x(-1), y(-1) { }
  34. Coordinate(int an_x, int an_y)
  35. : x(an_x), y(an_y) { }
  36. bool operator== (const Coordinate& other) const {
  37. return x == other.x && y == other.y;
  38. }
  39. bool operator< (const Coordinate& other) const {
  40. if (x < other.x)
  41. return true;
  42. else if (x == other.x)
  43. return y < other.y;
  44. else
  45. return false;
  46. }
  47. };
  48. std::ostream& operator<< (std::ostream& o, const Coordinate& c)
  49. {
  50. return o << "(" << c.x << ", " << c.y << ")";
  51. }
  52. namespace Wt {
  53. namespace Dbo {
  54. template <class Action>
  55. void field(Action& action, Coordinate& coordinate, const std::string& name,
  56. int size = -1)
  57. {
  58. field(action, coordinate.x, name + "_x", 1000);
  59. field(action, coordinate.y, name + "_y", 1000);
  60. }
  61. }
  62. }
  63. struct DboFixture : DboFixtureBase
  64. {
  65. DboFixture() :
  66. DboFixtureBase()
  67. {
  68. session_->mapClass<A>(SCHEMA "table_a");
  69. session_->mapClass<B>(SCHEMA "table_b");
  70. session_->mapClass<C>(SCHEMA "table_c");
  71. session_->mapClass<D>(SCHEMA "table_d");
  72. session_->mapClass<E>(SCHEMA "table_e");
  73. session_->mapClass<F>(SCHEMA "table_f");
  74. try {
  75. session_->dropTables();
  76. } catch (...) {
  77. }
  78. std::cerr << session_->tableCreationSql() << std::endl;
  79. //session_->dropTables();
  80. session_->createTables();
  81. Wt::registerType<Coordinate>();
  82. }
  83. };
  84. namespace Wt {
  85. namespace Dbo {
  86. template<>
  87. struct dbo_traits<D> : public dbo_default_traits
  88. {
  89. typedef Coordinate IdType;
  90. static IdType invalidId() { return Coordinate(); }
  91. static const char *surrogateIdField() { return 0; }
  92. static const char *versionField() { return 0; }
  93. };
  94. template<> struct dbo_traits<const D> : dbo_traits<D> {};
  95. template<>
  96. struct dbo_traits<E> : public dbo_default_traits
  97. {
  98. static const char *versionField() { return 0; }
  99. };
  100. template<> struct dbo_traits<const E> : dbo_traits<E> {};
  101. }
  102. }
  103. typedef dbo::collection<dbo::ptr<A> > As;
  104. typedef dbo::collection<dbo::ptr<B> > Bs;
  105. typedef dbo::collection<dbo::ptr<C> > Cs;
  106. typedef dbo::collection<dbo::ptr<D> > Ds;
  107. class A : public dbo::Dbo<A> {
  108. public:
  109. dbo::ptr<B> b;
  110. dbo::ptr<D> dthing;
  111. dbo::ptr<A> parent;
  112. dbo::ptr<C> c;
  113. std::vector<unsigned char> binary;
  114. Wt::WDate date;
  115. Wt::WTime time;
  116. Wt::WDateTime datetime;
  117. Wt::WString wstring;
  118. Wt::WString wstring2;
  119. std::string string;
  120. std::string string2;
  121. boost::optional<std::string> string3;
  122. boost::posix_time::ptime ptime;
  123. boost::posix_time::time_duration pduration;
  124. bool checked;
  125. int i;
  126. ::int64_t i64;
  127. long long ll;
  128. float f;
  129. double d;
  130. bool operator== (const A& other) const {
  131. if (binary.size() != other.binary.size()){
  132. DEBUG(std::cerr << "ERROR: binary.size = " << binary.size()
  133. << " | " << other.binary.size() << std::endl);
  134. return false;
  135. }
  136. for (unsigned j = 0; j < binary.size(); ++j)
  137. if (binary[j] != other.binary[j]){
  138. DEBUG(std::cerr << "ERROR: binary" << std::endl);
  139. return false;
  140. }
  141. //Debug printings:
  142. if (date != other.date) {
  143. DEBUG(std::cerr << "ERROR: date = " << date.toString() << " | "
  144. << other.date.toString() << std::endl);
  145. }
  146. if (time != other.time) {
  147. DEBUG(std::cerr << "ERROR: time = " << time.toString() << " | "
  148. << other.time.toString() << std::endl);
  149. }
  150. if (datetime != other.datetime) {
  151. DEBUG(std::cerr << "ERROR: datetime = " << datetime.toString() << " | "
  152. << other.datetime.toString() << std::endl);
  153. }
  154. if (wstring != other.wstring) {
  155. DEBUG(std::cerr << "ERROR: wstring = " << wstring << " | "
  156. << other.wstring << std::endl);
  157. }
  158. if (wstring2 != other.wstring2) {
  159. DEBUG(std::cerr << "ERROR: wstring2 = " << wstring2 << " | "
  160. << other.wstring2 << std::endl);
  161. }
  162. if (string != other.string) {
  163. DEBUG(std::cerr << "ERROR: string = " << string << " | " << other.string
  164. << std::endl);
  165. }
  166. if (string2 != other.string2) {
  167. DEBUG(std::cerr << "ERROR: string2 = " << string2 << " | "
  168. << other.string2 << std::endl);
  169. }
  170. if (string3 != other.string3) {
  171. DEBUG(std::cerr << "ERROR: string3 = " << (string3 ? *string3 : "<optional empty>") << " | "
  172. << (other.string3 ? *other.string3 : "<optional empty>") << std::endl);
  173. }
  174. if (ptime != other.ptime) {
  175. DEBUG(std::cerr << "ERROR: ptime = " << ptime<< " | " << other.ptime
  176. << std::endl);
  177. }
  178. if (pduration != other.pduration) {
  179. DEBUG(std::cerr << "ERROR: pduration = " << pduration << " | "
  180. << other.pduration << std::endl);
  181. }
  182. if (i != other.i) {
  183. DEBUG(std::cerr << "ERROR: i = " << i << " | " << other.i << std::endl);
  184. }
  185. if (i64 != other.i64) {
  186. DEBUG(std::cerr << "ERROR: i64 = " <<i64 << " | "
  187. << other.i64 << std::endl);
  188. }
  189. if (ll != other.ll) {
  190. DEBUG(std::cerr << "ERROR: ll = " << ll << " | "
  191. << other.ll << std::endl);
  192. }
  193. if (checked != other.checked) {
  194. DEBUG(std::cerr << "ERROR: checked = " << checked << " | "
  195. << other.checked << std::endl);
  196. }
  197. if (f != other.f) {
  198. DEBUG(std::cerr << "ERROR: f = " << std::setprecision(10) << f << " | " << other.f << std::endl);
  199. }
  200. if (d != other.d) {
  201. // NOTE: this may fail in dbo_test1 when run under valgrind with postgres on 64-bit Linux
  202. // probably due to valgrind emulation of floating point
  203. DEBUG(std::cerr << "ERROR: d = " << std::setprecision(20) << d << " | " << other.d << std::endl);
  204. }
  205. if (b != other.b) {
  206. DEBUG(std::cerr << "ERROR: b = " << b << " | " << other.b << std::endl);
  207. }
  208. if (dthing != other.dthing) {
  209. DEBUG(std::cerr << "ERROR: dthing = " << dthing << " | " << other.dthing
  210. << std::endl);
  211. }
  212. if (parent != other.parent) {
  213. DEBUG(std::cerr << "ERROR: parent = " << parent << " | " << other.parent
  214. << std::endl);
  215. }
  216. std::cout << "time = " << time.toString("hh:mm:ss.zzz") << " ; " << other.time.toString("hh:mm:ss.zzz") << std::endl;
  217. std::cout << "string = " << string << " ; " << other.string << std::endl;
  218. std::cout << "wstring = " << wstring.toUTF8() << " ; " << other.wstring.toUTF8() << std::endl;
  219. std::cout << "date = " << date.toString() << " ; " << other.date.toString() << std::endl;
  220. std::cout << "datetime = " << datetime.toString() << " ; " << other.datetime.toString() << std::endl;
  221. std::cout << "i = " << i << " ; " << other.i << std::endl;
  222. std::cout << "i64 = " << i64 << " ; " << other.i64 << std::endl;
  223. std::cout << "ll = " << ll << " ; " << other.ll << std::endl;
  224. std::cout << "f = " << f << " ; " << other.f << std::endl;
  225. std::cout << "d = " << d << " ; " << other.d << std::endl;
  226. std::cout << "b = " << b << " ; " << other.b << std::endl;
  227. std::cout << "dthing = " << dthing << " ; " << other.dthing << std::endl;
  228. std::cout << "parent = " << parent << " ; " << other.parent << std::endl;
  229. return date == other.date
  230. && (time == other.time || !fractionalSeconds)
  231. && datetime == other.datetime
  232. && wstring == other.wstring
  233. && wstring2 == other.wstring2
  234. && string == other.string
  235. && string2 == other.string2
  236. && string3 == other.string3
  237. && ptime == other.ptime
  238. && pduration == pduration
  239. && i == other.i
  240. && i64 == other.i64
  241. && ll == other.ll
  242. && checked == other.checked
  243. && f == other.f
  244. && d == other.d
  245. && b == other.b
  246. && dthing == other.dthing
  247. && parent == other.parent;
  248. }
  249. As asManyToOne;
  250. template <class Action>
  251. void persist(Action& a)
  252. {
  253. dbo::field(a, date, "date");
  254. dbo::field(a, time, "time");
  255. dbo::field(a, binary, "binary");
  256. dbo::field(a, datetime, "datetime");
  257. dbo::field(a, wstring, "wstring");
  258. dbo::field(a, wstring2, "wstring2", 30);
  259. dbo::field(a, string, "string");
  260. dbo::field(a, string2, "string2", 50);
  261. dbo::field(a, string3, "string3");
  262. dbo::field(a, ptime, "ptime");
  263. dbo::field(a, pduration, "pduration");
  264. dbo::field(a, i, "i");
  265. dbo::field(a, i64, "i64");
  266. dbo::field(a, ll, "ll");
  267. dbo::field(a, checked, "checked");
  268. dbo::field(a, f, "f");
  269. dbo::field(a, d, "d");
  270. dbo::belongsTo(a, b, "b");
  271. dbo::belongsTo(a, c);
  272. if (a.session()) {
  273. dbo::belongsTo(a, dthing);
  274. dbo::belongsTo(a, parent, a.session()->template tableName<A>()
  275. + std::string("_parent"));
  276. dbo::hasMany(a, asManyToOne, dbo::ManyToOne,
  277. a.session()->template tableName<A>()
  278. + std::string("_parent"));
  279. }
  280. }
  281. };
  282. class B {
  283. public:
  284. enum State {
  285. State1 = 0,
  286. State2 = 1
  287. };
  288. std::string name;
  289. State state;
  290. As asManyToOne;
  291. Cs csManyToMany;
  292. Cs csManyToOne;
  293. B() : state(State1) { }
  294. B(const std::string& aName, State aState)
  295. : name(aName), state(aState)
  296. { }
  297. bool operator== (const B& other) const {
  298. return name == other.name
  299. && state == other.state;
  300. }
  301. template <class Action>
  302. void persist(Action& a)
  303. {
  304. dbo::field(a, state, "state");
  305. dbo::field(a, name, "name", 1000);
  306. dbo::hasMany(a, asManyToOne, dbo::ManyToOne, "b");
  307. dbo::hasMany(a, csManyToMany, dbo::ManyToMany, SCHEMA "b_c", "the_b",
  308. dbo::NotNull
  309. | dbo::OnDeleteCascade
  310. | dbo::OnUpdateCascade);
  311. dbo::hasMany(a, csManyToOne, dbo::ManyToOne, "b2");
  312. }
  313. };
  314. class C {
  315. public:
  316. std::string name;
  317. dbo::weak_ptr<A> aOneToOne;
  318. dbo::ptr<B> b;
  319. dbo::weak_ptr<D> dOneToOne;
  320. Bs bsManyToMany;
  321. Ds dsManyToMany;
  322. C() { }
  323. C(const std::string& aName)
  324. : name(aName)
  325. { }
  326. bool operator== (const C& other) const {
  327. return name == other.name;
  328. }
  329. template <class Action>
  330. void persist(Action& a)
  331. {
  332. dbo::field(a, name, "name", 1000);
  333. dbo::belongsTo(a, b, "b2");
  334. dbo::hasMany(a, bsManyToMany, dbo::ManyToMany, SCHEMA "b_c", "the_c",
  335. dbo::NotNull
  336. | dbo::OnDeleteCascade
  337. | dbo::OnUpdateCascade );
  338. dbo::hasMany(a, dsManyToMany, dbo::ManyToMany, SCHEMA "c_d");
  339. dbo::hasOne(a, aOneToOne);
  340. dbo::hasOne(a, dOneToOne, "c_d2");
  341. }
  342. };
  343. class D {
  344. public:
  345. Coordinate id;
  346. std::string name;
  347. dbo::ptr<C> c;
  348. As asManyToOne;
  349. Cs csManyToMany;
  350. D() { }
  351. D(const Coordinate& anId, const std::string& aName)
  352. : id(anId),
  353. name(aName)
  354. { }
  355. template <class Action>
  356. void persist(Action& a)
  357. {
  358. dbo::id(a, id, "id");
  359. dbo::field(a, name, "name", 1000);
  360. dbo::belongsTo(a, c, "c_d2");
  361. dbo::hasMany(a, asManyToOne, dbo::ManyToOne);
  362. dbo::hasMany(a, csManyToMany, dbo::ManyToMany, SCHEMA "c_d");
  363. }
  364. };
  365. class E {
  366. public:
  367. std::string name;
  368. E() { }
  369. E(const std::string& aName)
  370. : name(aName)
  371. { }
  372. bool operator== (const E& other) const {
  373. return name == other.name;
  374. }
  375. template <class Action>
  376. void persist(Action& a)
  377. {
  378. dbo::field(a, name, "name", 1000);
  379. }
  380. };
  381. class F {
  382. public:
  383. std::string firstName;
  384. std::string lastName;
  385. std::string gender;
  386. F() { }
  387. F(const std::string& aFirstName, const std::string& aLastName, const std::string& aGender)
  388. : firstName(aFirstName), lastName(aLastName), gender(aGender)
  389. { }
  390. template <class Action>
  391. void persist(Action& a)
  392. {
  393. dbo::field(a, firstName, "first_name", 64);
  394. dbo::field(a, lastName, "last_name", 64);
  395. dbo::field(a, gender, "gender", 64);
  396. }
  397. };
  398. BOOST_AUTO_TEST_CASE( dbo_test1 )
  399. {
  400. DboFixture f;
  401. dbo::Session *session_ = f.session_;
  402. A a1;
  403. a1.datetime = Wt::WDateTime(Wt::WDate(2009, 10, 1), Wt::WTime(12, 11, 31));
  404. for (unsigned i = 0; i < 255; ++i)
  405. a1.binary.push_back(i);
  406. a1.date = Wt::WDate(1976, 6, 14);
  407. a1.time = Wt::WTime(13, 14, 15, 102);
  408. // There is a bug in the implementation of milliseconds in mariadb c client
  409. #ifdef MYSQL
  410. a1.time = Wt::WTime(13, 14, 15);
  411. #endif //MYSQL
  412. a1.wstring = "Hello";
  413. a1.wstring2 = Wt::WString::fromUTF8("Kitty euro\xe2\x82\xac greek \xc6\x94");
  414. a1.string = "There";
  415. a1.string2 = "Big Owl";
  416. a1.ptime = boost::posix_time::ptime
  417. (boost::gregorian::date(2005,boost::gregorian::Jan,1),
  418. boost::posix_time::time_duration(1,2,3));
  419. a1.pduration = boost::posix_time::hours(1) +
  420. boost::posix_time::seconds(10);
  421. a1.checked = true;
  422. a1.i = 42;
  423. a1.i64 = 9223372036854775805LL;
  424. a1.ll = 6066005651767221LL;
  425. a1.f = (float)42.42;
  426. a1.d = 42.424242;
  427. /* Create an A, check that it is found during the same transaction */
  428. {
  429. dbo::Transaction t(*session_);
  430. dbo::ptr<A> ptrA = session_->add(new A(a1));
  431. BOOST_REQUIRE(ptrA->session() == session_);
  432. BOOST_REQUIRE(ptrA->self() == ptrA);
  433. As allAs = session_->find<A>();
  434. BOOST_REQUIRE(allAs.size() == 1);
  435. dbo::ptr<A> a2 = *allAs.begin();
  436. BOOST_REQUIRE(*a2 == a1);
  437. BOOST_REQUIRE(a2->self() == ptrA);
  438. }
  439. /* Check that A is found during other transaction */
  440. {
  441. dbo::Transaction t(*session_);
  442. As allAs = session_->find<A>();
  443. BOOST_REQUIRE(allAs.size() == 1);
  444. dbo::ptr<A> a2 = *allAs.begin();
  445. BOOST_REQUIRE(*a2 == a1);
  446. a2.modify()->parent = a2;
  447. }
  448. /* Remove the A, check it is no longer found during the same transaction */
  449. {
  450. dbo::Transaction t(*session_);
  451. {
  452. As allAs = session_->find<A>();
  453. BOOST_REQUIRE(allAs.size() == 1);
  454. dbo::ptr<A> a2 = *allAs.begin();
  455. BOOST_REQUIRE(a2->parent == a2);
  456. // NOTE: if you do not reset self-reference in parent, memory is leaked
  457. a2.modify()->parent.reset();
  458. #ifdef MYSQL
  459. a2.flush();
  460. #endif
  461. a2.remove();
  462. }
  463. {
  464. As allAs = session_->find<A>();
  465. BOOST_REQUIRE(allAs.size() == 0);
  466. }
  467. t.commit();
  468. }
  469. /* Check it is no longer found during other transaction */
  470. {
  471. dbo::Transaction t(*session_);
  472. As allAs = session_->find<A>();
  473. BOOST_REQUIRE(allAs.size() == 0);
  474. }
  475. }
  476. BOOST_AUTO_TEST_CASE( dbo_test2 )
  477. {
  478. DboFixture f;
  479. dbo::Session *session_ = f.session_;
  480. A a1;
  481. a1.datetime = Wt::WDateTime(Wt::WDate(2009, 10, 1), Wt::WTime(12, 11, 31));
  482. a1.date = Wt::WDate(1980, 12, 4);
  483. a1.time = Wt::WTime(12, 13, 14, 123);
  484. // There is a bug in the implementation of milliseconds in mariadb c client
  485. #ifdef MYSQL
  486. a1.time = Wt::WTime(13, 14, 15);
  487. #endif //MYSQL
  488. a1.wstring = "Hello";
  489. a1.string = "There";
  490. a1.checked = false;
  491. a1.i = 42;
  492. a1.i64 = 9223372036854775804LL;
  493. a1.ll = 6066005651767221LL;
  494. a1.f = (float)42.42;
  495. a1.d = 42.424242;
  496. B b1;
  497. b1.name = "b1";
  498. b1.state = B::State1;
  499. /* Create an A + B */
  500. {
  501. dbo::Transaction t(*session_);
  502. a1.b = session_->add(new B(b1));
  503. dbo::ptr<A> a = session_->add(new A(a1));
  504. As allAs = session_->find<A>();
  505. BOOST_REQUIRE(allAs.size() == 1);
  506. dbo::ptr<A> a2 = *allAs.begin();
  507. BOOST_REQUIRE(*a2 == a1);
  508. }
  509. /* Check that A + B are found in other transaction */
  510. {
  511. dbo::Transaction t(*session_);
  512. As allAs = session_->find<A>();
  513. BOOST_REQUIRE(allAs.size() == 1);
  514. dbo::ptr<A> a2 = *allAs.begin();
  515. BOOST_REQUIRE(*a2 == a1);
  516. BOOST_REQUIRE(*a2->b == b1);
  517. }
  518. }
  519. BOOST_AUTO_TEST_CASE( dbo_test3 )
  520. {
  521. DboFixture f;
  522. dbo::Session *session_ = f.session_;
  523. /* Create B's many-to-many C's */
  524. {
  525. dbo::Transaction t(*session_);
  526. dbo::ptr<B> b1 = session_->add(new B("b1", B::State1));
  527. dbo::ptr<B> b2 = session_->add(new B("b2", B::State2));
  528. dbo::ptr<B> b3 = session_->add(new B("b3", B::State1));
  529. dbo::ptr<C> c1 = session_->add(new C("c1"));
  530. dbo::ptr<C> c2 = session_->add(new C("c2"));
  531. dbo::ptr<C> c3 = session_->add(new C("c3"));
  532. B *m = b1.modify();
  533. m->csManyToMany.insert(c1);
  534. BOOST_REQUIRE(b1->csManyToMany.size() == 1);
  535. BOOST_REQUIRE(c1->bsManyToMany.size() == 1);
  536. BOOST_REQUIRE(c1->bsManyToMany.count(b1) == 1);
  537. BOOST_REQUIRE(c1->bsManyToMany.count(b2) == 0);
  538. BOOST_REQUIRE(c1->bsManyToMany.count(b3) == 0);
  539. BOOST_REQUIRE(b1->csManyToMany.count(c1) == 1);
  540. BOOST_REQUIRE(b1->csManyToMany.count(c2) == 0);
  541. BOOST_REQUIRE(b1->csManyToMany.count(c3) == 0);
  542. b1.modify()->csManyToMany.insert(c2);
  543. BOOST_REQUIRE(b1->csManyToMany.size() == 2);
  544. BOOST_REQUIRE(c1->bsManyToMany.size() == 1);
  545. BOOST_REQUIRE(c2->bsManyToMany.size() == 1);
  546. BOOST_REQUIRE(c3->bsManyToMany.size() == 0);
  547. Cs cs = b1->csManyToMany;
  548. for (Cs::const_iterator i = cs.begin(); i != cs.end(); ++i) {
  549. std::cerr << "C: " << (*i)->name << std::endl;
  550. }
  551. b1.modify()->csManyToMany.erase(c2);
  552. BOOST_REQUIRE(b1->csManyToMany.size() == 1);
  553. BOOST_REQUIRE(c1->bsManyToMany.size() == 1);
  554. BOOST_REQUIRE(c2->bsManyToMany.size() == 0);
  555. BOOST_REQUIRE(c3->bsManyToMany.size() == 0);
  556. b1.modify()->csManyToMany.insert(c2);
  557. b1.modify()->csManyToMany.erase(c2);
  558. BOOST_REQUIRE(b1->csManyToMany.size() == 1);
  559. BOOST_REQUIRE(c1->bsManyToMany.size() == 1);
  560. BOOST_REQUIRE(c2->bsManyToMany.size() == 0);
  561. BOOST_REQUIRE(c3->bsManyToMany.size() == 0);
  562. /*
  563. * I had to write this example to convince myself that I actually
  564. * implemented this so that this kind of things simply work !
  565. */
  566. dbo::collection<std::string> names
  567. = session_->query<std::string>("select \"name\" from " SCHEMA "\"table_b\"");
  568. for (dbo::collection<std::string>::const_iterator i = names.begin();
  569. i != names.end(); ++i)
  570. std::cerr << *i << std::endl;
  571. }
  572. {
  573. dbo::Transaction t(*session_);
  574. dbo::ptr<B> b1 = session_->query< dbo::ptr<B> >
  575. ("select distinct B from " SCHEMA "\"table_b\" B ").where("B.\"name\" = ?").bind("b1");
  576. std::size_t count = session_->query< dbo::ptr<B> >
  577. ("select distinct B from " SCHEMA "\"table_b\" B ").where("B.\"name\" = ?").bind("b1")
  578. .resultList().size();
  579. dbo::ptr<C> c1 = session_->find<C>().where("\"name\" = ?").bind("c1");
  580. BOOST_REQUIRE(count == 1);
  581. BOOST_REQUIRE(b1->csManyToMany.size() == 1);
  582. BOOST_REQUIRE(c1->bsManyToMany.size() == 1);
  583. //this test case does not work in firebird,
  584. //the name field is of the 'blob subtype text' datatype,
  585. //and according to the firebird documentation,
  586. //order by is not supported on columns of this datatype
  587. //http://www.firebirdsql.org/refdocs/langrefupd21-blob.html
  588. #ifndef FIREBIRD
  589. typedef dbo::collection<dbo::ptr<C> > Cs;
  590. Cs c2 = session_->find<C>().orderBy("\"name\" desc");
  591. Cs c3 = session_->find<C>().orderBy("\"name\" desc").limit(2);
  592. std::vector<std::string> c2_compare;
  593. c2_compare.push_back("c3");
  594. c2_compare.push_back("c2");
  595. c2_compare.push_back("c1");
  596. std::vector<std::string> c3_compare;
  597. c3_compare.push_back("c3");
  598. c3_compare.push_back("c2");
  599. int c = 0;
  600. BOOST_REQUIRE(c2.size() == c2_compare.size());
  601. for (Cs::const_iterator i = c2.begin(); i != c2.end(); ++i)
  602. BOOST_REQUIRE((*i)->name == c2_compare[c++]);
  603. c = 0;
  604. BOOST_REQUIRE(c3.size() == c3_compare.size());
  605. for (Cs::const_iterator i = c3.begin(); i != c3.end(); ++i)
  606. BOOST_REQUIRE((*i)->name == c3_compare[c++]);
  607. #endif
  608. }
  609. }
  610. BOOST_AUTO_TEST_CASE( dbo_test4 )
  611. {
  612. DboFixture f;
  613. dbo::Session *session_ = f.session_;
  614. {
  615. dbo::Transaction t(*session_);
  616. dbo::ptr<A> a1(new A());
  617. BOOST_REQUIRE(a1->self() == a1);
  618. a1.modify()->datetime = Wt::WDateTime(Wt::WDate(2009, 10, 1),
  619. Wt::WTime(12, 11, 31));
  620. a1.modify()->date = Wt::WDate(1980, 12, 4);
  621. a1.modify()->wstring = "Hello";
  622. a1.modify()->string = "There";
  623. a1.modify()->i = 42;
  624. a1.modify()->i64 = 9223372036854775803LL;
  625. a1.modify()->ll = 6066005651767220LL;
  626. a1.modify()->f = (float)42.42;
  627. a1.modify()->d = 42.424242;
  628. dbo::ptr<A> a2(new A(*a1));
  629. a2.modify()->wstring = "Oh my god";
  630. a2.modify()->i = 142;
  631. dbo::ptr<B> b(new B());
  632. b.modify()->name = "b";
  633. b.modify()->state = B::State1;
  634. a1.modify()->b = b;
  635. a2.modify()->b = b;
  636. session_->add(a1);
  637. session_->add(a2);
  638. session_->add(b);
  639. typedef dbo::ptr_tuple<B, A>::type BA;
  640. typedef dbo::collection<BA> BAs;
  641. // The query below becomes:
  642. // select count(1) from ( select B."id", B."name", A."id", A."date", A."b_id"
  643. // from "table_b" B join "table_a" A on A."b_id" = B."id");
  644. // when it is used to return the size of the collection.
  645. // This is not valid SQL by the SQL standard definition,
  646. // because 2 id fields are mentioned in the select clause.
  647. //
  648. // A valid alternative would be:
  649. // select count(1) from ( select B."id", B."name", A."id" as id2, A."date",
  650. // A."b_id" from "table_b" B join "table_a" A on A."b_id" = B."id");
  651. //
  652. // Firebird & mysql are not able to execute this query.
  653. #if !defined(FIREBIRD) && !defined(MYSQL)
  654. dbo::Query<BA> q = session_->query<BA>
  655. ("select B, A "
  656. "from " SCHEMA "\"table_b\" B join " SCHEMA "\"table_a\" A on A.\"b_id\" = B.\"id\"")
  657. .orderBy("A.\"i\"");
  658. std::vector<dbo::FieldInfo> fields = q.fields();
  659. std::vector<dbo::FieldInfo> fields2 = q.fields();
  660. BOOST_REQUIRE(fields.size() == fields2.size());
  661. BAs bas;
  662. bas = q.resultList();
  663. BOOST_REQUIRE(bas.size() == 2);
  664. int ii = 0;
  665. for (BAs::const_iterator i = bas.begin(); i != bas.end(); ++i) {
  666. dbo::ptr<A> a_result;
  667. dbo::ptr<B> b_result;
  668. boost::tie(b_result, a_result) = *i;
  669. if (ii == 0) {
  670. BOOST_REQUIRE(a_result == a1);
  671. BOOST_REQUIRE(b_result == b);
  672. } else if (ii == 1) {
  673. BOOST_REQUIRE(a_result == a2);
  674. BOOST_REQUIRE(b_result == b);
  675. }
  676. ++ii;
  677. }
  678. BOOST_REQUIRE(ii == 2);
  679. #endif //FIREBIRD && MYSQL
  680. }
  681. }
  682. BOOST_AUTO_TEST_CASE( dbo_test4b )
  683. {
  684. DboFixture f;
  685. dbo::Session *session_ = f.session_;
  686. {
  687. dbo::Transaction t(*session_);
  688. dbo::ptr<A> a1(new A());
  689. dbo::ptr<A> a2(new A());
  690. dbo::ptr<A> a3(new A());
  691. dbo::ptr<A> a4(new A());
  692. dbo::ptr<A> a5(new A());
  693. dbo::ptr<A> a6(new A());
  694. dbo::ptr<B> b1(new B());
  695. dbo::ptr<B> b2(new B());
  696. dbo::ptr<B> b3(new B());
  697. dbo::ptr<C> c1(new C());
  698. dbo::ptr<C> c2(new C());
  699. dbo::ptr<C> c3(new C());
  700. a1.modify()->wstring = "a1";
  701. a2.modify()->wstring = "a2";
  702. a3.modify()->wstring = "a3";
  703. a4.modify()->wstring = "a4";
  704. a5.modify()->wstring = "a5";
  705. a6.modify()->wstring = "a6";
  706. b1.modify()->name = "b1";
  707. b2.modify()->name = "b2";
  708. b3.modify()->name = "b3";
  709. c1.modify()->name = "c1";
  710. c2.modify()->name = "c2";
  711. c3.modify()->name = "c3";
  712. a1.modify()->b = b1;
  713. a2.modify()->b = b1;
  714. a3.modify()->b = b2;
  715. a4.modify()->b = b2;
  716. a5.modify()->b = b3;
  717. a6.modify()->b = b3;
  718. c1.modify()->b = b1;
  719. c2.modify()->b = b2;
  720. c3.modify()->b = b3;
  721. session_->add(b1);
  722. session_->add(b2);
  723. session_->add(b3);
  724. session_->add(a1);
  725. session_->add(a2);
  726. session_->add(a3);
  727. session_->add(a4);
  728. session_->add(a5);
  729. session_->add(a6);
  730. session_->add(c1);
  731. session_->add(c2);
  732. session_->add(c3);
  733. }
  734. {
  735. dbo::Transaction t(*session_);
  736. typedef dbo::ptr_tuple<A, B, C>::type ABC;
  737. typedef dbo::collection<ABC> C_ABCs;
  738. typedef std::vector<ABC> ABCs;
  739. #if !defined(FIREBIRD) && !defined(MYSQL)
  740. dbo::Query<ABC> q = session_->query<ABC>
  741. ("select A, B, C "
  742. "from " SCHEMA "\"table_a\" A join " SCHEMA "\"table_b\" B on (A.\"b_id\" = B.\"id\") join " SCHEMA "\"table_c\" C on (C.\"b2_id\" = B.\"id\")")
  743. .orderBy("A.\"id\"");
  744. C_ABCs c_abcs = q.resultList();
  745. ABCs abcs(c_abcs.begin(), c_abcs.end());
  746. BOOST_REQUIRE(abcs.size() == 6);
  747. int ii = 0;
  748. for (ABCs::const_iterator i = abcs.begin(); i != abcs.end(); ++i) {
  749. dbo::ptr<A> a_result;
  750. dbo::ptr<B> b_result;
  751. dbo::ptr<C> c_result;
  752. boost::tie(a_result, b_result, c_result) = *i;
  753. switch (ii)
  754. {
  755. case 0:
  756. BOOST_REQUIRE(a_result->wstring == "a1");
  757. BOOST_REQUIRE(b_result->name == "b1");
  758. BOOST_REQUIRE(c_result->name == "c1");
  759. break;
  760. case 1:
  761. BOOST_REQUIRE(a_result->wstring == "a2");
  762. BOOST_REQUIRE(b_result->name == "b1");
  763. BOOST_REQUIRE(c_result->name == "c1");
  764. break;
  765. case 2:
  766. BOOST_REQUIRE(a_result->wstring == "a3");
  767. BOOST_REQUIRE(b_result->name == "b2");
  768. BOOST_REQUIRE(c_result->name == "c2");
  769. break;
  770. case 3:
  771. BOOST_REQUIRE(a_result->wstring == "a4");
  772. BOOST_REQUIRE(b_result->name == "b2");
  773. BOOST_REQUIRE(c_result->name == "c2");
  774. break;
  775. case 4:
  776. BOOST_REQUIRE(a_result->wstring == "a5");
  777. BOOST_REQUIRE(b_result->name == "b3");
  778. BOOST_REQUIRE(c_result->name == "c3");
  779. break;
  780. case 5:
  781. BOOST_REQUIRE(a_result->wstring == "a6");
  782. BOOST_REQUIRE(b_result->name == "b3");
  783. BOOST_REQUIRE(c_result->name == "c3");
  784. break;
  785. }
  786. ++ii;
  787. }
  788. BOOST_REQUIRE(ii == 6);
  789. #endif //FIREBIRD && MYSQL
  790. }
  791. }
  792. BOOST_AUTO_TEST_CASE( dbo_test4c )
  793. {
  794. DboFixture f;
  795. dbo::Session *session_ = f.session_;
  796. {
  797. dbo::Transaction t(*session_);
  798. dbo::ptr<A> a1(new A());
  799. dbo::ptr<A> a2(new A());
  800. dbo::ptr<A> a3(new A());
  801. dbo::ptr<A> a4(new A());
  802. dbo::ptr<B> b1(new B());
  803. dbo::ptr<B> b2(new B());
  804. dbo::ptr<C> c1(new C());
  805. dbo::ptr<C> c2(new C());
  806. a1.modify()->wstring = "a1";
  807. a2.modify()->wstring = "a2";
  808. a3.modify()->wstring = "a3";
  809. a4.modify()->wstring = "a4";
  810. b1.modify()->name = "b1";
  811. b2.modify()->name = "b2";
  812. c1.modify()->name = "c1";
  813. c2.modify()->name = "c2";
  814. a1.modify()->b = b1;
  815. a1.modify()->c = c1;
  816. // a2 has no c
  817. a2.modify()->b = b2;
  818. // a3 has no b
  819. a3.modify()->c = c2;
  820. // a4 has no b or c
  821. session_->add(b1);
  822. session_->add(b2);
  823. session_->add(c1);
  824. session_->add(c2);
  825. session_->add(a1);
  826. session_->add(a2);
  827. session_->add(a3);
  828. session_->add(a4);
  829. }
  830. {
  831. dbo::Transaction t(*session_);
  832. typedef dbo::ptr_tuple<A, B, C>::type ABC;
  833. typedef dbo::collection<ABC> C_ABCs;
  834. typedef std::vector<ABC> ABCs;
  835. #if !defined(FIREBIRD) && !defined(MYSQL)
  836. dbo::Query<ABC> q = session_->query<ABC>
  837. ("select A, B, C "
  838. "from " SCHEMA "\"table_a\" A "
  839. "left join " SCHEMA "\"table_b\" B on A.\"b_id\" = B.\"id\" "
  840. "left join " SCHEMA "\"table_c\" C on A.\"" SCHEMA "table_c_id\" = C.\"id\"")
  841. .orderBy("A.\"id\"");
  842. C_ABCs c_abcs = q.resultList();
  843. ABCs abcs(c_abcs.begin(), c_abcs.end());
  844. BOOST_REQUIRE(abcs.size() == 4);
  845. int ii = 0;
  846. for (ABCs::const_iterator i = abcs.begin(); i != abcs.end(); ++i) {
  847. dbo::ptr<A> a_result;
  848. dbo::ptr<B> b_result;
  849. dbo::ptr<C> c_result;
  850. boost::tie(a_result, b_result, c_result) = *i;
  851. switch (ii)
  852. {
  853. case 0:
  854. BOOST_REQUIRE(a_result->wstring == "a1");
  855. BOOST_REQUIRE(b_result->name == "b1");
  856. BOOST_REQUIRE(c_result->name == "c1");
  857. break;
  858. case 1:
  859. BOOST_REQUIRE(a_result->wstring == "a2");
  860. BOOST_REQUIRE(b_result->name == "b2");
  861. BOOST_REQUIRE(!a_result->c);
  862. break;
  863. case 2:
  864. BOOST_REQUIRE(a_result->wstring == "a3");
  865. BOOST_REQUIRE(!a_result->b);
  866. BOOST_REQUIRE(c_result->name == "c2");
  867. break;
  868. case 3:
  869. BOOST_REQUIRE(a_result->wstring == "a4");
  870. BOOST_REQUIRE(!a_result->b);
  871. BOOST_REQUIRE(!a_result->c);
  872. break;
  873. }
  874. ++ii;
  875. }
  876. BOOST_REQUIRE(ii == 4);
  877. #endif //FIREBIRD && MYSQL
  878. }
  879. }
  880. BOOST_AUTO_TEST_CASE( dbo_test5 )
  881. {
  882. DboFixture f;
  883. dbo::Session *session_ = f.session_;
  884. {
  885. dbo::Transaction t(*session_);
  886. dbo::ptr<A> a1(new A());
  887. a1.modify()->datetime = Wt::WDateTime(Wt::WDate(2009, 10, 1),
  888. Wt::WTime(12, 11, 31));
  889. a1.modify()->date = Wt::WDate(1976, 11, 1);
  890. a1.modify()->wstring = "Hello";
  891. a1.modify()->string = "There";
  892. a1.modify()->i = 42;
  893. a1.modify()->i64 = 9223372036854775802LL;
  894. a1.modify()->ll = 6066005651767219LL;
  895. a1.modify()->f = (float)42.42;
  896. a1.modify()->d = 42.424242;
  897. dbo::ptr<A> a2(new A(*a1));
  898. a2.modify()->wstring = "Oh my god";
  899. a2.modify()->i = 142;
  900. dbo::ptr<B> b(new B());
  901. b.modify()->name = "b";
  902. b.modify()->state = B::State1;
  903. a1.modify()->b = b;
  904. a2.modify()->b = b;
  905. session_->add(a1);
  906. session_->add(a2);
  907. session_->add(b);
  908. session_->flush();
  909. t.rollback();
  910. a1.remove();
  911. a2.remove();
  912. b.remove();
  913. }
  914. {
  915. dbo::Transaction t(*session_);
  916. }
  917. }
  918. BOOST_AUTO_TEST_CASE( dbo_test6 )
  919. {
  920. DboFixture f;
  921. dbo::Session *session_ = f.session_;
  922. {
  923. dbo::Transaction t(*session_);
  924. dbo::ptr<A> a1(new A());
  925. a1.modify()->datetime = Wt::WDateTime(Wt::WDate(2009, 10, 1),
  926. Wt::WTime(12, 11, 31));
  927. a1.modify()->date = Wt::WDate(1980, 1, 1);
  928. a1.modify()->wstring = "Hello";
  929. a1.modify()->string = "There";
  930. a1.modify()->i = 42;
  931. a1.modify()->i64 = 9223372036854775802LL;
  932. a1.modify()->ll = 6066005651767219LL;
  933. a1.modify()->f = (float)42.42;
  934. a1.modify()->d = 42.424242;
  935. session_->add(a1);
  936. }
  937. {
  938. dbo::Transaction t(*session_);
  939. dbo::ptr<A> a1 = session_->find<A>();
  940. a1.modify()->i = 41;
  941. a1.flush();
  942. t.rollback();
  943. session_->rereadAll();
  944. dbo::Transaction t2(*session_);
  945. dbo::ptr<A> a2 = session_->find<A>();
  946. BOOST_REQUIRE(a1 == a2);
  947. BOOST_REQUIRE(a1->i == 42);
  948. t2.commit();
  949. }
  950. }
  951. BOOST_AUTO_TEST_CASE( dbo_test7 )
  952. {
  953. DboFixture f;
  954. dbo::Session *session_ = f.session_;
  955. #ifndef FIREBIRD
  956. #ifndef ORACLE //todo: ask koen http://stackoverflow.com/questions/1881853/oracle-select-without-from
  957. {
  958. dbo::Transaction t(*session_);
  959. std::string result = session_->query<std::string > ("select 'dima '' ? '");
  960. BOOST_REQUIRE(result == "dima ' ? ");
  961. }
  962. #endif // ORACLE
  963. #endif //FIREBIRD
  964. int aId = -1;
  965. {
  966. dbo::Transaction t(*session_);
  967. dbo::ptr<A> a1(new A());
  968. a1.modify()->datetime = Wt::WDateTime(Wt::WDate(2009, 10, 1),
  969. Wt::WTime(12, 11, 31));
  970. a1.modify()->date = Wt::WDate(1980, 1, 1);
  971. a1.modify()->wstring = "Hello";
  972. a1.modify()->string = "There";
  973. a1.modify()->i = 42;
  974. a1.modify()->i64 = 9223372036854775801LL;
  975. a1.modify()->ll = 6066005651767219LL;
  976. a1.modify()->f = (float)42.42;
  977. a1.modify()->d = 42.424242;
  978. session_->add(a1);
  979. a1.flush();
  980. aId = (int)a1.id();
  981. }
  982. {
  983. dbo::Transaction t(*session_);
  984. int id1, id2;
  985. boost::tie(id1, id2) = session_->query<boost::tuple<int, int> >
  986. ("select \"id\", \"id\" from " SCHEMA "\"table_a\"").resultValue();
  987. BOOST_REQUIRE(id1 == aId);
  988. BOOST_REQUIRE(id2 == aId);
  989. #ifdef POSTGRES
  990. dbo::ptr<A> a;
  991. int id;
  992. boost::tie(a, id) = session_->query<boost::tuple<dbo::ptr<A>, int> >
  993. ("select (a), a.\"id\" from " SCHEMA "\"table_a\" a").resultValue();
  994. BOOST_REQUIRE(id == aId);
  995. BOOST_REQUIRE(a.id() == aId);
  996. #endif
  997. }
  998. }
  999. BOOST_AUTO_TEST_CASE( dbo_test8 )
  1000. {
  1001. DboFixture f;
  1002. dbo::Session *session_ = f.session_;
  1003. {
  1004. dbo::Transaction t(*session_);
  1005. session_->execute("delete from " SCHEMA "\"table_a\"");
  1006. }
  1007. }
  1008. BOOST_AUTO_TEST_CASE( dbo_test9 )
  1009. {
  1010. DboFixture f;
  1011. dbo::Session *session_ = f.session_;
  1012. {
  1013. dbo::Transaction t(*session_);
  1014. dbo::ptr<A> a(new A());
  1015. typedef dbo::query_result_traits< dbo::ptr<A> > A_traits;
  1016. std::vector<boost::any> values;
  1017. A_traits::getValues(a, values);
  1018. std::cerr << values.size() << std::endl;
  1019. }
  1020. }
  1021. BOOST_AUTO_TEST_CASE( dbo_test10 )
  1022. {
  1023. DboFixture f;
  1024. dbo::Session *session_ = f.session_;
  1025. {
  1026. dbo::Transaction t(*session_);
  1027. dbo::ptr<D> d(new D());
  1028. BOOST_REQUIRE(Wt::asString(boost::any(Coordinate(10, 4)))
  1029. == "(10, 4)");
  1030. d.modify()->id = Coordinate(42, 43);
  1031. d.modify()->name = "Object @ (42, 43)";
  1032. session_->add(d);
  1033. t.commit();
  1034. // No transaction, but should just fetch it from the session.
  1035. // This checks that saving the dbo sets the id properly
  1036. BOOST_REQUIRE(session_->load<D>(Coordinate(42, 43)) == d);
  1037. }
  1038. {
  1039. dbo::Transaction t2(*session_);
  1040. try {
  1041. session_->load<D>(Coordinate(10, 11));
  1042. BOOST_REQUIRE(false); // Expected an exception
  1043. } catch (const dbo::ObjectNotFoundException&) {
  1044. }
  1045. dbo::ptr<D> d2 = session_->load<D>(Coordinate(42, 43));
  1046. BOOST_REQUIRE(d2 && d2.id() == Coordinate(42, 43));
  1047. dbo::ptr<C> c1 = session_->add(new C("c1"));
  1048. dbo::ptr<C> c2 = session_->add(new C("c2"));
  1049. dbo::ptr<C> c3 = session_->add(new C("c3"));
  1050. d2.modify()->csManyToMany.insert(c1);
  1051. BOOST_REQUIRE(d2->csManyToMany.size() == 1);
  1052. BOOST_REQUIRE(c1->dsManyToMany.size() == 1);
  1053. BOOST_REQUIRE(d2->csManyToMany.count(c1) == 1);
  1054. std::cerr << "Failing now" << std::endl;
  1055. BOOST_REQUIRE(c1->dsManyToMany.count(d2) == 1);
  1056. d2.modify()->csManyToMany.insert(c2);
  1057. BOOST_REQUIRE(d2->csManyToMany.size() == 2);
  1058. BOOST_REQUIRE(c1->dsManyToMany.size() == 1);
  1059. BOOST_REQUIRE(c2->dsManyToMany.size() == 1);
  1060. BOOST_REQUIRE(c3->dsManyToMany.size() == 0);
  1061. d2.modify()->csManyToMany.erase(c2);
  1062. BOOST_REQUIRE(d2->csManyToMany.size() == 1);
  1063. BOOST_REQUIRE(c1->dsManyToMany.size() == 1);
  1064. BOOST_REQUIRE(c2->dsManyToMany.size() == 0);
  1065. BOOST_REQUIRE(c3->dsManyToMany.size() == 0);
  1066. d2.modify()->csManyToMany.insert(c2);
  1067. d2.modify()->csManyToMany.erase(c2);
  1068. BOOST_REQUIRE(d2->csManyToMany.size() == 1);
  1069. BOOST_REQUIRE(c1->dsManyToMany.size() == 1);
  1070. BOOST_REQUIRE(c2->dsManyToMany.size() == 0);
  1071. BOOST_REQUIRE(c3->dsManyToMany.size() == 0);
  1072. }
  1073. {
  1074. /*
  1075. * Check that we fail gracefully when inserting an object with a
  1076. * duplicate ID
  1077. */
  1078. dbo::Transaction t(*session_);
  1079. dbo::ptr<D> d(new D());
  1080. d.modify()->id = Coordinate(42, 43);
  1081. d.modify()->name = "Object2 @ (42, 43)";
  1082. session_->add(d);
  1083. bool caught = false;
  1084. try {
  1085. std::cerr << "The test was - check that we fail gracefully when inserting "
  1086. "an object with a duplicate ID (search try{)."<< std::endl;
  1087. t.commit();
  1088. } catch (std::exception& e) {
  1089. std::cerr << "Catching exception: " << e.what() << std::endl;
  1090. caught = true;
  1091. }
  1092. BOOST_REQUIRE(caught);
  1093. t.rollback();
  1094. {
  1095. dbo::Transaction t2(*session_);
  1096. dbo::ptr<D> d3 = session_->find<D>();
  1097. BOOST_REQUIRE(d3.id() == Coordinate(42, 43));
  1098. }
  1099. }
  1100. bool caught = false;
  1101. try {
  1102. dbo::Transaction outer(*session_);
  1103. {
  1104. /*
  1105. * Check that we fail gracefully when inserting an object with a
  1106. * duplicate ID
  1107. */
  1108. dbo::Transaction t(*session_);
  1109. dbo::ptr<D> d(new D());
  1110. d.modify()->id = Coordinate(42, 43);
  1111. d.modify()->name = "Object2 @ (42, 43)";
  1112. session_->add(d);
  1113. BOOST_REQUIRE(t.commit() == false); // Doesn't actaully commit
  1114. }
  1115. } catch (std::exception& e) {
  1116. std::cerr << "Catching exception: " << e.what() << std::endl;
  1117. caught = true;
  1118. }
  1119. BOOST_REQUIRE(caught);
  1120. }
  1121. BOOST_AUTO_TEST_CASE( dbo_test11 )
  1122. {
  1123. DboFixture f;
  1124. dbo::Session *session_ = f.session_;
  1125. {
  1126. dbo::Transaction t(*session_);
  1127. session_->add(new C("c1"));
  1128. dbo::Query< dbo::ptr<C> > query = session_->find<C>();
  1129. dbo::QueryModel< dbo::ptr<C> > *model
  1130. = new dbo::QueryModel< dbo::ptr<C> >();
  1131. model->setQuery(query);
  1132. t.commit();
  1133. boost::any d;
  1134. model->addAllFieldsAsColumns();
  1135. BOOST_REQUIRE(model->columnCount() == 4);
  1136. BOOST_REQUIRE(model->rowCount() == 1);
  1137. BOOST_REQUIRE(Wt::asString(model->headerData(0)) == "id");
  1138. BOOST_REQUIRE(Wt::asString(model->headerData(1)) == "version");
  1139. BOOST_REQUIRE(Wt::asString(model->headerData(2)) == "name");
  1140. BOOST_REQUIRE(Wt::asString(model->headerData(3)) == "b2_id");
  1141. BOOST_REQUIRE(Wt::asString(model->data(0, 2)) == "c1");
  1142. model->setData(0, 2, std::string("changed"));
  1143. BOOST_REQUIRE(Wt::asString(model->data(0, 2)) == "changed");
  1144. BOOST_REQUIRE(Wt::asString(model->data(0, 2)) == "changed");
  1145. {
  1146. dbo::Transaction t2(*session_);
  1147. dbo::ptr<C> c = session_->find<C>();
  1148. BOOST_REQUIRE(c->name == "changed");
  1149. }
  1150. model->insertRow(1);
  1151. model->setData(1, 2, std::string("new C"));
  1152. {
  1153. dbo::Transaction t2(*session_);
  1154. BOOST_REQUIRE(session_->find<C>().resultList().size() == 2);
  1155. }
  1156. model->removeRows(0, 2);
  1157. {
  1158. dbo::Transaction t2(*session_);
  1159. BOOST_REQUIRE(session_->find<C>().resultList().size() == 0);
  1160. }
  1161. delete model;
  1162. }
  1163. }
  1164. BOOST_AUTO_TEST_CASE( dbo_test12 )
  1165. {
  1166. DboFixture f;
  1167. dbo::Session *session_ = f.session_;
  1168. {
  1169. dbo::Transaction t(*session_);
  1170. session_->add(new D(Coordinate(5, 6), "yes"));
  1171. dbo::ptr<D> d1 = session_->find<D>();
  1172. BOOST_REQUIRE(d1->name == "yes");
  1173. BOOST_REQUIRE(d1->id == Coordinate(5, 6));
  1174. session_->add(new C("c1"));
  1175. dbo::Query< dbo::ptr<C> > query = session_->find<C>();
  1176. dbo::QueryModel< dbo::ptr<C> > *model
  1177. = new dbo::QueryModel< dbo::ptr<C> >();
  1178. model->setQuery(query);
  1179. boost::any d;
  1180. model->addAllFieldsAsColumns();
  1181. BOOST_REQUIRE(model->columnCount() == 4);
  1182. BOOST_REQUIRE(model->rowCount() == 1);
  1183. BOOST_REQUIRE(Wt::asString(model->headerData(0)) == "id");
  1184. BOOST_REQUIRE(Wt::asString(model->headerData(1)) == "version");
  1185. BOOST_REQUIRE(Wt::asString(model->headerData(2)) == "name");
  1186. BOOST_REQUIRE(Wt::asString(model->headerData(3)) == "b2_id");
  1187. BOOST_REQUIRE(Wt::asString(model->data(0, 2)) == "c1");
  1188. model->setData(0, 2, std::string("changed"));
  1189. BOOST_REQUIRE(Wt::asString(model->data(0, 2)) == "changed");
  1190. BOOST_REQUIRE(model->resultRow(0) == session_->find<C>());
  1191. BOOST_REQUIRE(model->stableResultRow(0) == session_->find<C>());
  1192. {
  1193. dbo::ptr<C> c = session_->find<C>();
  1194. BOOST_REQUIRE(c->name == "changed");
  1195. }
  1196. model->insertRow(1);
  1197. model->setData(1, 2, std::string("new C"));
  1198. BOOST_REQUIRE(session_->find<C>().resultList().size() == 2);
  1199. model->removeRow(0);
  1200. BOOST_REQUIRE(model->rowCount() == 1);
  1201. model->setData(0, 2, std::string("changed again"));
  1202. BOOST_REQUIRE(Wt::asString(model->data(0, 2)) == "changed again");
  1203. BOOST_REQUIRE(session_->find<C>().resultList().size() == 1);
  1204. {
  1205. dbo::ptr<C> c = session_->find<C>();
  1206. BOOST_REQUIRE(c->name == "changed again");
  1207. }
  1208. t.commit();
  1209. delete model;
  1210. }
  1211. }
  1212. BOOST_AUTO_TEST_CASE( dbo_test13 )
  1213. {
  1214. DboFixture f;
  1215. dbo::Session *session_ = f.session_;
  1216. {
  1217. dbo::Transaction t(*session_);
  1218. dbo::ptr<B> b1 = session_->add(new B("b1", B::State1));
  1219. dbo::ptr<B> b2 = session_->add(new B("b2", B::State2));
  1220. dbo::ptr<B> b3 = session_->add(new B("b3", B::State1));
  1221. {
  1222. dbo::collection<dbo::ptr<B> > c;
  1223. c = session_->query< dbo::ptr<B> >
  1224. ("select B from " SCHEMA "\"table_b\" B ")
  1225. .where("B.\"state\" = ?").orderBy("B.\"name\"")
  1226. .limit(1).bind(0);
  1227. BOOST_REQUIRE(c.size() == 1);
  1228. }
  1229. dbo::ptr<B> d = session_->query< dbo::ptr<B> >
  1230. ("select B from " SCHEMA "\"table_b\" B ")
  1231. .where("B.\"state\" = ?").orderBy("B.\"name\"")
  1232. .limit(1).bind(0);
  1233. BOOST_REQUIRE(d == b1 || d == b3);
  1234. }
  1235. }
  1236. BOOST_AUTO_TEST_CASE( dbo_test14 )
  1237. {
  1238. DboFixture f;
  1239. dbo::Session *session_ = f.session_;
  1240. A a1;
  1241. a1.datetime = Wt::WDateTime(Wt::WDate(2009, 10, 1), Wt::WTime(12, 11, 31));
  1242. a1.date = Wt::WDate(1980, 12, 4);
  1243. a1.time = Wt::WTime(12, 13, 14, 123);
  1244. a1.wstring = "Hello";
  1245. a1.string = "There";
  1246. a1.checked = false;
  1247. a1.i = 42;
  1248. a1.i64 = 9223372036854775804LL;
  1249. a1.ll = 6066005651767221LL;
  1250. a1.f = (float)42.42;
  1251. a1.d = 42.424242;
  1252. B b1;
  1253. b1.name = "b1";
  1254. b1.state = B::State1;
  1255. /* Create an A + B */
  1256. {
  1257. dbo::Transaction t(*session_);
  1258. dbo::ptr<A> a = session_->add(new A(a1));
  1259. dbo::ptr<B> b = session_->add(new B(b1));
  1260. BOOST_REQUIRE(!a->b);
  1261. b.modify()->asManyToOne.insert(a);
  1262. BOOST_REQUIRE(b->asManyToOne.count(dbo::ptr<A>()) == 0);
  1263. BOOST_REQUIRE(a->b == b);
  1264. BOOST_REQUIRE(b->asManyToOne.count(a) == 1);
  1265. b.modify()->asManyToOne.erase(a);
  1266. BOOST_REQUIRE(!a->b);
  1267. b.modify()->asManyToOne.insert(a);
  1268. }
  1269. /* Check that A + B are found in other transaction */
  1270. {
  1271. dbo::Transaction t(*session_);
  1272. As allAs = session_->find<A>();
  1273. BOOST_REQUIRE(allAs.size() == 1);
  1274. dbo::ptr<A> a2 = *allAs.begin();
  1275. BOOST_REQUIRE(*a2->b == b1);
  1276. }
  1277. }
  1278. BOOST_AUTO_TEST_CASE( dbo_test15 )
  1279. {
  1280. DboFixture f;
  1281. dbo::Session *session_ = f.session_;
  1282. {
  1283. dbo::Transaction t(*session_);
  1284. dbo::ptr<A> a = session_->add(new A());
  1285. dbo::ptr<B> b = session_->add(new B("b", B::State1));
  1286. a.modify()->b = b;
  1287. {
  1288. dbo::collection<dbo::ptr<A> > c = session_->query< dbo::ptr<A> >
  1289. ("select A from " SCHEMA "\"table_a\" A ").where("\"b_id\" = ?").bind(b);
  1290. BOOST_REQUIRE(c.size() == 1);
  1291. }
  1292. }
  1293. }
  1294. BOOST_AUTO_TEST_CASE( dbo_test16 )
  1295. {
  1296. DboFixture f;
  1297. dbo::Session *session = f.session_;
  1298. {
  1299. dbo::Transaction t(*session);
  1300. A a1;
  1301. a1.date = Wt::WDate(1976, 6, 14);
  1302. a1.time = Wt::WTime(13, 14, 15, 102);
  1303. for (unsigned i = 0; i < 255; ++i)
  1304. a1.binary.push_back(i);
  1305. a1.datetime = Wt::WDateTime(Wt::WDate(2009, 10, 1), Wt::WTime(12, 11, 31));
  1306. a1.wstring = "Hello";
  1307. a1.string = "There";
  1308. a1.ptime = boost::posix_time::ptime
  1309. (boost::gregorian::date(2005,boost::gregorian::Jan,1),
  1310. boost::posix_time::time_duration(1,2,3));
  1311. a1.pduration = boost::posix_time::hours(1) + boost::posix_time::seconds(10);
  1312. a1.i = 42;
  1313. a1.i64 = 9223372036854775805LL;
  1314. a1.ll = 6066005651767221LL;
  1315. a1.checked = true;
  1316. a1.f = (float)42.42;
  1317. a1.d = 42.424242;
  1318. dbo::ptr<A> a = session->add(new A());
  1319. t.commit();
  1320. {
  1321. dbo::Transaction t(*session);
  1322. dbo::Query< dbo::ptr<A> > query = session->find<A>();
  1323. dbo::QueryModel< dbo::ptr<A> > *model
  1324. = new dbo::QueryModel< dbo::ptr<A> >();
  1325. model->setQuery(query);
  1326. model->addColumn ("date");
  1327. model->addColumn ("time");
  1328. model->addColumn ("binary");
  1329. model->addColumn ("datetime");
  1330. model->addColumn ("wstring");
  1331. model->addColumn ("string");
  1332. model->addColumn ("ptime");
  1333. model->addColumn ("pduration");
  1334. model->addColumn ("i");
  1335. model->addColumn ("i64");
  1336. model->addColumn ("ll");
  1337. model->addColumn ("checked");
  1338. model->addColumn ("f");
  1339. model->addColumn ("d");
  1340. Wt::WDate date(1982, 12, 2);
  1341. Wt::WTime time(14, 15, 16, 0);
  1342. std::vector<unsigned char> bin;
  1343. for (unsigned i = 0; i < 255; ++i)
  1344. bin.push_back(255 - i);
  1345. Wt::WString ws("Hey");
  1346. std::string s("Test");
  1347. boost::posix_time::ptime p_time
  1348. (boost::gregorian::date(2010,boost::gregorian::Sep,9),
  1349. boost::posix_time::time_duration(3,2,1));
  1350. boost::posix_time::time_duration p_duration
  1351. = boost::posix_time::hours(1) + boost::posix_time::seconds(10);
  1352. int i = 50;
  1353. ::int64_t i64 = 8223372036854775805LL;;
  1354. long long ll = 7066005651767221LL;
  1355. float f = (float)53.53;
  1356. double d = 53.5353;
  1357. bool checked = false;
  1358. model->setData(0, 0, boost::any(date));
  1359. model->setData(0, 1, boost::any(time));
  1360. model->setData(0, 2, boost::any(bin));
  1361. model->setData(0, 3, boost::any(Wt::WDateTime(date, time)));
  1362. model->setData(0, 4, boost::any(ws));
  1363. model->setData(0, 5, boost::any(s));
  1364. model->setData(0, 6, boost::any(p_time));
  1365. model->setData(0, 7, boost::any(p_duration));
  1366. model->setData(0, 8, boost::any(i));
  1367. model->setData(0, 9, boost::any(i64));
  1368. model->setData(0, 10, boost::any(ll));
  1369. model->setData(0, 11, boost::any(checked));
  1370. model->setData(0, 12, boost::any(f));
  1371. model->setData(0, 13, boost::any(d));
  1372. //TODO, also set data using strings to test string to any value conversion
  1373. dbo::ptr<A> aa = session->find<A>().resultValue();
  1374. BOOST_REQUIRE(aa->date == date);
  1375. BOOST_REQUIRE(aa->time == time);
  1376. BOOST_REQUIRE(aa->binary == bin);
  1377. BOOST_REQUIRE(aa->datetime == Wt::WDateTime(date, time));
  1378. BOOST_REQUIRE(aa->wstring == ws);
  1379. BOOST_REQUIRE(aa->string == s);
  1380. BOOST_REQUIRE(aa->ptime == p_time);
  1381. BOOST_REQUIRE(aa->pduration == p_duration);
  1382. BOOST_REQUIRE(aa->i == i);
  1383. BOOST_REQUIRE(aa->i64 == i64);
  1384. BOOST_REQUIRE(aa->ll == ll);
  1385. BOOST_REQUIRE(aa->checked == checked);
  1386. BOOST_REQUIRE(aa->f == f);
  1387. BOOST_REQUIRE(aa->d == d);
  1388. delete model;
  1389. }
  1390. }
  1391. }
  1392. BOOST_AUTO_TEST_CASE( dbo_test17 )
  1393. {
  1394. DboFixture f;
  1395. dbo::Session *session_ = f.session_;
  1396. {
  1397. dbo::Transaction t(*session_);
  1398. dbo::ptr<A> a = session_->add(new A());
  1399. dbo::ptr<B> b = session_->add(new B("b", B::State1));
  1400. a.modify()->b = b;
  1401. }
  1402. #if !defined(FIREBIRD) && !defined(MYSQL)
  1403. {
  1404. dbo::Transaction t(*session_);
  1405. dbo::ptr<A> a = session_->find<A>();
  1406. dbo::ptr<B> b = a->b;
  1407. a.modify()->b.reset(); // 1
  1408. a.remove(); // 3 (a belongs to b)
  1409. b.remove(); // 2
  1410. }
  1411. #endif //!FIREBIRD && !MYSQL
  1412. }
  1413. BOOST_AUTO_TEST_CASE( dbo_test18 )
  1414. {
  1415. DboFixture f;
  1416. dbo::Session *session_ = f.session_;
  1417. {
  1418. dbo::Transaction t(*session_);
  1419. dbo::ptr<A> a = session_->add(new A());
  1420. dbo::ptr<C> c = session_->add(new C());
  1421. BOOST_REQUIRE(!c->aOneToOne);
  1422. a.modify()->c = c;
  1423. BOOST_REQUIRE(c->aOneToOne == a);
  1424. a.modify()->c.reset();
  1425. BOOST_REQUIRE(!c->aOneToOne);
  1426. c.modify()->aOneToOne = a;
  1427. BOOST_REQUIRE(a->c == c);
  1428. BOOST_REQUIRE(c->aOneToOne->c == c);
  1429. dbo::ptr<A> a2 = c->aOneToOne;
  1430. }
  1431. }
  1432. BOOST_AUTO_TEST_CASE( dbo_test19 )
  1433. {
  1434. DboFixture f;
  1435. dbo::Session *session_ = f.session_;
  1436. {
  1437. dbo::Transaction t(*session_);
  1438. dbo::ptr<A> a = session_->add(new A());
  1439. dbo::ptr<B> b = session_->add(new B("b", B::State1));
  1440. a.modify()->b = b;
  1441. }
  1442. try {
  1443. dbo::Transaction t(*session_);
  1444. dbo::ptr<A> a = session_->find<A>();
  1445. a.remove(); // 3
  1446. throw std::runtime_error("Auch");
  1447. } catch (std::exception& ) {
  1448. session_->rereadAll();
  1449. dbo::Transaction t(*session_);
  1450. t.commit();
  1451. }
  1452. }
  1453. BOOST_AUTO_TEST_CASE( dbo_test20 )
  1454. {
  1455. DboFixture f;
  1456. // Oracle does not support: " select 1 " (must have from)
  1457. #if !defined(FIREBIRD) && !defined(ORACLE)
  1458. {
  1459. dbo::Session *session_ = f.session_;
  1460. dbo::Transaction t(*session_);
  1461. dbo::QueryModel<std::string> *model = new dbo::QueryModel<std::string>();
  1462. model->setQuery(session_->query<std::string>("select 'dima '' ?'"));
  1463. model->addAllFieldsAsColumns();
  1464. std::cerr << model->columnCount() << std::endl
  1465. << model->rowCount() << std::endl;
  1466. std::cerr << Wt::asString(model->data(0, 0)) << std::endl;
  1467. delete model;
  1468. }
  1469. #endif //FIREBIRD
  1470. }
  1471. BOOST_AUTO_TEST_CASE( dbo_test21 )
  1472. {
  1473. DboFixture f;
  1474. {
  1475. dbo::Session *session_ = f.session_;
  1476. dbo::Transaction t(*session_);
  1477. dbo::QueryModel<std::string> *model = new dbo::QueryModel<std::string>();
  1478. model->setQuery(session_->query<std::string>
  1479. ("SELECT cast(round(number, 2) as text) AS column_number "
  1480. "FROM table"));
  1481. model->addColumn("column_number", "label");
  1482. delete model;
  1483. }
  1484. }
  1485. BOOST_AUTO_TEST_CASE( dbo_test22a )
  1486. {
  1487. #ifdef POSTGRES
  1488. DboFixture f;
  1489. dbo::Session *session_ = f.session_;
  1490. Wt::WDateTime datetime1 = Wt::WDateTime(Wt::WDate(2009, 10, 1),
  1491. Wt::WTime(12, 11, 31));
  1492. {
  1493. dbo::Transaction t(*session_);
  1494. session_->execute("SET TIME ZONE \"America/New_York\"");
  1495. dbo::ptr<A> a1(new A());
  1496. a1.modify()->datetime = datetime1;
  1497. session_->add(a1);
  1498. t.commit();
  1499. }
  1500. {
  1501. dbo::Transaction t(*session_);
  1502. dbo::ptr<A> a2 = session_->find<A>();
  1503. BOOST_REQUIRE(a2->datetime == datetime1);
  1504. }
  1505. #endif //POSTGRES
  1506. }
  1507. BOOST_AUTO_TEST_CASE( dbo_test22b )
  1508. {
  1509. #ifdef POSTGRES
  1510. DboFixture f;
  1511. dbo::Session *session_ = f.session_;
  1512. Wt::WDateTime datetime1 = Wt::WDateTime(Wt::WDate(2009, 10, 1),
  1513. Wt::WTime(12, 11, 31));
  1514. {
  1515. dbo::Transaction t(*session_);
  1516. session_->execute("SET TIME ZONE \"Europe/Brussels\"");
  1517. dbo::ptr<A> a1(new A());
  1518. a1.modify()->datetime = datetime1;
  1519. session_->add(a1);
  1520. t.commit();
  1521. }
  1522. {
  1523. dbo::Transaction t(*session_);
  1524. dbo::ptr<A> a2 = session_->find<A>();
  1525. BOOST_REQUIRE(a2->datetime == datetime1);
  1526. }
  1527. #endif //POSTGRES
  1528. }
  1529. BOOST_AUTO_TEST_CASE( dbo_test22c )
  1530. {
  1531. #ifdef POSTGRES
  1532. DboFixture f;
  1533. dbo::Session *session_ = f.session_;
  1534. Wt::WDateTime datetime1 = Wt::WDateTime(Wt::WDate(2009, 10, 1),
  1535. Wt::WTime(12, 11, 31));
  1536. {
  1537. dbo::Transaction t(*session_);
  1538. session_->execute("ALTER TABLE " SCHEMA "table_a ALTER COLUMN datetime "
  1539. "TYPE TIMESTAMP WITH TIME ZONE" );
  1540. session_->execute("SET TIME ZONE \"America/New_York\"");
  1541. dbo::ptr<A> a1(new A());
  1542. a1.modify()->datetime = datetime1;
  1543. session_->add(a1);
  1544. t.commit();
  1545. }
  1546. {
  1547. dbo::Transaction t(*session_);
  1548. dbo::ptr<A> a2 = session_->find<A>();
  1549. BOOST_REQUIRE(a2->datetime == datetime1);
  1550. }
  1551. #endif //POSTGRES
  1552. }
  1553. BOOST_AUTO_TEST_CASE( dbo_test22d )
  1554. {
  1555. #ifdef POSTGRES
  1556. DboFixture f;
  1557. dbo::Session *session_ = f.session_;
  1558. Wt::WDateTime datetime1 = Wt::WDateTime(Wt::WDate(2009, 10, 1),
  1559. Wt::WTime(12, 11, 31));
  1560. {
  1561. dbo::Transaction t(*session_);
  1562. session_->execute("ALTER TABLE " SCHEMA "table_a ALTER COLUMN datetime "
  1563. "TYPE TIMESTAMP WITH TIME ZONE" );
  1564. session_->execute("SET TIME ZONE \"Europe/Brussels\"");
  1565. dbo::ptr<A> a1(new A());
  1566. a1.modify()->datetime = datetime1;
  1567. session_->add(a1);
  1568. t.commit();
  1569. }
  1570. {
  1571. dbo::Transaction t(*session_);
  1572. dbo::ptr<A> a2 = session_->find<A>();
  1573. BOOST_REQUIRE(a2->datetime == datetime1);
  1574. }
  1575. #endif //POSTGRES
  1576. }
  1577. // dbo_test23x tests are dbo::ptr<const C> tests
  1578. // the main test is to make sure they compile
  1579. BOOST_AUTO_TEST_CASE( dbo_test23a )
  1580. {
  1581. DboFixture f;
  1582. dbo::Session *session_ = f.session_;
  1583. {
  1584. dbo::Transaction t(*session_);
  1585. A *a1 = new A();
  1586. a1->ll = 123456L;
  1587. dbo::ptr<const A> aPtr(a1);
  1588. session_->add(aPtr);
  1589. t.commit();
  1590. }
  1591. {
  1592. dbo::Transaction t(*session_);
  1593. dbo::ptr<const A> a1 = session_->find<const A>();
  1594. dbo::ptr<A> a2 = session_->find<A>();
  1595. dbo::collection<dbo::ptr<const A> > as1 = session_->find<const A>();
  1596. dbo::ptr<const A> a3 = as1.front();
  1597. BOOST_REQUIRE(a1 == a2);
  1598. BOOST_REQUIRE(a2 == a3);
  1599. BOOST_REQUIRE(a3 == a2);
  1600. BOOST_REQUIRE(a2 == a1);
  1601. BOOST_REQUIRE(a1 == a3);
  1602. BOOST_REQUIRE(a3 == a1);
  1603. }
  1604. }
  1605. BOOST_AUTO_TEST_CASE( dbo_test23b )
  1606. {
  1607. DboFixture f;
  1608. dbo::Session *session_ = f.session_;
  1609. {
  1610. dbo::Transaction t(*session_);
  1611. A *a1 = new A();
  1612. a1->ll = 123456L;
  1613. dbo::ptr<A> aPtr1(a1);
  1614. C *c1 = new C();
  1615. c1->name = "Jos";
  1616. dbo::ptr<C> cPtr1(c1);
  1617. aPtr1.modify()->c = cPtr1;
  1618. session_->add(aPtr1);
  1619. session_->add(cPtr1);
  1620. t.commit();
  1621. }
  1622. {
  1623. dbo::Transaction t(*session_);
  1624. dbo::ptr<const C> c1 = session_->find<const C>();
  1625. dbo::weak_ptr<A> a1 = c1->aOneToOne;
  1626. dbo::weak_ptr<const A> a2 = a1;
  1627. dbo::ptr<A> a3 = a1;
  1628. dbo::ptr<const A> a4 = a1;
  1629. BOOST_REQUIRE(a1 == a2);
  1630. BOOST_REQUIRE(a2 == a1);
  1631. BOOST_REQUIRE(a2 == a3);
  1632. BOOST_REQUIRE(a3 == a2);
  1633. BOOST_REQUIRE(a3 == a4);
  1634. BOOST_REQUIRE(a4 == a3);
  1635. BOOST_REQUIRE(a1 == a4);
  1636. BOOST_REQUIRE(a4 == a1);
  1637. BOOST_REQUIRE(a1 == a3);
  1638. BOOST_REQUIRE(a3 == a1);
  1639. BOOST_REQUIRE(a2 == a4);
  1640. BOOST_REQUIRE(a4 == a2);
  1641. }
  1642. }
  1643. BOOST_AUTO_TEST_CASE( dbo_test23c )
  1644. {
  1645. DboFixture f;
  1646. dbo::Session *session_ = f.session_;
  1647. {
  1648. dbo::Transaction t(*session_);
  1649. D *d = new D();
  1650. d->id = Coordinate(2, 4);
  1651. dbo::ptr<D> dPtr = session_->add(d);
  1652. dbo::ptr<C> cPtr = session_->add(new C());
  1653. dPtr.modify()->c = cPtr;
  1654. t.commit();
  1655. }
  1656. {
  1657. dbo::Transaction t(*session_);
  1658. dbo::ptr<const D> d = session_->find<const D>();
  1659. BOOST_REQUIRE(d.id() == Coordinate(2, 4));
  1660. dbo::ptr<const C> c = session_->find<const C>();
  1661. dbo::weak_ptr<const D> d2 = c->dOneToOne;
  1662. BOOST_REQUIRE(c->dOneToOne.id() == Coordinate(2, 4));
  1663. }
  1664. }
  1665. BOOST_AUTO_TEST_CASE( dbo_test24a )
  1666. {
  1667. DboFixture f;
  1668. dbo::Session *session_ = f.session_;
  1669. {
  1670. dbo::Transaction t(*session_);
  1671. dbo::ptr<E> e1(new E("e1"));
  1672. dbo::ptr<C> c1(new C("c1"));
  1673. session_->add(e1);
  1674. session_->add(c1);
  1675. typedef dbo::ptr_tuple<E, C>::type EC;
  1676. EC ec = session_->query< EC >
  1677. ("select E, C from " SCHEMA "\"table_e\" E, " SCHEMA "\"table_c\" C");
  1678. BOOST_REQUIRE(ec.get<0>()->name == "e1");
  1679. BOOST_REQUIRE(ec.get<1>()->name == "c1");
  1680. }
  1681. }
  1682. BOOST_AUTO_TEST_CASE( dbo_test24b )
  1683. {
  1684. #ifndef SQLITE3
  1685. DboFixture f;
  1686. dbo::Session *session_ = f.session_;
  1687. {
  1688. dbo::Transaction t(*session_);
  1689. dbo::ptr<E> e1(new E("e1"));
  1690. session_->add(e1);
  1691. typedef dbo::ptr_tuple<E, E>::type EE;
  1692. EE ee = session_->query< EE >
  1693. ("select \"E1\", \"E2\" from " SCHEMA "\"table_e\" \"E1\" "
  1694. "right join " SCHEMA "\"table_e\" \"E2\" on \"E1\".\"id\" != \"E2\".\"id\"");
  1695. BOOST_REQUIRE(ee.get<1>()->name == "e1");
  1696. }
  1697. #endif // SQLITE3
  1698. }
  1699. BOOST_AUTO_TEST_CASE( dbo_test24c )
  1700. {
  1701. DboFixture f;
  1702. dbo::Session *session_ = f.session_;
  1703. {
  1704. dbo::Transaction t(*session_);
  1705. dbo::ptr<D> d1(new D(Coordinate(42, 43), "d1"));
  1706. dbo::ptr<C> c1(new C("c1"));
  1707. session_->add(d1);
  1708. session_->add(c1);
  1709. typedef dbo::ptr_tuple<D, C>::type DC;
  1710. DC dc = session_->query< DC >
  1711. ("select D, C from " SCHEMA "\"table_d\" D, " SCHEMA "\"table_c\" C");
  1712. BOOST_REQUIRE(dc.get<0>()->name == "d1");
  1713. BOOST_REQUIRE(dc.get<1>()->name == "c1");
  1714. }
  1715. }
  1716. BOOST_AUTO_TEST_CASE( dbo_test25 )
  1717. {
  1718. #ifndef FIREBIRD // Cannot order by on blobs in Firebird...
  1719. DboFixture f;
  1720. dbo::Session *session_ = f.session_;
  1721. {
  1722. dbo::Transaction t(*session_);
  1723. dbo::ptr<F> e1 = session_->add(new F("Alice", "Kramden", "Female"));
  1724. dbo::ptr<F> e2 = session_->add(new F("Ralph", "Kramden", "Male"));
  1725. dbo::ptr<F> e3 = session_->add(new F("Trixie", "Norton", "Female"));
  1726. dbo::ptr<F> e4 = session_->add(new F("Ed", "Norton", "Male"));
  1727. t.commit();
  1728. }
  1729. {
  1730. dbo::Query< dbo::ptr<F> > query = session_->find<F>().orderBy("\"id\"");
  1731. dbo::QueryModel< dbo::ptr<F> > *model
  1732. = new dbo::QueryModel< dbo::ptr<F> >();
  1733. model->setQuery(query);
  1734. model->addAllFieldsAsColumns();
  1735. BOOST_REQUIRE(model->columnCount() == 5);
  1736. BOOST_REQUIRE(model->rowCount() == 4);
  1737. BOOST_REQUIRE(Wt::asString(model->headerData(0)) == "id");
  1738. BOOST_REQUIRE(Wt::asString(model->headerData(1)) == "version");
  1739. BOOST_REQUIRE(Wt::asString(model->headerData(2)) == "first_name");
  1740. BOOST_REQUIRE(Wt::asString(model->headerData(3)) == "last_name");
  1741. BOOST_REQUIRE(Wt::asString(model->headerData(4)) == "gender");
  1742. BOOST_REQUIRE(Wt::asString(model->data(0, 2)) == "Alice");
  1743. BOOST_REQUIRE(Wt::asString(model->data(1, 2)) == "Ralph");
  1744. BOOST_REQUIRE(Wt::asString(model->data(2, 2)) == "Trixie");
  1745. BOOST_REQUIRE(Wt::asString(model->data(3, 2)) == "Ed");
  1746. // sort on first name
  1747. model->sort(2, Wt::AscendingOrder);
  1748. BOOST_REQUIRE(Wt::asString(model->data(0, 2)) == "Alice");
  1749. BOOST_REQUIRE(Wt::asString(model->data(1, 2)) == "Ed");
  1750. BOOST_REQUIRE(Wt::asString(model->data(2, 2)) == "Ralph");
  1751. BOOST_REQUIRE(Wt::asString(model->data(3, 2)) == "Trixie");
  1752. delete model;
  1753. }
  1754. {
  1755. class custom_sort_model : public dbo::QueryModel< dbo::ptr<F> > {
  1756. public:
  1757. custom_sort_model() : dbo::QueryModel< dbo::ptr<F> >() { }
  1758. virtual std::string createOrderBy(int column, Wt::SortOrder order)
  1759. {
  1760. std::string dir = (order == Wt::AscendingOrder ? "asc" : "desc");
  1761. return "\"" + fieldInfo(column).name() + "\" " + dir +
  1762. ((column != 3) ? ", \"last_name\"" : "") +
  1763. ((column != 2) ? ", \"first_name\"" : "");
  1764. }
  1765. };
  1766. dbo::Query< dbo::ptr<F> > query = session_->find<F>().orderBy("\"id\"");
  1767. custom_sort_model *model = new custom_sort_model();
  1768. model->setQuery(query);
  1769. model->addAllFieldsAsColumns();
  1770. BOOST_REQUIRE(model->columnCount() == 5);
  1771. BOOST_REQUIRE(model->rowCount() == 4);
  1772. BOOST_REQUIRE(Wt::asString(model->headerData(0)) == "id");
  1773. BOOST_REQUIRE(Wt::asString(model->headerData(1)) == "version");
  1774. BOOST_REQUIRE(Wt::asString(model->headerData(2)) == "first_name");
  1775. BOOST_REQUIRE(Wt::asString(model->headerData(3)) == "last_name");
  1776. BOOST_REQUIRE(Wt::asString(model->headerData(4)) == "gender");
  1777. BOOST_REQUIRE(Wt::asString(model->data(0, 2)) == "Alice");
  1778. BOOST_REQUIRE(Wt::asString(model->data(1, 2)) == "Ralph");
  1779. BOOST_REQUIRE(Wt::asString(model->data(2, 2)) == "Trixie");
  1780. BOOST_REQUIRE(Wt::asString(model->data(3, 2)) == "Ed");
  1781. // sort on last name ascending, then first name ascending
  1782. model->sort(3, Wt::AscendingOrder);
  1783. BOOST_REQUIRE(Wt::asString(model->data(0, 2)) == "Alice");
  1784. BOOST_REQUIRE(Wt::asString(model->data(1, 2)) == "Ralph");
  1785. BOOST_REQUIRE(Wt::asString(model->data(2, 2)) == "Ed");
  1786. BOOST_REQUIRE(Wt::asString(model->data(3, 2)) == "Trixie");
  1787. // sort on last name descending, then first name ascending
  1788. model->sort(3, Wt::DescendingOrder);
  1789. BOOST_REQUIRE(Wt::asString(model->data(0, 2)) == "Ed");
  1790. BOOST_REQUIRE(Wt::asString(model->data(1, 2)) == "Trixie");
  1791. BOOST_REQUIRE(Wt::asString(model->data(2, 2)) == "Alice");
  1792. BOOST_REQUIRE(Wt::asString(model->data(3, 2)) == "Ralph");
  1793. // sort on first name, then last name ascending
  1794. model->sort(2, Wt::AscendingOrder);
  1795. BOOST_REQUIRE(Wt::asString(model->data(0, 2)) == "Alice");
  1796. BOOST_REQUIRE(Wt::asString(model->data(1, 2)) == "Ed");
  1797. BOOST_REQUIRE(Wt::asString(model->data(2, 2)) == "Ralph");
  1798. BOOST_REQUIRE(Wt::asString(model->data(3, 2)) == "Trixie");
  1799. // sort on gender, then last name, then first name
  1800. model->sort(4, Wt::AscendingOrder);
  1801. BOOST_REQUIRE(Wt::asString(model->data(0, 2)) == "Alice");
  1802. BOOST_REQUIRE(Wt::asString(model->data(1, 2)) == "Trixie");
  1803. BOOST_REQUIRE(Wt::asString(model->data(2, 2)) == "Ralph");
  1804. BOOST_REQUIRE(Wt::asString(model->data(3, 2)) == "Ed");
  1805. delete model;
  1806. }
  1807. #endif // FIREBIRD
  1808. }
  1809. namespace {
  1810. struct CheckExpected : Wt::WObject {
  1811. DboFixture& f_;
  1812. dbo::Session *session2_;
  1813. CheckExpected(DboFixture &f) : f_(f) {
  1814. session2_ = new dbo::Session();
  1815. session2_->setConnectionPool(*f_.connectionPool_);
  1816. session2_->mapClass<F>(SCHEMA "table_f");
  1817. }
  1818. virtual ~CheckExpected() {
  1819. delete session2_;
  1820. }
  1821. bool operator() (std::string &expected) {
  1822. {
  1823. dbo::Transaction t2(*session2_);
  1824. dbo::ptr<F> c = session2_->find<F>();
  1825. if (c->firstName != expected)
  1826. BOOST_ERROR(std::string("CheckExpected: firstName != expected, firstName: '") +
  1827. c->firstName + "', expected: '" + expected + "'");
  1828. else
  1829. BOOST_TEST_MESSAGE(std::string("CheckExpected OK: firstName: '") +
  1830. c->firstName + "', expected: '" + expected + "'");
  1831. }
  1832. return true;
  1833. }
  1834. };
  1835. }
  1836. BOOST_AUTO_TEST_CASE( dbo_test26 )
  1837. {
  1838. #ifndef SQLITE3 // sqlite3 ":memory:" does not share database between sessions
  1839. DboFixture f;
  1840. dbo::Session *session_ = f.session_;
  1841. CheckExpected checkExpected(f);
  1842. {
  1843. dbo::Transaction t(*session_);
  1844. session_->add(new F("Alice", "Kramden", "Female"));
  1845. dbo::Query< dbo::ptr<F> > query = session_->find<F>();
  1846. dbo::QueryModel< dbo::ptr<F> > *model
  1847. = new dbo::QueryModel< dbo::ptr<F> >();
  1848. model->setQuery(query);
  1849. model->addAllFieldsAsColumns();
  1850. BOOST_REQUIRE(model->columnCount() == 5);
  1851. BOOST_REQUIRE(model->rowCount() == 1);
  1852. t.commit();
  1853. BOOST_REQUIRE(Wt::asString(model->data(0, 2)) == "Alice");
  1854. std::string ExpectedFirstName = "Alice";
  1855. BOOST_REQUIRE(checkExpected(ExpectedFirstName));
  1856. /*
  1857. * Set-up a handler to verify that updates are visible
  1858. * in a second session when model->dataChanged() is emitted
  1859. */
  1860. model->dataChanged().connect(boost::bind<bool>(boost::ref(checkExpected),
  1861. boost::ref(ExpectedFirstName)));
  1862. /*
  1863. * The setItemData() convenience method commits
  1864. * a transaction prior to emitting dataChanged()
  1865. */
  1866. ExpectedFirstName = "AliceTwo";
  1867. Wt::WAbstractItemModel::DataMap map;
  1868. map[Wt::EditRole] = ExpectedFirstName;
  1869. model->setItemData(model->index(0, 2), map); // checkExpected() will be called
  1870. BOOST_REQUIRE(Wt::asString(model->data(0, 2)) == ExpectedFirstName);
  1871. /*
  1872. * The setData() should be equivalent to above setItemData() and
  1873. * commit a transaction prior to emitting dataChanged()
  1874. */
  1875. ExpectedFirstName = "AliceThree";
  1876. model->setData(0, 2, ExpectedFirstName); // checkExpected() will be called
  1877. BOOST_REQUIRE(Wt::asString(model->data(0, 2)) == ExpectedFirstName);
  1878. delete model;
  1879. }
  1880. #endif // SQLITE3
  1881. }
  1882. BOOST_AUTO_TEST_CASE( dbo_test27 )
  1883. {
  1884. #ifdef MYSQL
  1885. /* Allegedly fails, see #4734 */
  1886. DboFixture f;
  1887. dbo::Session *session_ = f.session_;
  1888. {
  1889. dbo::Transaction t(*session_);
  1890. dbo::ptr<B> b(new B());
  1891. b.modify()->name = "b";
  1892. session_->add(b);
  1893. }
  1894. {
  1895. dbo::Transaction t(*session_);
  1896. /* The count fails ! */
  1897. std::string auth = session_->query<std::string>
  1898. ("select sha1(?) from " SCHEMA "\"table_b\" where \"name\"=?")
  1899. .bind("shhhh").bind("b");
  1900. }
  1901. #endif
  1902. }