File indexing completed on 2025-02-23 05:15:24

0001 //
0002 // Copyright (C) 2011-2013 Denis Chapligin
0003 // Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton
0004 // Distributed under the Boost Software License, Version 1.0.
0005 // (See accompanying file LICENSE_1_0.txt or copy at
0006 // http://www.boost.org/LICENSE_1_0.txt)
0007 //
0008 
0009 #include "soci/soci.h"
0010 #include "soci/db2/soci-db2.h"
0011 #include "common-tests.h"
0012 #include <iostream>
0013 #include <string>
0014 #include <cstdlib>
0015 #include <ctime>
0016 
0017 using namespace soci;
0018 using namespace soci::tests;
0019 
0020 std::string connectString;
0021 backend_factory const &backEnd = *soci::factory_db2();
0022 
0023 //
0024 // Support for soci Common Tests
0025 //
0026 
0027 struct table_creator_one : public table_creator_base
0028 {
0029     table_creator_one(soci::session & sql)
0030         : table_creator_base(sql)
0031     {
0032         sql << "CREATE TABLE SOCI_TEST(ID INTEGER, VAL SMALLINT, C CHAR, STR VARCHAR(20), SH SMALLINT, UL NUMERIC(20), D DOUBLE, "
0033             "NUM76 NUMERIC(7,6), "
0034             "TM TIMESTAMP, I1 INTEGER, I2 INTEGER, I3 INTEGER, NAME VARCHAR(20))";
0035     }
0036 };
0037 
0038 struct table_creator_two : public table_creator_base
0039 {
0040     table_creator_two(soci::session & sql)
0041         : table_creator_base(sql)
0042     {
0043         sql << "CREATE TABLE SOCI_TEST(NUM_FLOAT DOUBLE, NUM_INT INTEGER, NAME VARCHAR(20), SOMETIME TIMESTAMP, CHR CHAR)";
0044     }
0045 };
0046 
0047 struct table_creator_three : public table_creator_base
0048 {
0049     table_creator_three(soci::session & sql)
0050         : table_creator_base(sql)
0051     {
0052         sql << "CREATE TABLE SOCI_TEST(NAME VARCHAR(100) NOT NULL, PHONE VARCHAR(15))";
0053     }
0054 };
0055 
0056 struct table_creator_for_get_affected_rows : table_creator_base
0057 {
0058     table_creator_for_get_affected_rows(soci::session & sql)
0059         : table_creator_base(sql)
0060     {
0061         sql << "CREATE TABLE SOCI_TEST(VAL INTEGER)";
0062     }
0063 };
0064 
0065 class test_context :public test_context_base
0066 {
0067 public:
0068     test_context(backend_factory const & pi_back_end, std::string const & pi_connect_string)
0069         : test_context_base(pi_back_end, pi_connect_string) {}
0070 
0071     table_creator_base* table_creator_1(soci::session & pr_s) const override
0072     {
0073         pr_s << "SET CURRENT SCHEMA = 'DB2INST1'";
0074         return new table_creator_one(pr_s);
0075     }
0076 
0077     table_creator_base* table_creator_2(soci::session & pr_s) const override
0078     {
0079         pr_s << "SET CURRENT SCHEMA = 'DB2INST1'";
0080         return new table_creator_two(pr_s);
0081     }
0082 
0083     table_creator_base* table_creator_3(soci::session & pr_s) const override
0084     {
0085         pr_s << "SET CURRENT SCHEMA = 'DB2INST1'";
0086         return new table_creator_three(pr_s);
0087     }
0088 
0089     table_creator_base* table_creator_4(soci::session& s) const override
0090     {
0091         return new table_creator_for_get_affected_rows(s);
0092     }
0093 
0094     std::string to_date_time(std::string const & pi_datdt_string) const override
0095     {
0096         return "to_date('" + pi_datdt_string + "', 'YYYY-MM-DD HH24:MI:SS')";
0097     }
0098 
0099     std::string sql_length(std::string const& s) const override
0100     {
0101         return "length(" + s + ")";
0102     }
0103 };
0104 
0105 
0106 //
0107 // Additional tests to exercise the DB2 backend
0108 //
0109 
0110 TEST_CASE("DB2 test 1", "[db2]")
0111 {
0112     soci::session sql(backEnd, connectString);
0113 
0114     sql << "SELECT CURRENT TIMESTAMP FROM SYSIBM.SYSDUMMY1";
0115     sql << "SELECT " << 123 << " FROM SYSIBM.SYSDUMMY1";
0116 
0117     std::string query = "CREATE TABLE DB2INST1.SOCI_TEST (ID BIGINT,DATA VARCHAR(8))";
0118     sql << query;
0119 
0120     {
0121         const int i = 7;
0122         sql << "insert into db2inst1.SOCI_TEST (id) values (:id)", use(i,"id");
0123         int j = 0;
0124         sql << "select id from db2inst1.SOCI_TEST where id=7", into(j);
0125         CHECK(j == i);
0126     }
0127 
0128     {
0129         const long int li = 9;
0130         sql << "insert into db2inst1.SOCI_TEST (id) values (:id)", use(li,"id");
0131         long int lj = 0;;
0132         sql << "select id from db2inst1.SOCI_TEST where id=9", into(lj);
0133         CHECK(lj == li);
0134     }
0135 
0136     {
0137         const long long ll = 11;
0138         sql << "insert into db2inst1.SOCI_TEST (id) values (:id)", use(ll,"id");
0139         long long lj = 0;
0140         sql << "select id from db2inst1.SOCI_TEST where id=11", into(lj);
0141         CHECK(lj == ll);
0142     }
0143 
0144     {
0145         const int i = 13;
0146         indicator i_ind = i_ok;
0147         sql << "insert into db2inst1.SOCI_TEST (id) values (:id)", use(i,i_ind,"id");
0148         int j = 0;
0149         indicator j_ind = i_null;
0150         sql << "select id from db2inst1.SOCI_TEST where id=13", into(j,j_ind);
0151         CHECK(j == i);
0152         CHECK(j_ind == i_ok);
0153     }
0154 
0155     {
0156         std::vector<int> numbers(100);
0157         for (int i = 0 ; i < 100 ; i++)
0158         {
0159             numbers[i] = i + 1000;
0160         }
0161         sql << "insert into db2inst1.SOCI_TEST (id) values (:id)", use(numbers,"id");
0162         sql << "select id from db2inst1.SOCI_TEST where id >= 1000 and id < 2000 order by id", into(numbers);
0163         for (int i = 0 ; i < 100 ; i++)
0164         {
0165             CHECK(numbers[i] == i + 1000);
0166         }
0167     }
0168 
0169     {
0170         std::vector<int> numbers(100);
0171         std::vector<indicator> inds(100);
0172         for (int i = 0 ; i < 100 ; i++)
0173         {
0174             numbers[i] = i + 2000;
0175             inds[i] = i_ok;
0176         }
0177         sql << "insert into db2inst1.SOCI_TEST (id) values (:id)", use(numbers,inds,"id");
0178         for (int i = 0 ; i < 100 ; i++)
0179         {
0180             numbers[i] = 0;
0181             inds[i] = i_null;
0182         }
0183         sql << "select id from db2inst1.SOCI_TEST where id >= 2000 and id < 3000 order by id", into(numbers,inds);
0184         for (int i = 0 ; i < 100 ; i++)
0185         {
0186             CHECK(numbers[i] == i + 2000);
0187             CHECK(inds[i] == i_ok);
0188         }
0189     }
0190 
0191     {
0192         int i = 0;
0193         statement st = (sql.prepare << "select id from db2inst1.SOCI_TEST where id < 1000", into(i));
0194         st.execute();
0195         st.fetch();
0196         CHECK (i == 7);
0197         st.fetch();
0198         CHECK (i == 9);
0199         st.fetch();
0200         CHECK (i == 11);
0201         st.fetch();
0202         CHECK (i == 13);
0203     }
0204 
0205     {
0206         int i = 0;
0207         indicator i_ind = i_null;
0208         std::string d;
0209         indicator d_ind = i_ok;
0210         statement st = (sql.prepare << "select id, data from db2inst1.SOCI_TEST where id = 13", into(i, i_ind), into(d, d_ind));
0211         st.execute();
0212         st.fetch();
0213         CHECK (i == 13);
0214         CHECK (i_ind == i_ok);
0215         CHECK (d_ind == i_null);
0216     }
0217 
0218     {
0219         std::vector<int> numbers(100);
0220         for (int i = 0 ; i < 100 ; i++)
0221         {
0222             numbers[i] = 0;
0223         }
0224         statement st = (sql.prepare << "select id from db2inst1.SOCI_TEST where id >= 1000 order by id", into(numbers));
0225         st.execute();
0226         st.fetch();
0227         for (int i = 0 ; i < 100 ; i++)
0228         {
0229             CHECK(numbers[i] == i + 1000);
0230         }
0231         st.fetch();
0232         for (int i = 0 ; i < 100 ; i++)
0233         {
0234             CHECK(numbers[i] == i + 2000);
0235         }
0236     }
0237 
0238     {
0239         std::vector<int> numbers(100);
0240         std::vector<indicator> inds(100);
0241         for (int i = 0 ; i < 100 ; i++)
0242         {
0243             numbers[i] = 0;
0244             inds[i] = i_null;
0245         }
0246         statement st = (sql.prepare << "select id from db2inst1.SOCI_TEST where id >= 1000 order by id", into(numbers, inds));
0247         st.execute();
0248         st.fetch();
0249         for (int i = 0 ; i < 100 ; i++)
0250         {
0251             CHECK(numbers[i] == i + 1000);
0252             CHECK(inds[i] == i_ok);
0253         }
0254         st.fetch();
0255         for (int i = 0 ; i < 100 ; i++)
0256         {
0257             CHECK(numbers[i] == i + 2000);
0258             CHECK(inds[i] == i_ok);
0259         }
0260     }
0261 
0262     {
0263         // XXX: what is the purpose of this test??  what is the expected value?
0264         int i = 0;
0265         statement st = (sql.prepare << "select id from db2inst1.SOCI_TEST", use(i));
0266     }
0267 
0268     {
0269         // XXX: what is the purpose of this test??  what is the expected value?
0270         int i = 0;
0271         indicator ind = i_ok;
0272         statement st = (sql.prepare << "select id from db2inst1.SOCI_TEST", use(i, ind));
0273     }
0274 
0275     {
0276         // XXX: what is the purpose of this test??  what is the expected value?
0277         std::vector<int> numbers(100);
0278         statement st = (sql.prepare << "select id from db2inst1.SOCI_TEST", use(numbers));
0279     }
0280 
0281     {
0282         // XXX: what is the purpose of this test??  what is the expected value?
0283         std::vector<int> numbers(100);
0284         std::vector<indicator> inds(100);
0285         statement st = (sql.prepare << "select id from db2inst1.SOCI_TEST", use(numbers, inds));
0286     }
0287 
0288     sql<<"DROP TABLE DB2INST1.SOCI_TEST";
0289     sql.commit();
0290 }
0291 
0292 TEST_CASE("DB2 test 2", "[db2]")
0293 {
0294     soci::session sql(backEnd, connectString);
0295 
0296     std::string query = "CREATE TABLE DB2INST1.SOCI_TEST (ID BIGINT,DATA VARCHAR(8),DT TIMESTAMP)";
0297     sql << query;
0298 
0299     {
0300         int i = 7;
0301         std::string n("test");
0302         sql << "insert into db2inst1.SOCI_TEST (id,data) values (:id,:name)", use(i,"id"),use(n,"name");
0303         int j;
0304         std::string m;
0305         sql << "select id,data from db2inst1.SOCI_TEST where id=7", into(j),into(m);
0306         CHECK (j == i);
0307         CHECK (m == n);
0308     }
0309 
0310     {
0311         int i = 8;
0312         sql << "insert into db2inst1.SOCI_TEST (id) values (:id)", use(i,"id");
0313         int j;
0314         std::string m;
0315         indicator ind = i_ok;
0316         sql << "select id,data from db2inst1.SOCI_TEST where id=8", into(j),into(m,ind);
0317         CHECK(j == i);
0318         CHECK(ind==i_null);
0319     }
0320 
0321     {
0322         std::tm dt;
0323         sql << "select current timestamp from sysibm.sysdummy1",into(dt);
0324         sql << "insert into db2inst1.SOCI_TEST (dt) values (:dt)",use(dt,"dt");
0325         std::tm dt2;
0326         sql << "select dt from db2inst1.SOCI_TEST where dt is not null", into(dt2);
0327         CHECK(dt2.tm_year == dt.tm_year);
0328         CHECK(dt2.tm_mon == dt.tm_mon);
0329         CHECK(dt2.tm_mday == dt.tm_mday);
0330         CHECK(dt2.tm_hour == dt.tm_hour);
0331         CHECK(dt2.tm_min == dt.tm_min);
0332         CHECK(dt2.tm_sec == dt.tm_sec);
0333     }
0334 
0335     sql<<"DROP TABLE DB2INST1.SOCI_TEST";
0336     sql.commit();
0337 }
0338 
0339 TEST_CASE("DB2 test 3", "[db2]")
0340 {
0341     soci::session sql(backEnd, connectString);
0342     int i;
0343 
0344     std::string query = "CREATE TABLE DB2INST1.SOCI_TEST (ID BIGINT,DATA VARCHAR(8),DT TIMESTAMP)";
0345     sql << query;
0346 
0347     std::vector<long long> ids(100);
0348     std::vector<std::string> data(100);
0349     std::vector<std::tm> dts(100);
0350     for (int i = 0; i < 100; i++)
0351     {
0352         ids[i] = 1000000000LL + i;
0353         data[i] = "test";
0354         dts[i].tm_year = 112;
0355         dts[i].tm_mon = 7;
0356         dts[i].tm_mday = 17;
0357         dts[i].tm_hour = 0;
0358         dts[i].tm_min = 0;
0359         dts[i].tm_sec = i % 60;
0360     }
0361 
0362     sql << "insert into db2inst1.SOCI_TEST (id, data, dt) values (:id, :data, :dt)",
0363         use(ids, "id"), use(data,"data"), use(dts, "dt");
0364 
0365     i = 0;
0366     rowset<row> rs = (sql.prepare<<"SELECT ID, DATA, DT FROM DB2INST1.SOCI_TEST");
0367     for (rowset<row>::const_iterator it = rs.begin(); it != rs.end(); it++)
0368     {
0369         const row & r = *it;
0370         const long long id = r.get<long long>(0);
0371         const std::string data = r.get<std::string>(1);
0372         const std::tm dt = r.get<std::tm>(2);
0373 
0374         CHECK(id == 1000000000LL + i);
0375         CHECK(data == "test");
0376         CHECK(dt.tm_year == 112);
0377         CHECK(dt.tm_mon == 7);
0378         CHECK(dt.tm_mday == 17);
0379         CHECK(dt.tm_hour == 0);
0380         CHECK(dt.tm_min == 0);
0381         CHECK(dt.tm_sec == i % 60);
0382 
0383         i += 1;
0384     }
0385 
0386     sql<<"DROP TABLE DB2INST1.SOCI_TEST";
0387     sql.commit();
0388 }
0389 
0390 
0391 int main(int argc, char** argv)
0392 {
0393 
0394 #ifdef _MSC_VER
0395     // Redirect errors, unrecoverable problems, and assert() failures to STDERR,
0396     // instead of debug message window.
0397     // This hack is required to run assert()-driven tests by Buildbot.
0398     // NOTE: Comment this 2 lines for debugging with Visual C++ debugger to catch assertions inside.
0399     _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
0400     _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
0401 #endif //_MSC_VER
0402 
0403     if (argc >= 2)
0404     {
0405         connectString = argv[1];
0406 
0407         argv[1] = argv[0];
0408 
0409         argc--;
0410         argv++;
0411     }
0412     else
0413     {
0414         std::cout << "usage: " << argv[0]
0415             << " connectstring [test-arguments...]\n"
0416             << "example: " << argv[0]
0417             << " \'DSN=SAMPLE;Uid=db2inst1;Pwd=db2inst1;autocommit=off\'\n";
0418         std::exit(1);
0419     }
0420 
0421     test_context tc(backEnd, connectString);
0422 
0423     return Catch::Session().run(argc, argv);
0424 }