Warning, file /sdk/codevis/thirdparty/soci/tests/sqlite3/test-sqlite3.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 //
0002 // Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton, David Courtney
0003 // Distributed under the Boost Software License, Version 1.0.
0004 // (See accompanying file LICENSE_1_0.txt or copy at
0005 // http://www.boost.org/LICENSE_1_0.txt)
0006 //
0007 
0008 #include <soci/soci.h>
0009 #include <soci/sqlite3/soci-sqlite3.h>
0010 #include "common-tests.h"
0011 #include <iostream>
0012 #include <sstream>
0013 #include <string>
0014 #include <cmath>
0015 #include <cstring>
0016 #include <ctime>
0017 
0018 using namespace soci;
0019 using namespace soci::tests;
0020 
0021 std::string connectString;
0022 backend_factory const &backEnd = *soci::factory_sqlite3();
0023 
0024 // ROWID test
0025 // In sqlite3 the row id can be called ROWID, _ROWID_ or oid
0026 TEST_CASE("SQLite rowid", "[sqlite][rowid][oid]")
0027 {
0028     soci::session sql(backEnd, connectString);
0029 
0030     try { sql << "drop table test1"; }
0031     catch (soci_error const &) {} // ignore if error
0032 
0033     sql <<
0034     "create table test1 ("
0035     "    id integer,"
0036     "    name varchar(100)"
0037     ")";
0038 
0039     sql << "insert into test1(id, name) values(7, \'John\')";
0040 
0041     rowid rid(sql);
0042     sql << "select oid from test1 where id = 7", into(rid);
0043 
0044     int id;
0045     std::string name;
0046 
0047     sql << "select id, name from test1 where oid = :rid",
0048     into(id), into(name), use(rid);
0049 
0050     CHECK(id == 7);
0051     CHECK(name == "John");
0052 
0053     sql << "drop table test1";
0054 }
0055 
0056 class SetupForeignKeys
0057 {
0058 public:
0059     SetupForeignKeys(soci::session& sql)
0060         : m_sql(sql)
0061     {
0062         m_sql <<
0063         "create table parent ("
0064         "    id integer primary key"
0065         ")";
0066 
0067         m_sql <<
0068         "create table child ("
0069         "    id integer primary key,"
0070         "    parent integer,"
0071         "    foreign key(parent) references parent(id)"
0072         ")";
0073 
0074         m_sql << "insert into parent(id) values(1)";
0075         m_sql << "insert into child(id, parent) values(100, 1)";
0076     }
0077 
0078     ~SetupForeignKeys()
0079     {
0080         m_sql << "drop table child";
0081         m_sql << "drop table parent";
0082     }
0083 
0084 private:
0085     SetupForeignKeys(const SetupForeignKeys&);
0086     SetupForeignKeys& operator=(const SetupForeignKeys&);
0087 
0088     soci::session& m_sql;
0089 };
0090 
0091 TEST_CASE("SQLite foreign keys are disabled by default", "[sqlite][foreignkeys]")
0092 {
0093     soci::session sql(backEnd, connectString);
0094 
0095     SetupForeignKeys setupForeignKeys(sql);
0096 
0097     sql << "delete from parent where id = 1";
0098 
0099     int parent = 0;
0100     sql << "select parent from child where id = 100 ", into(parent);
0101 
0102     CHECK(parent == 1);
0103 }
0104 
0105 TEST_CASE("SQLite foreign keys are enabled by foreign_keys option", "[sqlite][foreignkeys]")
0106 {
0107     soci::session sql(backEnd, "dbname=:memory: foreign_keys=on");
0108 
0109     SetupForeignKeys setupForeignKeys(sql);
0110 
0111     CHECK_THROWS_WITH(sql << "delete from parent where id = 1",
0112                       "sqlite3_statement_backend::loadOne: FOREIGN KEY "
0113                       "constraint failed while executing "
0114                       "\"delete from parent where id = 1\".");
0115 }
0116 
0117 class SetupAutoIncrementTable
0118 {
0119 public:
0120     SetupAutoIncrementTable(soci::session& sql)
0121         : m_sql(sql)
0122     {
0123         m_sql <<
0124         "create table t("
0125         "    id integer primary key autoincrement,"
0126         "    name text"
0127         ")";
0128     }
0129 
0130     ~SetupAutoIncrementTable()
0131     {
0132         m_sql << "drop table t";
0133     }
0134 
0135 private:
0136     SetupAutoIncrementTable(const SetupAutoIncrementTable&);
0137     SetupAutoIncrementTable& operator=(const SetupAutoIncrementTable&);
0138 
0139     soci::session& m_sql;
0140 };
0141 
0142 TEST_CASE("SQLite get_last_insert_id works with AUTOINCREMENT",
0143           "[sqlite][rowid]")
0144 {
0145     soci::session sql(backEnd, connectString);
0146     SetupAutoIncrementTable createTable(sql);
0147 
0148     sql << "insert into t(name) values('x')";
0149     sql << "insert into t(name) values('y')";
0150 
0151     long long val;
0152     sql.get_last_insert_id("t", val);
0153     CHECK(val == 2);
0154 }
0155 
0156 TEST_CASE("SQLite get_last_insert_id with AUTOINCREMENT does not reuse IDs when rows deleted",
0157           "[sqlite][rowid]")
0158 {
0159     soci::session sql(backEnd, connectString);
0160     SetupAutoIncrementTable createTable(sql);
0161 
0162     sql << "insert into t(name) values('x')";
0163     sql << "insert into t(name) values('y')";
0164 
0165     sql << "delete from t where id = 2";
0166 
0167     long long val;
0168     sql.get_last_insert_id("t", val);
0169     CHECK(val == 2);
0170 }
0171 
0172 class SetupNoAutoIncrementTable
0173 {
0174 public:
0175     SetupNoAutoIncrementTable(soci::session& sql)
0176         : m_sql(sql)
0177     {
0178         m_sql <<
0179         "create table t("
0180         "    id integer primary key,"
0181         "    name text"
0182         ")";
0183     }
0184 
0185     ~SetupNoAutoIncrementTable()
0186     {
0187         m_sql << "drop table t";
0188     }
0189 
0190 private:
0191     SetupNoAutoIncrementTable(const SetupNoAutoIncrementTable&);
0192     SetupNoAutoIncrementTable& operator=(const SetupNoAutoIncrementTable&);
0193 
0194     soci::session& m_sql;
0195 };
0196 
0197 TEST_CASE("SQLite get_last_insert_id without AUTOINCREMENT reuses IDs when rows deleted",
0198           "[sqlite][rowid]")
0199 {
0200     soci::session sql(backEnd, connectString);
0201     SetupNoAutoIncrementTable createTable(sql);
0202 
0203     sql << "insert into t(name) values('x')";
0204     sql << "insert into t(name) values('y')";
0205 
0206     sql << "delete from t where id = 2";
0207 
0208     long long val;
0209     sql.get_last_insert_id("t", val);
0210     CHECK(val == 1);
0211 }
0212 
0213 TEST_CASE("SQLite get_last_insert_id throws if table not found",
0214           "[sqlite][rowid]")
0215 {
0216     soci::session sql(backEnd, connectString);
0217 
0218     long long val;
0219     CHECK_THROWS(sql.get_last_insert_id("notexisting", val));
0220 }
0221 
0222 class SetupTableWithDoubleQuoteInName
0223 {
0224 public:
0225     SetupTableWithDoubleQuoteInName(soci::session& sql)
0226         : m_sql(sql)
0227     {
0228         m_sql <<
0229         "create table \"t\"\"fff\"("
0230         "    id integer primary key,"
0231         "    name text"
0232         ")";
0233     }
0234 
0235     ~SetupTableWithDoubleQuoteInName()
0236     {
0237         m_sql << "drop table \"t\"\"fff\"";
0238     }
0239 
0240 private:
0241     SetupTableWithDoubleQuoteInName(const SetupTableWithDoubleQuoteInName&);
0242     SetupTableWithDoubleQuoteInName& operator=(const SetupTableWithDoubleQuoteInName&);
0243 
0244     soci::session& m_sql;
0245 };
0246 
0247 TEST_CASE("SQLite get_last_insert_id escapes table name",
0248           "[sqlite][rowid]")
0249 {
0250     soci::session sql(backEnd, connectString);
0251     SetupTableWithDoubleQuoteInName table(sql);
0252 
0253     long long val;
0254     sql.get_last_insert_id("t\"fff", val);
0255     CHECK(val == 0);
0256 }
0257 
0258 // BLOB test
0259 struct blob_table_creator : public table_creator_base
0260 {
0261     blob_table_creator(soci::session & sql)
0262         : table_creator_base(sql)
0263     {
0264         sql <<
0265             "create table soci_test ("
0266             "    id integer,"
0267             "    img blob"
0268             ")";
0269     }
0270 };
0271 
0272 TEST_CASE("SQLite blob", "[sqlite][blob]")
0273 {
0274     soci::session sql(backEnd, connectString);
0275 
0276     blob_table_creator tableCreator(sql);
0277 
0278     char buf[] = "abcdefghijklmnopqrstuvwxyz";
0279 
0280     sql << "insert into soci_test(id, img) values(7, '')";
0281 
0282     {
0283         blob b(sql);
0284 
0285         sql << "select img from soci_test where id = 7", into(b);
0286         CHECK(b.get_len() == 0);
0287 
0288         b.write_from_start(buf, sizeof(buf));
0289         CHECK(b.get_len() == sizeof(buf));
0290         sql << "update soci_test set img=? where id = 7", use(b);
0291 
0292         b.append(buf, sizeof(buf));
0293         CHECK(b.get_len() == 2 * sizeof(buf));
0294         sql << "insert into soci_test(id, img) values(8, ?)", use(b);
0295     }
0296     {
0297         blob b(sql);
0298         sql << "select img from soci_test where id = 8", into(b);
0299         CHECK(b.get_len() == 2 * sizeof(buf));
0300         char buf2[100];
0301         b.read_from_start(buf2, 10);
0302         CHECK(std::strncmp(buf2, "abcdefghij", 10) == 0);
0303 
0304         sql << "select img from soci_test where id = 7", into(b);
0305         CHECK(b.get_len() == sizeof(buf));
0306 
0307     }
0308 }
0309 
0310 // This test was put in to fix a problem that occurs when there are both
0311 // into and use elements in the same query and one of them (into) binds
0312 // to a vector object.
0313 
0314 struct test3_table_creator : table_creator_base
0315 {
0316     test3_table_creator(soci::session & sql) : table_creator_base(sql)
0317     {
0318         sql << "create table soci_test( id integer, name varchar, subname varchar);";
0319     }
0320 };
0321 
0322 TEST_CASE("SQLite use and vector into", "[sqlite][use][into][vector]")
0323 {
0324     soci::session sql(backEnd, connectString);
0325 
0326     test3_table_creator tableCreator(sql);
0327 
0328     sql << "insert into soci_test(id,name,subname) values( 1,'john','smith')";
0329     sql << "insert into soci_test(id,name,subname) values( 2,'george','vals')";
0330     sql << "insert into soci_test(id,name,subname) values( 3,'ann','smith')";
0331     sql << "insert into soci_test(id,name,subname) values( 4,'john','grey')";
0332     sql << "insert into soci_test(id,name,subname) values( 5,'anthony','wall')";
0333 
0334     {
0335         std::vector<int> v(10);
0336 
0337         statement s(sql.prepare << "Select id from soci_test where name = :name");
0338 
0339         std::string name = "john";
0340 
0341         s.exchange(use(name, "name"));
0342         s.exchange(into(v));
0343 
0344         s.define_and_bind();
0345         s.execute(true);
0346 
0347         CHECK(v.size() == 2);
0348     }
0349 }
0350 
0351 
0352 // Test case from Amnon David 11/1/2007
0353 // I've noticed that table schemas in SQLite3 can sometimes have typeless
0354 // columns. One (and only?) example is the sqlite_sequence that sqlite
0355 // creates for autoincrement . Attempting to traverse this table caused
0356 // SOCI to crash. I've made the following code change in statement.cpp to
0357 // create a workaround:
0358 
0359 struct test4_table_creator : table_creator_base
0360 {
0361     test4_table_creator(soci::session & sql) : table_creator_base(sql)
0362     {
0363         sql << "create table soci_test (col INTEGER PRIMARY KEY AUTOINCREMENT, name char)";
0364     }
0365 };
0366 
0367 TEST_CASE("SQLite select from sequence", "[sqlite][sequence]")
0368 {
0369     // we need to have an table that uses autoincrement to test this.
0370     soci::session sql(backEnd, connectString);
0371 
0372     test4_table_creator tableCreator(sql);
0373 
0374     sql << "insert into soci_test(name) values('john')";
0375     sql << "insert into soci_test(name) values('james')";
0376 
0377     {
0378         int key;
0379         std::string name;
0380         sql << "select * from soci_test", into(key), into(name);
0381         CHECK(name == "john");
0382 
0383         rowset<row> rs = (sql.prepare << "select * from sqlite_sequence");
0384         rowset<row>::const_iterator it = rs.begin();
0385         row const& r1 = (*it);
0386         CHECK(r1.get<std::string>(0) == "soci_test");
0387         CHECK(r1.get<std::string>(1) == "2");
0388     }
0389 }
0390 
0391 struct longlong_table_creator : table_creator_base
0392 {
0393     longlong_table_creator(soci::session & sql)
0394         : table_creator_base(sql)
0395     {
0396         sql << "create table soci_test(val number(20))";
0397     }
0398 };
0399 
0400 // long long test
0401 TEST_CASE("SQLite long long", "[sqlite][longlong]")
0402 {
0403     soci::session sql(backEnd, connectString);
0404 
0405     longlong_table_creator tableCreator(sql);
0406 
0407     long long v1 = 1000000000000LL;
0408     sql << "insert into soci_test(val) values(:val)", use(v1);
0409 
0410     long long v2 = 0LL;
0411     sql << "select val from soci_test", into(v2);
0412 
0413     CHECK(v2 == v1);
0414 }
0415 
0416 TEST_CASE("SQLite vector long long", "[sqlite][vector][longlong]")
0417 {
0418     soci::session sql(backEnd, connectString);
0419 
0420     longlong_table_creator tableCreator(sql);
0421 
0422     std::vector<long long> v1;
0423     v1.push_back(1000000000000LL);
0424     v1.push_back(1000000000001LL);
0425     v1.push_back(1000000000002LL);
0426     v1.push_back(1000000000003LL);
0427     v1.push_back(1000000000004LL);
0428 
0429     sql << "insert into soci_test(val) values(:val)", use(v1);
0430 
0431     std::vector<long long> v2(10);
0432     sql << "select val from soci_test order by val desc", into(v2);
0433 
0434     REQUIRE(v2.size() == 5);
0435     CHECK(v2[0] == 1000000000004LL);
0436     CHECK(v2[1] == 1000000000003LL);
0437     CHECK(v2[2] == 1000000000002LL);
0438     CHECK(v2[3] == 1000000000001LL);
0439     CHECK(v2[4] == 1000000000000LL);
0440 }
0441 
0442 struct type_inference_table_creator : table_creator_base
0443 {
0444     type_inference_table_creator(soci::session & sql)
0445         : table_creator_base(sql)
0446     {
0447         sql << "create table soci_test(cvc varchar (10), cdec decimal (20), "
0448                "cll bigint, cull unsigned bigint, clls big int, culls unsigned big int)";
0449     }
0450 };
0451 
0452 // test for correct type inference form sqlite column type
0453 TEST_CASE("SQLite type inference", "[sqlite][sequence]")
0454 {
0455     soci::session sql(backEnd, connectString);
0456 
0457     type_inference_table_creator tableCreator(sql);
0458 
0459     std::string cvc = "john";
0460     double cdec = 12345.0;  // integers can be stored precisely in IEEE 754
0461     long long cll = 1000000000003LL;
0462     unsigned long long cull = 1000000000004ULL;
0463 
0464     sql << "insert into soci_test(cvc, cdec, cll, cull, clls, culls) values(:cvc, :cdec, :cll, :cull, :clls, :culls)",
0465         use(cvc), use(cdec), use(cll), use(cull), use(cll), use(cull);
0466 
0467     {
0468         rowset<row> rs = (sql.prepare << "select * from soci_test");
0469         rowset<row>::const_iterator it = rs.begin();
0470         row const& r1 = (*it);
0471         CHECK(r1.get<std::string>(0) == cvc);
0472         CHECK(r1.get<double>(1) == Approx(cdec));
0473         CHECK(r1.get<long long>(2) == cll);
0474         CHECK(r1.get<unsigned long long>(3) == cull);
0475         CHECK(r1.get<long long>(4) == cll);
0476         CHECK(r1.get<unsigned long long>(5) == cull);
0477     }
0478 }
0479 
0480 TEST_CASE("SQLite DDL wrappers", "[sqlite][ddl]")
0481 {
0482     soci::session sql(backEnd, connectString);
0483 
0484     int i = -1;
0485     sql << "select length(" + sql.empty_blob() + ")", into(i);
0486     CHECK(i == 0);
0487     sql << "select " + sql.nvl() + "(1, 2)", into(i);
0488     CHECK(i == 1);
0489     sql << "select " + sql.nvl() + "(NULL, 2)", into(i);
0490     CHECK(i == 2);
0491 }
0492 
0493 struct table_creator_for_get_last_insert_id : table_creator_base
0494 {
0495     table_creator_for_get_last_insert_id(soci::session & sql)
0496         : table_creator_base(sql)
0497     {
0498         sql << "create table soci_test(id integer primary key autoincrement)";
0499         sql << "insert into soci_test (id) values (41)";
0500         sql << "delete from soci_test where id = 41";
0501     }
0502 };
0503 
0504 TEST_CASE("SQLite last insert id", "[sqlite][last-insert-id]")
0505 {
0506     soci::session sql(backEnd, connectString);
0507     table_creator_for_get_last_insert_id tableCreator(sql);
0508     sql << "insert into soci_test default values";
0509     long long id;
0510     bool result = sql.get_last_insert_id("soci_test", id);
0511     CHECK(result == true);
0512     CHECK(id == 42);
0513 }
0514 
0515 struct table_creator_for_std_tm_bind : table_creator_base
0516 {
0517     table_creator_for_std_tm_bind(soci::session & sql)
0518         : table_creator_base(sql)
0519     {
0520         sql << "create table soci_test(date datetime)";
0521         sql << "insert into soci_test (date) values ('2017-04-04 00:00:00')";
0522         sql << "insert into soci_test (date) values ('2017-04-04 12:00:00')";
0523         sql << "insert into soci_test (date) values ('2017-04-05 00:00:00')";
0524     }
0525 };
0526 
0527 TEST_CASE("SQLite std::tm bind", "[sqlite][std-tm-bind]")
0528 {
0529     soci::session sql(backEnd, connectString);
0530     table_creator_for_std_tm_bind tableCreator(sql);
0531 
0532     std::time_t datetimeEpoch = 1491307200; // 2017-04-04 12:00:00
0533 
0534     std::tm datetime = *std::gmtime(&datetimeEpoch);
0535     soci::rowset<std::tm> rs = (sql.prepare << "select date from soci_test where date=:dt", soci::use(datetime));
0536 
0537     std::vector<std::tm> result;
0538     std::copy(rs.begin(), rs.end(), std::back_inserter(result));
0539     REQUIRE(result.size() == 1);
0540     result.front().tm_isdst = 0;
0541     CHECK(std::mktime(&result.front()) == std::mktime(&datetime));
0542 }
0543 
0544 // DDL Creation objects for common tests
0545 struct table_creator_one : public table_creator_base
0546 {
0547     table_creator_one(soci::session & sql)
0548         : table_creator_base(sql)
0549     {
0550         sql << "create table soci_test(id integer, val integer, c char, "
0551                  "str varchar(20), sh smallint, ul numeric(20), d float, "
0552                  "num76 numeric(7,6), "
0553                  "tm datetime, i1 integer, i2 integer, i3 integer, "
0554                  "name varchar(20))";
0555     }
0556 };
0557 
0558 struct table_creator_two : public table_creator_base
0559 {
0560     table_creator_two(soci::session & sql)
0561         : table_creator_base(sql)
0562     {
0563         sql  << "create table soci_test(num_float float, num_int integer,"
0564                      " name varchar(20), sometime datetime, chr char)";
0565     }
0566 };
0567 
0568 struct table_creator_three : public table_creator_base
0569 {
0570     table_creator_three(soci::session & sql)
0571         : table_creator_base(sql)
0572     {
0573         sql << "create table soci_test(name varchar(100) not null, "
0574             "phone varchar(15))";
0575     }
0576 };
0577 
0578 // Originally, submitted to SQLite3 backend and later moved to common test.
0579 // Test commit b394d039530f124802d06c3b1a969c3117683152
0580 // Author: Mika Fischer <mika.fischer@zoopnet.de>
0581 // Date:   Thu Nov 17 13:28:07 2011 +0100
0582 // Implement get_affected_rows for SQLite3 backend
0583 struct table_creator_for_get_affected_rows : table_creator_base
0584 {
0585     table_creator_for_get_affected_rows(soci::session & sql)
0586         : table_creator_base(sql)
0587     {
0588         sql << "create table soci_test(val integer)";
0589     }
0590 };
0591 
0592 //
0593 // Support for SOCI Common Tests
0594 //
0595 
0596 struct table_creator_from_str : table_creator_base
0597 {
0598     table_creator_from_str(soci::session & sql, std::string const& sqlStr)
0599         : table_creator_base(sql)
0600     {
0601         sql << sqlStr;
0602     }
0603 };
0604 
0605 class test_context : public test_context_base
0606 {
0607 public:
0608     test_context(backend_factory const &backend,
0609                 std::string const &connstr)
0610         : test_context_base(backend, connstr) {}
0611 
0612     table_creator_base* table_creator_1(soci::session& s) const override
0613     {
0614         return new table_creator_one(s);
0615     }
0616 
0617     table_creator_base* table_creator_2(soci::session& s) const override
0618     {
0619         return new table_creator_two(s);
0620     }
0621 
0622     table_creator_base* table_creator_3(soci::session& s) const override
0623     {
0624         return new table_creator_three(s);
0625     }
0626 
0627     table_creator_base* table_creator_4(soci::session& s) const override
0628     {
0629         return new table_creator_for_get_affected_rows(s);
0630     }
0631 
0632     table_creator_base* table_creator_get_last_insert_id(soci::session& s) const override
0633     {
0634         return new table_creator_from_str(s,
0635             "create table soci_test (id integer primary key, val integer)");
0636     }
0637 
0638     table_creator_base* table_creator_xml(soci::session& s) const override
0639     {
0640         return new table_creator_from_str(s,
0641             "create table soci_test (id integer, x text)");
0642     }
0643 
0644     std::string to_date_time(std::string const &datdt_string) const override
0645     {
0646         return "datetime(\'" + datdt_string + "\')";
0647     }
0648 
0649     bool has_fp_bug() const override
0650     {
0651         /*
0652             SQLite seems to be buggy when using text conversion, e.g.:
0653 
0654                  % echo 'create table t(f real); \
0655                          insert into t(f) values(1.79999999999999982); \
0656                          select * from t;' | sqlite3
0657                  1.8
0658 
0659             And there doesn't seem to be any way to avoid this rounding, so we
0660             have no hope of getting back exactly what we write into it unless,
0661             perhaps, we start using sqlite3_bind_double() in the backend code.
0662          */
0663 
0664         return true;
0665     }
0666 
0667     bool enable_std_char_padding(soci::session&) const override
0668     {
0669         // SQLite does not support right padded char type.
0670         return false;
0671     }
0672 
0673     std::string sql_length(std::string const& s) const override
0674     {
0675         return "length(" + s + ")";
0676     }
0677 };
0678 
0679 int main(int argc, char** argv)
0680 {
0681 
0682 #ifdef _MSC_VER
0683     // Redirect errors, unrecoverable problems, and assert() failures to STDERR,
0684     // instead of debug message window.
0685     // This hack is required to run assert()-driven tests by Buildbot.
0686     // NOTE: Comment this 2 lines for debugging with Visual C++ debugger to catch assertions inside.
0687     _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
0688     _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
0689 #endif //_MSC_VER
0690 
0691     if (argc >= 2 && argv[1][0] != '-')
0692     {
0693         connectString = argv[1];
0694 
0695         // Replace the connect string with the process name to ensure that
0696         // CATCH uses the correct name in its messages.
0697         argv[1] = argv[0];
0698 
0699         argc--;
0700         argv++;
0701     }
0702     else
0703     {
0704         // If no file name is specfied then work in-memory
0705         connectString = ":memory:";
0706     }
0707 
0708     test_context tc(backEnd, connectString);
0709 
0710     return Catch::Session().run(argc, argv);
0711 }