SOCI Logo Get SOCI at SourceForge.net. Fast, secure and Free Open Source software downloads

test-mysql.cpp

Go to the documentation of this file.
00001 //
00002 // Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton
00003 // MySQL backend copyright (C) 2006 Pawel Aleksander Fedorynski
00004 // Distributed under the Boost Software License, Version 1.0.
00005 // (See accompanying file LICENSE_1_0.txt or copy at
00006 // http://www.boost.org/LICENSE_1_0.txt)
00007 //
00008 
00009 //
00010 #if defined(SOCI_HEADERS_BURIED)
00011 #       include <soci/core/soci.h>
00012 #       include <soci/backends/mysql/soci-mysql.h>
00013 #       include <soci/core/test/common-tests.h>
00014 #else
00015 #       include <soci.h>
00016 #       include <soci-mysql.h>
00017 #       include <test/common-tests.h>
00018 #endif
00019 //
00020 #include <iostream>
00021 #include <sstream>
00022 #include <string>
00023 #include <vector>
00024 #include <cassert>
00025 #include <cmath>
00026 #include <ctime>
00027 #include <ciso646>
00028 #include <cstdlib>
00029 // MySQL Client
00030 #if defined(SOCI_MYSQL_HEADERS_BURIED)
00031 #       include <mysql/mysqld_error.h>
00032 #       include <mysql/errmsg.h>
00033 #else
00034 #       include <mysqld_error.h>
00035 #       include <errmsg.h>
00036 #endif
00037 
00038 using namespace soci;
00039 using namespace soci::tests;
00040 
00041 std::string connectString;
00042 backend_factory const &backEnd = mysql;
00043 
00044 
00045 // procedure call test
00046 void test1()
00047 {
00048     {
00049         session sql(backEnd, connectString);
00050 
00051         mysql_session_backend *sessionBackEnd
00052             = static_cast<mysql_session_backend *>(sql.get_backend());
00053         std::string version = mysql_get_server_info(sessionBackEnd->conn_);
00054         int v;
00055         std::istringstream iss(version);
00056         if ((iss >> v) and v < 5)
00057         {
00058             std::cout << "skipping test 1 (MySQL server version ";
00059             std::cout << version << " does not support stored procedures)\n";
00060             return;
00061         }
00062 
00063         try { sql << "drop function myecho"; }
00064         catch (soci_error const &) {}
00065 
00066         sql <<
00067             "create function myecho(msg text) "
00068             "returns text deterministic "
00069             "  return msg; ";
00070 
00071         std::string in("my message");
00072         std::string out;
00073 
00074         statement st = (sql.prepare <<
00075             "select myecho(:input)",
00076             into(out),
00077             use(in, "input"));
00078 
00079         st.execute(1);
00080         assert(out == in);
00081 
00082         // explicit procedure syntax
00083         {
00084             std::string in("my message2");
00085             std::string out;
00086 
00087             procedure proc = (sql.prepare <<
00088                 "myecho(:input)",
00089                 into(out), use(in, "input"));
00090 
00091             proc.execute(1);
00092             assert(out == in);
00093         }
00094 
00095         sql << "drop function myecho";
00096     }
00097 
00098     std::cout << "test 1 passed" << std::endl;
00099 }
00100 
00101 // MySQL error reporting test.
00102 void test2()
00103 {
00104     {
00105         try
00106         {
00107             session sql(backEnd, "host=test.soci.invalid");
00108         }
00109         catch (mysql_soci_error const &e)
00110         {
00111             assert(e.err_num_ == CR_UNKNOWN_HOST);
00112         }
00113     }
00114 
00115     {
00116         session sql(backEnd, connectString);
00117         sql << "create table soci_test (id integer)";
00118         try
00119         {
00120             int n;
00121             sql << "select id from soci_test_nosuchtable", into(n);
00122         }
00123         catch (mysql_soci_error const &e)
00124         {
00125             assert(e.err_num_ == ER_NO_SUCH_TABLE);
00126         }
00127         try
00128         {
00129             sql << "insert into soci_test (invalid) values (256)";
00130         }
00131         catch (mysql_soci_error const &e)
00132         {
00133             assert(e.err_num_ == ER_BAD_FIELD_ERROR);
00134         }
00135         // A bulk operation.
00136         try
00137         {
00138             std::vector<int> v(3, 5);
00139             sql << "insert into soci_test_nosuchtable values (:n)", use(v);
00140         }
00141         catch (mysql_soci_error const &e)
00142         {
00143             assert(e.err_num_ == ER_NO_SUCH_TABLE);
00144         }
00145         sql << "drop table soci_test";
00146     }
00147 
00148     std::cout << "test 2 passed" << std::endl;
00149 }
00150 
00151 struct longlong_table_creator : table_creator_base
00152 {
00153     longlong_table_creator(session & sql)
00154         : table_creator_base(sql)
00155     {
00156         sql << "create table soci_test(val bigint)";
00157     }
00158 };
00159 
00160 // long long test
00161 void test3()
00162 {
00163     {
00164         session sql(backEnd, connectString);
00165 
00166         longlong_table_creator tableCreator(sql);
00167 
00168         long long v1 = 1000000000000LL;
00169         assert(v1 / 1000000 == 1000000);
00170 
00171         sql << "insert into soci_test(val) values(:val)", use(v1);
00172 
00173         long long v2 = 0LL;
00174         sql << "select val from soci_test", into(v2);
00175 
00176         assert(v2 == v1);
00177     }
00178 
00179     // vector<long long>
00180     {
00181         session sql(backEnd, connectString);
00182 
00183         longlong_table_creator tableCreator(sql);
00184 
00185         std::vector<long long> v1;
00186         v1.push_back(1000000000000LL);
00187         v1.push_back(1000000000001LL);
00188         v1.push_back(1000000000002LL);
00189         v1.push_back(1000000000003LL);
00190         v1.push_back(1000000000004LL);
00191 
00192         sql << "insert into soci_test(val) values(:val)", use(v1);
00193 
00194         std::vector<long long> v2(10);
00195         sql << "select val from soci_test order by val desc", into(v2);
00196 
00197         assert(v2.size() == 5);
00198         assert(v2[0] == 1000000000004LL);
00199         assert(v2[1] == 1000000000003LL);
00200         assert(v2[2] == 1000000000002LL);
00201         assert(v2[3] == 1000000000001LL);
00202         assert(v2[4] == 1000000000000LL);
00203     }
00204 
00205     std::cout << "test 3 passed" << std::endl;
00206 }
00207 
00208 template <typename T>
00209 void test_num(const char* s, bool valid, T value)
00210 {
00211     try
00212     {
00213         session sql(backEnd, connectString);
00214         T val;
00215         sql << "select \'" << s << "\'", into(val);
00216         if (valid)
00217         {
00218             double v1 = value;
00219             double v2 = val;
00220             double d = std::fabs(v1 - v2);
00221             double epsilon = 0.001;
00222             assert(d < epsilon ||
00223                    d < epsilon * (std::fabs(v1) + std::fabs(v2)));
00224         }
00225         else
00226         {
00227             std::cout << "string \"" << s << "\" parsed as " << val
00228                       << " but should have failed.\n";
00229             assert(false);
00230         }
00231     }
00232     catch (soci_error const& e)
00233     {
00234         if (valid)
00235         {
00236             std::cout << "couldn't parse number: \"" << s << "\"\n";
00237             assert(false);
00238         }
00239         else
00240         {
00241             assert(std::string(e.what()) == "Cannot convert data.");
00242         }
00243     }
00244 }
00245 
00246 // Number conversion test.
00247 void test4()
00248 {
00249     test_num<double>("", false, 0);
00250     test_num<double>("foo", false, 0);
00251     test_num<double>("1", true, 1);
00252     test_num<double>("12", true, 12);
00253     test_num<double>("123", true, 123);
00254     test_num<double>("12345", true, 12345);
00255     test_num<double>("12341234123412341234123412341234123412341234123412341",
00256         true, 1.23412e+52);
00257     test_num<double>("99999999999999999999999912222222222222222222222222223"
00258         "9999999999999999999999991222222222222222222222222222333333333333"
00259         "9999999999999999999999991222222222222222222222222222333333333333"
00260         "9999999999999999999999991222222222222222222222222222333333333333"
00261         "9999999999999999999999991222222222222222222222222222333333333333"
00262         "9999999999999999999999991222222222222222222222222222333333333333"
00263         "9999999999999999999999991222222222222222222222222222333333333333"
00264         "9999999999999999999999991222222222222222222222222222333333333333"
00265         "9999999999999999999999991222222222222222222222222222333333333333"
00266         "9999999999999999999999991222222222222222222222222222333333333333"
00267         "9999999999999999999999991222222222222222222222222222333333333333"
00268         "9999999999999999999999991222222222222222222222222222333333333333"
00269         "9999999999999999999999991222222222222222222222222222333333333333"
00270         "9999999999999999999999991222222222222222222222222222333333333333"
00271         "9999999999999999999999991222222222222222222222222222333333333333",
00272         false, 0);
00273     test_num<double>("1e3", true, 1000);
00274     test_num<double>("1.2", true, 1.2);
00275     test_num<double>("1.2345e2", true, 123.45);
00276     test_num<double>("1 ", false, 0);
00277     test_num<double>("     123", true, 123);
00278     test_num<double>("1,2", false, 0);
00279     test_num<double>("123abc", false, 0);
00280     test_num<double>("-0", true, 0);
00281 
00282     test_num<short>("123", true, 123);
00283     test_num<short>("100000", false, 0);
00284 
00285     test_num<int>("123", true, 123);
00286     test_num<int>("2147483647", true, 2147483647);
00287     test_num<int>("2147483647a", false, 0);
00288     test_num<int>("2147483648", false, 0);
00289     // -2147483648 causes a warning because it is interpreted as
00290     // 2147483648 (which doesn't fit in an integer) to which a negation
00291     // is applied.
00292     test_num<int>("-2147483648", true, -2147483647 - 1);
00293     test_num<int>("-2147483649", false, 0);
00294     test_num<int>("-0", true, 0);
00295     test_num<int>("1.1", false, 0);
00296 
00297     test_num<long long>("123", true, 123);
00298     test_num<long long>("9223372036854775807", true, 9223372036854775807LL);
00299     test_num<long long>("9223372036854775808", false, 0);
00300     
00301     std::cout << "test 4 passed" << std::endl;
00302 }
00303 
00304 void test5()
00305 {
00306     session sql(backEnd, connectString);
00307     std::tm t;
00308     sql << "select maketime(19, 54, 52)", into(t);
00309     assert(t.tm_year == 100);
00310     assert(t.tm_mon == 0);
00311     assert(t.tm_mday == 1);
00312     assert(t.tm_hour == 19);
00313     assert(t.tm_min == 54);
00314     assert(t.tm_sec == 52);
00315 
00316     std::cout << "test 5 passed" << std::endl;
00317 }
00318 
00319 // TEXT and BLOB types support test.
00320 void test6()
00321 {
00322     session sql(backEnd, connectString);
00323     std::string a("asdfg\0hjkl", 10);
00324     std::string b("lkjhg\0fd\0\0sa\0", 13);
00325     std::string c("\\0aa\\0bb\\0cc\\0", 10);
00326     // The maximum length for TEXT and BLOB is 65536.
00327     std::string x(60000, 'X');
00328     std::string y(60000, 'Y');
00329     // The default max_allowed_packet value for a MySQL server is 1M,
00330     // so let's limit ourselves to 800k, even though the maximum length
00331     // for LONGBLOB is 4G.
00332     std::string z(800000, 'Z');
00333 
00334     sql << "create table soci_test (id int, text_value text, "
00335         "blob_value blob, longblob_value longblob)";
00336     sql << "insert into soci_test values (1, \'foo\', \'bar\', \'baz\')";
00337     sql << "insert into soci_test "
00338         << "values (2, \'qwerty\\0uiop\', \'zxcv\\0bnm\', "
00339         << "\'qwerty\\0uiop\\0zxcvbnm\\0\')";
00340     sql << "insert into soci_test values (3, :a, :b, :c)",
00341            use(a), use(b), use(c);
00342     sql << "insert into soci_test values (4, :x, :y, :z)",
00343            use(x), use(y), use(z);
00344 
00345     std::vector<std::string> text_vec(100);
00346     std::vector<std::string> blob_vec(100);
00347     std::vector<std::string> longblob_vec(100);
00348     sql << "select text_value, blob_value, longblob_value "
00349         << "from soci_test order by id",
00350            into(text_vec), into(blob_vec), into(longblob_vec);
00351     assert(text_vec.size() == 4);
00352     assert(blob_vec.size() == 4);
00353     assert(longblob_vec.size() == 4);
00354     assert(text_vec[0] == "foo");
00355     assert(blob_vec[0] == "bar");
00356     assert(longblob_vec[0] == "baz");
00357     assert(text_vec[1] == std::string("qwerty\0uiop", 11));
00358     assert(blob_vec[1] == std::string("zxcv\0bnm", 8));
00359     assert(longblob_vec[1] == std::string("qwerty\0uiop\0zxcvbnm\0", 20));
00360     assert(text_vec[2] == a);
00361     assert(blob_vec[2] == b);
00362     assert(longblob_vec[2] == c);
00363     assert(text_vec[3] == x);
00364     assert(blob_vec[3] == y);
00365     assert(longblob_vec[3] == z);
00366 
00367     std::string text, blob, longblob;
00368     sql << "select text_value, blob_value, longblob_value "
00369         << "from soci_test where id = 1",
00370            into(text), into(blob), into(longblob);
00371     assert(text == "foo");
00372     assert(blob == "bar");
00373     assert(longblob == "baz");
00374     sql << "select text_value, blob_value, longblob_value "
00375         << "from soci_test where id = 2",
00376            into(text), into(blob), into(longblob);
00377     assert(text == std::string("qwerty\0uiop", 11));
00378     assert(blob == std::string("zxcv\0bnm", 8));
00379     assert(longblob == std::string("qwerty\0uiop\0zxcvbnm\0", 20));
00380     sql << "select text_value, blob_value, longblob_value "
00381         << "from soci_test where id = 3",
00382            into(text), into(blob), into(longblob);
00383     assert(text == a);
00384     assert(blob == b);
00385     assert(longblob == c);
00386     sql << "select text_value, blob_value, longblob_value "
00387         << "from soci_test where id = 4",
00388            into(text), into(blob), into(longblob);
00389     assert(text == x);
00390     assert(blob == y);
00391     assert(longblob == z);
00392 
00393     rowset<row> rs =
00394         (sql.prepare << "select text_value, blob_value, longblob_value "
00395                         "from soci_test order by id");
00396     rowset<row>::const_iterator r = rs.begin();
00397     assert(r->get_properties(0).get_data_type() == dt_string);
00398     assert(r->get<std::string>(0) == "foo");
00399     assert(r->get_properties(1).get_data_type() == dt_string);
00400     assert(r->get<std::string>(1) == "bar");
00401     assert(r->get_properties(2).get_data_type() == dt_string);
00402     assert(r->get<std::string>(2) == "baz");
00403     ++r;
00404     assert(r->get_properties(0).get_data_type() == dt_string);
00405     assert(r->get<std::string>(0) == std::string("qwerty\0uiop", 11));
00406     assert(r->get_properties(1).get_data_type() == dt_string);
00407     assert(r->get<std::string>(1) == std::string("zxcv\0bnm", 8));
00408     assert(r->get_properties(2).get_data_type() == dt_string);
00409     assert(r->get<std::string>(2) ==
00410            std::string("qwerty\0uiop\0zxcvbnm\0", 20));
00411     ++r;
00412     assert(r->get_properties(0).get_data_type() == dt_string);
00413     assert(r->get<std::string>(0) == a);
00414     assert(r->get_properties(1).get_data_type() == dt_string);
00415     assert(r->get<std::string>(1) == b);
00416     assert(r->get_properties(2).get_data_type() == dt_string);
00417     assert(r->get<std::string>(2) == c);
00418     ++r;
00419     assert(r->get_properties(0).get_data_type() == dt_string);
00420     assert(r->get<std::string>(0) == x);
00421     assert(r->get_properties(1).get_data_type() == dt_string);
00422     assert(r->get<std::string>(1) == y);
00423     assert(r->get_properties(2).get_data_type() == dt_string);
00424     assert(r->get<std::string>(2) == z);
00425     ++r;
00426     assert(r == rs.end());
00427 
00428     sql << "drop table soci_test";
00429 
00430     std::cout << "test 6 passed" << std::endl;
00431 }
00432 
00433 // DDL Creation objects for common tests
00434 struct table_creator_one : public table_creator_base
00435 {
00436     table_creator_one(session & sql)
00437         : table_creator_base(sql)
00438     {
00439         sql << "create table soci_test(id integer, val integer, c char, "
00440                  "str varchar(20), sh int2, ul numeric(20), d float8, "
00441                  "tm datetime, i1 integer, i2 integer, i3 integer, "
00442                  "name varchar(20)) type=InnoDB";
00443     }
00444 };
00445 
00446 struct table_creator_two : public table_creator_base
00447 {
00448     table_creator_two(session & sql)
00449         : table_creator_base(sql)
00450     {
00451         sql  << "create table soci_test(num_float float8, num_int integer,"
00452                      " name varchar(20), sometime datetime, chr char)";
00453     }
00454 };
00455 
00456 struct table_creator_three : public table_creator_base
00457 {
00458     table_creator_three(session & sql)
00459         : table_creator_base(sql)
00460     {
00461         sql << "create table soci_test(name varchar(100) not null, "
00462             "phone varchar(15))";
00463     }
00464 };
00465 
00466 //
00467 // Support for SOCI Common Tests
00468 //
00469 
00470 class test_context : public test_context_base
00471 {
00472 public:
00473     test_context(backend_factory const &backEnd,
00474                 std::string const &connectString)
00475         : test_context_base(backEnd, connectString) {}
00476 
00477     table_creator_base* table_creator_1(session& s) const
00478     {
00479         return new table_creator_one(s);
00480     }
00481 
00482     table_creator_base* table_creator_2(session& s) const
00483     {
00484         return new table_creator_two(s);
00485     }
00486 
00487     table_creator_base* table_creator_3(session& s) const
00488     {
00489         return new table_creator_three(s);
00490     }
00491 
00492     std::string to_date_time(std::string const &datdt_string) const
00493     {
00494         return "\'" + datdt_string + "\'";
00495     }
00496 
00497 };
00498 
00499 bool are_transactions_supported()
00500 {
00501     session sql(backEnd, connectString);
00502     sql << "drop table if exists soci_test";
00503     sql << "create table soci_test (id int) type=InnoDB";
00504     row r;
00505     sql << "show table status like \'soci_test\'", into(r);
00506     bool retv = (r.get<std::string>(1) == "InnoDB");
00507     sql << "drop table soci_test";
00508     return retv;
00509 }
00510 
00511 int main(int argc, char** argv)
00512 {
00513     if (argc == 2)
00514     {
00515         connectString = argv[1];
00516     }
00517     else
00518     {
00519         std::cout << "usage: " << argv[0]
00520             << " connectstring\n"
00521             << "example: " << argv[0]
00522             << " \"dbname=test user=root password=\'Ala ma kota\'\"\n";
00523         std::exit(1);
00524     }
00525 
00526     try
00527     {
00528         test_context tc(backEnd, connectString);
00529         common_tests tests(tc);
00530         bool checkTransactions = are_transactions_supported();
00531         tests.run(checkTransactions);
00532 
00533         std::cout << "\nSOCI MySQL Tests:\n\n";
00534 
00535         test1();
00536         test2();
00537         test3();
00538         test4();
00539         test5();
00540         test6();
00541 
00542         std::cout << "\nOK, all tests passed.\n\n";
00543         return EXIT_SUCCESS;
00544     }
00545     catch (std::exception const & e)
00546     {
00547         std::cout << e.what() << '\n';
00548         return EXIT_FAILURE;
00549     }
00550 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
SourceForge Logo

Generated on Sun Oct 3 2010 17:42:16 for EXTRAS-SOCI by Doxygen 1.7.1