mirror of
https://github.com/XRPLF/rippled.git
synced 2026-04-29 15:37:57 +00:00
b2855dc Merge pull request #378 from ravselj/sqlite_memory_leak bf5dad9 Memory leak fix in sqlite3_session_backend. 165737c Fix incorrect pointer instead pointee comparison. 625db74 Merge pull request #376 from ravselj/cmake_debug_postfix2 f3a1055 Added proper support for SOCI_DEBUG_POSTFIX by changing backend-loader macro. If debug postfix is specified in CMake then it is passed forward to soci-core backend loader which then combines proper name based on build configuration. 3459d7d Minor CMake fix that checks if shared mode is set before adding shared test(s). 66d407a Merge pull request #373 from musopr/ambiguous_session 9070742 Merge pull request #372 from musopr/clang_cxx_c11 7b08ec7 Fixed ambiguous 'session' reference e9748de Include SOCI_CXX_VERSION_FLAGS when compiling Clang abd6775 Merge pull request #368 from ravselj/cmake_debug_postfix cae0086 Added CMAKE_DEBUG_POSTFIX to SOCI_LIB_SUFFIX. This fixes backend loading when CMAKE_DEBUG_POSTFIX is used. 3dd4726 Enable MSVC multi process compiling by setting /MP flag.( VS2005+ ) e5f577f Merge pull request #365 from ravselj/sqlite_msvc_fixes c4dde08 Some trivial fixes in code to resolve MSVC warnings in SQLite back-end 330f0e0 Merge pull request #364 from ravselj/connection_pars b78c8ef Merge pull request #358 from ArnaudD-FR/bind_clean_up 9f415ee Merge pull request #362 from ArnaudD-FR/sqlite3_optim_split f1f0162 sqlite3 backend optimizations 0b1a835 Include soci-platform.h because of snprintf ac65d58 Merge pull request #361 from ArnaudD-FR/blob 24c8383 Bug fix - std::map with key type of const char* is replaced with std::string 3e02a54 Changes due to compiler warnings. 0c88f8c New data_type dt_blob and simple-interface support 403b8de Fix bind_clean_up when using 'row' 92ada95 Merge pull request #363 from ravselj/oracle_win_fix d1ad52f Add a unit test for CHAR(N) fields padding behaviour. 274d08a Explicitly set character set in Firebird unit tests for CHAR(N). 7623f76 More and better MSVC warnings fixes. caa2370 Removed dummy and not compilable operator<<(boost::optional). c025cc8 Fix inserting strings longer than 8000 bytes with ODBC/MS SQL. d8d765f Update documentations b5d6507 - oracle cmake Windows fix - test oracle compilation error fix a6b3514 Split Statement::clean_up into bind_clean_up and clean_up ba453c7 Make SQL state in ODBC backend error messages more clear. a374e54 Make ODBC backend error messages more homogeneous. c4255c9 Delete old /docs folder. 0d3b6b9 Merge pull request #344 from OniDaito/markdown_doc 04f9461 Merge pull request #352 from ravselj/cmake_bug_shared 955a915 - CMake bug fix when building MSVC with SHARED option enabled f7be373 Merge pull request #348 from msobczak/classic-makefiles 36f373f Added classic Makefile for PostgreSQL test. 615cb94 Updated classic Makefile for PostgreSQL backend. 821092c Don't use both -ansi and -std=gnu++98 flags with g++. 07543f5 Merge pull request #346 from msobczak/classic-makefiles 291fbe7 Merge pull request #347 from jsonn/master a87776e Make it easier to override SOCI_LIBDIR. 96e66f5 Corrected handling of generated file with backend search path. 0b26c32 Updated classic Makefiles for Oracle Express 11.2. 15a3705 Removed all the crap debian packaging threw in 6db2a65 Merge pull request #343 from OniDaito/master cf11404 Added Markdown docs ffbfdc0 Inlined the pragmas for the C++11 tests ae3ac9d Mistake with CXX11 pragma fixed in session.h 303a966 Merge pull request #341 from mloskot/issues/340 7d7516d Add more qualifications uses of session class with namespace soci::session. caa3e2b Merge pull request #335 from mloskot/issues/258 1e89d43 Fully qualify uses of session class with namespace soci::session. 1ed81ca Restore setting session with query transformation 84d29e2 Merge branch 'pull/336' 949924a Cope with GNU <=4.6 warning about the #pragma 3494b2b Wrap stream operator for boost::optional<int> with HAVE_BOOST af4b1a3 Report SOCI_CXX_C11 in CMake output 5744a16 Merge branch 'master' of https://github.com/OniDaito/soci into pull/336 0ab7b37 Remove old build .tcl scripts. 8f2195a Check Postgression availability before proceeding with build. cd3af53 Remove #include "error.h" of non-existent header 48a8bfa Added the C++11 changes back in 1aee2d1 Add -Wl,-flat_namespace -Wl,-undefined -Wl,suppress to LINK_FLAGS on Apple/OSX 2bf3aa7 Disable test of set_query_transformation with C++ lambda 1d26033 CMake should not terminate on unknown toolset d8b64cb Remove SociSystemInfo.cmake modul as redundant. fc3391f List Boost.DateTime in core dependencies f4ff281 Indicate Travis CI builds Oracle WITH_BOOST=OFF 4863376 Merge pull request #326 from mloskot/issues/224 0c18240 Restore Oracle build with tests on Travis CI. bc4abd7 Throw instead of truncating VARCHAR columns in Firebird backend. 4c612af No changes, just small code simplification in Firebird backend. ba206ed Extract common part of MySQL and ODBC MySQL tests in a header. a0fd859 Remove asserts from the SOCI headers and code. b36944c Check vector indices instead of asserting that they are valid. 75ef8d8 Handle dt_unsigned_long_long in the "simple" SOCI layer. 2e2f60b Remove asserts on unknown type from the "simple" SOCI layer. e21aef7 Throw instead of asserting if connection_pool::lease() fails. 4b4cecb Replace left over asserts with CATCH CHECK in the tests code. 388a8d3 Use compile-time asserts to check SQLINTEGER size. af80fd8 Use SQLT_BDOUBLE instead of SQLT_FLT in Oracle backend. c74132b Fix warning about pointer-to-int conversion in Firebird backend. 4916551 Reorganize more unit tests to use CATCH sections. 787b428 Fix duplicate test name in Oracle unit tests. 7f65799 Avoid warnings about int-to-pointer conversions in DB2 backend. 7e80c68 Use parameter names from the query, if given, in error messages. 8b0c372 Don't clean up SQLite3 statement prematurely. 9119ed8 Rename db2_statement_backend::names field to names_. f5c86b7 Make SOCI_NORETURN public and use it in declaration. 62c17b2 Add mktime_from_ymdhms() helper. ee0b9e4 Fix a clash between CATCH test cases defined in different files. 60a33f4 Reorganize "Use and into" unit test to use CATCH sections. db59a48 Merge pull request #314 from rpiotaix/release/3.2 82ea95f Don't add DB2_INCLUDE_DIR to global include directories. 4f570d7 Restore Travis CI builds for other databases 71edca9 Merge pull request #306 from mloskot/postgression 1e4b365 Add a Travis build using PostgreSQL server at Postgression. 6abb7e1 Typo 1ccff47 Replace raw & with & entity. 56d3aa6 No real changes, just remove trailing whitespace. ef6d90d Fix previous attempt to correct include of SQLite3 backend header 31a22a1 Include SQLite3 backend public headers using soci/ prefix. e4376ed Merge branch 'master' into develop-3.2.3 111b50a Merge branch 'hotfix/3.2.3' 0ef4912 Add 3.2.3 release notes 8da98b2 Add new contributors ee7e155 Bump version number in docs 30c02f3 Merge branch 'master' of git://github.com/Alex-Vol/soci into hotfix/3.2.3-PR263 5577606 Improve readability of ODBC error message Closes #229 8e14c5b Improve error message when an odbc error occurs 8a50af6 Merge branch 'hotfix/3.2.3' of https://github.com/SOCI/soci into hotfix/3.2.3 a948ab3 Remove unused HAVE_XXX defines 2c85be1 Fix missing strtoll on Cygwin and MinGW d9c059e Clarify documenation and examples on bulk operations. a08d750 [travis] Disable Oracle build 70e67aa Replace prefix underscore with suffix in private member names c799e4f Append each member of tuple/fusion instead of adding tuple/fusion 645e7a2 Merge github.com:pacocamberos/soci into pacocamberos-branch-mysql-blob e96bc2b Ignore CMakeLists.txt.user created by Qt Creator IDE f694e30 Bump library version number to 3.2.3 5ecebe9 fixed link error for msvc 64 bit 3278579 Fix email notifications for Travis CI builds. ad9075c Configure Travis CI to fail the build a.s.a.p. 7481868 Explicitly set extra_float_digits when using PostgreSQL in ODBC. 83bbbd4 update sqlite3 backend documentation 57530a1 Merge pull request #302 from vadz/rich-exceptions 5cda82a Avoid throwing from soci_error copy ctor and assignment operator. 8bb6610 Provide context of the error in soci_error when possible. a8ba1cb Add use_type_base::dump_value() for richer diagnostics. 76b3089 Add soci_error::get_error_message() method. e8e5978 No real changes, just remove trailing whitespace. a90018b Merge catch-tests branch. 7b8b37b Use REQUIRE() and not CHECK() for a test that can't be allowed to fail. c9dbe19 Move all tests from tests/assert to tests directory itself. 246f657 Convert the tests to use CATCH testing framework. b2060fb Add single header version of CATCH testing framework. b87407e Add values::get_number_of_columns() accessor. 9628081 Define SOCI_NORETURN: a portable __attribute__((noreturn)) equivalent. 6ebcbcd Remove the never used details::statement_impl::namedUses_. 0f1f295 Add helper exchange_type_cast<>() template function. 02207fc Rename "version" class in the ODBC test to "odbc_version". 42549d0 Merge pull request #297 from nbougalis/unshadow 7d5eb2d Use a base-class member instead of shadowing it. 37fbe8f Don't always disable ODBC MS SQL test under Unix, just when using Travis. ed37399 Fix ODBC backend get_affected_rows() when using FreeTDS driver. f212ca9 Skip test which fails when using ODBC with MS SQL Server. 629386f Merge pull request #294 from denisarnaud/develop 294becb Fix for the issue #169: cleaner way to include headers. 120b88c Accept oraocci12 as a possible Oracle library name too. 8e1ddcd Merge pull request #213 from ayllon/develop 6552eb1 No real changes, just simplify Firebird backend code a little. 34be702 Test exact round trip for NUMERIC values for all backends. 24c0539 Fix rounding error in Firebird NUMERIC/DECIMAL conversions. 69352bc Speculatively enable exact floating point comparisons for all backends. f497fb8 Disable exact floating point when using PostgreSQL ODBC driver. 6f9dd54 No changes, just fix a repetitive typo in "assert" in comments. 02f0a69 No changes, just remove annoying "EXECEPTION" typo. 4bf2d3c Explicitly disable exact floating point comparison in MySQL test. 1f3dd92 Replace accidental assignment with a comparison in Firebird unit test. c3cd309 Make text-to-double conversion exact in PostgreSQL backend. ff9146a Explicitly disable exact floating point comparison in SQLite test. 7039d00 Compare floating point values exactly in tests whenever possible. 53cd24e Don't start implicit transaction too eagerly in Firebird backend. 66f0d82 Add possibility to build Firebird using embedded library. 1489811 Update version to 4.0.0 in cmake too. 5838cc6 Reenable building, if not testing, Oracle backend. dc4fb73 Move ORACLE_HOME to Oracle-specific script. f9167a1 Avoid many warnings about floating point values comparison. c85744b Define GCC_WARNING_SUPPRESS and GCC_WARNING_RESTORE macros. ef7e9a9 Avoid warning about set but unused variable in Oracle backend. 86a4598 Avoid g++ warnings about casting away const with C-style casts. 2c887b3 Ignore CMake-generated files. f61d7f5 Add missing include for std::max 21824a1 fixed deadlock in soci::connection_pool::try_lease 6e6bd46 Documentation for SQLite3 result code support. 97cbb0a Update PostgreSQL backend documentation for UUID type support. 5448cf1 Spelling fix in an error message: s/Commiting/Committing/. 5b073e3 Remove the unnecessary "error.h" inclusion from PostgreSQL code. 5776dd4 Introduced sqlite3_soci_error exception as subclass of soci_error. This new exception exposes the SQLite3 result code returned when any failure happens. Using this method is preferable to scrubbing string error messages in soci_error exceptions. Useful when there needs to be a distinction between general errors and database constraint errors. Unit test added to prove the funtionality does what is expected. 6d766e7 Introduced support for UUID column type in PostgreSQL statement.cpp. Unit test added for UUID column support testing all supported kinds of UUID formatted strings on input and standardized UUID formatted strings on output. e106dc0 Optionally use the environment locale in the tests. 1b65061 Make sqlite3 and mysql backends work with any locale too. 8548642 Use locale-independent function for converting doubles to strings. 1260d4f Reimplement cstring_to_double() without using C++ standard library. bc884fe Remove unused HAVE_XXX defines 4ffb21b Fix missing strtoll on Cygwin and MinGW 7bd4991 Clarify documenation and examples on bulk operations. 4d0785e Temporarily disable using Oracle backend on Travis. da7e42c Merge pull request #242 from vadz/pgsql8-bytea 070b278 Merge branch 'fix_odbc_msvc_x86_64' of github.com:snikulov/soci into snikulov-fix_odbc_msvc_x86_64 fce8560 [travis] Disable Oracle build 0ff0e01 Replace prefix underscore with suffix in private member names 65a5ee3 Append each member of tuple/fusion instead of adding tuple/fusion 8e9fb42 Merge github.com:pacocamberos/soci into pacocamberos-branch-mysql-blob 3dca4e3 Ignore CMakeLists.txt.user created by Qt Creator IDE de7e6f0 Bump library version number to 3.2.3 946dd5a Fix PostgreSQL unit test to pass with PostgreSQL < 9.0. 0a47eaf vs2013 got strtoll/strtoull 58d31f9 Update version to 4.0.0. 89df841 Merge pull request #239 from vadz/soci-headers-prefix 417ef5c Include all public headers using "soci/" prefix inside SOCI itself. 5a99a15 Merge pull request #238 from vadz/cstrtod 0585bb1 Merge pull request #237 from vadz/odbc-header-fix 6f4162c Add helper cstring_to_double() and use it in PostgreSQL backend. 73119cb Fix compilation of ODBC-specific SOCI header with new include paths. d877390 Delete obsolete src/<backend>/test directories 06a970f Revert CMake setup for ODBC DB2 test f04147a Move ODBC test DSN files to new tests location 0219c43 Fix paths to ODBC test DSN files 928174c Fix Firebird includes of private headers bc171b6 Fix copy-n-paste error in CMake macro parameter name 1f4d6ef Fix includes to point to backend headers in subdirectories 552e81c Enable other tests in tests/assert 7a018a3 Move tests/assert into separate subdirectories e2ec7ff Ignore Qt Creator and Eclipse files 5d527ec Fix windows.h case for cross-compilation 024ccc8 Firebird: fix harmless warning in 64 bit builds. 802f78e Merge pull request #216 from dgrambow/develop 32c5f88 Add get_last_insert_id tests for sqlite3 and mysql backends ccd4c0d Add get_last_insert_id for sqlite3 and mysql backends Update docs/beyond.html accordingly 42aec23 Fix in soci::oracle to allow spaces in the params b2ea9f7 fixed link error for msvc 64 bit ef69fa9 [travis] Disable building tests due to #199 09acb8c [travis] Fix bash script syntax error cba671f [travis] Disable ctest run due to #199 d8f7d9d [travis] Restore soci-devel notifications 22257b3 [cmake] Remove unused log message 0cffb8a CMake 2.8.7 have problems with per target includes b430cb0 Attempt to correct -I paths for backend test 6c0721d Attempt to correct -I paths for backend folders 69d70c5 [travis] Disable tempoarily soci-devel notifications f4802f1 [travis] Log build script name 8890aea [travis] Set CMAKE_VERBOSE_MAKEFILE=ON 717c38a [travis] Remove superfluos ] from make invocation 843a43c Fix travis-ci to run CMake from root directory 9e43795 Update copyright year da025df Merge branch 'feature/125-new-layout' into develop 04a34f2 Link presentation from London C++ Meeting 11ef1fa Fix doc/index.html menu links 5393ee5 Merge branch 'hotfix/3.2.2' into develop b6d97ff Implement new source tree layout #125 git-subtree-dir: src/soci git-subtree-split: b2855dce54340522f149221c6ebe2d14fd1129ba
1178 lines
32 KiB
C++
1178 lines
32 KiB
C++
//
|
|
// // Copyright (C) 2004-2007 Maciej Sobczak, Stephen Hutton
|
|
// Distributed under the Boost Software License, Version 1.0.
|
|
// (See accompanying file LICENSE_1_0.txt or copy at
|
|
// http://www.boost.org/LICENSE_1_0.txt)
|
|
//
|
|
|
|
#include "common-tests.h"
|
|
#include "soci/soci.h"
|
|
#include "soci/oracle/soci-oracle.h"
|
|
#include <iostream>
|
|
#include <string>
|
|
#include <cstring>
|
|
#include <ctime>
|
|
|
|
using namespace soci;
|
|
using namespace soci::tests;
|
|
|
|
std::string connectString;
|
|
backend_factory const &backEnd = *soci::factory_oracle();
|
|
|
|
// Extra tests for date/time
|
|
TEST_CASE("Oracle datetime", "[oracle][datetime]")
|
|
{
|
|
soci::session sql(backEnd, connectString);
|
|
|
|
{
|
|
std::time_t now = std::time(NULL);
|
|
std::tm t1, t2;
|
|
t2 = *std::localtime(&now);
|
|
|
|
sql << "select t from (select :t as t from dual)",
|
|
into(t1), use(t2);
|
|
|
|
CHECK(t1.tm_sec == t2.tm_sec);
|
|
CHECK(t1.tm_min == t2.tm_min);
|
|
CHECK(t1.tm_hour == t2.tm_hour);
|
|
CHECK(t1.tm_mday == t2.tm_mday);
|
|
CHECK(t1.tm_mon == t2.tm_mon);
|
|
CHECK(t1.tm_year == t2.tm_year);
|
|
CHECK(t1.tm_wday == t2.tm_wday);
|
|
CHECK(t1.tm_yday == t2.tm_yday);
|
|
CHECK(t1.tm_isdst == t2.tm_isdst);
|
|
|
|
// make sure the date is stored properly in Oracle
|
|
char buf[25];
|
|
strftime(buf, sizeof(buf), "%m-%d-%Y %H:%M:%S", &t2);
|
|
|
|
std::string t_out;
|
|
std::string format("MM-DD-YYYY HH24:MI:SS");
|
|
sql << "select to_char(t, :format) from (select :t as t from dual)",
|
|
into(t_out), use(format), use(t2);
|
|
|
|
CHECK(t_out == std::string(buf));
|
|
}
|
|
|
|
{
|
|
// date and time - before year 2000
|
|
std::time_t then = std::time(NULL) - 17*365*24*60*60;
|
|
std::tm t1, t2;
|
|
t2 = *std::localtime(&then);
|
|
|
|
sql << "select t from (select :t as t from dual)",
|
|
into(t1), use(t2);
|
|
|
|
CHECK(t1.tm_sec == t2.tm_sec);
|
|
CHECK(t1.tm_min == t2.tm_min);
|
|
CHECK(t1.tm_hour == t2.tm_hour);
|
|
CHECK(t1.tm_mday == t2.tm_mday);
|
|
CHECK(t1.tm_mon == t2.tm_mon);
|
|
CHECK(t1.tm_year == t2.tm_year);
|
|
CHECK(t1.tm_wday == t2.tm_wday);
|
|
CHECK(t1.tm_yday == t2.tm_yday);
|
|
CHECK(t1.tm_isdst == t2.tm_isdst);
|
|
|
|
// make sure the date is stored properly in Oracle
|
|
char buf[25];
|
|
strftime(buf, sizeof(buf), "%m-%d-%Y %H:%M:%S", &t2);
|
|
|
|
std::string t_out;
|
|
std::string format("MM-DD-YYYY HH24:MI:SS");
|
|
sql << "select to_char(t, :format) from (select :t as t from dual)",
|
|
into(t_out), use(format), use(t2);
|
|
|
|
CHECK(t_out == std::string(buf));
|
|
}
|
|
}
|
|
|
|
// explicit calls test
|
|
TEST_CASE("Oracle explicit calls", "[oracle]")
|
|
{
|
|
soci::session sql(backEnd, connectString);
|
|
|
|
statement st(sql);
|
|
st.alloc();
|
|
int i = 0;
|
|
st.exchange(into(i));
|
|
st.prepare("select 7 from dual");
|
|
st.define_and_bind();
|
|
st.execute(1);
|
|
CHECK(i == 7);
|
|
}
|
|
|
|
// DDL + blob test
|
|
|
|
struct blob_table_creator : public table_creator_base
|
|
{
|
|
blob_table_creator(soci::session & sql)
|
|
: table_creator_base(sql)
|
|
{
|
|
sql <<
|
|
"create table soci_test ("
|
|
" id number(10) not null,"
|
|
" img blob"
|
|
")";
|
|
}
|
|
};
|
|
|
|
TEST_CASE("Oracle blob", "[oracle][blob]")
|
|
{
|
|
soci::session sql(backEnd, connectString);
|
|
|
|
blob_table_creator tableCreator(sql);
|
|
|
|
char buf[] = "abcdefghijklmnopqrstuvwxyz";
|
|
sql << "insert into soci_test (id, img) values (7, empty_blob())";
|
|
|
|
{
|
|
blob b(sql);
|
|
|
|
oracle_session_backend *sessionBackEnd
|
|
= static_cast<oracle_session_backend *>(sql.get_backend());
|
|
|
|
oracle_blob_backend *blobBackEnd
|
|
= static_cast<oracle_blob_backend *>(b.get_backend());
|
|
|
|
OCILobDisableBuffering(sessionBackEnd->svchp_,
|
|
sessionBackEnd->errhp_, blobBackEnd->lobp_);
|
|
|
|
sql << "select img from soci_test where id = 7", into(b);
|
|
CHECK(b.get_len() == 0);
|
|
|
|
// note: blob offsets start from 1
|
|
b.write(1, buf, sizeof(buf));
|
|
CHECK(b.get_len() == sizeof(buf));
|
|
b.trim(10);
|
|
CHECK(b.get_len() == 10);
|
|
|
|
// append does not work (Oracle bug #886191 ?)
|
|
//b.append(buf, sizeof(buf));
|
|
//CHECK(b.get_len() == sizeof(buf) + 10);
|
|
sql.commit();
|
|
}
|
|
|
|
{
|
|
blob b(sql);
|
|
sql << "select img from soci_test where id = 7", into(b);
|
|
//CHECK(b.get_len() == sizeof(buf) + 10);
|
|
CHECK(b.get_len() == 10);
|
|
char buf2[100];
|
|
b.read(1, buf2, 10);
|
|
CHECK(strncmp(buf2, "abcdefghij", 10) == 0);
|
|
}
|
|
}
|
|
|
|
// nested statement test
|
|
// (the same syntax is used for output cursors in PL/SQL)
|
|
|
|
struct basic_table_creator : public table_creator_base
|
|
{
|
|
basic_table_creator(soci::session & sql)
|
|
: table_creator_base(sql)
|
|
{
|
|
sql <<
|
|
"create table soci_test ("
|
|
" id number(5) not null,"
|
|
" name varchar2(100),"
|
|
" code number(5)"
|
|
")";
|
|
}
|
|
};
|
|
|
|
TEST_CASE("Oracle nested statement", "[oracle][blob]")
|
|
{
|
|
soci::session sql(backEnd, connectString);
|
|
basic_table_creator tableCreator(sql);
|
|
|
|
int id;
|
|
std::string name;
|
|
{
|
|
statement st1 = (sql.prepare <<
|
|
"insert into soci_test (id, name) values (:id, :name)",
|
|
use(id), use(name));
|
|
|
|
id = 1; name = "John"; st1.execute(1);
|
|
id = 2; name = "Anna"; st1.execute(1);
|
|
id = 3; name = "Mike"; st1.execute(1);
|
|
}
|
|
|
|
statement stInner(sql);
|
|
statement stOuter = (sql.prepare <<
|
|
"select cursor(select name from soci_test order by id)"
|
|
" from soci_test where id = 1",
|
|
into(stInner));
|
|
stInner.exchange(into(name));
|
|
stOuter.execute();
|
|
stOuter.fetch();
|
|
|
|
std::vector<std::string> names;
|
|
while (stInner.fetch()) { names.push_back(name); }
|
|
|
|
REQUIRE(names.size() == 3);
|
|
CHECK(names[0] == "John");
|
|
CHECK(names[1] == "Anna");
|
|
CHECK(names[2] == "Mike");
|
|
}
|
|
|
|
|
|
// ROWID test
|
|
TEST_CASE("Oracle rowid", "[oracle][rowid]")
|
|
{
|
|
soci::session sql(backEnd, connectString);
|
|
basic_table_creator tableCreator(sql);
|
|
|
|
sql << "insert into soci_test(id, name) values(7, \'John\')";
|
|
|
|
rowid rid(sql);
|
|
sql << "select rowid from soci_test where id = 7", into(rid);
|
|
|
|
int id;
|
|
std::string name;
|
|
sql << "select id, name from soci_test where rowid = :rid",
|
|
into(id), into(name), use(rid);
|
|
|
|
CHECK(id == 7);
|
|
CHECK(name == "John");
|
|
}
|
|
|
|
// Stored procedures
|
|
struct procedure_creator : procedure_creator_base
|
|
{
|
|
procedure_creator(soci::session & sql)
|
|
: procedure_creator_base(sql)
|
|
{
|
|
sql <<
|
|
"create or replace procedure soci_test(output out varchar2,"
|
|
"input in varchar2) as "
|
|
"begin output := input; end;";
|
|
}
|
|
};
|
|
|
|
TEST_CASE("Oracle stored procedure", "[oracle][stored-procedure]")
|
|
{
|
|
soci::session sql(backEnd, connectString);
|
|
procedure_creator procedure_creator(sql);
|
|
|
|
std::string in("my message");
|
|
std::string out;
|
|
statement st = (sql.prepare <<
|
|
"begin soci_test(:output, :input); end;",
|
|
use(out, "output"),
|
|
use(in, "input"));
|
|
st.execute(1);
|
|
CHECK(out == in);
|
|
|
|
// explicit procedure syntax
|
|
{
|
|
std::string in("my message2");
|
|
std::string out;
|
|
procedure proc = (sql.prepare <<
|
|
"soci_test(:output, :input)",
|
|
use(out, "output"), use(in, "input"));
|
|
proc.execute(1);
|
|
CHECK(out == in);
|
|
}
|
|
}
|
|
|
|
// bind into user-defined objects
|
|
struct string_holder
|
|
{
|
|
string_holder() {}
|
|
string_holder(const char* s) : s_(s) {}
|
|
string_holder(std::string s) : s_(s) {}
|
|
std::string get() const { return s_; }
|
|
private:
|
|
std::string s_;
|
|
};
|
|
|
|
namespace soci
|
|
{
|
|
template <>
|
|
struct type_conversion<string_holder>
|
|
{
|
|
typedef std::string base_type;
|
|
static void from_base(const std::string &s, indicator /* ind */,
|
|
string_holder &sh)
|
|
{
|
|
sh = string_holder(s);
|
|
}
|
|
|
|
static void to_base(const string_holder &sh, std::string &s, indicator &ind)
|
|
{
|
|
s = sh.get();
|
|
ind = i_ok;
|
|
}
|
|
};
|
|
}
|
|
|
|
struct in_out_procedure_creator : public procedure_creator_base
|
|
{
|
|
in_out_procedure_creator(soci::session & sql)
|
|
: procedure_creator_base(sql)
|
|
{
|
|
sql << "create or replace procedure soci_test(s in out varchar2)"
|
|
" as begin s := s || s; end;";
|
|
}
|
|
};
|
|
|
|
struct returns_null_procedure_creator : public procedure_creator_base
|
|
{
|
|
returns_null_procedure_creator(soci::session & sql)
|
|
: procedure_creator_base(sql)
|
|
{
|
|
sql << "create or replace procedure soci_test(s in out varchar2)"
|
|
" as begin s := NULL; end;";
|
|
}
|
|
};
|
|
|
|
TEST_CASE("Oracle user-defined objects", "[oracle][type_conversion]")
|
|
{
|
|
soci::session sql(backEnd, connectString);
|
|
{
|
|
basic_table_creator tableCreator(sql);
|
|
|
|
int id(1);
|
|
string_holder in("my string");
|
|
sql << "insert into soci_test(id, name) values(:id, :name)", use(id), use(in);
|
|
|
|
string_holder out;
|
|
sql << "select name from soci_test", into(out);
|
|
CHECK(out.get() == "my string");
|
|
|
|
row r;
|
|
sql << "select * from soci_test", into(r);
|
|
string_holder dynamicOut = r.get<string_holder>(1);
|
|
CHECK(dynamicOut.get() == "my string");
|
|
}
|
|
}
|
|
|
|
TEST_CASE("Oracle user-defined objects in/out", "[oracle][type_conversion]")
|
|
{
|
|
soci::session sql(backEnd, connectString);
|
|
|
|
// test procedure with user-defined type as in-out parameter
|
|
{
|
|
in_out_procedure_creator procedureCreator(sql);
|
|
|
|
std::string sh("test");
|
|
procedure proc = (sql.prepare << "soci_test(:s)", use(sh));
|
|
proc.execute(1);
|
|
CHECK(sh == "testtest");
|
|
}
|
|
|
|
// test procedure with user-defined type as in-out parameter
|
|
{
|
|
in_out_procedure_creator procedureCreator(sql);
|
|
|
|
string_holder sh("test");
|
|
procedure proc = (sql.prepare << "soci_test(:s)", use(sh));
|
|
proc.execute(1);
|
|
CHECK(sh.get() == "testtest");
|
|
}
|
|
}
|
|
|
|
TEST_CASE("Oracle null user-defined objects in/out", "[oracle][null][type_conversion]")
|
|
{
|
|
soci::session sql(backEnd, connectString);
|
|
|
|
// test procedure which returns null
|
|
returns_null_procedure_creator procedureCreator(sql);
|
|
|
|
string_holder sh;
|
|
indicator ind = i_ok;
|
|
procedure proc = (sql.prepare << "soci_test(:s)", use(sh, ind));
|
|
proc.execute(1);
|
|
CHECK(ind == i_null);
|
|
}
|
|
|
|
// test bulk insert features
|
|
TEST_CASE("Oracle bulk insert", "[oracle][insert][bulk]")
|
|
{
|
|
soci::session sql(backEnd, connectString);
|
|
|
|
basic_table_creator tableCreator(sql);
|
|
|
|
// verify exception is thrown if vectors of unequal size are passed in
|
|
{
|
|
std::vector<int> ids;
|
|
ids.push_back(1);
|
|
ids.push_back(2);
|
|
std::vector<int> codes;
|
|
codes.push_back(1);
|
|
|
|
try
|
|
{
|
|
sql << "insert into soci_test(id,code) values(:id,:code)",
|
|
use(ids), use(codes);
|
|
FAIL("expected exception not thrown");
|
|
}
|
|
catch (soci_error const &e)
|
|
{
|
|
std::string const error = e.what();
|
|
CAPTURE(error);
|
|
CHECK(error.find("Bind variable size mismatch")
|
|
!= std::string::npos);
|
|
}
|
|
|
|
try
|
|
{
|
|
sql << "select from soci_test", into(ids), into(codes);
|
|
FAIL("expected exception not thrown");
|
|
}
|
|
catch (std::exception const &e)
|
|
{
|
|
std::string const error = e.what();
|
|
CAPTURE(error);
|
|
CHECK(error.find("Bind variable size mismatch")
|
|
!= std::string::npos);
|
|
}
|
|
}
|
|
|
|
// verify partial insert occurs when one of the records is bad
|
|
{
|
|
std::vector<int> ids;
|
|
ids.push_back(100);
|
|
ids.push_back(1000000); // too big for column
|
|
|
|
try
|
|
{
|
|
sql << "insert into soci_test (id) values(:id)", use(ids, "id");
|
|
FAIL("expected exception not thrown");
|
|
}
|
|
catch (soci_error const &e)
|
|
{
|
|
std::string const error = e.what();
|
|
//TODO e could be made to tell which row(s) failed
|
|
CAPTURE(error);
|
|
CHECK(error.find("ORA-01438") != std::string::npos);
|
|
}
|
|
sql.commit();
|
|
int count(7);
|
|
sql << "select count(*) from soci_test", into(count);
|
|
CHECK(count == 1);
|
|
sql << "delete from soci_test";
|
|
}
|
|
|
|
// test insert
|
|
{
|
|
std::vector<int> ids;
|
|
for (int i = 0; i != 3; ++i)
|
|
{
|
|
ids.push_back(i+10);
|
|
}
|
|
|
|
statement st = (sql.prepare << "insert into soci_test(id) values(:id)",
|
|
use(ids));
|
|
st.execute(1);
|
|
int count;
|
|
sql << "select count(*) from soci_test", into(count);
|
|
CHECK(count == 3);
|
|
}
|
|
|
|
//verify an exception is thrown if into vector is zero length
|
|
{
|
|
std::vector<int> ids;
|
|
CHECK_THROWS_AS((sql << "select id from soci_test", into(ids)), soci_error);
|
|
}
|
|
|
|
// verify an exception is thrown if use vector is zero length
|
|
{
|
|
std::vector<int> ids;
|
|
CHECK_THROWS_AS((sql << "insert into soci_test(id) values(:id)", use(ids)), soci_error);
|
|
}
|
|
|
|
// test "no data" condition
|
|
{
|
|
std::vector<indicator> inds(3);
|
|
std::vector<int> ids_out(3);
|
|
statement st = (sql.prepare << "select id from soci_test where 1=0",
|
|
into(ids_out, inds));
|
|
|
|
// false return value means "no data"
|
|
CHECK(st.execute(1) == false);
|
|
|
|
// that's it - nothing else is guaranteed
|
|
// and nothing else is to be tested here
|
|
}
|
|
|
|
// test NULL indicators
|
|
{
|
|
std::vector<int> ids(3);
|
|
sql << "select id from soci_test", into(ids);
|
|
|
|
std::vector<indicator> inds_in;
|
|
inds_in.push_back(i_ok);
|
|
inds_in.push_back(i_null);
|
|
inds_in.push_back(i_ok);
|
|
|
|
std::vector<int> new_codes;
|
|
new_codes.push_back(10);
|
|
new_codes.push_back(11);
|
|
new_codes.push_back(10);
|
|
|
|
sql << "update soci_test set code = :code where id = :id",
|
|
use(new_codes, inds_in), use(ids);
|
|
|
|
std::vector<indicator> inds_out(3);
|
|
std::vector<int> codes(3);
|
|
|
|
sql << "select code from soci_test", into(codes, inds_out);
|
|
REQUIRE(codes.size() == 3);
|
|
REQUIRE(inds_out.size() == 3);
|
|
CHECK(codes[0] == 10);
|
|
CHECK(codes[2] == 10);
|
|
CHECK(inds_out[0] == i_ok);
|
|
CHECK(inds_out[1] == i_null);
|
|
CHECK(inds_out[2] == i_ok);
|
|
}
|
|
|
|
// verify an exception is thrown if null is selected
|
|
// and no indicator was provided
|
|
{
|
|
std::string msg;
|
|
std::vector<int> intos(3);
|
|
try
|
|
{
|
|
sql << "select code from soci_test", into(intos);
|
|
FAIL("expected exception not thrown");
|
|
}
|
|
catch (soci_error const &e)
|
|
{
|
|
CHECK(e.get_error_message() ==
|
|
"Null value fetched and no indicator defined." );
|
|
}
|
|
}
|
|
|
|
// test basic select
|
|
{
|
|
const size_t sz = 3;
|
|
std::vector<indicator> inds(sz);
|
|
std::vector<int> ids_out(sz);
|
|
statement st = (sql.prepare << "select id from soci_test",
|
|
into(ids_out, inds));
|
|
const bool gotData = st.execute(true);
|
|
CHECK(gotData);
|
|
REQUIRE(ids_out.size() == sz);
|
|
CHECK(ids_out[0] == 10);
|
|
CHECK(ids_out[2] == 12);
|
|
REQUIRE(inds.size() == 3);
|
|
CHECK(inds[0] == i_ok);
|
|
CHECK(inds[1] == i_ok);
|
|
CHECK(inds[2] == i_ok);
|
|
}
|
|
|
|
// verify execute(0)
|
|
{
|
|
std::vector<int> ids_out(2);
|
|
statement st = (sql.prepare << "select id from soci_test",
|
|
into(ids_out));
|
|
|
|
st.execute();
|
|
REQUIRE(ids_out.size() == 2);
|
|
bool gotData = st.fetch();
|
|
CHECK(gotData);
|
|
REQUIRE(ids_out.size() == 2);
|
|
CHECK(ids_out[0] == 10);
|
|
CHECK(ids_out[1] == 11);
|
|
gotData = st.fetch();
|
|
CHECK(gotData);
|
|
REQUIRE(ids_out.size() == 1);
|
|
CHECK(ids_out[0] == 12);
|
|
gotData = st.fetch();
|
|
CHECK(gotData == false);
|
|
}
|
|
|
|
// verify resizing happens if vector is larger
|
|
// than number of rows returned
|
|
{
|
|
std::vector<int> ids_out(4); // one too many
|
|
statement st2 = (sql.prepare << "select id from soci_test",
|
|
into(ids_out));
|
|
bool gotData = st2.execute(true);
|
|
CHECK(gotData);
|
|
REQUIRE(ids_out.size() == 3);
|
|
CHECK(ids_out[0] == 10);
|
|
CHECK(ids_out[2] == 12);
|
|
}
|
|
|
|
// verify resizing happens properly during fetch()
|
|
{
|
|
std::vector<int> more;
|
|
more.push_back(13);
|
|
more.push_back(14);
|
|
sql << "insert into soci_test(id) values(:id)", use(more);
|
|
|
|
std::vector<int> ids(2);
|
|
statement st3 = (sql.prepare << "select id from soci_test", into(ids));
|
|
bool gotData = st3.execute(true);
|
|
CHECK(gotData);
|
|
CHECK(ids[0] == 10);
|
|
CHECK(ids[1] == 11);
|
|
|
|
gotData = st3.fetch();
|
|
CHECK(gotData);
|
|
CHECK(ids[0] == 12);
|
|
CHECK(ids[1] == 13);
|
|
|
|
gotData = st3.fetch();
|
|
CHECK(gotData);
|
|
REQUIRE(ids.size() == 1);
|
|
CHECK(ids[0] == 14);
|
|
|
|
gotData = st3.fetch();
|
|
CHECK(gotData == false);
|
|
}
|
|
}
|
|
|
|
// more tests for bulk fetch
|
|
TEST_CASE("Oracle bulk fetch", "[oracle][fetch][bulk]")
|
|
{
|
|
soci::session sql(backEnd, connectString);
|
|
|
|
basic_table_creator tableCreator(sql);
|
|
|
|
std::vector<int> in;
|
|
for (int i = 1; i <= 10; ++i)
|
|
{
|
|
in.push_back(i);
|
|
}
|
|
|
|
sql << "insert into soci_test (id) values(:id)", use(in);
|
|
|
|
int count(0);
|
|
sql << "select count(*) from soci_test", into(count);
|
|
CHECK(count == 10);
|
|
|
|
// verify that the exception is thrown when trying to resize
|
|
// the output vector to the size that is bigger than that
|
|
// at the time of binding
|
|
{
|
|
std::vector<int> out(4);
|
|
statement st = (sql.prepare <<
|
|
"select id from soci_test", into(out));
|
|
|
|
st.execute();
|
|
|
|
st.fetch();
|
|
REQUIRE(out.size() == 4);
|
|
CHECK(out[0] == 1);
|
|
CHECK(out[1] == 2);
|
|
CHECK(out[2] == 3);
|
|
CHECK(out[3] == 4);
|
|
out.resize(5); // this should be detected as error
|
|
try
|
|
{
|
|
st.fetch();
|
|
FAIL("expected exception not thrown");
|
|
}
|
|
catch (soci_error const &e)
|
|
{
|
|
CHECK(e.get_error_message() ==
|
|
"Increasing the size of the output vector is not supported.");
|
|
}
|
|
}
|
|
|
|
// on the other hand, downsizing is OK
|
|
{
|
|
std::vector<int> out(4);
|
|
statement st = (sql.prepare <<
|
|
"select id from soci_test", into(out));
|
|
|
|
st.execute();
|
|
|
|
st.fetch();
|
|
REQUIRE(out.size() == 4);
|
|
CHECK(out[0] == 1);
|
|
CHECK(out[1] == 2);
|
|
CHECK(out[2] == 3);
|
|
CHECK(out[3] == 4);
|
|
out.resize(3); // ok
|
|
st.fetch();
|
|
REQUIRE(out.size() == 3);
|
|
CHECK(out[0] == 5);
|
|
CHECK(out[1] == 6);
|
|
CHECK(out[2] == 7);
|
|
out.resize(4); // ok, not bigger than initially
|
|
st.fetch();
|
|
REQUIRE(out.size() == 3); // downsized because of end of data
|
|
CHECK(out[0] == 8);
|
|
CHECK(out[1] == 9);
|
|
CHECK(out[2] == 10);
|
|
bool gotData = st.fetch();
|
|
CHECK(gotData == false); // end of data
|
|
}
|
|
}
|
|
|
|
struct person
|
|
{
|
|
int id;
|
|
std::string firstName;
|
|
string_holder lastName; //test mapping of type_conversion-based types
|
|
std::string gender;
|
|
};
|
|
|
|
// Object-Relational Mapping
|
|
// Note: Use the values class as shown below in type_conversions
|
|
// to achieve object relational mapping. The values class should
|
|
// not be used directly in any other fashion.
|
|
namespace soci
|
|
{
|
|
// name-based conversion
|
|
template<> struct type_conversion<person>
|
|
{
|
|
typedef values base_type;
|
|
|
|
static void from_base(values const &v, indicator /* ind */, person &p)
|
|
{
|
|
// ignoring possibility that the whole object might be NULL
|
|
|
|
p.id = v.get<int>("ID");
|
|
p.firstName = v.get<std::string>("FIRST_NAME");
|
|
p.lastName = v.get<string_holder>("LAST_NAME");
|
|
p.gender = v.get<std::string>("GENDER", "unknown");
|
|
}
|
|
|
|
static void to_base(person const & p, values & v, indicator & ind)
|
|
{
|
|
v.set("ID", p.id);
|
|
v.set("FIRST_NAME", p.firstName);
|
|
v.set("LAST_NAME", p.lastName);
|
|
v.set("GENDER", p.gender, p.gender.empty() ? i_null : i_ok);
|
|
ind = i_ok;
|
|
}
|
|
};
|
|
}
|
|
|
|
struct person_table_creator : public table_creator_base
|
|
{
|
|
person_table_creator(soci::session & sql)
|
|
: table_creator_base(sql)
|
|
{
|
|
sql << "create table soci_test(id numeric(5,0) NOT NULL,"
|
|
<< " last_name varchar2(20), first_name varchar2(20), "
|
|
" gender varchar2(10))";
|
|
}
|
|
};
|
|
|
|
struct times100_procedure_creator : public procedure_creator_base
|
|
{
|
|
times100_procedure_creator(soci::session & sql)
|
|
: procedure_creator_base(sql)
|
|
{
|
|
sql << "create or replace procedure soci_test(id in out number)"
|
|
" as begin id := id * 100; end;";
|
|
}
|
|
};
|
|
|
|
TEST_CASE("Oracle ORM", "[oracle][orm]")
|
|
{
|
|
soci::session sql(backEnd, connectString);
|
|
|
|
{
|
|
person_table_creator tableCreator(sql);
|
|
|
|
person p;
|
|
p.id = 1;
|
|
p.lastName = "Smith";
|
|
p.firstName = "Pat";
|
|
sql << "insert into soci_test(id, first_name, last_name, gender) "
|
|
<< "values(:ID, :FIRST_NAME, :LAST_NAME, :GENDER)", use(p);
|
|
|
|
// p should be unchanged
|
|
CHECK(p.id == 1);
|
|
CHECK(p.firstName == "Pat");
|
|
CHECK(p.lastName.get() == "Smith");
|
|
|
|
person p1;
|
|
sql << "select * from soci_test", into(p1);
|
|
CHECK(p1.id == 1);
|
|
CHECK(p1.firstName == "Pat");
|
|
CHECK(p1.lastName.get() == "Smith");
|
|
CHECK(p1.gender == "unknown");
|
|
|
|
p.firstName = "Patricia";
|
|
sql << "update soci_test set first_name = :FIRST_NAME "
|
|
"where id = :ID", use(p);
|
|
|
|
// p should be unchanged
|
|
CHECK(p.id == 1);
|
|
CHECK(p.firstName == "Patricia");
|
|
CHECK(p.lastName.get() == "Smith");
|
|
// Note: gender is now "unknown" because of the mapping, not ""
|
|
CHECK(p.gender == "unknown");
|
|
|
|
person p2;
|
|
sql << "select * from soci_test", into(p2);
|
|
CHECK(p2.id == 1);
|
|
CHECK(p2.firstName == "Patricia");
|
|
CHECK(p2.lastName.get() == "Smith");
|
|
|
|
// insert a second row so we can test fetching
|
|
person p3;
|
|
p3.id = 2;
|
|
p3.firstName = "Joe";
|
|
p3.lastName = "Smith";
|
|
sql << "insert into soci_test(id, first_name, last_name, gender) "
|
|
<< "values(:ID, :FIRST_NAME, :LAST_NAME, :GENDER)", use(p3);
|
|
|
|
person p4;
|
|
statement st = (sql.prepare << "select * from soci_test order by id",
|
|
into(p4));
|
|
|
|
st.execute();
|
|
bool gotData = st.fetch();
|
|
CHECK(gotData);
|
|
CHECK(p4.id == 1);
|
|
CHECK(p4.firstName == "Patricia");
|
|
|
|
gotData = st.fetch();
|
|
CHECK(gotData);
|
|
CHECK(p4.id == 2);
|
|
CHECK(p4.firstName == "Joe");
|
|
gotData = st.fetch();
|
|
CHECK(gotData == false);
|
|
}
|
|
|
|
// test with stored procedure
|
|
{
|
|
times100_procedure_creator procedureCreator(sql);
|
|
|
|
person p;
|
|
p.id = 1;
|
|
p.firstName = "Pat";
|
|
p.lastName = "Smith";
|
|
procedure proc = (sql.prepare << "soci_test(:ID)", use(p));
|
|
proc.execute(1);
|
|
CHECK(p.id == 100);
|
|
CHECK(p.firstName == "Pat");
|
|
CHECK(p.lastName.get() == "Smith");
|
|
}
|
|
|
|
// test with stored procedure which returns null
|
|
{
|
|
returns_null_procedure_creator procedureCreator(sql);
|
|
|
|
person p;
|
|
try
|
|
{
|
|
procedure proc = (sql.prepare << "soci_test(:FIRST_NAME)",
|
|
use(p));
|
|
proc.execute(1);
|
|
FAIL("expected exception not thrown");
|
|
}
|
|
catch (soci_error& e)
|
|
{
|
|
CHECK(e.get_error_message() ==
|
|
"Null value not allowed for this type");
|
|
}
|
|
|
|
procedure proc = (sql.prepare << "soci_test(:GENDER)",
|
|
use(p));
|
|
proc.execute(1);
|
|
CHECK(p.gender == "unknown");
|
|
|
|
}
|
|
}
|
|
|
|
// Experimental support for position based O/R Mapping
|
|
|
|
// additional type for position-based test
|
|
struct person2
|
|
{
|
|
int id;
|
|
std::string firstName;
|
|
std::string lastName;
|
|
std::string gender;
|
|
};
|
|
|
|
// additional type for stream-like test
|
|
struct person3 : person2 {};
|
|
|
|
namespace soci
|
|
{
|
|
// position-based conversion
|
|
template<> struct type_conversion<person2>
|
|
{
|
|
typedef values base_type;
|
|
|
|
static void from_base(values const &v, indicator /* ind */, person2 &p)
|
|
{
|
|
p.id = v.get<int>(0);
|
|
p.firstName = v.get<std::string>(1);
|
|
p.lastName = v.get<std::string>(2);
|
|
p.gender = v.get<std::string>(3, "whoknows");
|
|
}
|
|
|
|
// What about the "to" part? Does it make any sense to have it?
|
|
};
|
|
|
|
// stream-like conversion
|
|
template<> struct type_conversion<person3>
|
|
{
|
|
typedef values base_type;
|
|
|
|
static void from_base(values const &v, indicator /* ind */, person3 &p)
|
|
{
|
|
v >> p.id >> p.firstName >> p.lastName >> p.gender;
|
|
}
|
|
// TODO: The "to" part is certainly needed.
|
|
};
|
|
}
|
|
|
|
TEST_CASE("Oracle ORM by index", "[oracle][orm]")
|
|
{
|
|
soci::session sql(backEnd, connectString);
|
|
|
|
person_table_creator tableCreator(sql);
|
|
|
|
person p;
|
|
p.id = 1;
|
|
p.lastName = "Smith";
|
|
p.firstName = "Patricia";
|
|
sql << "insert into soci_test(id, first_name, last_name, gender) "
|
|
<< "values(:ID, :FIRST_NAME, :LAST_NAME, :GENDER)", use(p);
|
|
|
|
// test position-based conversion
|
|
person2 p3;
|
|
sql << "select id, first_name, last_name, gender from soci_test", into(p3);
|
|
CHECK(p3.id == 1);
|
|
CHECK(p3.firstName == "Patricia");
|
|
CHECK(p3.lastName == "Smith");
|
|
CHECK(p3.gender == "whoknows");
|
|
|
|
sql << "update soci_test set gender = 'F' where id = 1";
|
|
|
|
// additional test for stream-like conversion
|
|
person3 p4;
|
|
sql << "select id, first_name, last_name, gender from soci_test", into(p4);
|
|
CHECK(p4.id == 1);
|
|
CHECK(p4.firstName == "Patricia");
|
|
CHECK(p4.lastName == "Smith");
|
|
CHECK(p4.gender == "F");
|
|
}
|
|
|
|
//
|
|
// Backwards compatibility - support use of large strings with
|
|
// columns of type LONG
|
|
///
|
|
struct long_table_creator : public table_creator_base
|
|
{
|
|
long_table_creator(soci::session & sql)
|
|
: table_creator_base(sql)
|
|
{
|
|
sql << "create table soci_test(l long)";
|
|
}
|
|
};
|
|
|
|
TEST_CASE("Oracle large strings as long", "[oracle][compatibility]")
|
|
{
|
|
soci::session sql(backEnd, connectString);
|
|
long_table_creator creator(sql);
|
|
|
|
const std::string::size_type max = 32768;
|
|
std::string in(max, 'X');
|
|
|
|
sql << "insert into soci_test values(:l)", use(in);
|
|
|
|
std::string out;
|
|
sql << "select l from soci_test", into(out);
|
|
|
|
CHECK(out.size() == max);
|
|
CHECK(in == out);
|
|
}
|
|
|
|
// test for modifiable and const use elements
|
|
TEST_CASE("Oracle const and modifiable parameters", "[oracle][use]")
|
|
{
|
|
soci::session sql(backEnd, connectString);
|
|
|
|
int i = 7;
|
|
sql << "begin "
|
|
"select 2 * :i into :i from dual; "
|
|
"end;", use(i);
|
|
CHECK(i == 14);
|
|
|
|
const int j = 7;
|
|
try
|
|
{
|
|
sql << "begin "
|
|
"select 2 * :i into :i from dual;"
|
|
" end;", use(j);
|
|
|
|
FAIL("expected exception not thrown");
|
|
}
|
|
catch (soci_error const & e)
|
|
{
|
|
CHECK(e.get_error_message() ==
|
|
"Attempted modification of const use element");
|
|
}
|
|
}
|
|
|
|
struct longlong_table_creator : table_creator_base
|
|
{
|
|
longlong_table_creator(soci::session & sql)
|
|
: table_creator_base(sql)
|
|
{
|
|
sql << "create table soci_test(val number(20))";
|
|
}
|
|
};
|
|
|
|
// long long test
|
|
TEST_CASE("Oracle long long", "[oracle][longlong]")
|
|
{
|
|
{
|
|
soci::session sql(backEnd, connectString);
|
|
|
|
longlong_table_creator tableCreator(sql);
|
|
|
|
long long v1 = 1000000000000LL;
|
|
sql << "insert into soci_test(val) values(:val)", use(v1);
|
|
|
|
long long v2 = 0LL;
|
|
sql << "select val from soci_test", into(v2);
|
|
|
|
CHECK(v2 == v1);
|
|
}
|
|
|
|
// vector<long long>
|
|
{
|
|
soci::session sql(backEnd, connectString);
|
|
|
|
longlong_table_creator tableCreator(sql);
|
|
|
|
std::vector<long long> v1;
|
|
v1.push_back(1000000000000LL);
|
|
v1.push_back(1000000000001LL);
|
|
v1.push_back(1000000000002LL);
|
|
v1.push_back(1000000000003LL);
|
|
v1.push_back(1000000000004LL);
|
|
|
|
sql << "insert into soci_test(val) values(:val)", use(v1);
|
|
|
|
std::vector<long long> v2(10);
|
|
sql << "select val from soci_test order by val desc", into(v2);
|
|
|
|
REQUIRE(v2.size() == 5);
|
|
CHECK(v2[0] == 1000000000004LL);
|
|
CHECK(v2[1] == 1000000000003LL);
|
|
CHECK(v2[2] == 1000000000002LL);
|
|
CHECK(v2[3] == 1000000000001LL);
|
|
CHECK(v2[4] == 1000000000000LL);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Support for soci Common Tests
|
|
//
|
|
|
|
struct table_creator_one : public table_creator_base
|
|
{
|
|
table_creator_one(soci::session & sql)
|
|
: table_creator_base(sql)
|
|
{
|
|
sql << "create table soci_test(id number(10,0), val number(4,0), c char, "
|
|
"str varchar2(20), sh number, ul number, d number, "
|
|
"num76 numeric(7,6), "
|
|
"tm date, i1 number, i2 number, i3 number, name varchar2(20))";
|
|
}
|
|
};
|
|
|
|
struct table_creator_two : public table_creator_base
|
|
{
|
|
table_creator_two(soci::session & sql)
|
|
: table_creator_base(sql)
|
|
{
|
|
sql << "create table soci_test(num_float number, num_int numeric(4,0),"
|
|
" name varchar2(20), sometime date, chr char)";
|
|
}
|
|
};
|
|
|
|
struct table_creator_three : public table_creator_base
|
|
{
|
|
table_creator_three(soci::session & sql)
|
|
: table_creator_base(sql)
|
|
{
|
|
sql << "create table soci_test(name varchar2(100) not null, "
|
|
"phone varchar2(15))";
|
|
}
|
|
};
|
|
|
|
struct table_creator_four : public table_creator_base
|
|
{
|
|
table_creator_four(soci::session & sql)
|
|
: table_creator_base(sql)
|
|
{
|
|
sql << "create table soci_test(val number)";
|
|
}
|
|
};
|
|
|
|
class test_context :public test_context_base
|
|
{
|
|
public:
|
|
test_context(backend_factory const &backEnd,
|
|
std::string const &connectString)
|
|
: test_context_base(backEnd, connectString) {}
|
|
|
|
table_creator_base* table_creator_1(soci::session& s) const
|
|
{
|
|
return new table_creator_one(s);
|
|
}
|
|
|
|
table_creator_base* table_creator_2(soci::session& s) const
|
|
{
|
|
return new table_creator_two(s);
|
|
}
|
|
|
|
table_creator_base* table_creator_3(soci::session& s) const
|
|
{
|
|
return new table_creator_three(s);
|
|
}
|
|
|
|
table_creator_base* table_creator_4(soci::session& s) const
|
|
{
|
|
return new table_creator_four(s);
|
|
}
|
|
|
|
std::string to_date_time(std::string const &datdt_string) const
|
|
{
|
|
return "to_date('" + datdt_string + "', 'YYYY-MM-DD HH24:MI:SS')";
|
|
}
|
|
};
|
|
|
|
int main(int argc, char** argv)
|
|
{
|
|
#ifdef _MSC_VER
|
|
// Redirect errors, unrecoverable problems, and assert() failures to STDERR,
|
|
// instead of debug message window.
|
|
// This hack is required to run assert()-driven tests by Buildbot.
|
|
// NOTE: Comment this 2 lines for debugging with Visual C++ debugger to catch assertions inside.
|
|
_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
|
|
_CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
|
|
#endif //_MSC_VER
|
|
|
|
if (argc >= 2)
|
|
{
|
|
connectString = argv[1];
|
|
|
|
// Replace the connect string with the process name to ensure that
|
|
// CATCH uses the correct name in its messages.
|
|
argv[1] = argv[0];
|
|
|
|
argc--;
|
|
argv++;
|
|
}
|
|
else
|
|
{
|
|
std::cout << "usage: " << argv[0]
|
|
<< " connectstring [test-arguments...]\n"
|
|
<< "example: " << argv[0]
|
|
<< " \'service=orcl user=scott password=tiger\'\n";
|
|
std::exit(1);
|
|
}
|
|
|
|
test_context tc(backEnd, connectString);
|
|
|
|
return Catch::Session().run(argc, argv);
|
|
}
|