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

test-postgresql.cpp

Go to the documentation of this file.
00001 //
00002 // Copyright (C) 2004-2008 Maciej Sobczak, Stephen Hutton
00003 // Distributed under the Boost Software License, Version 1.0.
00004 // (See accompanying file LICENSE_1_0.txt or copy at
00005 // http://www.boost.org/LICENSE_1_0.txt)
00006 //
00007 
00008 //
00009 #if defined(SOCI_HEADERS_BURIED)
00010 #       include <soci/core/soci.h>
00011 #       include <soci/backends/postgresql/soci-postgresql.h>
00012 #       include <soci/core/test/common-tests.h>
00013 #else
00014 #       include <soci.h>
00015 #       include <soci-postgresql.h>
00016 #       include <test/common-tests.h>
00017 #endif
00018 //
00019 #include <iostream>
00020 #include <sstream>
00021 #include <string>
00022 #include <cassert>
00023 #include <cmath>
00024 #include <cstring>
00025 #include <ctime>
00026 #include <cstdlib>
00027 
00028 using namespace soci;
00029 using namespace soci::tests;
00030 
00031 std::string connectString;
00032 backend_factory const &backEnd = postgresql;
00033 
00034 // Postgres-specific tests
00035 
00036 struct oid_table_creator : public table_creator_base
00037 {
00038     oid_table_creator(session& sql)
00039     : table_creator_base(sql)
00040     {
00041         sql << "create table soci_test ("
00042                 " id integer,"
00043                 " name varchar(100)"
00044                 ") with oids";
00045     }
00046 };
00047 
00048 // ROWID test
00049 // Note: in PostgreSQL, there is no ROWID, there is OID.
00050 // It is still provided as a separate type for "portability",
00051 // whatever that means.
00052 void test1()
00053 {
00054     {
00055         session sql(backEnd, connectString);
00056 
00057         oid_table_creator tableCreator(sql);
00058 
00059         sql << "insert into soci_test(id, name) values(7, \'John\')";
00060 
00061         rowid rid(sql);
00062         sql << "select oid from soci_test where id = 7", into(rid);
00063 
00064         int id;
00065         std::string name;
00066 
00067 #ifndef SOCI_PGSQL_NOPARAMS
00068 
00069         sql << "select id, name from soci_test where oid = :rid",
00070             into(id), into(name), use(rid);
00071 
00072 #else
00073         // Older PostgreSQL does not support use elements.
00074 
00075         postgresql_rowid_backend *rbe
00076             = static_cast<postgresql_rowid_backend *>(rid.get_backend());
00077 
00078         unsigned long oid = rbe->value_;
00079 
00080         sql << "select id, name from soci_test where oid = " << oid,
00081             into(id), into(name);
00082 
00083 #endif // SOCI_PGSQL_NOPARAMS
00084 
00085         assert(id == 7);
00086         assert(name == "John");
00087     }
00088 
00089     std::cout << "test 1 passed" << std::endl;
00090 }
00091 
00092 // function call test
00093 class function_creator : function_creator_base
00094 {
00095 public:
00096 
00097     function_creator(session & sql)
00098     : function_creator_base(sql)
00099     {
00100         // before a language can be used it must be defined
00101         // if it has already been defined then an error will occur
00102         try { sql << "create language plpgsql"; }
00103         catch (soci_error const &) {} // ignore if error
00104 
00105 #ifndef SOCI_PGSQL_NOPARAMS
00106 
00107         sql  <<
00108             "create or replace function soci_test(msg varchar) "
00109             "returns varchar as $$ "
00110             "begin "
00111             "  return msg; "
00112             "end $$ language plpgsql";
00113 #else
00114 
00115        sql <<
00116             "create or replace function soci_test(varchar) "
00117             "returns varchar as \' "
00118             "begin "
00119             "  return $1; "
00120             "end \' language plpgsql";
00121 #endif
00122     }
00123 
00124 protected:
00125 
00126     std::string drop_statement()
00127     {
00128         return "drop function soci_test(varchar)";
00129     }
00130 };
00131 
00132 void test2()
00133 {
00134     {
00135         session sql(backEnd, connectString);
00136 
00137         function_creator functionCreator(sql);
00138 
00139         std::string in("my message");
00140         std::string out;
00141 
00142 #ifndef SOCI_PGSQL_NOPARAMS
00143 
00144         statement st = (sql.prepare <<
00145             "select soci_test(:input)",
00146             into(out),
00147             use(in, "input"));
00148 
00149 #else
00150         // Older PostgreSQL does not support use elements.
00151 
00152         statement st = (sql.prepare <<
00153             "select soci_test(\'" << in << "\')",
00154             into(out));
00155 
00156 #endif // SOCI_PGSQL_NOPARAMS
00157 
00158         st.execute(true);
00159         assert(out == in);
00160 
00161         // explicit procedure syntax
00162         {
00163             std::string in("my message2");
00164             std::string out;
00165 
00166 #ifndef SOCI_PGSQL_NOPARAMS
00167 
00168             procedure proc = (sql.prepare <<
00169                 "soci_test(:input)",
00170                 into(out), use(in, "input"));
00171 
00172 #else
00173         // Older PostgreSQL does not support use elements.
00174 
00175             procedure proc = (sql.prepare <<
00176                 "soci_test(\'" << in << "\')", into(out));
00177 
00178 #endif // SOCI_PGSQL_NOPARAMS
00179 
00180             proc.execute(true);
00181             assert(out == in);
00182         }
00183     }
00184 
00185     std::cout << "test 2 passed" << std::endl;
00186 }
00187 
00188 // BLOB test
00189 struct blob_table_creator : public table_creator_base
00190 {
00191     blob_table_creator(session & sql)
00192     : table_creator_base(sql)
00193     {
00194         sql <<
00195              "create table soci_test ("
00196              "    id integer,"
00197              "    img oid"
00198              ")";
00199     }
00200 };
00201 
00202 void test3()
00203 {
00204     {
00205         session sql(backEnd, connectString);
00206 
00207         blob_table_creator tableCreator(sql);
00208         
00209         char buf[] = "abcdefghijklmnopqrstuvwxyz";
00210 
00211         sql << "insert into soci_test(id, img) values(7, lo_creat(-1))";
00212 
00213         // in PostgreSQL, BLOB operations must be within transaction block
00214         transaction tr(sql);
00215 
00216         {
00217             blob b(sql);
00218 
00219             sql << "select img from soci_test where id = 7", into(b);
00220             assert(b.get_len() == 0);
00221 
00222             b.write(0, buf, sizeof(buf));
00223             assert(b.get_len() == sizeof(buf));
00224 
00225             b.append(buf, sizeof(buf));
00226             assert(b.get_len() == 2 * sizeof(buf));
00227         }
00228         {
00229             blob b(sql);
00230             sql << "select img from soci_test where id = 7", into(b);
00231             assert(b.get_len() == 2 * sizeof(buf));
00232             char buf2[100];
00233             b.read(0, buf2, 10);
00234             assert(std::strncmp(buf2, "abcdefghij", 10) == 0);
00235         }
00236 
00237         unsigned long oid;
00238         sql << "select img from soci_test where id = 7", into(oid);
00239         sql << "select lo_unlink(" << oid << ")";
00240     }
00241 
00242     std::cout << "test 3 passed" << std::endl;
00243 }
00244 
00245 struct longlong_table_creator : table_creator_base
00246 {
00247     longlong_table_creator(session & sql)
00248         : table_creator_base(sql)
00249     {
00250         sql << "create table soci_test(val int8)";
00251     }
00252 };
00253 
00254 // long long test
00255 void test4()
00256 {
00257     {
00258         session sql(backEnd, connectString);
00259 
00260         longlong_table_creator tableCreator(sql);
00261 
00262         long long v1 = 1000000000000LL;
00263         assert(v1 / 1000000 == 1000000);
00264 
00265         sql << "insert into soci_test(val) values(:val)", use(v1);
00266 
00267         long long v2 = 0LL;
00268         sql << "select val from soci_test", into(v2);
00269 
00270         assert(v2 == v1);
00271     }
00272 
00273     // vector<long long>
00274     {
00275         session sql(backEnd, connectString);
00276 
00277         longlong_table_creator tableCreator(sql);
00278 
00279         std::vector<long long> v1;
00280         v1.push_back(1000000000000LL);
00281         v1.push_back(1000000000001LL);
00282         v1.push_back(1000000000002LL);
00283         v1.push_back(1000000000003LL);
00284         v1.push_back(1000000000004LL);
00285 
00286         sql << "insert into soci_test(val) values(:val)", use(v1);
00287 
00288         std::vector<long long> v2(10);
00289         sql << "select val from soci_test order by val desc", into(v2);
00290 
00291         assert(v2.size() == 5);
00292         assert(v2[0] == 1000000000004LL);
00293         assert(v2[1] == 1000000000003LL);
00294         assert(v2[2] == 1000000000002LL);
00295         assert(v2[3] == 1000000000001LL);
00296         assert(v2[4] == 1000000000000LL);
00297     }
00298 
00299     std::cout << "test 4 passed" << std::endl;
00300 }
00301 
00302 struct boolean_table_creator : table_creator_base
00303 {
00304     boolean_table_creator(session & sql)
00305         : table_creator_base(sql)
00306     {
00307         sql << "create table soci_test(val boolean)";
00308     }
00309 };
00310 
00311 void test5()
00312 {
00313     {
00314         session sql(backEnd, connectString);
00315 
00316         boolean_table_creator tableCreator(sql);
00317 
00318         int i1 = 0;
00319 
00320         sql << "insert into soci_test(val) values(:val)", use(i1);
00321 
00322         int i2 = 7;
00323         sql << "select val from soci_test", into(i2);
00324 
00325         assert(i2 == i1);
00326 
00327         sql << "update soci_test set val = true";
00328         sql << "select val from soci_test", into(i2);
00329         assert(i2 == 1);
00330     }
00331 
00332     std::cout << "test 5 passed" << std::endl;
00333 }
00334 
00335 // dynamic backend test
00336 void test6()
00337 {
00338     try
00339     {
00340         session sql("nosuchbackend://" + connectString);
00341         assert(false);
00342     }
00343     catch (soci_error const & e)
00344     {
00345         assert(e.what() == std::string("Failed to open: libsoci_nosuchbackend.so"));
00346     }
00347 
00348     {
00349         dynamic_backends::register_backend("pgsql", backEnd);
00350 
00351         std::vector<std::string> backends = dynamic_backends::list_all();
00352         assert(backends.size() == 1);
00353         assert(backends[0] == "pgsql");
00354 
00355         {
00356             session sql("pgsql://" + connectString);
00357         }
00358 
00359         dynamic_backends::unload("pgsql");
00360 
00361         backends = dynamic_backends::list_all();
00362         assert(backends.empty());
00363     }
00364 
00365     {
00366         session sql("postgresql://" + connectString);
00367     }
00368 
00369     std::cout << "test 6 passed" << std::endl;
00370 }
00371 
00372 void test7()
00373 {
00374     {
00375         session sql(backEnd, connectString);
00376 
00377         int i;
00378         sql << "select 123", into(i);
00379         assert(i == 123);
00380 
00381         try
00382         {
00383             sql << "select 'ABC'", into (i);
00384             assert(false);
00385         }
00386         catch (soci_error const & e)
00387         {
00388             assert(e.what() == std::string("Cannot convert data."));
00389         }
00390     }
00391 
00392     std::cout << "test 7 passed" << std::endl;
00393 }
00394 
00395 void test8()
00396 {
00397     {
00398         session sql(backEnd, connectString);
00399 
00400         assert(sql.get_backend_name() == "postgresql");
00401     }
00402 
00403     std::cout << "test 8 passed" << std::endl;
00404 }
00405 
00406 // test for double-colon cast in SQL expressions
00407 void test9()
00408 {
00409     {
00410         session sql(backEnd, connectString);
00411 
00412         int a = 123;
00413         int b = 0;
00414         sql << "select :a::integer", use(a), into(b);
00415         assert(b == a);
00416     }
00417 
00418     std::cout << "test 9 passed" << std::endl;
00419 }
00420 
00421 // test for date, time and timestamp parsing
00422 void test10()
00423 {
00424     {
00425         session sql(backEnd, connectString);
00426 
00427         std::string someDate = "2009-06-17 22:51:03.123";
00428         std::tm t1, t2, t3;
00429 
00430         sql << "select :sd::date, :sd::time, :sd::timestamp",
00431             use(someDate, "sd"), into(t1), into(t2), into(t3);
00432 
00433         // t1 should contain only the date part
00434         assert(t1.tm_year == 2009 - 1900);
00435         assert(t1.tm_mon == 6 - 1);
00436         assert(t1.tm_mday == 17);
00437         assert(t1.tm_hour == 0);
00438         assert(t1.tm_min == 0);
00439         assert(t1.tm_sec == 0);
00440 
00441         // t2 should contain only the time of day part
00442         assert(t2.tm_year == 0);
00443         assert(t2.tm_mon == 0);
00444         assert(t2.tm_mday == 1);
00445         assert(t2.tm_hour == 22);
00446         assert(t2.tm_min == 51);
00447         assert(t2.tm_sec == 3);
00448 
00449         // t3 should contain all information
00450         assert(t3.tm_year == 2009 - 1900);
00451         assert(t3.tm_mon == 6 - 1);
00452         assert(t3.tm_mday == 17);
00453         assert(t3.tm_hour == 22);
00454         assert(t3.tm_min == 51);
00455         assert(t3.tm_sec == 3);
00456     }
00457 
00458     std::cout << "test 10 passed" << std::endl;
00459 }
00460 
00461 // DDL Creation objects for common tests
00462 struct table_creator_one : public table_creator_base
00463 {
00464     table_creator_one(session & sql)
00465         : table_creator_base(sql)
00466     {
00467         sql << "create table soci_test(id integer, val integer, c char, "
00468                  "str varchar(20), sh int2, ul numeric(20), d float8, "
00469                  "tm timestamp, i1 integer, i2 integer, i3 integer, "
00470                  "name varchar(20))";
00471     }
00472 };
00473 
00474 struct table_creator_two : public table_creator_base
00475 {
00476     table_creator_two(session & sql)
00477         : table_creator_base(sql)
00478     {
00479         sql  << "create table soci_test(num_float float8, num_int integer,"
00480                      " name varchar(20), sometime timestamp, chr char)";
00481     }
00482 };
00483 
00484 struct table_creator_three : public table_creator_base
00485 {
00486     table_creator_three(session & sql)
00487         : table_creator_base(sql)
00488     {
00489         sql << "create table soci_test(name varchar(100) not null, "
00490             "phone varchar(15))";
00491     }
00492 };
00493 
00494 //
00495 // Support for soci Common Tests
00496 //
00497 
00498 class test_context : public test_context_base
00499 {
00500 public:
00501     test_context(backend_factory const &backEnd,
00502                 std::string const &connectString)
00503         : test_context_base(backEnd, connectString) {}
00504 
00505     table_creator_base* table_creator_1(session& s) const
00506     {
00507         return new table_creator_one(s);
00508     }
00509 
00510     table_creator_base* table_creator_2(session& s) const
00511     {
00512         return new table_creator_two(s);
00513     }
00514 
00515     table_creator_base* table_creator_3(session& s) const
00516     {
00517         return new table_creator_three(s);
00518     }
00519 
00520     std::string to_date_time(std::string const &datdt_string) const
00521     {
00522         return "timestamptz(\'" + datdt_string + "\')";
00523     }
00524 
00525 };
00526 
00527 
00528 int main(int argc, char** argv)
00529 {
00530 
00531 #ifdef _MSC_VER
00532     // Redirect errors, unrecoverable problems, and assert() failures to STDERR,
00533     // instead of debug message window.
00534     // This hack is required to run asser()-driven tests by Buildbot.
00535     // NOTE: Comment this 2 lines for debugging with Visual C++ debugger to catch assertions inside.
00536     _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
00537     _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
00538 #endif //_MSC_VER
00539 
00540     if (argc == 2)
00541     {
00542         connectString = argv[1];
00543     }
00544     else
00545     {
00546         std::cout << "usage: " << argv[0]
00547             << " connectstring\n"
00548             << "example: " << argv[0]
00549             << " \'connect_string_for_PostgreSQL\'\n";
00550         return EXIT_FAILURE;
00551     }
00552 
00553     try
00554     {
00555         test_context tc(backEnd, connectString);
00556         common_tests tests(tc);
00557         tests.run();
00558 
00559         std::cout << "\nSOCI Postgres Tests:\n\n";
00560 
00561         test1();
00562         test2();
00563         test3();
00564         test4();
00565         test5();
00566 
00567 //         test6();
00568         std::cout << "test 6 skipped (dynamic backend)\n";
00569 
00570         test7();
00571         test8();
00572         test9();
00573         test10();
00574 
00575         std::cout << "\nOK, all tests passed.\n\n";
00576         return EXIT_SUCCESS;
00577     }
00578     catch (std::exception const & e)
00579     {
00580         std::cout << e.what() << '\n';
00581         return EXIT_FAILURE;
00582     }
00583 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
SourceForge Logo

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