mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Squashed 'src/soci/' changes from 6e9312c..b2855dc
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
This commit is contained in:
73
src/AUTHORS
73
src/AUTHORS
@@ -1,73 +0,0 @@
|
||||
=== SOCI Team ===
|
||||
|
||||
Alex Ott
|
||||
David Courtney
|
||||
Denis Arnaud
|
||||
Denis Chapligin
|
||||
Julian Taylor
|
||||
Maciej Sobczak
|
||||
Mateusz Łoskot
|
||||
Paweł Aleksander Fedoryński
|
||||
Rafał Bobrowski
|
||||
Sergei Nikulov
|
||||
Steve Hutton
|
||||
Vadim Zeitlin
|
||||
Viacheslav Naydenov
|
||||
|
||||
=== SOCI Contributors ===
|
||||
|
||||
We would like to thank you for your contributions
|
||||
- they allowed us to improve the quality of the SOCI library:
|
||||
|
||||
Andrey Belobrov
|
||||
Andrey Utkin
|
||||
Andriy Gapon
|
||||
Artyom Beilis
|
||||
Artyom Tonkikh
|
||||
avg-I
|
||||
b-s-a
|
||||
Brian R. Toonen
|
||||
Cengizhan Paşaoğlu
|
||||
Chris Weed
|
||||
Cory Bennett
|
||||
creste
|
||||
Daniel Lidström
|
||||
Eli Green
|
||||
Faik Uygur
|
||||
Fedor Trushkin
|
||||
Frank Bielig
|
||||
Frederic Chateau
|
||||
Gevorg Voskanyan
|
||||
Henning Basold
|
||||
Howard Butler
|
||||
Ilia Barahovski
|
||||
Jakub Stachowski
|
||||
jamercee
|
||||
Joerg Sonnenberger
|
||||
Krzysztof Bieleń
|
||||
Mario Valesco
|
||||
Martin Muenstermann
|
||||
Mathias Hasselmann
|
||||
Matt Arsenault
|
||||
Matthieu Kermagoret
|
||||
Michael Davidsaver
|
||||
Mika Fischer
|
||||
Paul Bondo
|
||||
Petr Vanek
|
||||
Philip Pemberton
|
||||
Rainer Bauer
|
||||
Ricardo Andrade
|
||||
ryandesign
|
||||
Robert Massaioli
|
||||
Roger Orr
|
||||
Sergey Belyashov
|
||||
Shridhar Daithankar
|
||||
Sören Meyer-Eppler
|
||||
soyersoyer
|
||||
Stefan Chrobot
|
||||
Tomasz Olszewski
|
||||
Vaclav Slavik
|
||||
xol
|
||||
|
||||
There are a lot of people that help to drive SOCI project forward,
|
||||
if we have forgot to mention someone in here, send us an email!
|
||||
338
src/CHANGES
338
src/CHANGES
@@ -1,338 +0,0 @@
|
||||
This file contains the history of changes in the SOCI library.
|
||||
|
||||
---
|
||||
Version 3.2.2 differs from 3.2.1 in the following ways:
|
||||
|
||||
- Fixed once_temp_type destructor with noexcept(false) specifier for C++11
|
||||
- Fix uninitialized indicators in conversion_into_type and conversion_use_type specialisations
|
||||
- Fixed placeholder matching for PostgreSQL-style casts with ORM
|
||||
- Fixed memory leaking in use binding in case of bind/unbind sequence
|
||||
- Fixed sscanf formatter for MinGW/MSVC in backends
|
||||
- Fixed partial placeholder name matching for ORM cases
|
||||
- Added test for use of indicators with rowset<row>
|
||||
- Added test for get_affected_rows after bulk operations
|
||||
|
||||
- DB2
|
||||
-- Enable build and testing on Travis CI
|
||||
-- Fixed use type size calculation during bind/pre_use
|
||||
|
||||
- Firebird
|
||||
-- Enable memory cleanup to avoid leaks after binding
|
||||
-- Added missing C++ library headers
|
||||
-- Added get_affected_rows() support for bulk operations
|
||||
-- Fixed compilation with VS2008
|
||||
-- Fixed building tests with the backend built as DLL.
|
||||
|
||||
- MySQL
|
||||
-- Added get_affected_rows() support for bulk operations
|
||||
|
||||
- ODBC
|
||||
-- Always call ASCII version of ODBC function SQLGetDiagRec
|
||||
-- Fixed invalid condition test in assertions
|
||||
-- Added get_affected_rows() support for bulk operations
|
||||
-- Added support for (unsigned) long long vectors
|
||||
-- Changed mapping of SQL_BIGINT to dt_long_long in ODBC backend
|
||||
-- Added some trivial optimizations in statement preparation code
|
||||
|
||||
- Oracle
|
||||
-- Fixed missing noData_ reported in particular case when OCIStmtExecute returns success
|
||||
-- Improved Oracle testing setup on Travis CI
|
||||
|
||||
- PostgreSQL
|
||||
-- Added session::get_next_sequence_value() for PostgreSQL backend
|
||||
-- Added get_affected_rows() support for bulk operations
|
||||
-- Applied RAII and simplified error handling logic
|
||||
-- Fixed issue with exceptions escaping postgresql_statement_backend destructor
|
||||
|
||||
- SQLite3
|
||||
-- Replaced sqlite3_prepare with sqlite3_prepare_v2
|
||||
-- Added missing <cstdarg> header
|
||||
-- Fixed wrong size used in memcpy() during bulk processing
|
||||
-- Added get_affected_rows() support for bulk operations
|
||||
-- Added shared_cache=true propery to control SQLITE_OPEN_SHAREDCACHE flag
|
||||
|
||||
- Documentation
|
||||
-- Corrected usage examples
|
||||
|
||||
- Building
|
||||
-- Updated CMake for Oracle 12g
|
||||
-- Restructured and improved Travis CI setup to do single build per backend
|
||||
-- Fixed wrong GCC_VERSION used in CMake config for commandline-overriden GCC
|
||||
-- Allows CMake to find 32-bit DB2 on Windows x64
|
||||
-- Removed redundant Oracle libclntsh library lookup
|
||||
-- Fixed SQLITE3_LIBRARIES handling by find_package_handle_standard_args
|
||||
|
||||
---
|
||||
Version 3.2.1 differs from 3.2.0 in the following ways:
|
||||
|
||||
- Fixed binding of Oracle type NUMBER(9,0) to C++ int, by Tomasz Olszewski
|
||||
- Fixed Oracle client library detection on Windows, by Tomasz Olszewski
|
||||
- Fixed PostgreSQL issue with deallocate_prepared_statement called for non-existing statement
|
||||
- Fixed prepared insert statements with custom data types support, by Tomasz Olszewski
|
||||
- Fixed recent improvements in x:=y name binding, by Poul Bondo
|
||||
- Fixed query transformation assignment in pooled sessions, by Stefan Chrobot
|
||||
- Cleaned up SOCI_POSTGRESQL_NOPARAMS and related options in code and documentation
|
||||
- Dropped patch (micro) version number from documentation URLs on the website
|
||||
|
||||
---
|
||||
Version 3.2.0 differs from 3.1.0 in the following ways:
|
||||
|
||||
- SOCI is now organization at GitHub
|
||||
-- Git repository moved to https://github.com/SOCI/soci
|
||||
-- Opened new bug tracker (SF.net tracker is read-only)
|
||||
-- Opened Wiki for FAQ and development articles
|
||||
-- Website, mailing lists and downloads remain on SourceForge.net
|
||||
-- Applied GitFlow branching model
|
||||
-- Added package maintenance repository https://github.com/SOCI/soci-pkg
|
||||
|
||||
- Core
|
||||
-- Added connection_parameters to enable support for session options used by core, backends or low-level API.
|
||||
-- Added user-defined query transformation support based on function, functor and lambda
|
||||
-- Fixed missing connection check and backend setup ensured for session
|
||||
-- Fixed backend initialization when used with connection pool (Core)
|
||||
-- Fixed memory leaks on exception thrown during statement preparation stage
|
||||
|
||||
- DB2
|
||||
-- Added new backend for IBM DB2
|
||||
|
||||
- Firebird
|
||||
-- Fixed bug in repeated statement execution
|
||||
-- Fixed issues with input parameter binding
|
||||
-- Fixed connection string parsing to handle possible white-spaces
|
||||
-- Fixed issues with C++ type unsigned long
|
||||
-- Fixed reading negative values into C++ type double
|
||||
-- Added option to fetch numeric/decimal data into string of characters
|
||||
-- Added CMake configuration
|
||||
-- Updated tests
|
||||
-- Continued regular testing on Windows and Unix platforms
|
||||
|
||||
- MySQL
|
||||
-- Replaced use of type=InnoDB with engine=InnoDB
|
||||
-- Improved CMake configuration
|
||||
|
||||
- ODBC
|
||||
-- Added connection_parameters option ODBC_OPTION_DRIVER_COMPLETE
|
||||
-- Fixed issues in handling C++ types int and long on 64-bit architectures
|
||||
-- Added missing CMake configuration for tests
|
||||
-- Continued regular testing on Windows and Unix platforms
|
||||
|
||||
- Oracle
|
||||
-- Implemented statement::get_affected_rows() operation
|
||||
-- Use OCI_THREADED and OCI_ENV_NO_MUTEX with OCIEnvCreate
|
||||
-- Added numerous fixes and improvements in tests
|
||||
-- Added option to fetch numeric/decimal data into string of characters
|
||||
-- Fixed issues in binding procedure IN/OUT parameters
|
||||
|
||||
- PostgreSQL
|
||||
-- Add reading of BYTEA data into std::string (not fully-featured binary data support yet)
|
||||
-- Add JSON data type support available in PostgreSQL 9.2+
|
||||
-- Fixed incorrect assertion in postgresql::get_error_details
|
||||
-- Fixed premature deallocation of prepared statements
|
||||
-- Fixed servers-side memory leak in prepared statements
|
||||
-- Fixed memory leak of PGresult on exception thrown
|
||||
-- Fixed isues in parsing complex PL/PSQL functions
|
||||
|
||||
- SQLite3
|
||||
-- Implemented statement::get_affected_rows() operation
|
||||
-- Fixed handling of database file path with spaces
|
||||
|
||||
- Building, testing and installation
|
||||
-- Marked Makefile.basic as deprecated (maintainer wanted)
|
||||
-- Cleaned numerous compilation warnings reported by various compilers
|
||||
-- Improved compilation using latest version of clang
|
||||
-- Added numerous improvements in CMake configuration
|
||||
-- Added SOCI_STATIC option to enable/disable static libraries build
|
||||
-- Fixed issues with ignored -DWITH_<dependency> options
|
||||
-- Fixed FindMySQL.cmake to allow use of mysqlclient from custom location
|
||||
-- Added support of SQLITE_ROOT_DIR variable to FindSQLite3.cmake module
|
||||
-- Fixed and tested CMake configuration on OSX
|
||||
-- Fixed and tested CMake configuration on FreeBSD
|
||||
-- Fixed and tested CMake configuration to use with Ninja
|
||||
-- Fixed building using Visual Studio 2010
|
||||
-- Added support for building using Visual Studio 2012
|
||||
-- Set up SOCI continuous integration at travis-ci.org
|
||||
-- Added Debian packaging support to soci-pkg repository
|
||||
-- Added Fedora/CentOS/RedHat packaging support to soci-pkg repository
|
||||
|
||||
- Documentation
|
||||
-- Review and update to catch up with current status quo
|
||||
-- Updated code examples
|
||||
-- Start maintenance and hosting of SOCI documentation per released version
|
||||
|
||||
---
|
||||
Version 3.1.0 differs from 3.0.0 in the following ways:
|
||||
|
||||
- Added Ada language binding
|
||||
|
||||
- Migraded build system from GNU Autotools and Visual Studio projects to CMake
|
||||
|
||||
- CMake build tested with Visual Studio, GCC and clang
|
||||
|
||||
- Incorporated a compromise for naming versioned shared libraries
|
||||
|
||||
- Enhanced and improved integration with Boost libraries:
|
||||
-- Boost.DateTime
|
||||
-- Boost.Fusion
|
||||
-- Boost.Optional
|
||||
-- Boost.Tuple
|
||||
|
||||
- Bug fixes and improvements in core and backends:
|
||||
-- Added soci::values::get_properties accessor useful for composing soci::type_conversion
|
||||
-- Export advanced API of backend loader from DLL.
|
||||
-- Added static factory registration functions for backends
|
||||
-- Added get_affected_rows operation
|
||||
-- Fixed thread-safety of connection pool under Windows
|
||||
-- Fixed bug with droping const qualifiers when binding to std::vector<soci::indicator>
|
||||
-- Fixed bug in default initialization of an object of const backend_factory wihch requires user-provided default constructor (see C++03/C++0x)
|
||||
-- Fixes for 64-bit builds
|
||||
-- Removed redundant exchange_traits breaking ODR on LP64
|
||||
-- Better ODBC support
|
||||
-- Type conversion support for unsigned integer types
|
||||
-- Bug ID:1971436 - incorrect rowset copy operations
|
||||
-- Bug ID:2010367 - memory leak (ODBC)
|
||||
-- Bug ID:2010409 - invalid memory allocaton in define by position (ODBC)
|
||||
-- Bug ID:2021243 - long long type support in Visual C++
|
||||
-- Patch ID:2483066 - 64bit Linux and 64bit integer submitted
|
||||
-- Patch ID:2809809 - Fix build with GCC 4.4
|
||||
-- Patch ID:2809810 - Fix SQLite3 build with GCC 4.3
|
||||
-- Patch ID:2581206 - Windows unicode application
|
||||
-- Patch ID:3058275 - install target for cmake build submitted
|
||||
-- Patch ID:3069375 - use $(prefix)/lib64 on AMD64 platforms.
|
||||
-- Improved performance while accessing query results (MySQL)
|
||||
-- Bug fixes for PROCEDURE support (MySQL)
|
||||
-- Removed throw statements from mysql_rowid_backend and mysql_blob_backend destructors (MySQL)
|
||||
-- Verify that prepared statements survive session::reconnect() operatoin (MySQL)
|
||||
-- Improved support for time and date (MySQL, PostgreSQL)
|
||||
-- Fixed bug with strings of length exceeding 255 characters (ODBC)
|
||||
-- Improved interpretation of the connect string (Oracle)
|
||||
-- Added handling of unsigned long long (Oracle, SQLite3, PostgreSQL)
|
||||
-- Fixes in integral types support (PostgreSQL)
|
||||
-- Support for colon-casts (PostgreSQL)
|
||||
-- Added possibility for use BLOB (PostgreSQL)
|
||||
-- Added support for connection property "synchronous=on|off" (SQLite3)
|
||||
-- Improved BLOB data handling (SQLite3)
|
||||
-- Improved boolean type suppport (SQLite3)
|
||||
-- Session timeout support (SQLite3)
|
||||
-- Improved tests clean-up (SQLite3)
|
||||
-- Added missing typedef of sqlite3_destructor_type which has been defined in sqlite3.h but since 3.3.10 (see comment for reference to SQLite ticket)
|
||||
|
||||
- Updated tests for various backends and SQL data types
|
||||
|
||||
- Migrated from CVS to Git repository
|
||||
|
||||
- Changed naming convensions and style across all the source code
|
||||
|
||||
- Firebird backend removed from official release as not actively maintained. Available in the Git repository.
|
||||
|
||||
---
|
||||
Version 3.0.0 differs from 2.2.0 in the following ways:
|
||||
|
||||
- Exposed the session's locale object.
|
||||
|
||||
- Moved the "no data" flag from indicators to statement.
|
||||
|
||||
- Allowed const objects as "use" elements.
|
||||
|
||||
- Added connection mode for Oracle.
|
||||
|
||||
- Added RAII support for transactions.
|
||||
|
||||
- Added the open/close/reconnect functionality.
|
||||
|
||||
- Added support for long long as a fundamental data type.
|
||||
|
||||
- Unified column names for dynamic rowset description, to overcome
|
||||
differences between database servers.
|
||||
|
||||
- Added the "simple" interface for interfacing from other languages.
|
||||
|
||||
- Added thread-safe connection pool.
|
||||
|
||||
- Added integrated support for Boost data types: gregorian_date,
|
||||
fusion and tuple.
|
||||
|
||||
- Added dynamic backend loading.
|
||||
|
||||
- Changed the naming convention to comply with Boost recommendations.
|
||||
|
||||
---
|
||||
Version 2.2.0 differs from 2.1.0 in the following ways:
|
||||
|
||||
- Added true support for statement preparation with PostgreSQL.
|
||||
|
||||
- Added support for the stream-like extraction from Row.
|
||||
|
||||
- Added STL-compatible iterator interface for select statements.
|
||||
|
||||
- Refactored the set of common tests to validate core library functionality
|
||||
independently on the target database server.
|
||||
|
||||
- Introduced new backends for MS SQL Server (via ODBC) and Firebird.
|
||||
|
||||
- Provided complete build system for both Unix (autotools) and
|
||||
Windows (solution and project files for MSVC++).
|
||||
|
||||
---
|
||||
Version 2.1.0 differs from 2.0.1 in the following ways:
|
||||
|
||||
- Added two additional backends: MySQL and SQLite3
|
||||
|
||||
- Restructured the source code layout so that the whole library was broken
|
||||
into the "core" part and independent "backends", each in its own
|
||||
directory together with appropriate tests.
|
||||
|
||||
- Provided basic Makefiles for static and shared libraries on
|
||||
Linux-compatible systems.
|
||||
|
||||
- Added the general class and function reference to the documentation.
|
||||
|
||||
---
|
||||
Version 2.0.1 differs from 2.0.0 in the following ways:
|
||||
|
||||
- Corrected some typos in documentation.
|
||||
|
||||
- Corrected handling of dynamic rowset description for those backends
|
||||
which do not have dedicated description functionality.
|
||||
|
||||
- A bug fix to correctly handle std::tm in the Oracle backend.
|
||||
|
||||
- A bug fix to correctly handle object relational mapping when
|
||||
Values::set<T>() and Values::get<T>() are called where T is a
|
||||
TypeConversion-based type.
|
||||
|
||||
---
|
||||
Version 2.0.0 differs from 1.2.1 in the following ways:
|
||||
|
||||
- The whole library was internally re-architectured to allow operation
|
||||
with many different backends. The top-level part of the library
|
||||
(the syntax layer) provides essentially the same interface as in previous
|
||||
versions of the library, but it can work with independent (and dynamically
|
||||
selected) backends, possibly targeting different database engines.
|
||||
As a prove of concept (and to encourage developments of new backends),
|
||||
the PostgreSQL backend was provided in addition to the Oracle one.
|
||||
During this re-architecturing, some minor bugs were fixed as well.
|
||||
|
||||
- The old Boost-style license was changed to the new (v. 1.0) Boost license.
|
||||
|
||||
---
|
||||
The version 1.2.1 differs from 1.2.0 in the following ways:
|
||||
|
||||
- A bug was fixed that caused compile errors on MS VC++ compiler.
|
||||
|
||||
---
|
||||
The version 1.2.0 differs from 1.1.0 in the following ways:
|
||||
|
||||
- A memory leak when reading into Row objects was fixed.
|
||||
|
||||
- Bulk (array) operations were introduced for high-performance
|
||||
applications, where the number of network round-trips can be
|
||||
significantly reduced by operating on whole arrays (vectors).
|
||||
|
||||
---
|
||||
The version 1.1.0 differs from 1.0.1 in the following ways:
|
||||
|
||||
- Explicit support for calling stored procedures was added.
|
||||
|
||||
- Dynamic row recognition (type discovery) was added.
|
||||
|
||||
- Support for user-defined data types was added.
|
||||
@@ -2,104 +2,13 @@
|
||||
#
|
||||
# This file is part of CMake configuration for SOCI library
|
||||
#
|
||||
# Copyright (C) 2009-2013 Mateusz Loskot <mateusz@loskot.net>
|
||||
# Copyright (C) 2013 Mateusz Loskot <mateusz@loskot.net>
|
||||
# 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)
|
||||
#
|
||||
###############################################################################
|
||||
# General settings
|
||||
###############################################################################
|
||||
cmake_minimum_required(VERSION 2.8.0 FATAL_ERROR)
|
||||
|
||||
project(SOCI)
|
||||
|
||||
###############################################################################
|
||||
# SOCI CMake modules
|
||||
###############################################################################
|
||||
|
||||
# Path to additional CMake modules
|
||||
set(CMAKE_MODULE_PATH ${SOCI_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH})
|
||||
set(CMAKE_MODULE_PATH ${SOCI_SOURCE_DIR}/cmake/modules ${CMAKE_MODULE_PATH})
|
||||
|
||||
include(SociUtilities)
|
||||
|
||||
colormsg(_HIBLUE_ "Configuring SOCI:")
|
||||
|
||||
###############################################################################
|
||||
# SOCI version information
|
||||
###############################################################################
|
||||
include(SociVersion)
|
||||
|
||||
soci_version(MAJOR 3 MINOR 2 PATCH 2)
|
||||
|
||||
###############################################################################
|
||||
# Build features and variants
|
||||
###############################################################################
|
||||
include(SociSystemInfo)
|
||||
include(SociConfig)
|
||||
|
||||
boost_report_value(SOCI_PLATFORM_NAME)
|
||||
boost_report_value(SOCI_COMPILER_NAME)
|
||||
|
||||
option(SOCI_SHARED "Enable build of shared libraries" ON)
|
||||
boost_report_value(SOCI_SHARED)
|
||||
|
||||
option(SOCI_STATIC "Enable build of static libraries" ON)
|
||||
boost_report_value(SOCI_STATIC)
|
||||
|
||||
option(SOCI_TESTS "Enable build of collection of SOCI tests" ON)
|
||||
boost_report_value(SOCI_TESTS)
|
||||
|
||||
# Put the libaries and binaries that get built into directories at the
|
||||
# top of the build tree rather than in hard-to-find leaf
|
||||
# directories. This simplifies manual testing and the use of the build
|
||||
# tree rather than installed Boost libraries.
|
||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
|
||||
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
|
||||
|
||||
###############################################################################
|
||||
# Find SOCI dependencies
|
||||
###############################################################################
|
||||
|
||||
set(SOCI_CORE_DEPENDENCIES)
|
||||
|
||||
include(SociDependencies)
|
||||
|
||||
#message("${SOCI_CORE_DEPENDENCIES}")
|
||||
|
||||
###############################################################################
|
||||
# Installation
|
||||
###############################################################################
|
||||
|
||||
if(APPLE OR CMAKE_SIZEOF_VOID_P EQUAL 4)
|
||||
set(SOCI_LIBDIR "lib")
|
||||
else()
|
||||
set(SOCI_LIBDIR "lib64")
|
||||
endif()
|
||||
|
||||
set(BINDIR "bin" CACHE PATH "The directory to install binaries into.")
|
||||
set(LIBDIR ${SOCI_LIBDIR} CACHE PATH "The directory to install libraries into.")
|
||||
set(DATADIR "share" CACHE PATH "The directory to install data files into.")
|
||||
set(INCLUDEDIR "include" CACHE PATH "The directory to install includes into.")
|
||||
|
||||
###############################################################################
|
||||
# Enable tests
|
||||
###############################################################################
|
||||
enable_testing()
|
||||
# Configure for testing with dashboard submissions to CDash
|
||||
#include(CTest) # disabled as unused
|
||||
|
||||
# Define "make check" as alias for "make test"
|
||||
add_custom_target(check COMMAND ctest)
|
||||
|
||||
###############################################################################
|
||||
# Build configured components
|
||||
###############################################################################
|
||||
include(SociBackend)
|
||||
|
||||
include_directories(${SOCI_SOURCE_DIR}/core)
|
||||
include_directories(${SOCI_SOURCE_DIR}/include/private)
|
||||
|
||||
add_subdirectory(core)
|
||||
add_subdirectory(backends)
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
## This file should be placed in the root directory of your project.
|
||||
## Then modify the CMakeLists.txt file in the root directory of your
|
||||
## project to incorporate the testing dashboard.
|
||||
## # The following are required to uses Dart and the Cdash dashboard
|
||||
## ENABLE_TESTING()
|
||||
## INCLUDE(CTest)
|
||||
set(CTEST_PROJECT_NAME "SOCI")
|
||||
set(CTEST_NIGHTLY_START_TIME "00:00:00 EST")
|
||||
|
||||
set(CTEST_DROP_METHOD "http")
|
||||
set(CTEST_DROP_SITE "my.cdash.org")
|
||||
set(CTEST_DROP_LOCATION "/submit.php?project=SOCI")
|
||||
set(CTEST_DROP_SITE_CDASH TRUE)
|
||||
@@ -1,23 +0,0 @@
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
35
src/README
35
src/README
@@ -1,35 +0,0 @@
|
||||
SOCI - The C++ Database Access Library.
|
||||
|
||||
Copyright (C) 2004-2008 Maciej Sobczak, Stephen Hutton,
|
||||
David Courtney, Pawel Aleksander Fedorynski,
|
||||
Rafal Bobrowski, Mateusz Loskot
|
||||
|
||||
The homepage of the SOCI library is:
|
||||
http://soci.sourceforge.net/
|
||||
|
||||
---
|
||||
|
||||
You should see the following files and directories here:
|
||||
|
||||
- README - This file.
|
||||
- LICENSE_1_0.txt - Full text of the Boost license.
|
||||
- CHANGES - The description of changes.
|
||||
|
||||
- contrib - Acknowledgements for contributions.
|
||||
|
||||
- doc/ - Documentation.
|
||||
|
||||
- build/ - Additional build scripts and configuration files
|
||||
for various compilation systems.
|
||||
|
||||
- src/ - The source code of the library.
|
||||
|
||||
- src/core/ - The main part of the SOCI library.
|
||||
|
||||
- src/backends/ - Directory containing implementations and tests for
|
||||
all available backends.
|
||||
|
||||
|
||||
Please see the doc/structure.html file for compilation instructions.
|
||||
|
||||
---
|
||||
@@ -8,7 +8,7 @@
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
#
|
||||
###############################################################################
|
||||
colormsg(_HIBLUE_ "Configuring SOCI database backends:")
|
||||
colormsg(_HIBLUE_ "Configuring SOCI backend libraries:")
|
||||
|
||||
# First, we'll investigate what can be found from database engines
|
||||
foreach(dep ${SOCI_BACKENDS_DB_DEPENDENCIES})
|
||||
|
||||
@@ -10,9 +10,5 @@
|
||||
###############################################################################
|
||||
soci_backend(DB2
|
||||
DEPENDS DB2
|
||||
HEADERS soci-db2.h
|
||||
DESCRIPTION "SOCI backend for DB2 Universal Database"
|
||||
AUTHORS "Denis Chapligin"
|
||||
DESCRIPTION "SOCI backend for DB2" AUTHORS "Denis Chapligin"
|
||||
MAINTAINERS "Denis Chapligin")
|
||||
|
||||
add_subdirectory(test)
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
//
|
||||
|
||||
#define SOCI_DB2_SOURCE
|
||||
#include "soci-db2.h"
|
||||
#include "soci/db2/soci-db2.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4355)
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
//
|
||||
|
||||
#define SOCI_DB2_SOURCE
|
||||
#include "soci-db2.h"
|
||||
#include <backend-loader.h>
|
||||
#include "soci/db2/soci-db2.h"
|
||||
#include "soci/backend-loader.h"
|
||||
|
||||
using namespace soci;
|
||||
using namespace soci::details;
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
//
|
||||
|
||||
#define SOCI_DB2_SOURCE
|
||||
#include "soci-db2.h"
|
||||
#include "soci/db2/soci-db2.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4355)
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
//
|
||||
|
||||
#define SOCI_DB2_SOURCE
|
||||
#include "soci-db2.h"
|
||||
#include <connection-parameters.h>
|
||||
#include "soci/db2/soci-db2.h"
|
||||
#include "soci/connection-parameters.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4355)
|
||||
@@ -74,7 +74,7 @@ void db2_session_backend::parseConnectString(std::string const & connectString)
|
||||
}
|
||||
if (!processingString.empty()) {
|
||||
parseKeyVal(processingString);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
db2_session_backend::db2_session_backend(
|
||||
@@ -89,7 +89,7 @@ db2_session_backend::db2_session_backend(
|
||||
if (cliRC != SQL_SUCCESS) {
|
||||
throw db2_soci_error("Error while allocating the enironment handle",cliRC);
|
||||
}
|
||||
|
||||
|
||||
cliRC = SQLAllocHandle(SQL_HANDLE_DBC, hEnv, &hDbc);
|
||||
if (cliRC != SQL_SUCCESS) {
|
||||
std::string msg=db2_soci_error::sqlState("Error while allocating the connection handle",SQL_HANDLE_ENV,hEnv);
|
||||
|
||||
@@ -1,282 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2011-2013 Denis Chapligin
|
||||
// Copyright (C) 2004-2006 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)
|
||||
//
|
||||
|
||||
#ifndef SOCI_DB2_H_INCLUDED
|
||||
#define SOCI_DB2_H_INCLUDED
|
||||
|
||||
#ifdef _WIN32
|
||||
# ifdef SOCI_DLL
|
||||
# ifdef SOCI_DB2_SOURCE
|
||||
# define SOCI_DB2_DECL __declspec(dllexport)
|
||||
# else
|
||||
# define SOCI_DB2_DECL __declspec(dllimport)
|
||||
# endif // SOCI_DB2_SOURCE
|
||||
# endif // SOCI_DLL
|
||||
#endif // _WIN32
|
||||
//
|
||||
// If SOCI_DB2_DECL isn't defined yet define it now
|
||||
#ifndef SOCI_DB2_DECL
|
||||
# define SOCI_DB2_DECL
|
||||
#endif
|
||||
|
||||
#include "soci-backend.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
|
||||
#include <sqlcli1.h>
|
||||
|
||||
namespace soci
|
||||
{
|
||||
namespace details { namespace db2
|
||||
{
|
||||
enum binding_method
|
||||
{
|
||||
BOUND_BY_NONE,
|
||||
BOUND_BY_NAME,
|
||||
BOUND_BY_POSITION
|
||||
};
|
||||
}}
|
||||
|
||||
static const std::size_t maxBuffer = 1024 * 1024 * 1024; //CLI limit is about 3 GB, but 1GB should be enough
|
||||
|
||||
class db2_soci_error : public soci_error {
|
||||
public:
|
||||
db2_soci_error(std::string const & msg, SQLRETURN rc) : soci_error(msg),errorCode(rc) {};
|
||||
~db2_soci_error() throw() { };
|
||||
|
||||
//We have to extract error information before exception throwing, cause CLI handles could be broken at the construction time
|
||||
static const std::string sqlState(std::string const & msg,const SQLSMALLINT htype,const SQLHANDLE hndl);
|
||||
|
||||
SQLRETURN errorCode;
|
||||
};
|
||||
|
||||
struct db2_statement_backend;
|
||||
|
||||
struct SOCI_DB2_DECL db2_standard_into_type_backend : details::standard_into_type_backend
|
||||
{
|
||||
db2_standard_into_type_backend(db2_statement_backend &st)
|
||||
: statement_(st),buf(NULL)
|
||||
{}
|
||||
|
||||
void define_by_pos(int& position, void* data, details::exchange_type type);
|
||||
|
||||
void pre_fetch();
|
||||
void post_fetch(bool gotData, bool calledFromFetch, indicator* ind);
|
||||
|
||||
void clean_up();
|
||||
|
||||
db2_statement_backend& statement_;
|
||||
|
||||
char* buf;
|
||||
void *data;
|
||||
details::exchange_type type;
|
||||
int position;
|
||||
SQLSMALLINT cType;
|
||||
SQLLEN valueLen;
|
||||
};
|
||||
|
||||
struct SOCI_DB2_DECL db2_vector_into_type_backend : details::vector_into_type_backend
|
||||
{
|
||||
db2_vector_into_type_backend(db2_statement_backend &st)
|
||||
: statement_(st),buf(NULL)
|
||||
{}
|
||||
|
||||
void define_by_pos(int& position, void* data, details::exchange_type type);
|
||||
|
||||
void pre_fetch();
|
||||
void post_fetch(bool gotData, indicator* ind);
|
||||
|
||||
void resize(std::size_t sz);
|
||||
std::size_t size();
|
||||
|
||||
void clean_up();
|
||||
|
||||
db2_statement_backend& statement_;
|
||||
|
||||
void prepare_indicators(std::size_t size);
|
||||
|
||||
SQLLEN *indptr;
|
||||
std::vector<SQLLEN> indVec;
|
||||
void *data;
|
||||
char *buf;
|
||||
int position_;
|
||||
details::exchange_type type;
|
||||
SQLSMALLINT cType;
|
||||
std::size_t colSize;
|
||||
};
|
||||
|
||||
struct SOCI_DB2_DECL db2_standard_use_type_backend : details::standard_use_type_backend
|
||||
{
|
||||
db2_standard_use_type_backend(db2_statement_backend &st)
|
||||
: statement_(st),buf(NULL),ind(0)
|
||||
{}
|
||||
|
||||
void bind_by_pos(int& position, void* data, details::exchange_type type, bool readOnly);
|
||||
void bind_by_name(std::string const& name, void* data, details::exchange_type type, bool readOnly);
|
||||
|
||||
void pre_use(indicator const* ind);
|
||||
void post_use(bool gotData, indicator* ind);
|
||||
|
||||
void clean_up();
|
||||
|
||||
db2_statement_backend& statement_;
|
||||
|
||||
void *prepare_for_bind(void *data, SQLLEN &size, SQLSMALLINT &sqlType, SQLSMALLINT &cType);
|
||||
|
||||
void *data;
|
||||
details::exchange_type type;
|
||||
int position;
|
||||
std::string name;
|
||||
char* buf;
|
||||
SQLLEN ind;
|
||||
};
|
||||
|
||||
struct SOCI_DB2_DECL db2_vector_use_type_backend : details::vector_use_type_backend
|
||||
{
|
||||
db2_vector_use_type_backend(db2_statement_backend &st)
|
||||
: statement_(st),buf(NULL) {}
|
||||
|
||||
void bind_by_pos(int& position, void* data, details::exchange_type type);
|
||||
void bind_by_name(std::string const& name, void* data, details::exchange_type type);
|
||||
|
||||
void pre_use(indicator const* ind);
|
||||
|
||||
std::size_t size();
|
||||
|
||||
void clean_up();
|
||||
|
||||
db2_statement_backend& statement_;
|
||||
|
||||
void prepare_indicators(std::size_t size);
|
||||
void prepare_for_bind(void *&data, SQLUINTEGER &size,SQLSMALLINT &sqlType, SQLSMALLINT &cType);
|
||||
void bind_helper(int &position, void *data, details::exchange_type type);
|
||||
|
||||
SQLLEN *indptr;
|
||||
std::vector<SQLLEN> indVec;
|
||||
void *data;
|
||||
char *buf;
|
||||
details::exchange_type type;
|
||||
std::size_t colSize;
|
||||
};
|
||||
|
||||
struct db2_session_backend;
|
||||
struct SOCI_DB2_DECL db2_statement_backend : details::statement_backend
|
||||
{
|
||||
db2_statement_backend(db2_session_backend &session);
|
||||
|
||||
void alloc();
|
||||
void clean_up();
|
||||
void prepare(std::string const& query, details::statement_type eType);
|
||||
|
||||
exec_fetch_result execute(int number);
|
||||
exec_fetch_result fetch(int number);
|
||||
|
||||
long long get_affected_rows();
|
||||
int get_number_of_rows();
|
||||
|
||||
std::string rewrite_for_procedure_call(std::string const& query);
|
||||
|
||||
int prepare_for_describe();
|
||||
void describe_column(int colNum, data_type& dtype, std::string& columnName);
|
||||
std::size_t column_size(int col);
|
||||
|
||||
db2_standard_into_type_backend* make_into_type_backend();
|
||||
db2_standard_use_type_backend* make_use_type_backend();
|
||||
db2_vector_into_type_backend* make_vector_into_type_backend();
|
||||
db2_vector_use_type_backend* make_vector_use_type_backend();
|
||||
|
||||
db2_session_backend& session_;
|
||||
|
||||
SQLHANDLE hStmt;
|
||||
std::string query_;
|
||||
std::vector<std::string> names;
|
||||
bool hasVectorUseElements;
|
||||
SQLUINTEGER numRowsFetched;
|
||||
details::db2::binding_method use_binding_method_;
|
||||
};
|
||||
|
||||
struct db2_rowid_backend : details::rowid_backend
|
||||
{
|
||||
db2_rowid_backend(db2_session_backend &session);
|
||||
|
||||
~db2_rowid_backend();
|
||||
};
|
||||
|
||||
struct db2_blob_backend : details::blob_backend
|
||||
{
|
||||
db2_blob_backend(db2_session_backend& session);
|
||||
|
||||
~db2_blob_backend();
|
||||
|
||||
std::size_t get_len();
|
||||
std::size_t read(std::size_t offset, char* buf, std::size_t toRead);
|
||||
std::size_t write(std::size_t offset, char const* buf, std::size_t toWrite);
|
||||
std::size_t append(char const* buf, std::size_t toWrite);
|
||||
void trim(std::size_t newLen);
|
||||
|
||||
db2_session_backend& session_;
|
||||
};
|
||||
|
||||
struct db2_session_backend : details::session_backend
|
||||
{
|
||||
db2_session_backend(connection_parameters const& parameters);
|
||||
|
||||
~db2_session_backend();
|
||||
|
||||
void begin();
|
||||
void commit();
|
||||
void rollback();
|
||||
|
||||
std::string get_backend_name() const { return "DB2"; }
|
||||
|
||||
void clean_up();
|
||||
|
||||
db2_statement_backend* make_statement_backend();
|
||||
db2_rowid_backend* make_rowid_backend();
|
||||
db2_blob_backend* make_blob_backend();
|
||||
|
||||
void parseConnectString(std::string const &);
|
||||
void parseKeyVal(std::string const &);
|
||||
|
||||
std::string dsn;
|
||||
std::string username;
|
||||
std::string password;
|
||||
bool autocommit;
|
||||
bool in_transaction;
|
||||
|
||||
SQLHANDLE hEnv; /* Environment handle */
|
||||
SQLHANDLE hDbc; /* Connection handle */
|
||||
};
|
||||
|
||||
struct SOCI_DB2_DECL db2_backend_factory : backend_factory
|
||||
{
|
||||
db2_backend_factory() {}
|
||||
db2_session_backend* make_session(
|
||||
connection_parameters const & parameters) const;
|
||||
};
|
||||
|
||||
extern SOCI_DB2_DECL db2_backend_factory const db2;
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
// for dynamic backend loading
|
||||
SOCI_DB2_DECL backend_factory const* factory_db2();
|
||||
SOCI_DB2_DECL void register_factory_db2();
|
||||
|
||||
} // extern "C"
|
||||
|
||||
} // namespace soci
|
||||
|
||||
#endif // SOCI_DB2_H_INCLUDED
|
||||
@@ -7,7 +7,9 @@
|
||||
//
|
||||
|
||||
#define SOCI_DB2_SOURCE
|
||||
#include "soci-db2.h"
|
||||
#include "soci/db2/soci-db2.h"
|
||||
#include "soci-exchange-cast.h"
|
||||
#include "soci-mktime.h"
|
||||
#include "common.h"
|
||||
#include <ctime>
|
||||
|
||||
@@ -37,7 +39,7 @@ void db2_standard_into_type_backend::define_by_pos(
|
||||
cType = SQL_C_CHAR;
|
||||
// Patch: set to min between column size and 100MB (used ot be 32769)
|
||||
// Column size for text data type can be too large for buffer allocation
|
||||
size = statement_.column_size(this->position);
|
||||
size = static_cast<SQLUINTEGER>(statement_.column_size(this->position));
|
||||
size = size > details::db2::cli_max_buffer ? details::db2::cli_max_buffer : size;
|
||||
size++;
|
||||
buf = new char[size];
|
||||
@@ -127,33 +129,26 @@ void db2_standard_into_type_backend::post_fetch(
|
||||
// only std::string and std::tm need special handling
|
||||
if (type == x_char)
|
||||
{
|
||||
char *c = static_cast<char*>(data);
|
||||
*c = buf[0];
|
||||
exchange_type_cast<x_char>(data) = buf[0];
|
||||
}
|
||||
if (type == x_stdstring)
|
||||
{
|
||||
std::string *s = static_cast<std::string *>(data);
|
||||
*s = buf;
|
||||
if (s->size() >= (details::db2::cli_max_buffer - 1))
|
||||
std::string& s = exchange_type_cast<x_stdstring>(data);
|
||||
s = buf;
|
||||
if (s.size() >= (details::db2::cli_max_buffer - 1))
|
||||
{
|
||||
throw soci_error("Buffer size overflow; maybe got too large string");
|
||||
}
|
||||
}
|
||||
else if (type == x_stdtm)
|
||||
{
|
||||
std::tm *t = static_cast<std::tm *>(data);
|
||||
std::tm& t = exchange_type_cast<x_stdtm>(data);
|
||||
|
||||
TIMESTAMP_STRUCT * ts = reinterpret_cast<TIMESTAMP_STRUCT*>(buf);
|
||||
t->tm_isdst = -1;
|
||||
t->tm_year = ts->year - 1900;
|
||||
t->tm_mon = ts->month - 1;
|
||||
t->tm_mday = ts->day;
|
||||
t->tm_hour = ts->hour;
|
||||
t->tm_min = ts->minute;
|
||||
t->tm_sec = ts->second;
|
||||
|
||||
// normalize and compute the remaining fields
|
||||
std::mktime(t);
|
||||
details::mktime_from_ymdhms(t,
|
||||
ts->year, ts->month, ts->day,
|
||||
ts->hour, ts->minute, ts->second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,9 @@
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#define SOCI_DB2_SOURCE
|
||||
#include "soci-db2.h"
|
||||
#include "soci/soci-platform.h"
|
||||
#include "soci/db2/soci-db2.h"
|
||||
#include "soci-exchange-cast.h"
|
||||
#include <cctype>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
@@ -55,8 +57,7 @@ void *db2_standard_use_type_backend::prepare_for_bind(
|
||||
cType = SQL_C_CHAR;
|
||||
size = sizeof(char) + 1;
|
||||
buf = new char[size];
|
||||
char *c = static_cast<char*>(data);
|
||||
buf[0] = *c;
|
||||
buf[0] = exchange_type_cast<x_char>(data);
|
||||
buf[1] = '\0';
|
||||
ind = SQL_NTS;
|
||||
}
|
||||
@@ -65,12 +66,12 @@ void *db2_standard_use_type_backend::prepare_for_bind(
|
||||
{
|
||||
// TODO: No textual value is assigned here!
|
||||
|
||||
std::string* s = static_cast<std::string*>(data);
|
||||
std::string const& s = exchange_type_cast<x_stdstring>(data);
|
||||
sqlType = SQL_LONGVARCHAR;
|
||||
cType = SQL_C_CHAR;
|
||||
size = s->size() + 1;
|
||||
size = static_cast<SQLINTEGER>(s.size()) + 1;
|
||||
buf = new char[size];
|
||||
strncpy(buf, s->c_str(), size);
|
||||
strncpy(buf, s.c_str(), size);
|
||||
ind = SQL_NTS;
|
||||
}
|
||||
break;
|
||||
@@ -79,7 +80,7 @@ void *db2_standard_use_type_backend::prepare_for_bind(
|
||||
sqlType = SQL_TIMESTAMP;
|
||||
cType = SQL_C_TIMESTAMP;
|
||||
buf = new char[sizeof(TIMESTAMP_STRUCT)];
|
||||
std::tm *t = static_cast<std::tm *>(data);
|
||||
std::tm const& t = exchange_type_cast<x_stdtm>(data);
|
||||
data = buf;
|
||||
size = 19; // This number is not the size in bytes, but the number
|
||||
// of characters in the date if it was written out
|
||||
@@ -87,12 +88,12 @@ void *db2_standard_use_type_backend::prepare_for_bind(
|
||||
|
||||
TIMESTAMP_STRUCT * ts = reinterpret_cast<TIMESTAMP_STRUCT*>(buf);
|
||||
|
||||
ts->year = static_cast<SQLSMALLINT>(t->tm_year + 1900);
|
||||
ts->month = static_cast<SQLUSMALLINT>(t->tm_mon + 1);
|
||||
ts->day = static_cast<SQLUSMALLINT>(t->tm_mday);
|
||||
ts->hour = static_cast<SQLUSMALLINT>(t->tm_hour);
|
||||
ts->minute = static_cast<SQLUSMALLINT>(t->tm_min);
|
||||
ts->second = static_cast<SQLUSMALLINT>(t->tm_sec);
|
||||
ts->year = static_cast<SQLSMALLINT>(t.tm_year + 1900);
|
||||
ts->month = static_cast<SQLUSMALLINT>(t.tm_mon + 1);
|
||||
ts->day = static_cast<SQLUSMALLINT>(t.tm_mday);
|
||||
ts->hour = static_cast<SQLUSMALLINT>(t.tm_hour);
|
||||
ts->minute = static_cast<SQLUSMALLINT>(t.tm_min);
|
||||
ts->second = static_cast<SQLUSMALLINT>(t.tm_sec);
|
||||
ts->fraction = 0;
|
||||
}
|
||||
break;
|
||||
@@ -135,8 +136,8 @@ void db2_standard_use_type_backend::bind_by_name(
|
||||
int position = -1;
|
||||
int count = 1;
|
||||
|
||||
for (std::vector<std::string>::iterator it = statement_.names.begin();
|
||||
it != statement_.names.end(); ++it)
|
||||
for (std::vector<std::string>::iterator it = statement_.names_.begin();
|
||||
it != statement_.names_.end(); ++it)
|
||||
{
|
||||
if (*it == name)
|
||||
{
|
||||
|
||||
@@ -7,17 +7,12 @@
|
||||
//
|
||||
|
||||
#define SOCI_DB2_SOURCE
|
||||
#include "soci-db2.h"
|
||||
#include "soci/db2/soci-db2.h"
|
||||
#include <cctype>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4355)
|
||||
#endif
|
||||
|
||||
using namespace soci;
|
||||
using namespace soci::details;
|
||||
|
||||
|
||||
db2_statement_backend::db2_statement_backend(db2_session_backend &session)
|
||||
: session_(session),hasVectorUseElements(false),use_binding_method_(details::db2::BOUND_BY_NONE)
|
||||
{
|
||||
@@ -102,7 +97,7 @@ void db2_statement_backend::prepare(std::string const & query ,
|
||||
}
|
||||
else // end of name
|
||||
{
|
||||
names.push_back(name);
|
||||
names_.push_back(name);
|
||||
name.clear();
|
||||
std::ostringstream ss;
|
||||
ss << '?';
|
||||
@@ -117,7 +112,7 @@ void db2_statement_backend::prepare(std::string const & query ,
|
||||
|
||||
if (state == in_name)
|
||||
{
|
||||
names.push_back(name);
|
||||
names_.push_back(name);
|
||||
std::ostringstream ss;
|
||||
ss << '?';
|
||||
query_ += ss.str();
|
||||
@@ -171,7 +166,7 @@ db2_statement_backend::fetch(int number )
|
||||
numRowsFetched = 0;
|
||||
|
||||
SQLSetStmtAttr(hStmt, SQL_ATTR_ROW_BIND_TYPE, SQL_BIND_BY_COLUMN, 0);
|
||||
SQLSetStmtAttr(hStmt, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER)number, 0);
|
||||
SQLSetStmtAttr(hStmt, SQL_ATTR_ROW_ARRAY_SIZE, db2::int_as_ptr(number), 0);
|
||||
SQLSetStmtAttr(hStmt, SQL_ATTR_ROWS_FETCHED_PTR, &numRowsFetched, 0);
|
||||
|
||||
SQLRETURN cliRC = SQLFetch(hStmt);
|
||||
@@ -200,7 +195,7 @@ long long db2_statement_backend::get_affected_rows()
|
||||
}
|
||||
else if (rows == -1)
|
||||
{
|
||||
throw soci_error("Error getting affected row count: statement did not perform an update, insert, delete, or merge");
|
||||
throw soci_error("Error getting affected row count: statement did not perform an update, insert, delete, or merge");
|
||||
}
|
||||
|
||||
return rows;
|
||||
@@ -211,6 +206,11 @@ int db2_statement_backend::get_number_of_rows()
|
||||
return numRowsFetched;
|
||||
}
|
||||
|
||||
std::string db2_statement_backend::get_parameter_name(int index) const
|
||||
{
|
||||
return names_.at(index);
|
||||
}
|
||||
|
||||
std::string db2_statement_backend::rewrite_for_procedure_call(
|
||||
std::string const &query)
|
||||
{
|
||||
@@ -278,7 +278,7 @@ SQLCHAR colNameBuffer[2048];
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t db2_statement_backend::column_size(int col) {
|
||||
size_t db2_statement_backend::column_size(int col) {
|
||||
SQLCHAR colNameBuffer[2048];
|
||||
SQLSMALLINT colNameBufferOverflow;
|
||||
SQLSMALLINT dataType;
|
||||
@@ -296,7 +296,7 @@ std::size_t db2_statement_backend::column_size(int col) {
|
||||
throw db2_soci_error(db2_soci_error::sqlState("Error while detecting column size",SQL_HANDLE_STMT,hStmt),cliRC);
|
||||
}
|
||||
|
||||
return colSize;
|
||||
return colSize;
|
||||
}
|
||||
|
||||
db2_standard_into_type_backend * db2_statement_backend::make_into_type_backend()
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
###############################################################################
|
||||
#
|
||||
# This file is part of CMake configuration for SOCI library
|
||||
#
|
||||
# Copyright (C) 2011 Denis Chapligin
|
||||
# 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)
|
||||
#
|
||||
###############################################################################
|
||||
soci_backend_test(
|
||||
BACKEND DB2
|
||||
SOURCE test-db2.cpp
|
||||
CONNSTR "DSN=SAMPLE;Uid=db2inst1;Pwd=db2inst1;autocommit=off")
|
||||
@@ -1,454 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2011-2013 Denis Chapligin
|
||||
// Copyright (C) 2004-2006 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 "soci.h"
|
||||
#include "soci-db2.h"
|
||||
#include "common-tests.h"
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
|
||||
using namespace soci;
|
||||
using namespace soci::tests;
|
||||
|
||||
std::string connectString;
|
||||
backend_factory const &backEnd = *soci::factory_db2();
|
||||
|
||||
|
||||
//
|
||||
// Support for soci Common Tests
|
||||
//
|
||||
|
||||
struct table_creator_one : public table_creator_base
|
||||
{
|
||||
table_creator_one(session & sql)
|
||||
: table_creator_base(sql)
|
||||
{
|
||||
sql << "CREATE TABLE SOCI_TEST(ID INTEGER, VAL SMALLINT, C CHAR, STR VARCHAR(20), SH SMALLINT, UL NUMERIC(20), D DOUBLE, "
|
||||
"TM TIMESTAMP, I1 INTEGER, I2 INTEGER, I3 INTEGER, NAME VARCHAR(20))";
|
||||
}
|
||||
};
|
||||
|
||||
struct table_creator_two : public table_creator_base
|
||||
{
|
||||
table_creator_two(session & sql)
|
||||
: table_creator_base(sql)
|
||||
{
|
||||
sql << "CREATE TABLE SOCI_TEST(NUM_FLOAT DOUBLE, NUM_INT INTEGER, NAME VARCHAR(20), SOMETIME TIMESTAMP, CHR CHAR)";
|
||||
}
|
||||
};
|
||||
|
||||
struct table_creator_three : public table_creator_base
|
||||
{
|
||||
table_creator_three(session & sql)
|
||||
: table_creator_base(sql)
|
||||
{
|
||||
sql << "CREATE TABLE SOCI_TEST(NAME VARCHAR(100) NOT NULL, PHONE VARCHAR(15))";
|
||||
}
|
||||
};
|
||||
|
||||
struct table_creator_for_get_affected_rows : table_creator_base
|
||||
{
|
||||
table_creator_for_get_affected_rows(session & sql)
|
||||
: table_creator_base(sql)
|
||||
{
|
||||
sql << "CREATE TABLE SOCI_TEST(VAL INTEGER)";
|
||||
}
|
||||
};
|
||||
|
||||
class test_context :public test_context_base
|
||||
{
|
||||
public:
|
||||
test_context(backend_factory const & pi_back_end, std::string const & pi_connect_string)
|
||||
: test_context_base(pi_back_end, pi_connect_string) {}
|
||||
|
||||
table_creator_base* table_creator_1(session & pr_s) const
|
||||
{
|
||||
pr_s << "SET CURRENT SCHEMA = 'DB2INST1'";
|
||||
return new table_creator_one(pr_s);
|
||||
}
|
||||
|
||||
table_creator_base* table_creator_2(session & pr_s) const
|
||||
{
|
||||
pr_s << "SET CURRENT SCHEMA = 'DB2INST1'";
|
||||
return new table_creator_two(pr_s);
|
||||
}
|
||||
|
||||
table_creator_base* table_creator_3(session & pr_s) const
|
||||
{
|
||||
pr_s << "SET CURRENT SCHEMA = 'DB2INST1'";
|
||||
return new table_creator_three(pr_s);
|
||||
}
|
||||
|
||||
table_creator_base* table_creator_4(session& s) const
|
||||
{
|
||||
return new table_creator_for_get_affected_rows(s);
|
||||
}
|
||||
|
||||
std::string to_date_time(std::string const & pi_datdt_string) const
|
||||
{
|
||||
return "to_date('" + pi_datdt_string + "', 'YYYY-MM-DD HH24:MI:SS')";
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// Additional tests to exercise the DB2 backend
|
||||
//
|
||||
|
||||
void test1()
|
||||
{
|
||||
{
|
||||
session sql(backEnd, connectString);
|
||||
|
||||
sql << "SELECT CURRENT TIMESTAMP FROM SYSIBM.SYSDUMMY1";
|
||||
sql << "SELECT " << 123 << " FROM SYSIBM.SYSDUMMY1";
|
||||
|
||||
std::string query = "CREATE TABLE DB2INST1.SOCI_TEST (ID BIGINT,DATA VARCHAR(8))";
|
||||
sql << query;
|
||||
|
||||
{
|
||||
const int i = 7;
|
||||
sql << "insert into db2inst1.SOCI_TEST (id) values (:id)", use(i,"id");
|
||||
int j = 0;
|
||||
sql << "select id from db2inst1.SOCI_TEST where id=7", into(j);
|
||||
assert(j == i);
|
||||
}
|
||||
|
||||
{
|
||||
const long int li = 9;
|
||||
sql << "insert into db2inst1.SOCI_TEST (id) values (:id)", use(li,"id");
|
||||
long int lj = 0;;
|
||||
sql << "select id from db2inst1.SOCI_TEST where id=9", into(lj);
|
||||
assert(lj == li);
|
||||
}
|
||||
|
||||
{
|
||||
const long long ll = 11;
|
||||
sql << "insert into db2inst1.SOCI_TEST (id) values (:id)", use(ll,"id");
|
||||
long long lj = 0;
|
||||
sql << "select id from db2inst1.SOCI_TEST where id=11", into(lj);
|
||||
assert(lj == ll);
|
||||
}
|
||||
|
||||
{
|
||||
const int i = 13;
|
||||
indicator i_ind = i_ok;
|
||||
sql << "insert into db2inst1.SOCI_TEST (id) values (:id)", use(i,i_ind,"id");
|
||||
int j = 0;
|
||||
indicator j_ind = i_null;
|
||||
sql << "select id from db2inst1.SOCI_TEST where id=13", into(j,j_ind);
|
||||
assert(j == i);
|
||||
assert(j_ind == i_ok);
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<int> numbers(100);
|
||||
for (int i = 0 ; i < 100 ; i++)
|
||||
{
|
||||
numbers[i] = i + 1000;
|
||||
}
|
||||
sql << "insert into db2inst1.SOCI_TEST (id) values (:id)", use(numbers,"id");
|
||||
sql << "select id from db2inst1.SOCI_TEST where id >= 1000 and id < 2000 order by id", into(numbers);
|
||||
for (int i = 0 ; i < 100 ; i++)
|
||||
{
|
||||
assert(numbers[i] == i + 1000);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<int> numbers(100);
|
||||
std::vector<indicator> inds(100);
|
||||
for (int i = 0 ; i < 100 ; i++)
|
||||
{
|
||||
numbers[i] = i + 2000;
|
||||
inds[i] = i_ok;
|
||||
}
|
||||
sql << "insert into db2inst1.SOCI_TEST (id) values (:id)", use(numbers,inds,"id");
|
||||
for (int i = 0 ; i < 100 ; i++)
|
||||
{
|
||||
numbers[i] = 0;
|
||||
inds[i] = i_null;
|
||||
}
|
||||
sql << "select id from db2inst1.SOCI_TEST where id >= 2000 and id < 3000 order by id", into(numbers,inds);
|
||||
for (int i = 0 ; i < 100 ; i++)
|
||||
{
|
||||
assert(numbers[i] == i + 2000);
|
||||
assert(inds[i] == i_ok);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
int i = 0;
|
||||
statement st = (sql.prepare << "select id from db2inst1.SOCI_TEST where id < 1000", into(i));
|
||||
st.execute();
|
||||
st.fetch();
|
||||
assert (i == 7);
|
||||
st.fetch();
|
||||
assert (i == 9);
|
||||
st.fetch();
|
||||
assert (i == 11);
|
||||
st.fetch();
|
||||
assert (i == 13);
|
||||
}
|
||||
|
||||
{
|
||||
int i = 0;
|
||||
indicator i_ind = i_null;
|
||||
std::string d;
|
||||
indicator d_ind = i_ok;
|
||||
statement st = (sql.prepare << "select id, data from db2inst1.SOCI_TEST where id = 13", into(i, i_ind), into(d, d_ind));
|
||||
st.execute();
|
||||
st.fetch();
|
||||
assert (i == 13);
|
||||
assert (i_ind == i_ok);
|
||||
assert (d_ind == i_null);
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<int> numbers(100);
|
||||
for (int i = 0 ; i < 100 ; i++)
|
||||
{
|
||||
numbers[i] = 0;
|
||||
}
|
||||
statement st = (sql.prepare << "select id from db2inst1.SOCI_TEST where id >= 1000 order by id", into(numbers));
|
||||
st.execute();
|
||||
st.fetch();
|
||||
for (int i = 0 ; i < 100 ; i++)
|
||||
{
|
||||
assert(numbers[i] == i + 1000);
|
||||
}
|
||||
st.fetch();
|
||||
for (int i = 0 ; i < 100 ; i++)
|
||||
{
|
||||
assert(numbers[i] == i + 2000);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<int> numbers(100);
|
||||
std::vector<indicator> inds(100);
|
||||
for (int i = 0 ; i < 100 ; i++)
|
||||
{
|
||||
numbers[i] = 0;
|
||||
inds[i] = i_null;
|
||||
}
|
||||
statement st = (sql.prepare << "select id from db2inst1.SOCI_TEST where id >= 1000 order by id", into(numbers, inds));
|
||||
st.execute();
|
||||
st.fetch();
|
||||
for (int i = 0 ; i < 100 ; i++)
|
||||
{
|
||||
assert(numbers[i] == i + 1000);
|
||||
assert(inds[i] == i_ok);
|
||||
}
|
||||
st.fetch();
|
||||
for (int i = 0 ; i < 100 ; i++)
|
||||
{
|
||||
assert(numbers[i] == i + 2000);
|
||||
assert(inds[i] == i_ok);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// XXX: what is the purpose of this test?? what is the expected value?
|
||||
int i = 0;
|
||||
statement st = (sql.prepare << "select id from db2inst1.SOCI_TEST", use(i));
|
||||
}
|
||||
|
||||
{
|
||||
// XXX: what is the purpose of this test?? what is the expected value?
|
||||
int i = 0;
|
||||
indicator ind = i_ok;
|
||||
statement st = (sql.prepare << "select id from db2inst1.SOCI_TEST", use(i, ind));
|
||||
}
|
||||
|
||||
{
|
||||
// XXX: what is the purpose of this test?? what is the expected value?
|
||||
std::vector<int> numbers(100);
|
||||
statement st = (sql.prepare << "select id from db2inst1.SOCI_TEST", use(numbers));
|
||||
}
|
||||
|
||||
{
|
||||
// XXX: what is the purpose of this test?? what is the expected value?
|
||||
std::vector<int> numbers(100);
|
||||
std::vector<indicator> inds(100);
|
||||
statement st = (sql.prepare << "select id from db2inst1.SOCI_TEST", use(numbers, inds));
|
||||
}
|
||||
|
||||
sql<<"DROP TABLE DB2INST1.SOCI_TEST";
|
||||
|
||||
sql.commit();
|
||||
}
|
||||
|
||||
std::cout << "test 1 passed" << std::endl;
|
||||
}
|
||||
|
||||
void test2() {
|
||||
{
|
||||
session sql(backEnd, connectString);
|
||||
|
||||
std::string query = "CREATE TABLE DB2INST1.SOCI_TEST (ID BIGINT,DATA VARCHAR(8),DT TIMESTAMP)";
|
||||
sql << query;
|
||||
|
||||
{
|
||||
int i = 7;
|
||||
std::string n("test");
|
||||
sql << "insert into db2inst1.SOCI_TEST (id,data) values (:id,:name)", use(i,"id"),use(n,"name");
|
||||
int j;
|
||||
std::string m;
|
||||
sql << "select id,data from db2inst1.SOCI_TEST where id=7", into(j),into(m);
|
||||
assert (j == i);
|
||||
assert (m == n);
|
||||
}
|
||||
|
||||
{
|
||||
int i = 8;
|
||||
sql << "insert into db2inst1.SOCI_TEST (id) values (:id)", use(i,"id");
|
||||
int j;
|
||||
std::string m;
|
||||
indicator ind = i_ok;
|
||||
sql << "select id,data from db2inst1.SOCI_TEST where id=8", into(j),into(m,ind);
|
||||
assert(j == i);
|
||||
assert(ind==i_null);
|
||||
}
|
||||
|
||||
{
|
||||
std::tm dt;
|
||||
sql << "select current timestamp from sysibm.sysdummy1",into(dt);
|
||||
sql << "insert into db2inst1.SOCI_TEST (dt) values (:dt)",use(dt,"dt");
|
||||
std::tm dt2;
|
||||
sql << "select dt from db2inst1.SOCI_TEST where dt is not null", into(dt2);
|
||||
assert(dt2.tm_year == dt.tm_year && dt2.tm_mon == dt.tm_mon && dt2.tm_mday == dt.tm_mday &&
|
||||
dt2.tm_hour == dt.tm_hour && dt2.tm_min == dt.tm_min && dt2.tm_sec == dt.tm_sec);
|
||||
}
|
||||
|
||||
sql<<"DROP TABLE DB2INST1.SOCI_TEST";
|
||||
sql.commit();
|
||||
}
|
||||
|
||||
std::cout << "test 2 passed" << std::endl;
|
||||
}
|
||||
|
||||
void test3() {
|
||||
{
|
||||
session sql(backEnd, connectString);
|
||||
int i;
|
||||
|
||||
std::string query = "CREATE TABLE DB2INST1.SOCI_TEST (ID BIGINT,DATA VARCHAR(8),DT TIMESTAMP)";
|
||||
sql << query;
|
||||
|
||||
std::vector<long long> ids(100);
|
||||
std::vector<std::string> data(100);
|
||||
std::vector<std::tm> dts(100);
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
ids[i] = 1000000000LL + i;
|
||||
data[i] = "test";
|
||||
dts[i].tm_year = 112;
|
||||
dts[i].tm_mon = 7;
|
||||
dts[i].tm_mday = 17;
|
||||
dts[i].tm_hour = 0;
|
||||
dts[i].tm_min = 0;
|
||||
dts[i].tm_sec = i % 60;
|
||||
}
|
||||
|
||||
sql << "insert into db2inst1.SOCI_TEST (id, data, dt) values (:id, :data, :dt)",
|
||||
use(ids, "id"), use(data,"data"), use(dts, "dt");
|
||||
|
||||
i = 0;
|
||||
rowset<row> rs = (sql.prepare<<"SELECT ID, DATA, DT FROM DB2INST1.SOCI_TEST");
|
||||
for (rowset<row>::const_iterator it = rs.begin(); it != rs.end(); it++)
|
||||
{
|
||||
const row & r = *it;
|
||||
const long long id = r.get<long long>(0);
|
||||
const std::string data = r.get<std::string>(1);
|
||||
const std::tm dt = r.get<std::tm>(2);
|
||||
|
||||
assert(id == 1000000000LL + i);
|
||||
assert(data == "test");
|
||||
assert(dt.tm_year == 112);
|
||||
assert(dt.tm_mon == 7);
|
||||
assert(dt.tm_mday == 17);
|
||||
assert(dt.tm_hour == 0);
|
||||
assert(dt.tm_min == 0);
|
||||
assert(dt.tm_sec == i % 60);
|
||||
|
||||
i += 1;
|
||||
}
|
||||
|
||||
sql<<"DROP TABLE DB2INST1.SOCI_TEST";
|
||||
sql.commit();
|
||||
}
|
||||
|
||||
std::cout << "test 3 passed" << std::endl;
|
||||
}
|
||||
|
||||
|
||||
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 asser()-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];
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "usage: " << argv[0]
|
||||
<< " connectstring\n"
|
||||
<< "example: " << argv[0]
|
||||
<< " \'DSN=SAMPLE;Uid=db2inst1;Pwd=db2inst1;autocommit=off\'\n";
|
||||
std::exit(1);
|
||||
}
|
||||
|
||||
test_context tc(backEnd, connectString);
|
||||
common_tests tests(tc);
|
||||
tests.run();
|
||||
|
||||
try
|
||||
{
|
||||
std::cout<<"\nSOCI DB2 Tests:\n\n";
|
||||
|
||||
session sql(backEnd, connectString);
|
||||
|
||||
try
|
||||
{
|
||||
// attempt to delete the test table from previous runs
|
||||
sql << "DROP TABLE DB2INST1.SOCI_TEST";
|
||||
}
|
||||
catch (soci_error const & e)
|
||||
{
|
||||
// if the table didn't exist, then proceed
|
||||
}
|
||||
|
||||
test1();
|
||||
test2();
|
||||
test3();
|
||||
// ...
|
||||
|
||||
std::cout << "\nOK, all tests passed.\n\n";
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
catch (std::exception const & e)
|
||||
{
|
||||
std::cout << e.what() << '\n';
|
||||
}
|
||||
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
@@ -7,7 +7,8 @@
|
||||
//
|
||||
|
||||
#define SOCI_DB2_SOURCE
|
||||
#include "soci-db2.h"
|
||||
#include "soci/db2/soci-db2.h"
|
||||
#include "soci-mktime.h"
|
||||
#include <cctype>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
@@ -209,20 +210,10 @@ void db2_vector_into_type_backend::post_fetch(bool gotData, indicator *ind)
|
||||
std::size_t const vsize = v.size();
|
||||
for (std::size_t i = 0; i != vsize; ++i)
|
||||
{
|
||||
std::tm t;
|
||||
|
||||
TIMESTAMP_STRUCT * ts = reinterpret_cast<TIMESTAMP_STRUCT*>(pos);
|
||||
t.tm_isdst = -1;
|
||||
t.tm_year = ts->year - 1900;
|
||||
t.tm_mon = ts->month - 1;
|
||||
t.tm_mday = ts->day;
|
||||
t.tm_hour = ts->hour;
|
||||
t.tm_min = ts->minute;
|
||||
t.tm_sec = ts->second;
|
||||
|
||||
// normalize and compute the remaining fields
|
||||
std::mktime(&t);
|
||||
v[i] = t;
|
||||
details::mktime_from_ymdhms(v[i],
|
||||
ts->year, ts->month, ts->day,
|
||||
ts->hour, ts->minute, ts->second);
|
||||
pos += colSize;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,8 @@
|
||||
//
|
||||
|
||||
#define SOCI_DB2_SOURCE
|
||||
#include "soci-db2.h"
|
||||
#include "soci/soci-platform.h"
|
||||
#include "soci/db2/soci-db2.h"
|
||||
#include <cctype>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
@@ -195,7 +196,7 @@ void db2_vector_use_type_backend::bind_helper(int &position, void *data, details
|
||||
prepare_for_bind(data, size, sqlType, cType);
|
||||
|
||||
SQLINTEGER arraySize = (SQLINTEGER)indVec.size();
|
||||
SQLSetStmtAttr(statement_.hStmt, SQL_ATTR_PARAMSET_SIZE, (SQLPOINTER)arraySize, 0);
|
||||
SQLSetStmtAttr(statement_.hStmt, SQL_ATTR_PARAMSET_SIZE, db2::int_as_ptr(arraySize), 0);
|
||||
|
||||
SQLRETURN cliRC = SQLBindParameter(statement_.hStmt, static_cast<SQLUSMALLINT>(position++),
|
||||
SQL_PARAM_INPUT, cType, sqlType, size, 0,
|
||||
@@ -231,8 +232,8 @@ void db2_vector_use_type_backend::bind_by_name(
|
||||
}
|
||||
statement_.use_binding_method_ = details::db2::BOUND_BY_NAME;
|
||||
|
||||
for (std::vector<std::string>::iterator it = statement_.names.begin();
|
||||
it != statement_.names.end(); ++it)
|
||||
for (std::vector<std::string>::iterator it = statement_.names_.begin();
|
||||
it != statement_.names_.end(); ++it)
|
||||
{
|
||||
if (*it == name)
|
||||
{
|
||||
|
||||
@@ -9,9 +9,6 @@
|
||||
#
|
||||
###############################################################################
|
||||
soci_backend(Empty
|
||||
HEADERS soci-empty.h
|
||||
DESCRIPTION "SOCI backend skeleton for development of new backends"
|
||||
DESCRIPTION "SOCI backend skeleton for new backends development"
|
||||
AUTHORS "Maciej Sobczak, Stephen Hutton"
|
||||
MAINTAINERS "Maciej Sobczak")
|
||||
|
||||
add_subdirectory(test)
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
//
|
||||
|
||||
#define SOCI_EMPTY_SOURCE
|
||||
#include "soci-empty.h"
|
||||
#include "soci/empty/soci-empty.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4355)
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
//
|
||||
|
||||
#define SOCI_EMPTY_SOURCE
|
||||
#include "soci-empty.h"
|
||||
#include <backend-loader.h>
|
||||
#include "soci/empty/soci-empty.h"
|
||||
#include "soci/backend-loader.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4355)
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
//
|
||||
|
||||
#define SOCI_EMPTY_SOURCE
|
||||
#include "soci-empty.h"
|
||||
#include "soci/empty/soci-empty.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4355)
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
//
|
||||
|
||||
#define SOCI_EMPTY_SOURCE
|
||||
#include "soci-empty.h"
|
||||
#include "soci/empty/soci-empty.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4355)
|
||||
|
||||
@@ -1,193 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2004-2006 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)
|
||||
//
|
||||
|
||||
#ifndef SOCI_EMPTY_H_INCLUDED
|
||||
#define SOCI_EMPTY_H_INCLUDED
|
||||
|
||||
#ifdef _WIN32
|
||||
# ifdef SOCI_DLL
|
||||
# ifdef SOCI_EMPTY_SOURCE
|
||||
# define SOCI_EMPTY_DECL __declspec(dllexport)
|
||||
# else
|
||||
# define SOCI_EMPTY_DECL __declspec(dllimport)
|
||||
# endif // SOCI_EMPTY_SOURCE
|
||||
# endif // SOCI_DLL
|
||||
#endif // _WIN32
|
||||
//
|
||||
// If SOCI_EMPTY_DECL isn't defined yet define it now
|
||||
#ifndef SOCI_EMPTY_DECL
|
||||
# define SOCI_EMPTY_DECL
|
||||
#endif
|
||||
|
||||
#include "soci-backend.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
|
||||
namespace soci
|
||||
{
|
||||
|
||||
struct empty_statement_backend;
|
||||
|
||||
struct SOCI_EMPTY_DECL empty_standard_into_type_backend : details::standard_into_type_backend
|
||||
{
|
||||
empty_standard_into_type_backend(empty_statement_backend &st)
|
||||
: statement_(st)
|
||||
{}
|
||||
|
||||
void define_by_pos(int& position, void* data, details::exchange_type type);
|
||||
|
||||
void pre_fetch();
|
||||
void post_fetch(bool gotData, bool calledFromFetch, indicator* ind);
|
||||
|
||||
void clean_up();
|
||||
|
||||
empty_statement_backend& statement_;
|
||||
};
|
||||
|
||||
struct SOCI_EMPTY_DECL empty_vector_into_type_backend : details::vector_into_type_backend
|
||||
{
|
||||
empty_vector_into_type_backend(empty_statement_backend &st)
|
||||
: statement_(st)
|
||||
{}
|
||||
|
||||
void define_by_pos(int& position, void* data, details::exchange_type type);
|
||||
|
||||
void pre_fetch();
|
||||
void post_fetch(bool gotData, indicator* ind);
|
||||
|
||||
void resize(std::size_t sz);
|
||||
std::size_t size();
|
||||
|
||||
void clean_up();
|
||||
|
||||
empty_statement_backend& statement_;
|
||||
};
|
||||
|
||||
struct SOCI_EMPTY_DECL empty_standard_use_type_backend : details::standard_use_type_backend
|
||||
{
|
||||
empty_standard_use_type_backend(empty_statement_backend &st)
|
||||
: statement_(st)
|
||||
{}
|
||||
|
||||
void bind_by_pos(int& position, void* data, details::exchange_type type, bool readOnly);
|
||||
void bind_by_name(std::string const& name, void* data, details::exchange_type type, bool readOnly);
|
||||
|
||||
void pre_use(indicator const* ind);
|
||||
void post_use(bool gotData, indicator* ind);
|
||||
|
||||
void clean_up();
|
||||
|
||||
empty_statement_backend& statement_;
|
||||
};
|
||||
|
||||
struct SOCI_EMPTY_DECL empty_vector_use_type_backend : details::vector_use_type_backend
|
||||
{
|
||||
empty_vector_use_type_backend(empty_statement_backend &st)
|
||||
: statement_(st) {}
|
||||
|
||||
void bind_by_pos(int& position, void* data, details::exchange_type type);
|
||||
void bind_by_name(std::string const& name, void* data, details::exchange_type type);
|
||||
|
||||
void pre_use(indicator const* ind);
|
||||
|
||||
std::size_t size();
|
||||
|
||||
void clean_up();
|
||||
|
||||
empty_statement_backend& statement_;
|
||||
};
|
||||
|
||||
struct empty_session_backend;
|
||||
struct SOCI_EMPTY_DECL empty_statement_backend : details::statement_backend
|
||||
{
|
||||
empty_statement_backend(empty_session_backend &session);
|
||||
|
||||
void alloc();
|
||||
void clean_up();
|
||||
void prepare(std::string const& query, details::statement_type eType);
|
||||
|
||||
exec_fetch_result execute(int number);
|
||||
exec_fetch_result fetch(int number);
|
||||
|
||||
long long get_affected_rows();
|
||||
int get_number_of_rows();
|
||||
|
||||
std::string rewrite_for_procedure_call(std::string const& query);
|
||||
|
||||
int prepare_for_describe();
|
||||
void describe_column(int colNum, data_type& dtype, std::string& columnName);
|
||||
|
||||
empty_standard_into_type_backend* make_into_type_backend();
|
||||
empty_standard_use_type_backend* make_use_type_backend();
|
||||
empty_vector_into_type_backend* make_vector_into_type_backend();
|
||||
empty_vector_use_type_backend* make_vector_use_type_backend();
|
||||
|
||||
empty_session_backend& session_;
|
||||
};
|
||||
|
||||
struct empty_rowid_backend : details::rowid_backend
|
||||
{
|
||||
empty_rowid_backend(empty_session_backend &session);
|
||||
|
||||
~empty_rowid_backend();
|
||||
};
|
||||
|
||||
struct empty_blob_backend : details::blob_backend
|
||||
{
|
||||
empty_blob_backend(empty_session_backend& session);
|
||||
|
||||
~empty_blob_backend();
|
||||
|
||||
std::size_t get_len();
|
||||
std::size_t read(std::size_t offset, char* buf, std::size_t toRead);
|
||||
std::size_t write(std::size_t offset, char const* buf, std::size_t toWrite);
|
||||
std::size_t append(char const* buf, std::size_t toWrite);
|
||||
void trim(std::size_t newLen);
|
||||
|
||||
empty_session_backend& session_;
|
||||
};
|
||||
|
||||
struct empty_session_backend : details::session_backend
|
||||
{
|
||||
empty_session_backend(connection_parameters const& parameters);
|
||||
|
||||
~empty_session_backend();
|
||||
|
||||
void begin();
|
||||
void commit();
|
||||
void rollback();
|
||||
|
||||
std::string get_backend_name() const { return "empty"; }
|
||||
|
||||
void clean_up();
|
||||
|
||||
empty_statement_backend* make_statement_backend();
|
||||
empty_rowid_backend* make_rowid_backend();
|
||||
empty_blob_backend* make_blob_backend();
|
||||
};
|
||||
|
||||
struct SOCI_EMPTY_DECL empty_backend_factory : backend_factory
|
||||
{
|
||||
empty_backend_factory() {}
|
||||
empty_session_backend* make_session(connection_parameters const& parameters) const;
|
||||
};
|
||||
|
||||
extern SOCI_EMPTY_DECL empty_backend_factory const empty;
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
// for dynamic backend loading
|
||||
SOCI_EMPTY_DECL backend_factory const* factory_empty();
|
||||
SOCI_EMPTY_DECL void register_factory_empty();
|
||||
|
||||
} // extern "C"
|
||||
|
||||
} // namespace soci
|
||||
|
||||
#endif // SOCI_EMPTY_H_INCLUDED
|
||||
@@ -6,7 +6,7 @@
|
||||
//
|
||||
|
||||
#define SOCI_EMPTY_SOURCE
|
||||
#include "soci-empty.h"
|
||||
#include "soci/empty/soci-empty.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4355)
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
//
|
||||
|
||||
#define SOCI_EMPTY_SOURCE
|
||||
#include "soci-empty.h"
|
||||
#include "soci/empty/soci-empty.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4355)
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
//
|
||||
|
||||
#define SOCI_EMPTY_SOURCE
|
||||
#include "soci-empty.h"
|
||||
#include "soci/empty/soci-empty.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4355)
|
||||
@@ -63,6 +63,12 @@ int empty_statement_backend::get_number_of_rows()
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::string empty_statement_backend::get_parameter_name(int /* index */) const
|
||||
{
|
||||
// ...
|
||||
return std::string();
|
||||
}
|
||||
|
||||
std::string empty_statement_backend::rewrite_for_procedure_call(
|
||||
std::string const &query)
|
||||
{
|
||||
|
||||
1
src/backends/empty/test/.gitignore
vendored
1
src/backends/empty/test/.gitignore
vendored
@@ -1 +0,0 @@
|
||||
test_empty
|
||||
@@ -1,14 +0,0 @@
|
||||
###############################################################################
|
||||
#
|
||||
# This file is part of CMake configuration for SOCI library
|
||||
#
|
||||
# Copyright (C) 2010 Mateusz Loskot
|
||||
# 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)
|
||||
#
|
||||
###############################################################################
|
||||
soci_backend_test(
|
||||
BACKEND Empty
|
||||
SOURCE test-empty.cpp
|
||||
CONNSTR "dummy")
|
||||
@@ -1,13 +0,0 @@
|
||||
COMPILER = g++
|
||||
CXXFLAGS = -Wall -pedantic -Wno-long-long
|
||||
INCLUDEDIRS = -I.. -I../../../core
|
||||
LIBDIRS = -L.. -L../../../core
|
||||
LIBS = -lsoci_core -lsoci_empty -ldl
|
||||
|
||||
|
||||
test-empty : test-empty.cpp
|
||||
${COMPILER} -o $@ $? ${CXXFLAGS} ${INCLUDEDIRS} ${LIBDIRS} ${LIBS}
|
||||
|
||||
|
||||
clean :
|
||||
rm -f test-empty
|
||||
@@ -1,170 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2004-2006 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 "soci.h"
|
||||
#include "soci-empty.h"
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
|
||||
using namespace soci;
|
||||
|
||||
std::string connectString;
|
||||
backend_factory const &backEnd = *soci::factory_empty();
|
||||
|
||||
|
||||
// NOTE:
|
||||
// This file is supposed to serve two purposes:
|
||||
// 1. To be a starting point for implementing new tests (for new backends).
|
||||
// 2. To exercise (at least some of) the syntax and try the SOCI library
|
||||
// against different compilers, even in those environments where there
|
||||
// is no database. SOCI uses advanced template techniques which are known
|
||||
// to cause problems on different versions of popular compilers, and this
|
||||
// test is handy to verify that the code is accepted by as many compilers
|
||||
// as possible.
|
||||
//
|
||||
// Both of these purposes mean that the actual code here is meaningless
|
||||
// from the database-development point of view. For new tests, you may wish
|
||||
// to remove this code and keep only the general structure of this file.
|
||||
|
||||
struct Person
|
||||
{
|
||||
int id;
|
||||
std::string firstName;
|
||||
std::string lastName;
|
||||
};
|
||||
|
||||
namespace soci
|
||||
{
|
||||
template<> struct type_conversion<Person>
|
||||
{
|
||||
typedef values base_type;
|
||||
static void from_base(values & /* r */, indicator /* ind */,
|
||||
Person & /* p */)
|
||||
{
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void test1()
|
||||
{
|
||||
{
|
||||
session sql(backEnd, connectString);
|
||||
|
||||
sql << "Do what I want.";
|
||||
sql << "Do what I want " << 123 << " times.";
|
||||
|
||||
std::string query = "some query";
|
||||
sql << query;
|
||||
|
||||
int i = 7;
|
||||
sql << "insert", use(i);
|
||||
sql << "select", into(i);
|
||||
|
||||
#if defined (__LP64__) || ( __WORDSIZE == 64 )
|
||||
long int li = 9;
|
||||
sql << "insert", use(li);
|
||||
sql << "select", into(li);
|
||||
#endif
|
||||
|
||||
long long ll = 11;
|
||||
sql << "insert", use(ll);
|
||||
sql << "select", into(ll);
|
||||
|
||||
indicator ind = i_ok;
|
||||
sql << "insert", use(i, ind);
|
||||
sql << "select", into(i, ind);
|
||||
|
||||
std::vector<int> numbers(100);
|
||||
sql << "insert", use(numbers);
|
||||
sql << "select", into(numbers);
|
||||
|
||||
std::vector<indicator> inds(100);
|
||||
sql << "insert", use(numbers, inds);
|
||||
sql << "select", into(numbers, inds);
|
||||
|
||||
{
|
||||
statement st = (sql.prepare << "select", into(i));
|
||||
st.execute();
|
||||
st.fetch();
|
||||
}
|
||||
{
|
||||
statement st = (sql.prepare << "select", into(i, ind));
|
||||
}
|
||||
{
|
||||
statement st = (sql.prepare << "select", into(numbers));
|
||||
}
|
||||
{
|
||||
statement st = (sql.prepare << "select", into(numbers, inds));
|
||||
}
|
||||
{
|
||||
statement st = (sql.prepare << "insert", use(i));
|
||||
}
|
||||
{
|
||||
statement st = (sql.prepare << "insert", use(i, ind));
|
||||
}
|
||||
{
|
||||
statement st = (sql.prepare << "insert", use(numbers));
|
||||
}
|
||||
{
|
||||
statement st = (sql.prepare << "insert", use(numbers, inds));
|
||||
}
|
||||
{
|
||||
Person p;
|
||||
sql << "select person", into(p);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
std::cout << "test 1 passed" << std::endl;
|
||||
}
|
||||
|
||||
|
||||
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 asser()-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];
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "usage: " << argv[0]
|
||||
<< " connectstring\n"
|
||||
<< "example: " << argv[0]
|
||||
<< " \'connect_string_for_empty_backend\'\n";
|
||||
std::exit(1);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
test1();
|
||||
// test2();
|
||||
// ...
|
||||
|
||||
std::cout << "\nOK, all tests passed.\n\n";
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
catch (std::exception const & e)
|
||||
{
|
||||
std::cout << e.what() << '\n';
|
||||
}
|
||||
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
@@ -6,11 +6,7 @@
|
||||
//
|
||||
|
||||
#define SOCI_EMPTY_SOURCE
|
||||
#include "soci-empty.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4355)
|
||||
#endif
|
||||
#include "soci/empty/soci-empty.h"
|
||||
|
||||
using namespace soci;
|
||||
using namespace soci::details;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
//
|
||||
|
||||
#define SOCI_EMPTY_SOURCE
|
||||
#include "soci-empty.h"
|
||||
#include "soci/empty/soci-empty.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4355)
|
||||
|
||||
@@ -11,9 +11,6 @@
|
||||
|
||||
soci_backend(Firebird
|
||||
DEPENDS Firebird
|
||||
HEADERS soci-firebird.h common.h
|
||||
DESCRIPTION "SOCI backend for Firebird database engine"
|
||||
DESCRIPTION "SOCI backend for Firebird"
|
||||
AUTHORS "Rafał Bobrowski"
|
||||
MAINTAINERS "Viacheslav Naydenov")
|
||||
|
||||
add_subdirectory(test)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# The following variable is specific to this backend and its correct
|
||||
# values might depend on your environment - feel free to set it accordingly.
|
||||
|
||||
FIREBIRDINCLUDEDIR = -I/usr/local/firebird/include
|
||||
FIREBIRDINCLUDEDIR = -I/usr/local/firebird/include
|
||||
|
||||
# The rest of the Makefile is indepentent of the target environment.
|
||||
|
||||
@@ -24,9 +24,9 @@ libsoci_firebird.a : ${OBJECTS}
|
||||
ar rv $@ $?
|
||||
rm *.o
|
||||
|
||||
soci-firebird.o : soci-firebird.cpp
|
||||
soci-firebird.o : soci-firebird.cpp
|
||||
${COMPILER} -c $? ${CXXFLAGS} ${INCLUDEDIRS}
|
||||
|
||||
|
||||
blob.o : blob.cpp
|
||||
${COMPILER} -c $? ${CXXFLAGS} ${INCLUDEDIRS}
|
||||
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
//
|
||||
|
||||
#define SOCI_FIREBIRD_SOURCE
|
||||
#include "soci-firebird.h"
|
||||
#include "error-firebird.h"
|
||||
#include "soci/firebird/soci-firebird.h"
|
||||
#include "firebird/error-firebird.h"
|
||||
|
||||
using namespace soci;
|
||||
using namespace soci::details::firebird;
|
||||
@@ -139,8 +139,8 @@ void firebird_blob_backend::open()
|
||||
|
||||
ISC_STATUS stat[20];
|
||||
|
||||
if (isc_open_blob2(stat, &session_.dbhp_, &session_.trhp_, &bhp_,
|
||||
&bid_, 0, NULL))
|
||||
if (isc_open_blob2(stat, &session_.dbhp_, session_.current_transaction(),
|
||||
&bhp_, &bid_, 0, NULL))
|
||||
{
|
||||
bhp_ = 0L;
|
||||
throw_iscerror(stat);
|
||||
@@ -238,7 +238,7 @@ void firebird_blob_backend::save()
|
||||
}
|
||||
|
||||
// create new blob
|
||||
if (isc_create_blob(stat, &session_.dbhp_, &session_.trhp_,
|
||||
if (isc_create_blob(stat, &session_.dbhp_, session_.current_transaction(),
|
||||
&bhp_, &bid_))
|
||||
{
|
||||
throw_iscerror(stat);
|
||||
|
||||
@@ -5,8 +5,9 @@
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#include "common.h"
|
||||
#include <soci-backend.h>
|
||||
#include "soci/soci-platform.h"
|
||||
#include "firebird/common.h"
|
||||
#include "soci/soci-backend.h"
|
||||
#include <ibase.h> // FireBird
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
@@ -90,44 +91,49 @@ void tmDecode(short type, void * src, std::tm * dst)
|
||||
void setTextParam(char const * s, std::size_t size, char * buf_,
|
||||
XSQLVAR * var)
|
||||
{
|
||||
//std::cerr << "setTextParam: var->sqltype=" << var->sqltype << std::endl;
|
||||
short sz = 0;
|
||||
if (size < static_cast<std::size_t>(var->sqllen))
|
||||
{
|
||||
sz = static_cast<short>(size);
|
||||
}
|
||||
else
|
||||
{
|
||||
sz = var->sqllen;
|
||||
}
|
||||
int const sqltype = var->sqltype & ~1;
|
||||
|
||||
if ((var->sqltype & ~1) == SQL_VARYING)
|
||||
if (sqltype == SQL_VARYING || sqltype == SQL_TEXT)
|
||||
{
|
||||
std::memcpy(buf_, &sz, sizeof(short));
|
||||
std::memcpy(buf_ + sizeof(short), s, sz);
|
||||
}
|
||||
else if ((var->sqltype & ~1) == SQL_TEXT)
|
||||
{
|
||||
std::memcpy(buf_, s, sz);
|
||||
if (sz < var->sqllen)
|
||||
if (size > static_cast<std::size_t>(var->sqllen))
|
||||
{
|
||||
std::memset(buf_+sz, ' ', var->sqllen - sz);
|
||||
std::ostringstream msg;
|
||||
msg << "Value \"" << s << "\" is too long ("
|
||||
<< size << " bytes) to be stored in column of size "
|
||||
<< var->sqllen << " bytes";
|
||||
throw soci_error(msg.str());
|
||||
}
|
||||
|
||||
short const sz = static_cast<short>(size);
|
||||
|
||||
if (sqltype == SQL_VARYING)
|
||||
{
|
||||
std::memcpy(buf_, &sz, sizeof(short));
|
||||
std::memcpy(buf_ + sizeof(short), s, sz);
|
||||
}
|
||||
else // sqltype == SQL_TEXT
|
||||
{
|
||||
std::memcpy(buf_, s, sz);
|
||||
if (sz < var->sqllen)
|
||||
{
|
||||
std::memset(buf_+sz, ' ', var->sqllen - sz);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ((var->sqltype & ~1) == SQL_SHORT)
|
||||
else if (sqltype == SQL_SHORT)
|
||||
{
|
||||
parse_decimal<short, unsigned short>(buf_, var, s);
|
||||
}
|
||||
else if ((var->sqltype & ~1) == SQL_LONG)
|
||||
else if (sqltype == SQL_LONG)
|
||||
{
|
||||
parse_decimal<int, unsigned int>(buf_, var, s);
|
||||
}
|
||||
else if ((var->sqltype & ~1) == SQL_INT64)
|
||||
else if (sqltype == SQL_INT64)
|
||||
{
|
||||
parse_decimal<long long, unsigned long long>(buf_, var, s);
|
||||
}
|
||||
else if ((var->sqltype & ~1) == SQL_TIMESTAMP
|
||||
|| (var->sqltype & ~1) == SQL_TYPE_DATE)
|
||||
else if (sqltype == SQL_TIMESTAMP
|
||||
|| sqltype == SQL_TYPE_DATE)
|
||||
{
|
||||
unsigned short year, month, day, hour, min, sec;
|
||||
if (std::sscanf(s, "%hu-%hu-%hu %hu:%hu:%hu",
|
||||
@@ -154,7 +160,7 @@ void setTextParam(char const * s, std::size_t size, char * buf_,
|
||||
std::memcpy(buf_, &t, sizeof(t));
|
||||
tmEncode(var->sqltype, &t, buf_);
|
||||
}
|
||||
else if ((var->sqltype & ~1) == SQL_TYPE_TIME)
|
||||
else if (sqltype == SQL_TYPE_TIME)
|
||||
{
|
||||
unsigned short hour, min, sec;
|
||||
if (std::sscanf(s, "%hu:%hu:%hu", &hour, &min, &sec) != 3)
|
||||
|
||||
@@ -1,236 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton, Rafal Bobrowski
|
||||
// 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)
|
||||
//
|
||||
|
||||
#ifndef SOCI_FIREBIRD_COMMON_H_INCLUDED
|
||||
#define SOCI_FIREBIRD_COMMON_H_INCLUDED
|
||||
|
||||
#include "soci-firebird.h"
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <ctime>
|
||||
#include <limits>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
namespace soci
|
||||
{
|
||||
|
||||
namespace details
|
||||
{
|
||||
|
||||
namespace firebird
|
||||
{
|
||||
|
||||
char * allocBuffer(XSQLVAR* var);
|
||||
|
||||
void tmEncode(short type, std::tm * src, void * dst);
|
||||
|
||||
void tmDecode(short type, void * src, std::tm * dst);
|
||||
|
||||
void setTextParam(char const * s, std::size_t size, char * buf_,
|
||||
XSQLVAR * var);
|
||||
|
||||
std::string getTextParam(XSQLVAR const *var);
|
||||
|
||||
template <typename IntType>
|
||||
const char *str2dec(const char * s, IntType &out, int &scale)
|
||||
{
|
||||
int sign = 1;
|
||||
if ('+' == *s)
|
||||
++s;
|
||||
else if ('-' == *s)
|
||||
{
|
||||
sign = -1;
|
||||
++s;
|
||||
}
|
||||
scale = 0;
|
||||
bool period = false;
|
||||
IntType res = 0;
|
||||
for (out = 0; *s; ++s, out = res)
|
||||
{
|
||||
if (*s == '.')
|
||||
{
|
||||
if (period)
|
||||
return s;
|
||||
period = true;
|
||||
continue;
|
||||
}
|
||||
int d = *s - '0';
|
||||
if (d < 0 || d > 9)
|
||||
return s;
|
||||
res = res * 10 + d * sign;
|
||||
if (1 == sign)
|
||||
{
|
||||
if (res < out)
|
||||
return s;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (res > out)
|
||||
return s;
|
||||
}
|
||||
if (period)
|
||||
++scale;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
template<typename T1>
|
||||
void to_isc(void * val, XSQLVAR * var, int x_scale = 0)
|
||||
{
|
||||
T1 value = *reinterpret_cast<T1*>(val);
|
||||
short scale = var->sqlscale + x_scale;
|
||||
short type = var->sqltype & ~1;
|
||||
long long divisor = 1, multiplier = 1;
|
||||
|
||||
if ((std::numeric_limits<T1>::is_integer == false) && scale >= 0 &&
|
||||
(type == SQL_SHORT || type == SQL_LONG || type == SQL_INT64))
|
||||
{
|
||||
throw soci_error("Can't convert non-integral value to integral column type");
|
||||
}
|
||||
|
||||
for (int i = 0; i > scale; --i)
|
||||
multiplier *= 10;
|
||||
for (int i = 0; i < scale; ++i)
|
||||
divisor *= 10;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case SQL_SHORT:
|
||||
{
|
||||
short tmp = static_cast<short>(value*multiplier/divisor);
|
||||
std::memcpy(var->sqldata, &tmp, sizeof(short));
|
||||
}
|
||||
break;
|
||||
case SQL_LONG:
|
||||
{
|
||||
int tmp = static_cast<int>(value*multiplier/divisor);
|
||||
std::memcpy(var->sqldata, &tmp, sizeof(int));
|
||||
}
|
||||
break;
|
||||
case SQL_INT64:
|
||||
{
|
||||
long long tmp = static_cast<long long>(value*multiplier/divisor);
|
||||
std::memcpy(var->sqldata, &tmp, sizeof(long long));
|
||||
}
|
||||
break;
|
||||
case SQL_FLOAT:
|
||||
{
|
||||
float sql_value = static_cast<float>(value);
|
||||
std::memcpy(var->sqldata, &sql_value, sizeof(float));
|
||||
}
|
||||
break;
|
||||
case SQL_DOUBLE:
|
||||
{
|
||||
double sql_value = static_cast<double>(value);
|
||||
std::memcpy(var->sqldata, &sql_value, sizeof(double));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw soci_error("Incorrect data type for numeric conversion");
|
||||
}
|
||||
}
|
||||
|
||||
template<typename IntType, typename UIntType>
|
||||
void parse_decimal(void * val, XSQLVAR * var, const char * s)
|
||||
{
|
||||
int scale;
|
||||
UIntType t1;
|
||||
IntType t2;
|
||||
if (!*str2dec(s, t1, scale))
|
||||
std::memcpy(val, &t1, sizeof(t1));
|
||||
else if (!*str2dec(s, t2, scale))
|
||||
std::memcpy(val, &t2, sizeof(t2));
|
||||
else
|
||||
throw soci_error("Could not parse decimal value.");
|
||||
to_isc<IntType>(val, var, scale);
|
||||
}
|
||||
|
||||
template<typename IntType>
|
||||
std::string format_decimal(const void *sqldata, int sqlscale)
|
||||
{
|
||||
IntType x = *reinterpret_cast<const IntType *>(sqldata);
|
||||
std::stringstream out;
|
||||
out << x;
|
||||
std::string r = out.str();
|
||||
if (sqlscale < 0)
|
||||
{
|
||||
if (static_cast<int>(r.size()) - (x < 0) <= -sqlscale)
|
||||
{
|
||||
r = std::string(size_t(x < 0), '-') +
|
||||
std::string(-sqlscale - (r.size() - (x < 0)) + 1, '0') +
|
||||
r.substr(size_t(x < 0), std::string::npos);
|
||||
}
|
||||
return r.substr(0, r.size() + sqlscale) + '.' +
|
||||
r.substr(r.size() + sqlscale, std::string::npos);
|
||||
}
|
||||
return r + std::string(sqlscale, '0');
|
||||
}
|
||||
|
||||
template<typename T1>
|
||||
T1 from_isc(XSQLVAR * var)
|
||||
{
|
||||
short scale = var->sqlscale;
|
||||
T1 tens = 1;
|
||||
|
||||
if (scale < 0)
|
||||
{
|
||||
if (std::numeric_limits<T1>::is_integer)
|
||||
{
|
||||
std::ostringstream msg;
|
||||
msg << "Can't convert value with scale " << -scale
|
||||
<< " to integral type";
|
||||
throw soci_error(msg.str());
|
||||
}
|
||||
|
||||
for (int i = 0; i > scale; --i)
|
||||
{
|
||||
tens *= 10;
|
||||
}
|
||||
}
|
||||
|
||||
switch (var->sqltype & ~1)
|
||||
{
|
||||
case SQL_SHORT:
|
||||
return static_cast<T1>(*reinterpret_cast<short*>(var->sqldata)/tens);
|
||||
case SQL_LONG:
|
||||
return static_cast<T1>(*reinterpret_cast<int*>(var->sqldata)/tens);
|
||||
case SQL_INT64:
|
||||
return static_cast<T1>(*reinterpret_cast<long long*>(var->sqldata)/tens);
|
||||
case SQL_FLOAT:
|
||||
return static_cast<T1>(*reinterpret_cast<float*>(var->sqldata));
|
||||
case SQL_DOUBLE:
|
||||
return static_cast<T1>(*reinterpret_cast<double*>(var->sqldata));
|
||||
default:
|
||||
throw soci_error("Incorrect data type for numeric conversion");
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::size_t getVectorSize(void *p)
|
||||
{
|
||||
std::vector<T> *v = static_cast<std::vector<T> *>(p);
|
||||
return v->size();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void resizeVector(void *p, std::size_t sz)
|
||||
{
|
||||
std::vector<T> *v = static_cast<std::vector<T> *>(p);
|
||||
v->resize(sz);
|
||||
}
|
||||
|
||||
} // namespace firebird
|
||||
|
||||
} // namespace details
|
||||
|
||||
} // namespace soci
|
||||
|
||||
#endif // SOCI_FIREBIRD_COMMON_H_INCLUDED
|
||||
@@ -6,8 +6,8 @@
|
||||
//
|
||||
|
||||
#define SOCI_FIREBIRD_SOURCE
|
||||
#include "soci-firebird.h"
|
||||
#include "error-firebird.h"
|
||||
#include "soci/firebird/soci-firebird.h"
|
||||
#include "firebird/error-firebird.h"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton, Rafal Bobrowski
|
||||
// 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)
|
||||
//
|
||||
|
||||
#ifndef SOCI_FIREBIRD_ERROR_H_INCLUDED
|
||||
#define SOCI_FIREBIRD_ERROR_H_INCLUDED
|
||||
|
||||
#include "soci-firebird.h"
|
||||
#include <string>
|
||||
|
||||
namespace soci
|
||||
{
|
||||
|
||||
namespace details
|
||||
{
|
||||
|
||||
namespace firebird
|
||||
{
|
||||
|
||||
void SOCI_FIREBIRD_DECL get_iscerror_details(ISC_STATUS * status_vector, std::string &msg);
|
||||
|
||||
bool SOCI_FIREBIRD_DECL check_iscerror(ISC_STATUS const * status_vector, long errNum);
|
||||
|
||||
void SOCI_FIREBIRD_DECL throw_iscerror(ISC_STATUS * status_vector);
|
||||
|
||||
} // namespace firebird
|
||||
|
||||
} // namespace details
|
||||
|
||||
} // namespace soci
|
||||
|
||||
#endif // SOCI_FIREBIRD_ERROR_H_INCLUDED
|
||||
@@ -6,8 +6,8 @@
|
||||
//
|
||||
|
||||
#define SOCI_FIREBIRD_SOURCE
|
||||
#include "soci-firebird.h"
|
||||
#include <backend-loader.h>
|
||||
#include "soci/firebird/soci-firebird.h"
|
||||
#include "soci/backend-loader.h"
|
||||
|
||||
using namespace soci;
|
||||
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton, Rafal Bobrowski
|
||||
// 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)
|
||||
//
|
||||
|
||||
#define SOCI_FIREBIRD_SOURCE
|
||||
#include "soci-firebird.h"
|
||||
|
||||
using namespace soci;
|
||||
|
||||
firebird_rowid_backend::firebird_rowid_backend(firebird_session_backend & /* session */)
|
||||
{
|
||||
// Unsupported in Firebird backend
|
||||
throw soci_error("RowIDs are not supported");
|
||||
}
|
||||
|
||||
firebird_rowid_backend::~firebird_rowid_backend()
|
||||
{
|
||||
}
|
||||
@@ -6,9 +6,9 @@
|
||||
//
|
||||
|
||||
#define SOCI_FIREBIRD_SOURCE
|
||||
#include "soci-firebird.h"
|
||||
#include "error-firebird.h"
|
||||
#include "session.h"
|
||||
#include "soci/firebird/soci-firebird.h"
|
||||
#include "firebird/error-firebird.h"
|
||||
#include "soci/session.h"
|
||||
#include <locale>
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
@@ -196,6 +196,20 @@ bool getISCConnectParameter(std::map<std::string, std::string> const & m, std::s
|
||||
}
|
||||
}
|
||||
|
||||
void setDPBOption(std::string& dpb, int const option, std::string const & value)
|
||||
{
|
||||
|
||||
if (dpb.empty())
|
||||
{
|
||||
dpb.append(1, static_cast<char>(isc_dpb_version1));
|
||||
}
|
||||
|
||||
// now we are adding new option
|
||||
dpb.append(1, static_cast<char>(option));
|
||||
dpb.append(1, static_cast<char>(value.size()));
|
||||
dpb.append(value);
|
||||
}
|
||||
|
||||
} // namespace anonymous
|
||||
|
||||
firebird_session_backend::firebird_session_backend(
|
||||
@@ -210,24 +224,25 @@ firebird_session_backend::firebird_session_backend(
|
||||
std::string param;
|
||||
|
||||
// preparing connection options
|
||||
std::string dpb;
|
||||
if (getISCConnectParameter(params, "user", param))
|
||||
{
|
||||
setDPBOption(isc_dpb_user_name, param);
|
||||
setDPBOption(dpb, isc_dpb_user_name, param);
|
||||
}
|
||||
|
||||
if (getISCConnectParameter(params, "password", param))
|
||||
{
|
||||
setDPBOption(isc_dpb_password, param);
|
||||
setDPBOption(dpb, isc_dpb_password, param);
|
||||
}
|
||||
|
||||
if (getISCConnectParameter(params, "role", param))
|
||||
{
|
||||
setDPBOption(isc_dpb_sql_role_name, param);
|
||||
setDPBOption(dpb, isc_dpb_sql_role_name, param);
|
||||
}
|
||||
|
||||
if (getISCConnectParameter(params, "charset", param))
|
||||
{
|
||||
setDPBOption(isc_dpb_lc_ctype, param);
|
||||
setDPBOption(dpb, isc_dpb_lc_ctype, param);
|
||||
}
|
||||
|
||||
if (getISCConnectParameter(params, "service", param) == false)
|
||||
@@ -238,7 +253,7 @@ firebird_session_backend::firebird_session_backend(
|
||||
// connecting data base
|
||||
if (isc_attach_database(stat, static_cast<short>(param.size()),
|
||||
const_cast<char*>(param.c_str()), &dbhp_,
|
||||
static_cast<short>(dpb_.size()), const_cast<char*>(dpb_.c_str())))
|
||||
static_cast<short>(dpb.size()), const_cast<char*>(dpb.c_str())))
|
||||
{
|
||||
throw_iscerror(stat);
|
||||
}
|
||||
@@ -247,16 +262,11 @@ firebird_session_backend::firebird_session_backend(
|
||||
{
|
||||
decimals_as_strings_ = param == "1" || param == "Y" || param == "y";
|
||||
}
|
||||
// starting transaction
|
||||
begin();
|
||||
}
|
||||
|
||||
|
||||
void firebird_session_backend::begin()
|
||||
{
|
||||
// Transaction is always started in ctor, because Firebird can't work
|
||||
// without active transaction.
|
||||
// Transaction will be automatically commited in cleanUp method.
|
||||
if (trhp_ == 0)
|
||||
{
|
||||
ISC_STATUS stat[stat_size];
|
||||
@@ -272,20 +282,6 @@ firebird_session_backend::~firebird_session_backend()
|
||||
cleanUp();
|
||||
}
|
||||
|
||||
void firebird_session_backend::setDPBOption(int const option, std::string const & value)
|
||||
{
|
||||
|
||||
if (dpb_.size() == 0)
|
||||
{
|
||||
dpb_.append(1, static_cast<char>(isc_dpb_version1));
|
||||
}
|
||||
|
||||
// now we are adding new option
|
||||
dpb_.append(1, static_cast<char>(option));
|
||||
dpb_.append(1, static_cast<char>(value.size()));
|
||||
dpb_.append(value);
|
||||
}
|
||||
|
||||
void firebird_session_backend::commit()
|
||||
{
|
||||
ISC_STATUS stat[stat_size];
|
||||
@@ -299,11 +295,6 @@ void firebird_session_backend::commit()
|
||||
|
||||
trhp_ = 0;
|
||||
}
|
||||
|
||||
#ifndef SOCI_FIREBIRD_NORESTARTTRANSACTION
|
||||
begin();
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void firebird_session_backend::rollback()
|
||||
@@ -319,11 +310,14 @@ void firebird_session_backend::rollback()
|
||||
|
||||
trhp_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef SOCI_FIREBIRD_NORESTARTTRANSACTION
|
||||
isc_tr_handle* firebird_session_backend::current_transaction()
|
||||
{
|
||||
// It will do nothing if we're already inside a transaction.
|
||||
begin();
|
||||
#endif
|
||||
|
||||
return &trhp_;
|
||||
}
|
||||
|
||||
void firebird_session_backend::cleanUp()
|
||||
@@ -364,9 +358,9 @@ firebird_statement_backend * firebird_session_backend::make_statement_backend()
|
||||
return new firebird_statement_backend(*this);
|
||||
}
|
||||
|
||||
firebird_rowid_backend * firebird_session_backend::make_rowid_backend()
|
||||
details::rowid_backend* firebird_session_backend::make_rowid_backend()
|
||||
{
|
||||
return new firebird_rowid_backend(*this);
|
||||
throw soci_error("RowIDs are not supported");
|
||||
}
|
||||
|
||||
firebird_blob_backend * firebird_session_backend::make_blob_backend()
|
||||
|
||||
@@ -1,349 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton, Rafal Bobrowski
|
||||
// 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)
|
||||
//
|
||||
//
|
||||
|
||||
#ifndef SOCI_FIREBIRD_H_INCLUDED
|
||||
#define SOCI_FIREBIRD_H_INCLUDED
|
||||
|
||||
#ifdef _WIN32
|
||||
# ifdef SOCI_DLL
|
||||
# ifdef SOCI_FIREBIRD_SOURCE
|
||||
# define SOCI_FIREBIRD_DECL __declspec(dllexport)
|
||||
# else
|
||||
# define SOCI_FIREBIRD_DECL __declspec(dllimport)
|
||||
# endif // SOCI_DLL
|
||||
# endif // SOCI_FIREBIRD_SOURCE
|
||||
#endif // _WIN32
|
||||
|
||||
//
|
||||
// If SOCI_FIREBIRD_DECL isn't defined yet define it now
|
||||
#ifndef SOCI_FIREBIRD_DECL
|
||||
# define SOCI_FIREBIRD_DECL
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <ciso646> // To understand and/or/not on MSVC9
|
||||
#endif
|
||||
#include <soci-backend.h>
|
||||
#include <ibase.h> // FireBird
|
||||
#include <cstdlib>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
namespace soci
|
||||
{
|
||||
|
||||
std::size_t const stat_size = 20;
|
||||
|
||||
// size of buffer for error messages. All examples use this value.
|
||||
// Anyone knows, where it is stated that 512 bytes is enough ?
|
||||
std::size_t const SOCI_FIREBIRD_ERRMSG = 512;
|
||||
|
||||
class SOCI_FIREBIRD_DECL firebird_soci_error : public soci_error
|
||||
{
|
||||
public:
|
||||
firebird_soci_error(std::string const & msg,
|
||||
ISC_STATUS const * status = 0);
|
||||
|
||||
~firebird_soci_error() throw() {};
|
||||
|
||||
std::vector<ISC_STATUS> status_;
|
||||
};
|
||||
|
||||
enum BuffersType
|
||||
{
|
||||
eStandard, eVector
|
||||
};
|
||||
|
||||
struct firebird_statement_backend;
|
||||
struct firebird_standard_into_type_backend : details::standard_into_type_backend
|
||||
{
|
||||
firebird_standard_into_type_backend(firebird_statement_backend &st)
|
||||
: statement_(st), buf_(NULL)
|
||||
{}
|
||||
|
||||
virtual void define_by_pos(int &position,
|
||||
void *data, details::exchange_type type);
|
||||
|
||||
virtual void pre_fetch();
|
||||
virtual void post_fetch(bool gotData, bool calledFromFetch,
|
||||
indicator *ind);
|
||||
|
||||
virtual void clean_up();
|
||||
|
||||
firebird_statement_backend &statement_;
|
||||
virtual void exchangeData();
|
||||
|
||||
void *data_;
|
||||
details::exchange_type type_;
|
||||
int position_;
|
||||
|
||||
char *buf_;
|
||||
short indISCHolder_;
|
||||
};
|
||||
|
||||
struct firebird_vector_into_type_backend : details::vector_into_type_backend
|
||||
{
|
||||
firebird_vector_into_type_backend(firebird_statement_backend &st)
|
||||
: statement_(st), buf_(NULL)
|
||||
{}
|
||||
|
||||
virtual void define_by_pos(int &position,
|
||||
void *data, details::exchange_type type);
|
||||
|
||||
virtual void pre_fetch();
|
||||
virtual void post_fetch(bool gotData, indicator *ind);
|
||||
|
||||
virtual void resize(std::size_t sz);
|
||||
virtual std::size_t size();
|
||||
|
||||
virtual void clean_up();
|
||||
|
||||
firebird_statement_backend &statement_;
|
||||
virtual void exchangeData(std::size_t row);
|
||||
|
||||
void *data_;
|
||||
details::exchange_type type_;
|
||||
int position_;
|
||||
|
||||
char *buf_;
|
||||
short indISCHolder_;
|
||||
};
|
||||
|
||||
struct firebird_standard_use_type_backend : details::standard_use_type_backend
|
||||
{
|
||||
firebird_standard_use_type_backend(firebird_statement_backend &st)
|
||||
: statement_(st), buf_(NULL), indISCHolder_(0)
|
||||
{}
|
||||
|
||||
virtual void bind_by_pos(int &position,
|
||||
void *data, details::exchange_type type, bool readOnly);
|
||||
virtual void bind_by_name(std::string const &name,
|
||||
void *data, details::exchange_type type, bool readOnly);
|
||||
|
||||
virtual void pre_use(indicator const *ind);
|
||||
virtual void post_use(bool gotData, indicator *ind);
|
||||
|
||||
virtual void clean_up();
|
||||
|
||||
firebird_statement_backend &statement_;
|
||||
virtual void exchangeData();
|
||||
|
||||
void *data_;
|
||||
details::exchange_type type_;
|
||||
int position_;
|
||||
|
||||
char *buf_;
|
||||
short indISCHolder_;
|
||||
};
|
||||
|
||||
struct firebird_vector_use_type_backend : details::vector_use_type_backend
|
||||
{
|
||||
firebird_vector_use_type_backend(firebird_statement_backend &st)
|
||||
: statement_(st), inds_(NULL), buf_(NULL), indISCHolder_(0)
|
||||
{}
|
||||
|
||||
virtual void bind_by_pos(int &position,
|
||||
void *data, details::exchange_type type);
|
||||
virtual void bind_by_name(std::string const &name,
|
||||
void *data, details::exchange_type type);
|
||||
|
||||
virtual void pre_use(indicator const *ind);
|
||||
|
||||
virtual std::size_t size();
|
||||
|
||||
virtual void clean_up();
|
||||
|
||||
firebird_statement_backend &statement_;
|
||||
virtual void exchangeData(std::size_t row);
|
||||
|
||||
void *data_;
|
||||
details::exchange_type type_;
|
||||
int position_;
|
||||
indicator const *inds_;
|
||||
|
||||
char *buf_;
|
||||
short indISCHolder_;
|
||||
};
|
||||
|
||||
struct firebird_session_backend;
|
||||
struct firebird_statement_backend : details::statement_backend
|
||||
{
|
||||
firebird_statement_backend(firebird_session_backend &session);
|
||||
|
||||
virtual void alloc();
|
||||
virtual void clean_up();
|
||||
virtual void prepare(std::string const &query,
|
||||
details::statement_type eType);
|
||||
|
||||
virtual exec_fetch_result execute(int number);
|
||||
virtual exec_fetch_result fetch(int number);
|
||||
|
||||
virtual long long get_affected_rows();
|
||||
virtual int get_number_of_rows();
|
||||
|
||||
virtual std::string rewrite_for_procedure_call(std::string const &query);
|
||||
|
||||
virtual int prepare_for_describe();
|
||||
virtual void describe_column(int colNum, data_type &dtype,
|
||||
std::string &columnName);
|
||||
|
||||
virtual firebird_standard_into_type_backend * make_into_type_backend();
|
||||
virtual firebird_standard_use_type_backend * make_use_type_backend();
|
||||
virtual firebird_vector_into_type_backend * make_vector_into_type_backend();
|
||||
virtual firebird_vector_use_type_backend * make_vector_use_type_backend();
|
||||
|
||||
firebird_session_backend &session_;
|
||||
|
||||
isc_stmt_handle stmtp_;
|
||||
XSQLDA * sqldap_;
|
||||
XSQLDA * sqlda2p_;
|
||||
|
||||
bool boundByName_;
|
||||
bool boundByPos_;
|
||||
|
||||
friend struct firebird_vector_into_type_backend;
|
||||
friend struct firebird_standard_into_type_backend;
|
||||
friend struct firebird_vector_use_type_backend;
|
||||
friend struct firebird_standard_use_type_backend;
|
||||
|
||||
protected:
|
||||
int rowsFetched_;
|
||||
bool endOfRowSet_;
|
||||
|
||||
long long rowsAffectedBulk_; // number of rows affected by the last bulk operation
|
||||
|
||||
virtual void exchangeData(bool gotData, int row);
|
||||
virtual void prepareSQLDA(XSQLDA ** sqldap, int size = 10);
|
||||
virtual void rewriteQuery(std::string const & query,
|
||||
std::vector<char> & buffer);
|
||||
virtual void rewriteParameters(std::string const & src,
|
||||
std::vector<char> & dst);
|
||||
|
||||
BuffersType intoType_;
|
||||
BuffersType useType_;
|
||||
|
||||
std::vector<std::vector<indicator> > inds_;
|
||||
std::vector<void*> intos_;
|
||||
std::vector<void*> uses_;
|
||||
|
||||
// named parameters
|
||||
std::map <std::string, int> names_;
|
||||
|
||||
bool procedure_;
|
||||
};
|
||||
|
||||
struct firebird_rowid_backend : details::rowid_backend
|
||||
{
|
||||
firebird_rowid_backend(firebird_session_backend &session);
|
||||
|
||||
~firebird_rowid_backend();
|
||||
};
|
||||
|
||||
struct firebird_blob_backend : details::blob_backend
|
||||
{
|
||||
firebird_blob_backend(firebird_session_backend &session);
|
||||
|
||||
~firebird_blob_backend();
|
||||
|
||||
virtual std::size_t get_len();
|
||||
virtual std::size_t read(std::size_t offset, char *buf,
|
||||
std::size_t toRead);
|
||||
virtual std::size_t write(std::size_t offset, char const *buf,
|
||||
std::size_t toWrite);
|
||||
virtual std::size_t append(char const *buf, std::size_t toWrite);
|
||||
virtual void trim(std::size_t newLen);
|
||||
|
||||
firebird_session_backend &session_;
|
||||
|
||||
virtual void save();
|
||||
virtual void assign(ISC_QUAD const & bid)
|
||||
{
|
||||
cleanUp();
|
||||
|
||||
bid_ = bid;
|
||||
from_db_ = true;
|
||||
}
|
||||
|
||||
// BLOB id from in database
|
||||
ISC_QUAD bid_;
|
||||
|
||||
// BLOB id was fetched from database (true)
|
||||
// or this is new BLOB
|
||||
bool from_db_;
|
||||
|
||||
// BLOB handle
|
||||
isc_blob_handle bhp_;
|
||||
|
||||
protected:
|
||||
|
||||
virtual void open();
|
||||
virtual long getBLOBInfo();
|
||||
virtual void load();
|
||||
virtual void writeBuffer(std::size_t offset, char const * buf,
|
||||
std::size_t toWrite);
|
||||
virtual void cleanUp();
|
||||
|
||||
// buffer for BLOB data
|
||||
std::vector<char> data_;
|
||||
|
||||
bool loaded_;
|
||||
long max_seg_size_;
|
||||
};
|
||||
|
||||
struct firebird_session_backend : details::session_backend
|
||||
{
|
||||
firebird_session_backend(connection_parameters const & parameters);
|
||||
|
||||
~firebird_session_backend();
|
||||
|
||||
virtual void begin();
|
||||
virtual void commit();
|
||||
virtual void rollback();
|
||||
|
||||
virtual bool get_next_sequence_value(session & s,
|
||||
std::string const & sequence, long & value);
|
||||
|
||||
virtual std::string get_backend_name() const { return "firebird"; }
|
||||
|
||||
void cleanUp();
|
||||
|
||||
virtual firebird_statement_backend * make_statement_backend();
|
||||
virtual firebird_rowid_backend * make_rowid_backend();
|
||||
virtual firebird_blob_backend * make_blob_backend();
|
||||
|
||||
virtual void setDPBOption(int const option, std::string const & value);
|
||||
|
||||
bool get_option_decimals_as_strings() { return decimals_as_strings_; }
|
||||
|
||||
isc_db_handle dbhp_;
|
||||
isc_tr_handle trhp_;
|
||||
std::string dpb_;
|
||||
bool decimals_as_strings_;
|
||||
};
|
||||
|
||||
struct firebird_backend_factory : backend_factory
|
||||
{
|
||||
firebird_backend_factory() {}
|
||||
virtual firebird_session_backend * make_session(
|
||||
connection_parameters const & parameters) const;
|
||||
};
|
||||
|
||||
extern SOCI_FIREBIRD_DECL firebird_backend_factory const firebird;
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
// for dynamic backend loading
|
||||
SOCI_FIREBIRD_DECL backend_factory const * factory_firebird();
|
||||
SOCI_FIREBIRD_DECL void register_factory_firebird();
|
||||
|
||||
} // extern "C"
|
||||
|
||||
} // namespace soci
|
||||
|
||||
#endif // SOCI_FIREBIRD_H_INCLUDED
|
||||
@@ -6,9 +6,10 @@
|
||||
//
|
||||
|
||||
#define SOCI_FIREBIRD_SOURCE
|
||||
#include "soci-firebird.h"
|
||||
#include "common.h"
|
||||
#include <soci.h>
|
||||
#include "soci/firebird/soci-firebird.h"
|
||||
#include "soci-exchange-cast.h"
|
||||
#include "firebird/common.h"
|
||||
#include "soci/soci.h"
|
||||
|
||||
using namespace soci;
|
||||
using namespace soci::details;
|
||||
@@ -70,46 +71,36 @@ void firebird_standard_into_type_backend::exchangeData()
|
||||
{
|
||||
// simple cases
|
||||
case x_char:
|
||||
*reinterpret_cast<char*>(data_) = getTextParam(var)[0];
|
||||
exchange_type_cast<x_char>(data_) = getTextParam(var)[0];
|
||||
break;
|
||||
case x_short:
|
||||
{
|
||||
short t = from_isc<short>(var);
|
||||
*reinterpret_cast<short*>(data_) = t;
|
||||
}
|
||||
exchange_type_cast<x_short>(data_) = from_isc<short>(var);
|
||||
break;
|
||||
case x_integer:
|
||||
{
|
||||
int t = from_isc<int>(var);
|
||||
*reinterpret_cast<int *>(data_) = t;
|
||||
}
|
||||
exchange_type_cast<x_integer>(data_) = from_isc<int>(var);
|
||||
break;
|
||||
case x_long_long:
|
||||
{
|
||||
long long t = from_isc<long long>(var);
|
||||
*reinterpret_cast<long long *>(data_) = t;
|
||||
}
|
||||
exchange_type_cast<x_long_long>(data_) = from_isc<long long>(var);
|
||||
break;
|
||||
case x_double:
|
||||
{
|
||||
double t = from_isc<double>(var);
|
||||
*reinterpret_cast<double*>(data_) = t;
|
||||
}
|
||||
exchange_type_cast<x_double>(data_) = from_isc<double>(var);
|
||||
break;
|
||||
|
||||
// cases that require adjustments and buffer management
|
||||
case x_stdstring:
|
||||
*(reinterpret_cast<std::string*>(data_)) = getTextParam(var);
|
||||
exchange_type_cast<x_stdstring>(data_) = getTextParam(var);
|
||||
break;
|
||||
case x_stdtm:
|
||||
tmDecode(var->sqltype,
|
||||
buf_, static_cast<std::tm*>(data_));
|
||||
{
|
||||
std::tm& t = exchange_type_cast<x_stdtm>(data_);
|
||||
tmDecode(var->sqltype, buf_, &t);
|
||||
|
||||
// isc_decode_timestamp() used by tmDecode() incorrectly sets
|
||||
// tm_isdst to 0 in the struct that it creates, see
|
||||
// http://tracker.firebirdsql.org/browse/CORE-3877, work around it
|
||||
// by pretending the DST is actually unknown.
|
||||
static_cast<std::tm*>(data_)->tm_isdst = -1;
|
||||
// isc_decode_timestamp() used by tmDecode() incorrectly sets
|
||||
// tm_isdst to 0 in the struct that it creates, see
|
||||
// http://tracker.firebirdsql.org/browse/CORE-3877, work around it
|
||||
// by pretending the DST is actually unknown.
|
||||
t.tm_isdst = -1;
|
||||
}
|
||||
break;
|
||||
|
||||
// cases that require special handling
|
||||
@@ -140,7 +131,7 @@ void firebird_standard_into_type_backend::clean_up()
|
||||
delete [] buf_;
|
||||
buf_ = NULL;
|
||||
}
|
||||
std::vector<void*>::iterator it =
|
||||
std::vector<void*>::iterator it =
|
||||
std::find(statement_.intos_.begin(), statement_.intos_.end(), this);
|
||||
if (it != statement_.intos_.end())
|
||||
statement_.intos_.erase(it);
|
||||
|
||||
@@ -6,9 +6,10 @@
|
||||
//
|
||||
|
||||
#define SOCI_FIREBIRD_SOURCE
|
||||
#include "soci-firebird.h"
|
||||
#include "common.h"
|
||||
#include <soci.h>
|
||||
#include "soci/firebird/soci-firebird.h"
|
||||
#include "soci-exchange-cast.h"
|
||||
#include "firebird/common.h"
|
||||
#include "soci/soci.h"
|
||||
|
||||
using namespace soci;
|
||||
using namespace soci::details;
|
||||
@@ -104,7 +105,7 @@ void firebird_standard_use_type_backend::exchangeData()
|
||||
switch (type_)
|
||||
{
|
||||
case x_char:
|
||||
setTextParam(static_cast<char*>(data_), 1, buf_, var);
|
||||
setTextParam(&exchange_type_cast<x_char>(data_), 1, buf_, var);
|
||||
break;
|
||||
case x_short:
|
||||
to_isc<short>(data_, var);
|
||||
@@ -121,13 +122,12 @@ void firebird_standard_use_type_backend::exchangeData()
|
||||
|
||||
case x_stdstring:
|
||||
{
|
||||
std::string *tmp = static_cast<std::string*>(data_);
|
||||
setTextParam(tmp->c_str(), tmp->size(), buf_, var);
|
||||
std::string const& tmp = exchange_type_cast<x_stdstring>(data_);
|
||||
setTextParam(tmp.c_str(), tmp.size(), buf_, var);
|
||||
}
|
||||
break;
|
||||
case x_stdtm:
|
||||
tmEncode(var->sqltype,
|
||||
static_cast<std::tm*>(data_), buf_);
|
||||
tmEncode(var->sqltype, &exchange_type_cast<x_stdtm>(data_), buf_);
|
||||
break;
|
||||
|
||||
// cases that require special handling
|
||||
@@ -175,7 +175,7 @@ void firebird_standard_use_type_backend::clean_up()
|
||||
delete [] buf_;
|
||||
buf_ = NULL;
|
||||
}
|
||||
std::vector<void*>::iterator it =
|
||||
std::vector<void*>::iterator it =
|
||||
std::find(statement_.uses_.begin(), statement_.uses_.end(), this);
|
||||
if (it != statement_.uses_.end())
|
||||
statement_.uses_.erase(it);
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
//
|
||||
|
||||
#define SOCI_FIREBIRD_SOURCE
|
||||
#include "soci-firebird.h"
|
||||
#include "error-firebird.h"
|
||||
#include "soci/firebird/soci-firebird.h"
|
||||
#include "firebird/error-firebird.h"
|
||||
#include <cctype>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
@@ -18,11 +18,11 @@ using namespace soci::details::firebird;
|
||||
|
||||
firebird_statement_backend::firebird_statement_backend(firebird_session_backend &session)
|
||||
: session_(session), stmtp_(0), sqldap_(NULL), sqlda2p_(NULL),
|
||||
boundByName_(false), boundByPos_(false), rowsFetched_(0), endOfRowSet_(false), rowsAffectedBulk_(-1LL),
|
||||
boundByName_(false), boundByPos_(false), rowsFetched_(0), endOfRowSet_(false), rowsAffectedBulk_(-1LL),
|
||||
intoType_(eStandard), useType_(eStandard), procedure_(false)
|
||||
{}
|
||||
|
||||
void firebird_statement_backend::prepareSQLDA(XSQLDA ** sqldap, int size)
|
||||
void firebird_statement_backend::prepareSQLDA(XSQLDA ** sqldap, short size)
|
||||
{
|
||||
if (*sqldap != NULL)
|
||||
{
|
||||
@@ -53,13 +53,13 @@ void firebird_statement_backend::clean_up()
|
||||
|
||||
ISC_STATUS stat[stat_size];
|
||||
|
||||
if (stmtp_ != NULL)
|
||||
if (stmtp_ != 0)
|
||||
{
|
||||
if (isc_dsql_free_statement(stat, &stmtp_, DSQL_drop))
|
||||
{
|
||||
throw_iscerror(stat);
|
||||
}
|
||||
stmtp_ = NULL;
|
||||
stmtp_ = 0;
|
||||
}
|
||||
|
||||
if (sqldap_ != NULL)
|
||||
@@ -165,7 +165,7 @@ namespace
|
||||
if (res_buffer[0] == isc_info_sql_stmt_type)
|
||||
{
|
||||
length = isc_vax_integer(res_buffer+1, 2);
|
||||
stype = isc_vax_integer(res_buffer+3, length);
|
||||
stype = isc_vax_integer(res_buffer+3, static_cast<short>(length));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -226,7 +226,7 @@ void firebird_statement_backend::rewriteQuery(
|
||||
}
|
||||
|
||||
// prepare temporary statement
|
||||
if (isc_dsql_prepare(stat, &(session_.trhp_), &tmpStmtp, 0,
|
||||
if (isc_dsql_prepare(stat, session_.current_transaction(), &tmpStmtp, 0,
|
||||
&tmpQuery[0], SQL_DIALECT_V6, sqldap_))
|
||||
{
|
||||
throw_iscerror(stat);
|
||||
@@ -302,7 +302,7 @@ void firebird_statement_backend::prepare(std::string const & query,
|
||||
ISC_STATUS stat[stat_size];
|
||||
|
||||
// prepare real statement
|
||||
if (isc_dsql_prepare(stat, &(session_.trhp_), &stmtp_, 0,
|
||||
if (isc_dsql_prepare(stat, session_.current_transaction(), &stmtp_, 0,
|
||||
&queryBuffer[0], SQL_DIALECT_V6, sqldap_))
|
||||
{
|
||||
throw_iscerror(stat);
|
||||
@@ -423,7 +423,7 @@ firebird_statement_backend::execute(int number)
|
||||
}
|
||||
|
||||
// then execute query
|
||||
if (isc_dsql_execute(stat, &session_.trhp_, &stmtp_, SQL_DIALECT_V6, t))
|
||||
if (isc_dsql_execute(stat, session_.current_transaction(), &stmtp_, SQL_DIALECT_V6, t))
|
||||
{
|
||||
// preserve the number of rows affected so far.
|
||||
rowsAffectedBulk_ = rowsAffectedBulkTemp;
|
||||
@@ -442,7 +442,7 @@ firebird_statement_backend::execute(int number)
|
||||
else
|
||||
{
|
||||
// use elements aren't vectors
|
||||
if (isc_dsql_execute(stat, &session_.trhp_, &stmtp_, SQL_DIALECT_V6, t))
|
||||
if (isc_dsql_execute(stat, session_.current_transaction(), &stmtp_, SQL_DIALECT_V6, t))
|
||||
{
|
||||
throw_iscerror(stat);
|
||||
}
|
||||
@@ -492,7 +492,8 @@ firebird_statement_backend::fetch(int number)
|
||||
rowsFetched_ = 0;
|
||||
for (int i = 0; i < number; ++i)
|
||||
{
|
||||
long fetch_stat = isc_dsql_fetch(stat, &stmtp_, SQL_DIALECT_V6, sqldap_);
|
||||
ISC_STATUS const
|
||||
fetch_stat = isc_dsql_fetch(stat, &stmtp_, SQL_DIALECT_V6, sqldap_);
|
||||
|
||||
// there is more data to read
|
||||
if (fetch_stat == 0)
|
||||
@@ -610,7 +611,7 @@ long long firebird_statement_backend::get_affected_rows()
|
||||
int len = isc_vax_integer(p, 2);
|
||||
p += 2;
|
||||
|
||||
row_count += isc_vax_integer(p, len);
|
||||
row_count += isc_vax_integer(p, static_cast<short>(len));
|
||||
p += len;
|
||||
}
|
||||
break;
|
||||
@@ -631,6 +632,19 @@ int firebird_statement_backend::get_number_of_rows()
|
||||
return rowsFetched_;
|
||||
}
|
||||
|
||||
std::string firebird_statement_backend::get_parameter_name(int index) const
|
||||
{
|
||||
for (std::map<std::string, int>::const_iterator i = names_.begin();
|
||||
i != names_.end();
|
||||
++i)
|
||||
{
|
||||
if (i->second == index)
|
||||
return i->first;
|
||||
}
|
||||
|
||||
return std::string();
|
||||
}
|
||||
|
||||
std::string firebird_statement_backend::rewrite_for_procedure_call(
|
||||
std::string const &query)
|
||||
{
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
###############################################################################
|
||||
#
|
||||
# This file is part of CMake configuration for SOCI library
|
||||
#
|
||||
# Copyright (C) 2013 Viacheslav Naydenov
|
||||
# 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)
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
soci_backend_test(
|
||||
BACKEND Firebird
|
||||
SOURCE test-firebird.cpp
|
||||
CONNSTR "dummy")
|
||||
@@ -1,22 +0,0 @@
|
||||
# The following variable is specific to this backend and its correct
|
||||
# values might depend on your environment - feel free to set it accordingly.
|
||||
|
||||
FIREBIRDINCLUDEDIR = -I/usr/local/firebird/include
|
||||
FIREBIRDLIBDIR = -L/usr/local/firebird/lib
|
||||
FIREBIRDLIBS = -lfbclient -lpthread
|
||||
|
||||
# The rest of the Makefile is indepentent of the target environment.
|
||||
|
||||
COMPILER = g++
|
||||
CXXFLAGS = -Wall -pedantic -Wno-long-long
|
||||
INCLUDEDIRS = -I.. -I../../../core ${FIREBIRDINCLUDEDIR}
|
||||
LIBDIRS = -L.. -L../../../core ${FIREBIRDLIBDIR}
|
||||
LIBS = -lsoci_core -lsoci_firebird -ldl ${FIREBIRDLIBS}
|
||||
|
||||
|
||||
test-firebird : test-firebird.cpp
|
||||
${COMPILER} -o $@ $? ${CXXFLAGS} ${INCLUDEDIRS} ${LIBDIRS} ${LIBS}
|
||||
|
||||
|
||||
clean :
|
||||
rm -f *.o test-firebird
|
||||
File diff suppressed because it is too large
Load Diff
@@ -6,8 +6,8 @@
|
||||
//
|
||||
|
||||
#define SOCI_FIREBIRD_SOURCE
|
||||
#include "soci-firebird.h"
|
||||
#include "common.h"
|
||||
#include "soci/firebird/soci-firebird.h"
|
||||
#include "firebird/common.h"
|
||||
|
||||
using namespace soci;
|
||||
using namespace soci::details;
|
||||
@@ -201,7 +201,7 @@ void firebird_vector_into_type_backend::clean_up()
|
||||
delete [] buf_;
|
||||
buf_ = NULL;
|
||||
}
|
||||
std::vector<void*>::iterator it =
|
||||
std::vector<void*>::iterator it =
|
||||
std::find(statement_.intos_.begin(), statement_.intos_.end(), this);
|
||||
if (it != statement_.intos_.end())
|
||||
statement_.intos_.erase(it);
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
//
|
||||
|
||||
#define SOCI_FIREBIRD_SOURCE
|
||||
#include "soci-firebird.h"
|
||||
#include "common.h"
|
||||
#include "soci/firebird/soci-firebird.h"
|
||||
#include "firebird/common.h"
|
||||
|
||||
using namespace soci;
|
||||
using namespace soci::details;
|
||||
@@ -200,7 +200,7 @@ void firebird_vector_use_type_backend::clean_up()
|
||||
delete [] buf_;
|
||||
buf_ = NULL;
|
||||
}
|
||||
std::vector<void*>::iterator it =
|
||||
std::vector<void*>::iterator it =
|
||||
std::find(statement_.uses_.begin(), statement_.uses_.end(), this);
|
||||
if (it != statement_.uses_.end())
|
||||
statement_.uses_.erase(it);
|
||||
|
||||
@@ -10,9 +10,6 @@
|
||||
###############################################################################
|
||||
soci_backend(MySQL
|
||||
DEPENDS MySQL
|
||||
HEADERS soci-mysql.h common.h
|
||||
DESCRIPTION "SOCI backend for MySQL database engine"
|
||||
DESCRIPTION "SOCI backend for MySQL"
|
||||
AUTHORS "Pawel Aleksander Fedorynski"
|
||||
MAINTAINERS "Pawel Aleksander Fedorynski")
|
||||
|
||||
add_subdirectory(test)
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
//
|
||||
|
||||
#define SOCI_MYSQL_SOURCE
|
||||
#include "soci-mysql.h"
|
||||
#include "soci/mysql/soci-mysql.h"
|
||||
#include <ciso646>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
//
|
||||
|
||||
#include "common.h"
|
||||
#include "soci-backend.h"
|
||||
#include "soci/soci-backend.h"
|
||||
#include "soci-mktime.h"
|
||||
#include <ciso646>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
@@ -64,22 +65,14 @@ void soci::details::mysql::parse_std_tm(char const *buf, std::tm &t)
|
||||
second = parse10(p1, p2, errMsg);
|
||||
}
|
||||
|
||||
t.tm_isdst = -1;
|
||||
t.tm_year = year - 1900;
|
||||
t.tm_mon = month - 1;
|
||||
t.tm_mday = day;
|
||||
t.tm_hour = hour;
|
||||
t.tm_min = minute;
|
||||
t.tm_sec = second;
|
||||
|
||||
std::mktime(&t);
|
||||
details::mktime_from_ymdhms(t, year, month, day, hour, minute, second);
|
||||
}
|
||||
|
||||
char * soci::details::mysql::quote(MYSQL * conn, const char *s, int len)
|
||||
char * soci::details::mysql::quote(MYSQL * conn, const char *s, size_t len)
|
||||
{
|
||||
char *retv = new char[2 * len + 3];
|
||||
retv[0] = '\'';
|
||||
int len_esc = mysql_real_escape_string(conn, retv + 1, s, len);
|
||||
int len_esc = mysql_real_escape_string(conn, retv + 1, s, static_cast<unsigned long>(len));
|
||||
retv[len_esc + 1] = '\'';
|
||||
retv[len_esc + 2] = '\0';
|
||||
|
||||
|
||||
@@ -8,10 +8,13 @@
|
||||
#ifndef SOCI_MYSQL_COMMON_H_INCLUDED
|
||||
#define SOCI_MYSQL_COMMON_H_INCLUDED
|
||||
|
||||
#include "soci-mysql.h"
|
||||
#include "soci/mysql/soci-mysql.h"
|
||||
#include "soci-cstrtod.h"
|
||||
#include "soci-compiler.h"
|
||||
// std
|
||||
#include <cstddef>
|
||||
#include <ctime>
|
||||
#include <locale>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
@@ -39,7 +42,13 @@ template <typename T>
|
||||
bool is_infinity_or_nan(T x)
|
||||
{
|
||||
T y = x - x;
|
||||
|
||||
// We really need exact floating point comparison here.
|
||||
GCC_WARNING_SUPPRESS(float-equal)
|
||||
|
||||
return (y != y);
|
||||
|
||||
GCC_WARNING_RESTORE(float-equal)
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@@ -51,13 +60,21 @@ void parse_num(char const *buf, T &x)
|
||||
{
|
||||
throw soci_error("Cannot convert data.");
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
void parse_num(char const *buf, double &x)
|
||||
{
|
||||
x = cstring_to_double(buf);
|
||||
|
||||
if (is_infinity_or_nan(x)) {
|
||||
throw soci_error("Cannot convert data.");
|
||||
throw soci_error(std::string("Cannot convert data: string \"") + buf +
|
||||
"\" is not a finite number.");
|
||||
}
|
||||
}
|
||||
|
||||
// helper for escaping strings
|
||||
char * quote(MYSQL * conn, const char *s, int len);
|
||||
char * quote(MYSQL * conn, const char *s, size_t len);
|
||||
|
||||
// helper for vector operations
|
||||
template <typename T>
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
//
|
||||
|
||||
#define SOCI_MYSQL_SOURCE
|
||||
#include "soci-mysql.h"
|
||||
#include <backend-loader.h>
|
||||
#include "soci/mysql/soci-mysql.h"
|
||||
#include "soci/backend-loader.h"
|
||||
#include <ciso646>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
//
|
||||
|
||||
#define SOCI_MYSQL_SOURCE
|
||||
#include "soci-mysql.h"
|
||||
#include "soci/mysql/soci-mysql.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
//
|
||||
|
||||
#define SOCI_MYSQL_SOURCE
|
||||
#include "soci-mysql.h"
|
||||
#include <connection-parameters.h>
|
||||
#include "soci/mysql/soci-mysql.h"
|
||||
#include "soci/connection-parameters.h"
|
||||
// std
|
||||
#include <cctype>
|
||||
#include <cerrno>
|
||||
@@ -199,7 +199,7 @@ void parse_connect_string(const string & connectString,
|
||||
throw soci_error(err);
|
||||
}
|
||||
*port = std::atoi(val.c_str());
|
||||
if (port < 0)
|
||||
if (*port < 0)
|
||||
{
|
||||
throw soci_error(err);
|
||||
}
|
||||
@@ -272,6 +272,18 @@ void parse_connect_string(const string & connectString,
|
||||
|
||||
} // namespace anonymous
|
||||
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wuninitialized"
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ > 6)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
|
||||
#endif
|
||||
|
||||
|
||||
mysql_session_backend::mysql_session_backend(
|
||||
connection_parameters const & parameters)
|
||||
{
|
||||
@@ -320,7 +332,11 @@ mysql_session_backend::mysql_session_backend(
|
||||
db_p ? db.c_str() : NULL,
|
||||
port_p ? port : 0,
|
||||
unix_socket_p ? unix_socket.c_str() : NULL,
|
||||
#ifdef CLIENT_MULTI_RESULTS
|
||||
CLIENT_FOUND_ROWS | CLIENT_MULTI_RESULTS) == NULL)
|
||||
#else
|
||||
CLIENT_FOUND_ROWS) == NULL)
|
||||
#endif
|
||||
{
|
||||
string errMsg = mysql_error(conn_);
|
||||
unsigned int errNum = mysql_errno(conn_);
|
||||
@@ -329,6 +345,16 @@ mysql_session_backend::mysql_session_backend(
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ > 6)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
mysql_session_backend::~mysql_session_backend()
|
||||
{
|
||||
clean_up();
|
||||
@@ -364,6 +390,14 @@ void mysql_session_backend::rollback()
|
||||
hard_exec(conn_, "ROLLBACK");
|
||||
}
|
||||
|
||||
bool mysql_session_backend::get_last_insert_id(
|
||||
session & /* s */, std::string const & /* table */, long & value)
|
||||
{
|
||||
value = static_cast<long>(mysql_insert_id(conn_));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void mysql_session_backend::clean_up()
|
||||
{
|
||||
if (conn_ != NULL)
|
||||
|
||||
@@ -1,273 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton
|
||||
// MySQL backend copyright (C) 2006 Pawel Aleksander Fedorynski
|
||||
// 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)
|
||||
//
|
||||
|
||||
#ifndef SOCI_MYSQL_H_INCLUDED
|
||||
#define SOCI_MYSQL_H_INCLUDED
|
||||
|
||||
#ifdef _WIN32
|
||||
# ifdef SOCI_DLL
|
||||
# ifdef SOCI_MYSQL_SOURCE
|
||||
# define SOCI_MYSQL_DECL __declspec(dllexport)
|
||||
# else
|
||||
# define SOCI_MYSQL_DECL __declspec(dllimport)
|
||||
# endif // SOCI_DLL
|
||||
# endif // SOCI_MYSQL_SOURCE
|
||||
#endif // _WIN32
|
||||
//
|
||||
// If SOCI_MYSQL_DECL isn't defined yet define it now
|
||||
#ifndef SOCI_MYSQL_DECL
|
||||
# define SOCI_MYSQL_DECL
|
||||
#endif
|
||||
|
||||
#include "soci-backend.h"
|
||||
#ifdef _WIN32
|
||||
#include <winsock.h> // SOCKET
|
||||
#endif // _WIN32
|
||||
#include <mysql.h> // MySQL Client
|
||||
#include <vector>
|
||||
|
||||
|
||||
namespace soci
|
||||
{
|
||||
|
||||
class mysql_soci_error : public soci_error
|
||||
{
|
||||
public:
|
||||
mysql_soci_error(std::string const & msg, int errNum)
|
||||
: soci_error(msg), err_num_(errNum) {}
|
||||
|
||||
unsigned int err_num_;
|
||||
};
|
||||
|
||||
struct mysql_statement_backend;
|
||||
struct mysql_standard_into_type_backend : details::standard_into_type_backend
|
||||
{
|
||||
mysql_standard_into_type_backend(mysql_statement_backend &st)
|
||||
: statement_(st) {}
|
||||
|
||||
virtual void define_by_pos(int &position,
|
||||
void *data, details::exchange_type type);
|
||||
|
||||
virtual void pre_fetch();
|
||||
virtual void post_fetch(bool gotData, bool calledFromFetch,
|
||||
indicator *ind);
|
||||
|
||||
virtual void clean_up();
|
||||
|
||||
mysql_statement_backend &statement_;
|
||||
|
||||
void *data_;
|
||||
details::exchange_type type_;
|
||||
int position_;
|
||||
};
|
||||
|
||||
struct mysql_vector_into_type_backend : details::vector_into_type_backend
|
||||
{
|
||||
mysql_vector_into_type_backend(mysql_statement_backend &st)
|
||||
: statement_(st) {}
|
||||
|
||||
virtual void define_by_pos(int &position,
|
||||
void *data, details::exchange_type type);
|
||||
|
||||
virtual void pre_fetch();
|
||||
virtual void post_fetch(bool gotData, indicator *ind);
|
||||
|
||||
virtual void resize(std::size_t sz);
|
||||
virtual std::size_t size();
|
||||
|
||||
virtual void clean_up();
|
||||
|
||||
mysql_statement_backend &statement_;
|
||||
|
||||
void *data_;
|
||||
details::exchange_type type_;
|
||||
int position_;
|
||||
};
|
||||
|
||||
struct mysql_standard_use_type_backend : details::standard_use_type_backend
|
||||
{
|
||||
mysql_standard_use_type_backend(mysql_statement_backend &st)
|
||||
: statement_(st), position_(0), buf_(NULL) {}
|
||||
|
||||
virtual void bind_by_pos(int &position,
|
||||
void *data, details::exchange_type type, bool readOnly);
|
||||
virtual void bind_by_name(std::string const &name,
|
||||
void *data, details::exchange_type type, bool readOnly);
|
||||
|
||||
virtual void pre_use(indicator const *ind);
|
||||
virtual void post_use(bool gotData, indicator *ind);
|
||||
|
||||
virtual void clean_up();
|
||||
|
||||
mysql_statement_backend &statement_;
|
||||
|
||||
void *data_;
|
||||
details::exchange_type type_;
|
||||
int position_;
|
||||
std::string name_;
|
||||
char *buf_;
|
||||
};
|
||||
|
||||
struct mysql_vector_use_type_backend : details::vector_use_type_backend
|
||||
{
|
||||
mysql_vector_use_type_backend(mysql_statement_backend &st)
|
||||
: statement_(st), position_(0) {}
|
||||
|
||||
virtual void bind_by_pos(int &position,
|
||||
void *data, details::exchange_type type);
|
||||
virtual void bind_by_name(std::string const &name,
|
||||
void *data, details::exchange_type type);
|
||||
|
||||
virtual void pre_use(indicator const *ind);
|
||||
|
||||
virtual std::size_t size();
|
||||
|
||||
virtual void clean_up();
|
||||
|
||||
mysql_statement_backend &statement_;
|
||||
|
||||
void *data_;
|
||||
details::exchange_type type_;
|
||||
int position_;
|
||||
std::string name_;
|
||||
std::vector<char *> buffers_;
|
||||
};
|
||||
|
||||
struct mysql_session_backend;
|
||||
struct mysql_statement_backend : details::statement_backend
|
||||
{
|
||||
mysql_statement_backend(mysql_session_backend &session);
|
||||
|
||||
virtual void alloc();
|
||||
virtual void clean_up();
|
||||
virtual void prepare(std::string const &query,
|
||||
details::statement_type eType);
|
||||
|
||||
virtual exec_fetch_result execute(int number);
|
||||
virtual exec_fetch_result fetch(int number);
|
||||
|
||||
virtual long long get_affected_rows();
|
||||
virtual int get_number_of_rows();
|
||||
|
||||
virtual std::string rewrite_for_procedure_call(std::string const &query);
|
||||
|
||||
virtual int prepare_for_describe();
|
||||
virtual void describe_column(int colNum, data_type &dtype,
|
||||
std::string &columnName);
|
||||
|
||||
virtual mysql_standard_into_type_backend * make_into_type_backend();
|
||||
virtual mysql_standard_use_type_backend * make_use_type_backend();
|
||||
virtual mysql_vector_into_type_backend * make_vector_into_type_backend();
|
||||
virtual mysql_vector_use_type_backend * make_vector_use_type_backend();
|
||||
|
||||
mysql_session_backend &session_;
|
||||
|
||||
MYSQL_RES *result_;
|
||||
|
||||
// The query is split into chunks, separated by the named parameters;
|
||||
// e.g. for "SELECT id FROM ttt WHERE name = :foo AND gender = :bar"
|
||||
// we will have query chunks "SELECT id FROM ttt WHERE name = ",
|
||||
// "AND gender = " and names "foo", "bar".
|
||||
std::vector<std::string> queryChunks_;
|
||||
std::vector<std::string> names_; // list of names for named binds
|
||||
|
||||
long long rowsAffectedBulk_; // number of rows affected by the last bulk operation
|
||||
|
||||
int numberOfRows_; // number of rows retrieved from the server
|
||||
int currentRow_; // "current" row number to consume in postFetch
|
||||
int rowsToConsume_; // number of rows to be consumed in postFetch
|
||||
|
||||
bool justDescribed_; // to optimize row description with immediately
|
||||
// following actual statement execution
|
||||
|
||||
// Prefetch the row offsets in order to use mysql_row_seek() for
|
||||
// random access to rows, since mysql_data_seek() is expensive.
|
||||
std::vector<MYSQL_ROW_OFFSET> resultRowOffsets_;
|
||||
|
||||
bool hasIntoElements_;
|
||||
bool hasVectorIntoElements_;
|
||||
bool hasUseElements_;
|
||||
bool hasVectorUseElements_;
|
||||
|
||||
// the following maps are used for finding data buffers according to
|
||||
// use elements specified by the user
|
||||
|
||||
typedef std::map<int, char **> UseByPosBuffersMap;
|
||||
UseByPosBuffersMap useByPosBuffers_;
|
||||
|
||||
typedef std::map<std::string, char **> UseByNameBuffersMap;
|
||||
UseByNameBuffersMap useByNameBuffers_;
|
||||
};
|
||||
|
||||
struct mysql_rowid_backend : details::rowid_backend
|
||||
{
|
||||
mysql_rowid_backend(mysql_session_backend &session);
|
||||
|
||||
~mysql_rowid_backend();
|
||||
};
|
||||
|
||||
struct mysql_blob_backend : details::blob_backend
|
||||
{
|
||||
mysql_blob_backend(mysql_session_backend &session);
|
||||
|
||||
~mysql_blob_backend();
|
||||
|
||||
virtual std::size_t get_len();
|
||||
virtual std::size_t read(std::size_t offset, char *buf,
|
||||
std::size_t toRead);
|
||||
virtual std::size_t write(std::size_t offset, char const *buf,
|
||||
std::size_t toWrite);
|
||||
virtual std::size_t append(char const *buf, std::size_t toWrite);
|
||||
virtual void trim(std::size_t newLen);
|
||||
|
||||
mysql_session_backend &session_;
|
||||
};
|
||||
|
||||
struct mysql_session_backend : details::session_backend
|
||||
{
|
||||
mysql_session_backend(connection_parameters const & parameters);
|
||||
|
||||
~mysql_session_backend();
|
||||
|
||||
virtual void begin();
|
||||
virtual void commit();
|
||||
virtual void rollback();
|
||||
|
||||
virtual std::string get_backend_name() const { return "mysql"; }
|
||||
|
||||
void clean_up();
|
||||
|
||||
virtual mysql_statement_backend * make_statement_backend();
|
||||
virtual mysql_rowid_backend * make_rowid_backend();
|
||||
virtual mysql_blob_backend * make_blob_backend();
|
||||
|
||||
MYSQL *conn_;
|
||||
};
|
||||
|
||||
|
||||
struct mysql_backend_factory : backend_factory
|
||||
{
|
||||
mysql_backend_factory() {}
|
||||
virtual mysql_session_backend * make_session(
|
||||
connection_parameters const & parameters) const;
|
||||
};
|
||||
|
||||
extern SOCI_MYSQL_DECL mysql_backend_factory const mysql;
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
// for dynamic backend loading
|
||||
SOCI_MYSQL_DECL backend_factory const * factory_mysql();
|
||||
SOCI_MYSQL_DECL void register_factory_mysql();
|
||||
|
||||
} // extern "C"
|
||||
|
||||
} // namespace soci
|
||||
|
||||
#endif // SOCI_MYSQL_H_INCLUDED
|
||||
@@ -7,11 +7,11 @@
|
||||
//
|
||||
|
||||
#define SOCI_MYSQL_SOURCE
|
||||
#include "soci-mysql.h"
|
||||
#include <soci-platform.h>
|
||||
#include "soci/mysql/soci-mysql.h"
|
||||
#include "soci/soci-platform.h"
|
||||
#include "common.h"
|
||||
#include "soci-exchange-cast.h"
|
||||
// std
|
||||
#include <cassert>
|
||||
#include <ciso646>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
@@ -49,7 +49,7 @@ void mysql_standard_into_type_backend::post_fetch(
|
||||
// no need to do anything (fetch() will return false)
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (gotData)
|
||||
{
|
||||
int pos = position_ - 1;
|
||||
@@ -78,56 +78,34 @@ void mysql_standard_into_type_backend::post_fetch(
|
||||
switch (type_)
|
||||
{
|
||||
case x_char:
|
||||
{
|
||||
char *dest = static_cast<char*>(data_);
|
||||
*dest = *buf;
|
||||
}
|
||||
exchange_type_cast<x_char>(data_) = *buf;
|
||||
break;
|
||||
case x_stdstring:
|
||||
{
|
||||
std::string *dest = static_cast<std::string *>(data_);
|
||||
std::string& dest = exchange_type_cast<x_stdstring>(data_);
|
||||
unsigned long * lengths =
|
||||
mysql_fetch_lengths(statement_.result_);
|
||||
dest->assign(buf, lengths[pos]);
|
||||
dest.assign(buf, lengths[pos]);
|
||||
}
|
||||
break;
|
||||
case x_short:
|
||||
{
|
||||
short *dest = static_cast<short*>(data_);
|
||||
parse_num(buf, *dest);
|
||||
}
|
||||
parse_num(buf, exchange_type_cast<x_short>(data_));
|
||||
break;
|
||||
case x_integer:
|
||||
{
|
||||
int *dest = static_cast<int*>(data_);
|
||||
parse_num(buf, *dest);
|
||||
}
|
||||
parse_num(buf, exchange_type_cast<x_integer>(data_));
|
||||
break;
|
||||
case x_long_long:
|
||||
{
|
||||
long long *dest = static_cast<long long *>(data_);
|
||||
parse_num(buf, *dest);
|
||||
}
|
||||
parse_num(buf, exchange_type_cast<x_long_long>(data_));
|
||||
break;
|
||||
case x_unsigned_long_long:
|
||||
{
|
||||
unsigned long long *dest =
|
||||
static_cast<unsigned long long*>(data_);
|
||||
parse_num(buf, *dest);
|
||||
}
|
||||
parse_num(buf, exchange_type_cast<x_unsigned_long_long>(data_));
|
||||
break;
|
||||
case x_double:
|
||||
{
|
||||
double *dest = static_cast<double*>(data_);
|
||||
parse_num(buf, *dest);
|
||||
}
|
||||
parse_num(buf, exchange_type_cast<x_double>(data_));
|
||||
break;
|
||||
case x_stdtm:
|
||||
{
|
||||
// attempt to parse the string and convert to std::tm
|
||||
std::tm *dest = static_cast<std::tm *>(data_);
|
||||
parse_std_tm(buf, *dest);
|
||||
}
|
||||
// attempt to parse the string and convert to std::tm
|
||||
parse_std_tm(buf, exchange_type_cast<x_stdtm>(data_));
|
||||
break;
|
||||
default:
|
||||
throw soci_error("Into element used with non-supported type.");
|
||||
|
||||
@@ -7,19 +7,17 @@
|
||||
//
|
||||
|
||||
#define SOCI_MYSQL_SOURCE
|
||||
#include "soci-mysql.h"
|
||||
#include "soci/mysql/soci-mysql.h"
|
||||
#include "common.h"
|
||||
#include <soci-platform.h>
|
||||
#include "soci/soci-platform.h"
|
||||
#include "soci-dtocstr.h"
|
||||
#include "soci-exchange-cast.h"
|
||||
// std
|
||||
#include <ciso646>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <limits>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4355)
|
||||
#endif
|
||||
|
||||
using namespace soci;
|
||||
using namespace soci::details;
|
||||
using namespace soci::details::mysql;
|
||||
@@ -55,15 +53,15 @@ void mysql_standard_use_type_backend::pre_use(indicator const *ind)
|
||||
{
|
||||
case x_char:
|
||||
{
|
||||
char buf[] = { *static_cast<char*>(data_), '\0' };
|
||||
char buf[] = { exchange_type_cast<x_char>(data_), '\0' };
|
||||
buf_ = quote(statement_.session_.conn_, buf, 1);
|
||||
}
|
||||
break;
|
||||
case x_stdstring:
|
||||
{
|
||||
std::string *s = static_cast<std::string *>(data_);
|
||||
std::string const& s = exchange_type_cast<x_stdstring>(data_);
|
||||
buf_ = quote(statement_.session_.conn_,
|
||||
s->c_str(), s->size());
|
||||
s.c_str(), s.size());
|
||||
}
|
||||
break;
|
||||
case x_short:
|
||||
@@ -72,7 +70,7 @@ void mysql_standard_use_type_backend::pre_use(indicator const *ind)
|
||||
= std::numeric_limits<short>::digits10 + 3;
|
||||
buf_ = new char[bufSize];
|
||||
snprintf(buf_, bufSize, "%d",
|
||||
static_cast<int>(*static_cast<short*>(data_)));
|
||||
static_cast<int>(exchange_type_cast<x_short>(data_)));
|
||||
}
|
||||
break;
|
||||
case x_integer:
|
||||
@@ -80,7 +78,7 @@ void mysql_standard_use_type_backend::pre_use(indicator const *ind)
|
||||
std::size_t const bufSize
|
||||
= std::numeric_limits<int>::digits10 + 3;
|
||||
buf_ = new char[bufSize];
|
||||
snprintf(buf_, bufSize, "%d", *static_cast<int*>(data_));
|
||||
snprintf(buf_, bufSize, "%d", exchange_type_cast<x_integer>(data_));
|
||||
}
|
||||
break;
|
||||
case x_long_long:
|
||||
@@ -88,7 +86,7 @@ void mysql_standard_use_type_backend::pre_use(indicator const *ind)
|
||||
std::size_t const bufSize
|
||||
= std::numeric_limits<long long>::digits10 + 3;
|
||||
buf_ = new char[bufSize];
|
||||
snprintf(buf_, bufSize, "%" LL_FMT_FLAGS "d", *static_cast<long long *>(data_));
|
||||
snprintf(buf_, bufSize, "%" LL_FMT_FLAGS "d", exchange_type_cast<x_long_long>(data_));
|
||||
}
|
||||
break;
|
||||
case x_unsigned_long_long:
|
||||
@@ -97,23 +95,23 @@ void mysql_standard_use_type_backend::pre_use(indicator const *ind)
|
||||
= std::numeric_limits<unsigned long long>::digits10 + 3;
|
||||
buf_ = new char[bufSize];
|
||||
snprintf(buf_, bufSize, "%" LL_FMT_FLAGS "u",
|
||||
*static_cast<unsigned long long *>(data_));
|
||||
exchange_type_cast<x_unsigned_long_long>(data_));
|
||||
}
|
||||
break;
|
||||
|
||||
case x_double:
|
||||
{
|
||||
if (is_infinity_or_nan(*static_cast<double*>(data_))) {
|
||||
double const d = exchange_type_cast<x_double>(data_);
|
||||
if (is_infinity_or_nan(d)) {
|
||||
throw soci_error(
|
||||
"Use element used with infinity or NaN, which are "
|
||||
"not supported by the MySQL server.");
|
||||
}
|
||||
|
||||
std::size_t const bufSize = 100;
|
||||
buf_ = new char[bufSize];
|
||||
std::string const s = double_to_cstring(d);
|
||||
|
||||
snprintf(buf_, bufSize, "%.20g",
|
||||
*static_cast<double*>(data_));
|
||||
buf_ = new char[s.size() + 1];
|
||||
std::strcpy(buf_, s.c_str());
|
||||
}
|
||||
break;
|
||||
case x_stdtm:
|
||||
@@ -121,11 +119,11 @@ void mysql_standard_use_type_backend::pre_use(indicator const *ind)
|
||||
std::size_t const bufSize = 22;
|
||||
buf_ = new char[bufSize];
|
||||
|
||||
std::tm *t = static_cast<std::tm *>(data_);
|
||||
std::tm const& t = exchange_type_cast<x_stdtm>(data_);
|
||||
snprintf(buf_, bufSize,
|
||||
"\'%d-%02d-%02d %02d:%02d:%02d\'",
|
||||
t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
|
||||
t->tm_hour, t->tm_min, t->tm_sec);
|
||||
t.tm_year + 1900, t.tm_mon + 1, t.tm_mday,
|
||||
t.tm_hour, t.tm_min, t.tm_sec);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -7,14 +7,9 @@
|
||||
//
|
||||
|
||||
#define SOCI_MYSQL_SOURCE
|
||||
#include "soci-mysql.h"
|
||||
#include "soci/mysql/soci-mysql.h"
|
||||
#include <cctype>
|
||||
#include <ciso646>
|
||||
//#include <iostream>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4355)
|
||||
#endif
|
||||
|
||||
using namespace soci;
|
||||
using namespace soci::details;
|
||||
@@ -23,7 +18,7 @@ using std::string;
|
||||
|
||||
mysql_statement_backend::mysql_statement_backend(
|
||||
mysql_session_backend &session)
|
||||
: session_(session), result_(NULL),
|
||||
: session_(session), result_(NULL),
|
||||
rowsAffectedBulk_(-1LL), justDescribed_(false),
|
||||
hasIntoElements_(false), hasVectorIntoElements_(false),
|
||||
hasUseElements_(false), hasVectorUseElements_(false)
|
||||
@@ -37,7 +32,7 @@ void mysql_statement_backend::alloc()
|
||||
|
||||
void mysql_statement_backend::clean_up()
|
||||
{
|
||||
// 'reset' the value for a
|
||||
// 'reset' the value for a
|
||||
// potential new execution.
|
||||
rowsAffectedBulk_ = -1;
|
||||
|
||||
@@ -145,7 +140,7 @@ mysql_statement_backend::execute(int number)
|
||||
if (justDescribed_ == false)
|
||||
{
|
||||
clean_up();
|
||||
|
||||
|
||||
if (number > 1 && hasIntoElements_)
|
||||
{
|
||||
throw soci_error(
|
||||
@@ -158,7 +153,7 @@ mysql_statement_backend::execute(int number)
|
||||
{
|
||||
numberOfExecutions = hasUseElements_ ? 1 : number;
|
||||
}
|
||||
|
||||
|
||||
std::string query;
|
||||
if (not useByPosBuffers_.empty() or not useByNameBuffers_.empty())
|
||||
{
|
||||
@@ -237,7 +232,7 @@ mysql_statement_backend::execute(int number)
|
||||
// bulk operation
|
||||
//std::cerr << "bulk operation:\n" << query << std::endl;
|
||||
if (0 != mysql_real_query(session_.conn_, query.c_str(),
|
||||
query.size()))
|
||||
static_cast<unsigned long>(query.size())))
|
||||
{
|
||||
// preserve the number of rows affected so far.
|
||||
rowsAffectedBulk_ = rowsAffectedBulkTemp;
|
||||
@@ -270,7 +265,7 @@ mysql_statement_backend::execute(int number)
|
||||
|
||||
//std::cerr << query << std::endl;
|
||||
if (0 != mysql_real_query(session_.conn_, query.c_str(),
|
||||
query.size()))
|
||||
static_cast<unsigned long>(query.size())))
|
||||
{
|
||||
throw mysql_soci_error(mysql_error(session_.conn_),
|
||||
mysql_errno(session_.conn_));
|
||||
@@ -338,7 +333,7 @@ mysql_statement_backend::fetch(int number)
|
||||
// function, and the actual consumption of this data will take place
|
||||
// in the postFetch functions, called for each into element.
|
||||
// Here, we only prepare for this to happen (to emulate "the Oracle way").
|
||||
|
||||
|
||||
// forward the "cursor" from the last fetch
|
||||
currentRow_ += rowsToConsume_;
|
||||
|
||||
@@ -380,6 +375,11 @@ int mysql_statement_backend::get_number_of_rows()
|
||||
return numberOfRows_ - currentRow_;
|
||||
}
|
||||
|
||||
std::string mysql_statement_backend::get_parameter_name(int index) const
|
||||
{
|
||||
return names_.at(index);
|
||||
}
|
||||
|
||||
std::string mysql_statement_backend::rewrite_for_procedure_call(
|
||||
std::string const &query)
|
||||
{
|
||||
|
||||
1
src/backends/mysql/test/.gitignore
vendored
1
src/backends/mysql/test/.gitignore
vendored
@@ -1 +0,0 @@
|
||||
test_mysql
|
||||
@@ -1,14 +0,0 @@
|
||||
###############################################################################
|
||||
#
|
||||
# This file is part of CMake configuration for SOCI library
|
||||
#
|
||||
# Copyright (C) 2010 Mateusz Loskot
|
||||
# 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)
|
||||
#
|
||||
###############################################################################
|
||||
soci_backend_test(
|
||||
BACKEND MySQL
|
||||
SOURCE test-mysql.cpp
|
||||
CONNSTR "dummy")
|
||||
@@ -1,22 +0,0 @@
|
||||
# The following variables are specific to this backend and their correct
|
||||
# values might depend on your environment - feel free to set it accordingly.
|
||||
|
||||
MYSQLLIBDIR = -L/usr/lib/mysql
|
||||
MYSQLLIBS = -lmysqlclient -lz
|
||||
MYSQLINCLUDEDIR = -I/usr/include/mysql
|
||||
|
||||
# The rest of the Makefile is independent of the target environment.
|
||||
|
||||
COMPILER = g++
|
||||
CXXFLAGS = -Wall -pedantic -Wno-long-long
|
||||
INCLUDEDIRS = -I.. -I../../../core ${MYSQLINCLUDEDIR}
|
||||
LIBDIRS = -L.. -L../../../core ${MYSQLLIBDIR}
|
||||
LIBS = -lsoci_core -lsoci_mysql -ldl ${MYSQLLIBS}
|
||||
|
||||
|
||||
test-mysql : test-mysql.cpp
|
||||
${COMPILER} -o $@ $? ${CXXFLAGS} ${INCLUDEDIRS} ${LIBDIRS} ${LIBS}
|
||||
|
||||
|
||||
clean :
|
||||
rm -f test-mysql
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,21 +7,16 @@
|
||||
//
|
||||
|
||||
#define SOCI_MYSQL_SOURCE
|
||||
#include "soci-mysql.h"
|
||||
#include "soci/mysql/soci-mysql.h"
|
||||
#include "common.h"
|
||||
#include <soci-platform.h>
|
||||
#include "soci/soci-platform.h"
|
||||
#include <ciso646>
|
||||
#include <cstdlib>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4355)
|
||||
#endif
|
||||
|
||||
using namespace soci;
|
||||
using namespace soci::details;
|
||||
using namespace soci::details::mysql;
|
||||
|
||||
|
||||
void mysql_vector_into_type_backend::define_by_pos(
|
||||
int &position, void *data, exchange_type type)
|
||||
{
|
||||
@@ -79,7 +74,7 @@ void mysql_vector_into_type_backend::post_fetch(bool gotData, indicator *ind)
|
||||
}
|
||||
|
||||
ind[i] = i_null;
|
||||
|
||||
|
||||
// no need to convert data if it is null, go to next row
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -7,9 +7,10 @@
|
||||
//
|
||||
|
||||
#define SOCI_MYSQL_SOURCE
|
||||
#include "soci-mysql.h"
|
||||
#include "soci/mysql/soci-mysql.h"
|
||||
#include "common.h"
|
||||
#include <soci-platform.h>
|
||||
#include "soci/soci-platform.h"
|
||||
#include "soci-dtocstr.h"
|
||||
// std
|
||||
#include <ciso646>
|
||||
#include <cstddef>
|
||||
@@ -21,10 +22,6 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4355)
|
||||
#endif
|
||||
|
||||
using namespace soci;
|
||||
using namespace soci::details;
|
||||
using namespace soci::details::mysql;
|
||||
@@ -144,10 +141,10 @@ void mysql_vector_use_type_backend::pre_use(indicator const *ind)
|
||||
"not supported by the MySQL server.");
|
||||
}
|
||||
|
||||
std::size_t const bufSize = 100;
|
||||
buf = new char[bufSize];
|
||||
std::string const s = double_to_cstring(v[i]);
|
||||
|
||||
snprintf(buf, bufSize, "%.20g", v[i]);
|
||||
buf = new char[s.size() + 1];
|
||||
std::strcpy(buf, s.c_str());
|
||||
}
|
||||
break;
|
||||
case x_stdtm:
|
||||
|
||||
@@ -10,9 +10,6 @@
|
||||
###############################################################################
|
||||
soci_backend(ODBC
|
||||
DEPENDS ODBC
|
||||
HEADERS soci-odbc.h utility.h
|
||||
DESCRIPTION "SOCI backend for ODBC"
|
||||
AUTHORS "Maciej Sobczak, Stephen Hutton, David Courtney"
|
||||
MAINTAINERS "Vadim Zeitlin, Mateusz Loskot, Maciej Sobczak")
|
||||
|
||||
add_subdirectory(test)
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
//
|
||||
|
||||
#define SOCI_ODBC_SOURCE
|
||||
#include "soci-odbc.h"
|
||||
#include "soci/odbc/soci-odbc.h"
|
||||
|
||||
using namespace soci;
|
||||
using namespace soci::details;
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
//
|
||||
|
||||
#define SOCI_ODBC_SOURCE
|
||||
#include "soci-odbc.h"
|
||||
#include <backend-loader.h>
|
||||
#include "soci/odbc/soci-odbc.h"
|
||||
#include "soci/backend-loader.h"
|
||||
|
||||
using namespace soci;
|
||||
using namespace soci::details;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
//
|
||||
|
||||
#define SOCI_ODBC_SOURCE
|
||||
#include "soci-odbc.h"
|
||||
#include "soci/odbc/soci-odbc.h"
|
||||
|
||||
using namespace soci;
|
||||
using namespace soci::details;
|
||||
|
||||
@@ -6,8 +6,9 @@
|
||||
//
|
||||
|
||||
#define SOCI_ODBC_SOURCE
|
||||
#include "soci-odbc.h"
|
||||
#include "session.h"
|
||||
#include "soci/soci-platform.h"
|
||||
#include "soci/odbc/soci-odbc.h"
|
||||
#include "soci/session.h"
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
@@ -33,8 +34,7 @@ odbc_session_backend::odbc_session_backend(
|
||||
rc = SQLSetEnvAttr(henv_, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);
|
||||
if (is_odbc_error(rc))
|
||||
{
|
||||
throw odbc_soci_error(SQL_HANDLE_ENV, henv_,
|
||||
"Setting ODBC version");
|
||||
throw odbc_soci_error(SQL_HANDLE_ENV, henv_, "setting ODBC version 3");
|
||||
}
|
||||
|
||||
// Allocate connection handle
|
||||
@@ -42,7 +42,7 @@ odbc_session_backend::odbc_session_backend(
|
||||
if (is_odbc_error(rc))
|
||||
{
|
||||
throw odbc_soci_error(SQL_HANDLE_DBC, hdbc_,
|
||||
"Allocating connection handle");
|
||||
"allocating connection handle");
|
||||
}
|
||||
|
||||
SQLCHAR outConnString[1024];
|
||||
@@ -74,20 +74,66 @@ odbc_session_backend::odbc_session_backend(
|
||||
|
||||
std::string const & connectString = parameters.get_connect_string();
|
||||
rc = SQLDriverConnect(hdbc_, hwnd_for_prompt,
|
||||
(SQLCHAR *)connectString.c_str(),
|
||||
sqlchar_cast(connectString),
|
||||
(SQLSMALLINT)connectString.size(),
|
||||
outConnString, 1024, &strLength,
|
||||
static_cast<SQLUSMALLINT>(completion));
|
||||
|
||||
if (is_odbc_error(rc))
|
||||
{
|
||||
throw odbc_soci_error(SQL_HANDLE_DBC, hdbc_,
|
||||
"Error Connecting to database");
|
||||
throw odbc_soci_error(SQL_HANDLE_DBC, hdbc_, "connecting to database");
|
||||
}
|
||||
|
||||
connection_string_.assign((const char*)outConnString, strLength);
|
||||
|
||||
reset_transaction();
|
||||
|
||||
configure_connection();
|
||||
}
|
||||
|
||||
void odbc_session_backend::configure_connection()
|
||||
{
|
||||
if ( get_database_product() == prod_postgresql )
|
||||
{
|
||||
// Increase the number of digits used for floating point values to
|
||||
// ensure that the conversions to/from text round trip correctly, which
|
||||
// is not the case with the default value of 0. Use the maximal
|
||||
// supported value, which was 2 until 9.x and is 3 since it.
|
||||
|
||||
char product_ver[1024];
|
||||
SQLSMALLINT len = sizeof(product_ver);
|
||||
SQLRETURN rc = SQLGetInfo(hdbc_, SQL_DBMS_VER, product_ver, len, &len);
|
||||
if (is_odbc_error(rc))
|
||||
{
|
||||
throw odbc_soci_error(SQL_HANDLE_DBC, henv_,
|
||||
"getting PostgreSQL ODBC driver version");
|
||||
}
|
||||
|
||||
// The returned string is of the form "##.##.#### ...", but we don't
|
||||
// need to parse it fully, we just need the major version which,
|
||||
// conveniently, comes first.
|
||||
unsigned major_ver = 0;
|
||||
if (std::sscanf(product_ver, "%u", &major_ver) != 1)
|
||||
{
|
||||
throw soci_error("DBMS version \"" + std::string(product_ver) +
|
||||
"\" in unrecognizable format.");
|
||||
}
|
||||
|
||||
odbc_statement_backend st(*this);
|
||||
st.alloc();
|
||||
|
||||
std::string const q(major_ver >= 9 ? "SET extra_float_digits = 3"
|
||||
: "SET extra_float_digits = 2");
|
||||
rc = SQLExecDirect(st.hstmt_, sqlchar_cast(q), static_cast<SQLINTEGER>(q.size()));
|
||||
|
||||
st.clean_up();
|
||||
|
||||
if (is_odbc_error(rc))
|
||||
{
|
||||
throw odbc_soci_error(SQL_HANDLE_DBC, henv_,
|
||||
"setting extra_float_digits for PostgreSQL");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
odbc_session_backend::~odbc_session_backend()
|
||||
@@ -101,8 +147,7 @@ void odbc_session_backend::begin()
|
||||
(SQLPOINTER)SQL_AUTOCOMMIT_OFF, 0 );
|
||||
if (is_odbc_error(rc))
|
||||
{
|
||||
throw odbc_soci_error(SQL_HANDLE_DBC, hdbc_,
|
||||
"Begin Transaction");
|
||||
throw odbc_soci_error(SQL_HANDLE_DBC, hdbc_, "beginning transaction");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,8 +156,7 @@ void odbc_session_backend::commit()
|
||||
SQLRETURN rc = SQLEndTran(SQL_HANDLE_DBC, hdbc_, SQL_COMMIT);
|
||||
if (is_odbc_error(rc))
|
||||
{
|
||||
throw odbc_soci_error(SQL_HANDLE_DBC, hdbc_,
|
||||
"Committing");
|
||||
throw odbc_soci_error(SQL_HANDLE_DBC, hdbc_, "committing transaction");
|
||||
}
|
||||
reset_transaction();
|
||||
}
|
||||
@@ -122,8 +166,7 @@ void odbc_session_backend::rollback()
|
||||
SQLRETURN rc = SQLEndTran(SQL_HANDLE_DBC, hdbc_, SQL_ROLLBACK);
|
||||
if (is_odbc_error(rc))
|
||||
{
|
||||
throw odbc_soci_error(SQL_HANDLE_DBC, hdbc_,
|
||||
"Rolling back");
|
||||
throw odbc_soci_error(SQL_HANDLE_DBC, hdbc_, "rolling back transaction");
|
||||
}
|
||||
reset_transaction();
|
||||
}
|
||||
@@ -216,8 +259,7 @@ void odbc_session_backend::reset_transaction()
|
||||
(SQLPOINTER)SQL_AUTOCOMMIT_ON, 0 );
|
||||
if (is_odbc_error(rc))
|
||||
{
|
||||
throw odbc_soci_error(SQL_HANDLE_DBC, hdbc_,
|
||||
"Set Auto Commit");
|
||||
throw odbc_soci_error(SQL_HANDLE_DBC, hdbc_, "enabling auto commit");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -227,22 +269,19 @@ void odbc_session_backend::clean_up()
|
||||
SQLRETURN rc = SQLDisconnect(hdbc_);
|
||||
if (is_odbc_error(rc))
|
||||
{
|
||||
throw odbc_soci_error(SQL_HANDLE_DBC, hdbc_,
|
||||
"SQLDisconnect");
|
||||
throw odbc_soci_error(SQL_HANDLE_DBC, hdbc_, "disconnecting");
|
||||
}
|
||||
|
||||
rc = SQLFreeHandle(SQL_HANDLE_DBC, hdbc_);
|
||||
if (is_odbc_error(rc))
|
||||
{
|
||||
throw odbc_soci_error(SQL_HANDLE_DBC, hdbc_,
|
||||
"SQLFreeHandle DBC");
|
||||
throw odbc_soci_error(SQL_HANDLE_DBC, hdbc_, "freeing connection");
|
||||
}
|
||||
|
||||
rc = SQLFreeHandle(SQL_HANDLE_ENV, henv_);
|
||||
if (is_odbc_error(rc))
|
||||
{
|
||||
throw odbc_soci_error(SQL_HANDLE_ENV, henv_,
|
||||
"SQLFreeHandle ENV");
|
||||
throw odbc_soci_error(SQL_HANDLE_ENV, henv_, "freeing environment");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -274,7 +313,7 @@ odbc_session_backend::get_database_product()
|
||||
if (is_odbc_error(rc))
|
||||
{
|
||||
throw odbc_soci_error(SQL_HANDLE_DBC, henv_,
|
||||
"SQLGetInfo(SQL_DBMS_NAME)");
|
||||
"getting ODBC driver name");
|
||||
}
|
||||
|
||||
if (strcmp(product_name, "Firebird") == 0)
|
||||
|
||||
@@ -1,432 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton, David Courtney
|
||||
// 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)
|
||||
//
|
||||
|
||||
#ifndef SOCI_ODBC_H_INCLUDED
|
||||
#define SOCI_ODBC_H_INCLUDED
|
||||
|
||||
#ifdef _WIN32
|
||||
# ifdef SOCI_DLL
|
||||
# ifdef SOCI_ODBC_SOURCE
|
||||
# define SOCI_ODBC_DECL __declspec(dllexport)
|
||||
# else
|
||||
# define SOCI_ODBC_DECL __declspec(dllimport)
|
||||
# endif // SOCI_ODBC_SOURCE
|
||||
# endif // SOCI_DLL
|
||||
#endif // _WIN32
|
||||
//
|
||||
// If SOCI_ODBC_DECL isn't defined yet define it now
|
||||
#ifndef SOCI_ODBC_DECL
|
||||
# define SOCI_ODBC_DECL
|
||||
#endif
|
||||
|
||||
#include <vector>
|
||||
#include <soci-backend.h>
|
||||
#if defined(_MSC_VER) || defined(__MINGW32__)
|
||||
#include <soci-platform.h>
|
||||
#include <windows.h>
|
||||
#endif
|
||||
#include <sqlext.h> // ODBC
|
||||
#include <string.h> // strcpy()
|
||||
|
||||
namespace soci
|
||||
{
|
||||
|
||||
// TODO: Do we want to make it a part of public interface? --mloskot
|
||||
namespace details
|
||||
{
|
||||
std::size_t const odbc_max_buffer_length = 100 * 1024 * 1024;
|
||||
}
|
||||
|
||||
// Option allowing to specify the "driver completion" parameter of
|
||||
// SQLDriverConnect(). Its possible values are the same as the allowed values
|
||||
// for this parameter in the official ODBC, i.e. one of SQL_DRIVER_XXX (in
|
||||
// string form as all options are strings currently).
|
||||
extern SOCI_ODBC_DECL char const * odbc_option_driver_complete;
|
||||
|
||||
struct odbc_statement_backend;
|
||||
|
||||
// Helper of into and use backends.
|
||||
class odbc_standard_type_backend_base
|
||||
{
|
||||
protected:
|
||||
odbc_standard_type_backend_base(odbc_statement_backend &st)
|
||||
: statement_(st) {}
|
||||
|
||||
// Check if we need to pass 64 bit integers as strings to the database as
|
||||
// some drivers don't support them directly.
|
||||
inline bool use_string_for_bigint() const;
|
||||
|
||||
// If we do need to use strings for 64 bit integers, this constant defines
|
||||
// the maximal string length needed.
|
||||
enum
|
||||
{
|
||||
// This is the length of decimal representation of UINT64_MAX + 1.
|
||||
max_bigint_length = 21
|
||||
};
|
||||
|
||||
odbc_statement_backend &statement_;
|
||||
};
|
||||
|
||||
struct odbc_standard_into_type_backend : details::standard_into_type_backend,
|
||||
private odbc_standard_type_backend_base
|
||||
{
|
||||
odbc_standard_into_type_backend(odbc_statement_backend &st)
|
||||
: odbc_standard_type_backend_base(st), buf_(0)
|
||||
{}
|
||||
|
||||
virtual void define_by_pos(int &position,
|
||||
void *data, details::exchange_type type);
|
||||
|
||||
virtual void pre_fetch();
|
||||
virtual void post_fetch(bool gotData, bool calledFromFetch,
|
||||
indicator *ind);
|
||||
|
||||
virtual void clean_up();
|
||||
|
||||
char *buf_; // generic buffer
|
||||
void *data_;
|
||||
details::exchange_type type_;
|
||||
int position_;
|
||||
SQLSMALLINT odbcType_;
|
||||
SQLLEN valueLen_;
|
||||
};
|
||||
|
||||
struct odbc_vector_into_type_backend : details::vector_into_type_backend,
|
||||
private odbc_standard_type_backend_base
|
||||
{
|
||||
odbc_vector_into_type_backend(odbc_statement_backend &st)
|
||||
: odbc_standard_type_backend_base(st), indHolders_(NULL),
|
||||
data_(NULL), buf_(NULL) {}
|
||||
|
||||
virtual void define_by_pos(int &position,
|
||||
void *data, details::exchange_type type);
|
||||
|
||||
virtual void pre_fetch();
|
||||
virtual void post_fetch(bool gotData, indicator *ind);
|
||||
|
||||
virtual void resize(std::size_t sz);
|
||||
virtual std::size_t size();
|
||||
|
||||
virtual void clean_up();
|
||||
|
||||
// helper function for preparing indicators
|
||||
// (as part of the define_by_pos)
|
||||
void prepare_indicators(std::size_t size);
|
||||
|
||||
|
||||
SQLLEN *indHolders_;
|
||||
std::vector<SQLLEN> indHolderVec_;
|
||||
void *data_;
|
||||
char *buf_; // generic buffer
|
||||
details::exchange_type type_;
|
||||
std::size_t colSize_; // size of the string column (used for strings)
|
||||
SQLSMALLINT odbcType_;
|
||||
};
|
||||
|
||||
struct odbc_standard_use_type_backend : details::standard_use_type_backend,
|
||||
private odbc_standard_type_backend_base
|
||||
{
|
||||
odbc_standard_use_type_backend(odbc_statement_backend &st)
|
||||
: odbc_standard_type_backend_base(st),
|
||||
position_(-1), data_(0), buf_(0), indHolder_(0) {}
|
||||
|
||||
virtual void bind_by_pos(int &position,
|
||||
void *data, details::exchange_type type, bool readOnly);
|
||||
virtual void bind_by_name(std::string const &name,
|
||||
void *data, details::exchange_type type, bool readOnly);
|
||||
|
||||
virtual void pre_use(indicator const *ind);
|
||||
virtual void post_use(bool gotData, indicator *ind);
|
||||
|
||||
virtual void clean_up();
|
||||
|
||||
// Return the pointer to the buffer containing data to be used by ODBC.
|
||||
// This can be either data_ itself or buf_, that is allocated by this
|
||||
// function if necessary.
|
||||
//
|
||||
// Also fill in the size of the data and SQL and C types of it.
|
||||
void* prepare_for_bind(SQLLEN &size,
|
||||
SQLSMALLINT &sqlType, SQLSMALLINT &cType);
|
||||
|
||||
int position_;
|
||||
void *data_;
|
||||
details::exchange_type type_;
|
||||
char *buf_;
|
||||
SQLLEN indHolder_;
|
||||
};
|
||||
|
||||
struct odbc_vector_use_type_backend : details::vector_use_type_backend,
|
||||
private odbc_standard_type_backend_base
|
||||
{
|
||||
odbc_vector_use_type_backend(odbc_statement_backend &st)
|
||||
: odbc_standard_type_backend_base(st), indHolders_(NULL),
|
||||
data_(NULL), buf_(NULL) {}
|
||||
|
||||
// helper function for preparing indicators
|
||||
// (as part of the define_by_pos)
|
||||
void prepare_indicators(std::size_t size);
|
||||
|
||||
// common part for bind_by_pos and bind_by_name
|
||||
void prepare_for_bind(void *&data, SQLUINTEGER &size, SQLSMALLINT &sqlType, SQLSMALLINT &cType);
|
||||
void bind_helper(int &position,
|
||||
void *data, details::exchange_type type);
|
||||
|
||||
virtual void bind_by_pos(int &position,
|
||||
void *data, details::exchange_type type);
|
||||
virtual void bind_by_name(std::string const &name,
|
||||
void *data, details::exchange_type type);
|
||||
|
||||
virtual void pre_use(indicator const *ind);
|
||||
|
||||
virtual std::size_t size();
|
||||
|
||||
virtual void clean_up();
|
||||
|
||||
|
||||
SQLLEN *indHolders_;
|
||||
std::vector<SQLLEN> indHolderVec_;
|
||||
void *data_;
|
||||
details::exchange_type type_;
|
||||
char *buf_; // generic buffer
|
||||
std::size_t colSize_; // size of the string column (used for strings)
|
||||
// used for strings only
|
||||
std::size_t maxSize_;
|
||||
};
|
||||
|
||||
struct odbc_session_backend;
|
||||
struct odbc_statement_backend : details::statement_backend
|
||||
{
|
||||
odbc_statement_backend(odbc_session_backend &session);
|
||||
|
||||
virtual void alloc();
|
||||
virtual void clean_up();
|
||||
virtual void prepare(std::string const &query,
|
||||
details::statement_type eType);
|
||||
|
||||
virtual exec_fetch_result execute(int number);
|
||||
virtual exec_fetch_result fetch(int number);
|
||||
|
||||
virtual long long get_affected_rows();
|
||||
virtual int get_number_of_rows();
|
||||
|
||||
virtual std::string rewrite_for_procedure_call(std::string const &query);
|
||||
|
||||
virtual int prepare_for_describe();
|
||||
virtual void describe_column(int colNum, data_type &dtype,
|
||||
std::string &columnName);
|
||||
|
||||
// helper for defining into vector<string>
|
||||
std::size_t column_size(int position);
|
||||
|
||||
virtual odbc_standard_into_type_backend * make_into_type_backend();
|
||||
virtual odbc_standard_use_type_backend * make_use_type_backend();
|
||||
virtual odbc_vector_into_type_backend * make_vector_into_type_backend();
|
||||
virtual odbc_vector_use_type_backend * make_vector_use_type_backend();
|
||||
|
||||
odbc_session_backend &session_;
|
||||
SQLHSTMT hstmt_;
|
||||
SQLULEN numRowsFetched_;
|
||||
bool hasVectorUseElements_;
|
||||
bool boundByName_;
|
||||
bool boundByPos_;
|
||||
|
||||
long long rowsAffected_; // number of rows affected by the last operation
|
||||
|
||||
std::string query_;
|
||||
std::vector<std::string> names_; // list of names for named binds
|
||||
|
||||
};
|
||||
|
||||
struct odbc_rowid_backend : details::rowid_backend
|
||||
{
|
||||
odbc_rowid_backend(odbc_session_backend &session);
|
||||
|
||||
~odbc_rowid_backend();
|
||||
};
|
||||
|
||||
struct odbc_blob_backend : details::blob_backend
|
||||
{
|
||||
odbc_blob_backend(odbc_session_backend &session);
|
||||
|
||||
~odbc_blob_backend();
|
||||
|
||||
virtual std::size_t get_len();
|
||||
virtual std::size_t read(std::size_t offset, char *buf,
|
||||
std::size_t toRead);
|
||||
virtual std::size_t write(std::size_t offset, char const *buf,
|
||||
std::size_t toWrite);
|
||||
virtual std::size_t append(char const *buf, std::size_t toWrite);
|
||||
virtual void trim(std::size_t newLen);
|
||||
|
||||
odbc_session_backend &session_;
|
||||
};
|
||||
|
||||
struct odbc_session_backend : details::session_backend
|
||||
{
|
||||
odbc_session_backend(connection_parameters const & parameters);
|
||||
|
||||
~odbc_session_backend();
|
||||
|
||||
virtual void begin();
|
||||
virtual void commit();
|
||||
virtual void rollback();
|
||||
|
||||
virtual bool get_next_sequence_value(session & s,
|
||||
std::string const & sequence, long & value);
|
||||
virtual bool get_last_insert_id(session & s,
|
||||
std::string const & table, long & value);
|
||||
|
||||
virtual std::string get_backend_name() const { return "odbc"; }
|
||||
|
||||
void reset_transaction();
|
||||
|
||||
void clean_up();
|
||||
|
||||
virtual odbc_statement_backend * make_statement_backend();
|
||||
virtual odbc_rowid_backend * make_rowid_backend();
|
||||
virtual odbc_blob_backend * make_blob_backend();
|
||||
|
||||
enum database_product
|
||||
{
|
||||
prod_uninitialized, // Never returned by get_database_product().
|
||||
prod_firebird,
|
||||
prod_mssql,
|
||||
prod_mysql,
|
||||
prod_oracle,
|
||||
prod_postgresql,
|
||||
prod_sqlite,
|
||||
prod_unknown = -1
|
||||
};
|
||||
|
||||
// Determine the type of the database we're connected to.
|
||||
database_product get_database_product();
|
||||
|
||||
// Return full ODBC connection string.
|
||||
std::string get_connection_string() const { return connection_string_; }
|
||||
|
||||
SQLHENV henv_;
|
||||
SQLHDBC hdbc_;
|
||||
|
||||
std::string connection_string_;
|
||||
database_product product_;
|
||||
};
|
||||
|
||||
class SOCI_ODBC_DECL odbc_soci_error : public soci_error
|
||||
{
|
||||
SQLCHAR message_[SQL_MAX_MESSAGE_LENGTH + 1];
|
||||
SQLCHAR sqlstate_[SQL_SQLSTATE_SIZE + 1];
|
||||
SQLINTEGER sqlcode_;
|
||||
|
||||
public:
|
||||
odbc_soci_error(SQLSMALLINT htype,
|
||||
SQLHANDLE hndl,
|
||||
std::string const & msg)
|
||||
: soci_error(msg)
|
||||
{
|
||||
const char* socierror = NULL;
|
||||
|
||||
SQLSMALLINT length, i = 1;
|
||||
switch ( SQLGetDiagRecA(htype, hndl, i, sqlstate_, &sqlcode_,
|
||||
message_, SQL_MAX_MESSAGE_LENGTH + 1,
|
||||
&length) )
|
||||
{
|
||||
case SQL_SUCCESS:
|
||||
// The error message was successfully retrieved.
|
||||
break;
|
||||
|
||||
case SQL_INVALID_HANDLE:
|
||||
socierror = "[SOCI]: Invalid handle.";
|
||||
break;
|
||||
|
||||
case SQL_ERROR:
|
||||
socierror = "[SOCI]: SQLGetDiagRec() error.";
|
||||
break;
|
||||
|
||||
case SQL_SUCCESS_WITH_INFO:
|
||||
socierror = "[SOCI]: Error message too long.";
|
||||
break;
|
||||
|
||||
case SQL_NO_DATA:
|
||||
socierror = "[SOCI]: No error.";
|
||||
break;
|
||||
|
||||
default:
|
||||
socierror = "[SOCI]: Unexpected SQLGetDiagRec() return value.";
|
||||
break;
|
||||
}
|
||||
|
||||
if (socierror)
|
||||
{
|
||||
// Use our own error message if we failed to retrieve the ODBC one.
|
||||
strcpy(reinterpret_cast<char*>(message_), socierror);
|
||||
|
||||
// Use "General warning" SQLSTATE code.
|
||||
strcpy(reinterpret_cast<char*>(sqlstate_), "01000");
|
||||
|
||||
sqlcode_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
SQLCHAR const * odbc_error_code() const
|
||||
{
|
||||
return reinterpret_cast<SQLCHAR const *>(sqlstate_);
|
||||
}
|
||||
SQLINTEGER native_error_code() const
|
||||
{
|
||||
return sqlcode_;
|
||||
}
|
||||
SQLCHAR const * odbc_error_message() const
|
||||
{
|
||||
return reinterpret_cast<SQLCHAR const *>(message_);
|
||||
}
|
||||
};
|
||||
|
||||
inline bool is_odbc_error(SQLRETURN rc)
|
||||
{
|
||||
if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO && rc != SQL_NO_DATA)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool odbc_standard_type_backend_base::use_string_for_bigint() const
|
||||
{
|
||||
// Oracle ODBC driver doesn't support SQL_C_[SU]BIGINT data types
|
||||
// (see appendix G.1 of Oracle Database Administrator's reference at
|
||||
// http://docs.oracle.com/cd/B19306_01/server.102/b15658/app_odbc.htm),
|
||||
// so we need a special workaround for this case and we represent 64
|
||||
// bit integers as strings and rely on ODBC driver for transforming
|
||||
// them to SQL_NUMERIC.
|
||||
return statement_.session_.get_database_product()
|
||||
== odbc_session_backend::prod_oracle;
|
||||
}
|
||||
|
||||
struct odbc_backend_factory : backend_factory
|
||||
{
|
||||
odbc_backend_factory() {}
|
||||
virtual odbc_session_backend * make_session(
|
||||
connection_parameters const & parameters) const;
|
||||
};
|
||||
|
||||
extern SOCI_ODBC_DECL odbc_backend_factory const odbc;
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
// for dynamic backend loading
|
||||
SOCI_ODBC_DECL backend_factory const * factory_odbc();
|
||||
SOCI_ODBC_DECL void register_factory_odbc();
|
||||
|
||||
} // extern "C"
|
||||
|
||||
} // namespace soci
|
||||
|
||||
#endif // SOCI_EMPTY_H_INCLUDED
|
||||
@@ -6,8 +6,10 @@
|
||||
//
|
||||
|
||||
#define SOCI_ODBC_SOURCE
|
||||
#include <soci-platform.h>
|
||||
#include "soci-odbc.h"
|
||||
#include "soci/soci-platform.h"
|
||||
#include "soci/odbc/soci-odbc.h"
|
||||
#include "soci-exchange-cast.h"
|
||||
#include "soci-mktime.h"
|
||||
#include <ctime>
|
||||
#include <stdio.h> // sscanf()
|
||||
|
||||
@@ -22,7 +24,6 @@ void odbc_standard_into_type_backend::define_by_pos(
|
||||
position_ = position++;
|
||||
|
||||
SQLUINTEGER size = 0;
|
||||
|
||||
switch (type_)
|
||||
{
|
||||
case x_char:
|
||||
@@ -35,7 +36,7 @@ void odbc_standard_into_type_backend::define_by_pos(
|
||||
odbcType_ = SQL_C_CHAR;
|
||||
// Patch: set to min between column size and 100MB (used ot be 32769)
|
||||
// Column size for text data type can be too large for buffer allocation
|
||||
size = statement_.column_size(position_);
|
||||
size = static_cast<SQLUINTEGER>(statement_.column_size(position_));
|
||||
size = size > odbc_max_buffer_length ? odbc_max_buffer_length : size;
|
||||
size++;
|
||||
buf_ = new char[size];
|
||||
@@ -101,8 +102,9 @@ void odbc_standard_into_type_backend::define_by_pos(
|
||||
static_cast<SQLUSMALLINT>(odbcType_), data, size, &valueLen_);
|
||||
if (is_odbc_error(rc))
|
||||
{
|
||||
throw odbc_soci_error(SQL_HANDLE_STMT, statement_.hstmt_,
|
||||
"into type pre_fetch");
|
||||
std::ostringstream ss;
|
||||
ss << "binding output column #" << position_;
|
||||
throw odbc_soci_error(SQL_HANDLE_STMT, statement_.hstmt_, ss.str());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,46 +148,39 @@ void odbc_standard_into_type_backend::post_fetch(
|
||||
// only std::string and std::tm need special handling
|
||||
if (type_ == x_char)
|
||||
{
|
||||
char *c = static_cast<char*>(data_);
|
||||
*c = buf_[0];
|
||||
exchange_type_cast<x_char>(data_) = buf_[0];
|
||||
}
|
||||
if (type_ == x_stdstring)
|
||||
else if (type_ == x_stdstring)
|
||||
{
|
||||
std::string *s = static_cast<std::string *>(data_);
|
||||
*s = buf_;
|
||||
if (s->size() >= (odbc_max_buffer_length - 1))
|
||||
std::string& s = exchange_type_cast<x_stdstring>(data_);
|
||||
s = buf_;
|
||||
if (s.size() >= (odbc_max_buffer_length - 1))
|
||||
{
|
||||
throw soci_error("Buffer size overflow; maybe got too large string");
|
||||
}
|
||||
}
|
||||
else if (type_ == x_stdtm)
|
||||
{
|
||||
std::tm *t = static_cast<std::tm *>(data_);
|
||||
std::tm& t = exchange_type_cast<x_stdtm>(data_);
|
||||
|
||||
TIMESTAMP_STRUCT * ts = reinterpret_cast<TIMESTAMP_STRUCT*>(buf_);
|
||||
t->tm_isdst = -1;
|
||||
t->tm_year = ts->year - 1900;
|
||||
t->tm_mon = ts->month - 1;
|
||||
t->tm_mday = ts->day;
|
||||
t->tm_hour = ts->hour;
|
||||
t->tm_min = ts->minute;
|
||||
t->tm_sec = ts->second;
|
||||
|
||||
// normalize and compute the remaining fields
|
||||
std::mktime(t);
|
||||
details::mktime_from_ymdhms(t,
|
||||
ts->year, ts->month, ts->day,
|
||||
ts->hour, ts->minute, ts->second);
|
||||
}
|
||||
else if (type_ == x_long_long && use_string_for_bigint())
|
||||
{
|
||||
long long *ll = static_cast<long long *>(data_);
|
||||
if (sscanf(buf_, "%" LL_FMT_FLAGS "d", ll) != 1)
|
||||
long long& ll = exchange_type_cast<x_long_long>(data_);
|
||||
if (sscanf(buf_, "%" LL_FMT_FLAGS "d", &ll) != 1)
|
||||
{
|
||||
throw soci_error("Failed to parse the returned 64-bit integer value");
|
||||
}
|
||||
}
|
||||
else if (type_ == x_unsigned_long_long && use_string_for_bigint())
|
||||
{
|
||||
unsigned long long *ll = static_cast<unsigned long long *>(data_);
|
||||
if (sscanf(buf_, "%" LL_FMT_FLAGS "u", ll) != 1)
|
||||
unsigned long long& ll = exchange_type_cast<x_unsigned_long_long>(data_);
|
||||
if (sscanf(buf_, "%" LL_FMT_FLAGS "u", &ll) != 1)
|
||||
{
|
||||
throw soci_error("Failed to parse the returned 64-bit integer value");
|
||||
}
|
||||
|
||||
@@ -4,8 +4,9 @@
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#define SOCI_ODBC_SOURCE
|
||||
#include <soci-platform.h>
|
||||
#include "soci-odbc.h"
|
||||
#include "soci/soci-platform.h"
|
||||
#include "soci/odbc/soci-odbc.h"
|
||||
#include "soci-exchange-cast.h"
|
||||
#include <cctype>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
@@ -15,12 +16,6 @@
|
||||
using namespace soci;
|
||||
using namespace soci::details;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4996)
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
|
||||
|
||||
void* odbc_standard_use_type_backend::prepare_for_bind(
|
||||
SQLLEN &size, SQLSMALLINT &sqlType, SQLSMALLINT &cType)
|
||||
{
|
||||
@@ -45,7 +40,7 @@ void* odbc_standard_use_type_backend::prepare_for_bind(
|
||||
size = max_bigint_length;
|
||||
buf_ = new char[size];
|
||||
snprintf(buf_, size, "%" LL_FMT_FLAGS "d",
|
||||
*static_cast<long long *>(data_));
|
||||
exchange_type_cast<x_long_long>(data_));
|
||||
indHolder_ = SQL_NTS;
|
||||
}
|
||||
else // Normal case, use ODBC support.
|
||||
@@ -63,7 +58,7 @@ void* odbc_standard_use_type_backend::prepare_for_bind(
|
||||
size = max_bigint_length;
|
||||
buf_ = new char[size];
|
||||
snprintf(buf_, size, "%" LL_FMT_FLAGS "u",
|
||||
*static_cast<unsigned long long *>(data_));
|
||||
exchange_type_cast<x_unsigned_long_long>(data_));
|
||||
indHolder_ = SQL_NTS;
|
||||
}
|
||||
else // Normal case, use ODBC support.
|
||||
@@ -84,25 +79,34 @@ void* odbc_standard_use_type_backend::prepare_for_bind(
|
||||
cType = SQL_C_CHAR;
|
||||
size = 2;
|
||||
buf_ = new char[size];
|
||||
buf_[0] = *static_cast<char*>(data_);
|
||||
buf_[0] = exchange_type_cast<x_char>(data_);
|
||||
buf_[1] = '\0';
|
||||
indHolder_ = SQL_NTS;
|
||||
break;
|
||||
case x_stdstring:
|
||||
{
|
||||
std::string* s = static_cast<std::string*>(data_);
|
||||
std::string const& s = exchange_type_cast<x_stdstring>(data_);
|
||||
sqlType = SQL_VARCHAR;
|
||||
cType = SQL_C_CHAR;
|
||||
size = s->size();
|
||||
size = s.size();
|
||||
buf_ = new char[size+1];
|
||||
memcpy(buf_, s->c_str(), size);
|
||||
memcpy(buf_, s.c_str(), size);
|
||||
buf_[size++] = '\0';
|
||||
indHolder_ = SQL_NTS;
|
||||
|
||||
// Strings of greater length are silently truncated at 8000 limit by MS
|
||||
// SQL unless SQL_SS_LENGTH_UNLIMITED (which is defined as 0, but not
|
||||
// available in all headers) is used.
|
||||
if (size > 8000)
|
||||
{
|
||||
sqlType = SQL_LONGVARCHAR;
|
||||
size = 0 /* SQL_SS_LENGTH_UNLIMITED */;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case x_stdtm:
|
||||
{
|
||||
std::tm *t = static_cast<std::tm *>(data_);
|
||||
std::tm const& t = exchange_type_cast<x_stdtm>(data_);
|
||||
|
||||
sqlType = SQL_TIMESTAMP;
|
||||
cType = SQL_C_TIMESTAMP;
|
||||
@@ -113,12 +117,12 @@ void* odbc_standard_use_type_backend::prepare_for_bind(
|
||||
|
||||
TIMESTAMP_STRUCT * ts = reinterpret_cast<TIMESTAMP_STRUCT*>(buf_);
|
||||
|
||||
ts->year = static_cast<SQLSMALLINT>(t->tm_year + 1900);
|
||||
ts->month = static_cast<SQLUSMALLINT>(t->tm_mon + 1);
|
||||
ts->day = static_cast<SQLUSMALLINT>(t->tm_mday);
|
||||
ts->hour = static_cast<SQLUSMALLINT>(t->tm_hour);
|
||||
ts->minute = static_cast<SQLUSMALLINT>(t->tm_min);
|
||||
ts->second = static_cast<SQLUSMALLINT>(t->tm_sec);
|
||||
ts->year = static_cast<SQLSMALLINT>(t.tm_year + 1900);
|
||||
ts->month = static_cast<SQLUSMALLINT>(t.tm_mon + 1);
|
||||
ts->day = static_cast<SQLUSMALLINT>(t.tm_mday);
|
||||
ts->hour = static_cast<SQLUSMALLINT>(t.tm_hour);
|
||||
ts->minute = static_cast<SQLUSMALLINT>(t.tm_min);
|
||||
ts->second = static_cast<SQLUSMALLINT>(t.tm_sec);
|
||||
ts->fraction = 0;
|
||||
}
|
||||
break;
|
||||
@@ -219,8 +223,9 @@ void odbc_standard_use_type_backend::pre_use(indicator const *ind)
|
||||
|
||||
if (is_odbc_error(rc))
|
||||
{
|
||||
throw odbc_soci_error(SQL_HANDLE_STMT, statement_.hstmt_,
|
||||
"Binding");
|
||||
std::ostringstream ss;
|
||||
ss << "binding input parameter #" << position_;
|
||||
throw odbc_soci_error(SQL_HANDLE_STMT, statement_.hstmt_, ss.str());
|
||||
}
|
||||
|
||||
// then handle indicators
|
||||
|
||||
@@ -6,18 +6,11 @@
|
||||
//
|
||||
|
||||
#define SOCI_ODBC_SOURCE
|
||||
#include "soci-odbc.h"
|
||||
#include "soci/odbc/soci-odbc.h"
|
||||
#include <cctype>
|
||||
#include <sstream>
|
||||
#include <cstring>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// disables the warning about converting int to void*. This is a 64 bit compatibility
|
||||
// warning, but odbc requires the value to be converted on this line
|
||||
// SQLSetStmtAttr(hstmt_, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER)number, 0);
|
||||
#pragma warning(disable:4312)
|
||||
#endif
|
||||
|
||||
using namespace soci;
|
||||
using namespace soci::details;
|
||||
|
||||
@@ -38,7 +31,7 @@ void odbc_statement_backend::alloc()
|
||||
if (is_odbc_error(rc))
|
||||
{
|
||||
throw odbc_soci_error(SQL_HANDLE_DBC, session_.hdbc_,
|
||||
"Allocating statement");
|
||||
"allocating statement");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,11 +124,12 @@ void odbc_statement_backend::prepare(std::string const & query,
|
||||
query_ += "?";
|
||||
}
|
||||
|
||||
SQLRETURN rc = SQLPrepare(hstmt_, (SQLCHAR*)query_.c_str(), (SQLINTEGER)query_.size());
|
||||
SQLRETURN rc = SQLPrepare(hstmt_, sqlchar_cast(query_), (SQLINTEGER)query_.size());
|
||||
if (is_odbc_error(rc))
|
||||
{
|
||||
throw odbc_soci_error(SQL_HANDLE_STMT, hstmt_,
|
||||
query_.c_str());
|
||||
std::ostringstream ss;
|
||||
ss << "preparing query \"" << query_ << "\"";
|
||||
throw odbc_soci_error(SQL_HANDLE_STMT, hstmt_, ss.str());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,15 +142,15 @@ odbc_statement_backend::execute(int number)
|
||||
{
|
||||
SQLSetStmtAttr(hstmt_, SQL_ATTR_PARAMS_PROCESSED_PTR, &rows_processed, 0);
|
||||
}
|
||||
|
||||
|
||||
// if we are called twice for the same statement we need to close the open
|
||||
// cursor or an "invalid cursor state" error will occur on execute
|
||||
SQLCloseCursor(hstmt_);
|
||||
|
||||
|
||||
SQLRETURN rc = SQLExecute(hstmt_);
|
||||
if (is_odbc_error(rc))
|
||||
{
|
||||
// If executing bulk operation a partial
|
||||
// If executing bulk operation a partial
|
||||
// number of rows affected may be available.
|
||||
if (hasVectorUseElements_)
|
||||
{
|
||||
@@ -177,12 +171,14 @@ odbc_statement_backend::execute(int number)
|
||||
// Move forward to the next result while there are rows processed.
|
||||
while (rows_processed > 0 && SQLMoreResults(hstmt_) == SQL_SUCCESS);
|
||||
}
|
||||
throw odbc_soci_error(SQL_HANDLE_STMT, hstmt_,
|
||||
"Statement Execute");
|
||||
throw odbc_soci_error(SQL_HANDLE_STMT, hstmt_, "executing statement");
|
||||
}
|
||||
// We should preserve the number of rows affected here
|
||||
// where we know for sure that a bulk operation was executed.
|
||||
else
|
||||
else if (hasVectorUseElements_)
|
||||
{
|
||||
// We already have the number of rows, no need to do anything.
|
||||
rowsAffected_ = rows_processed;
|
||||
}
|
||||
else // We need to retrieve the number of rows affected explicitly.
|
||||
{
|
||||
rowsAffected_ = 0;
|
||||
|
||||
@@ -192,7 +188,7 @@ odbc_statement_backend::execute(int number)
|
||||
if (is_odbc_error(rc))
|
||||
{
|
||||
throw odbc_soci_error(SQL_HANDLE_STMT, hstmt_,
|
||||
"Getting number of affected rows");
|
||||
"getting number of affected rows");
|
||||
}
|
||||
rowsAffected_ += res;
|
||||
}
|
||||
@@ -229,8 +225,7 @@ odbc_statement_backend::fetch(int number)
|
||||
|
||||
if (is_odbc_error(rc))
|
||||
{
|
||||
throw odbc_soci_error(SQL_HANDLE_STMT, hstmt_,
|
||||
"Statement Fetch");
|
||||
throw odbc_soci_error(SQL_HANDLE_STMT, hstmt_, "fetching data");
|
||||
}
|
||||
|
||||
return ef_success;
|
||||
@@ -243,7 +238,12 @@ long long odbc_statement_backend::get_affected_rows()
|
||||
|
||||
int odbc_statement_backend::get_number_of_rows()
|
||||
{
|
||||
return numRowsFetched_;
|
||||
return static_cast<int>(numRowsFetched_);
|
||||
}
|
||||
|
||||
std::string odbc_statement_backend::get_parameter_name(int index) const
|
||||
{
|
||||
return names_.at(index);
|
||||
}
|
||||
|
||||
std::string odbc_statement_backend::rewrite_for_procedure_call(
|
||||
@@ -276,8 +276,9 @@ void odbc_statement_backend::describe_column(int colNum, data_type & type,
|
||||
|
||||
if (is_odbc_error(rc))
|
||||
{
|
||||
throw odbc_soci_error(SQL_HANDLE_STMT, hstmt_,
|
||||
"describe Column");
|
||||
std::ostringstream ss;
|
||||
ss << "getting description of column at position " << colNum;
|
||||
throw odbc_soci_error(SQL_HANDLE_STMT, hstmt_, ss.str());
|
||||
}
|
||||
|
||||
char const *name = reinterpret_cast<char const *>(colNameBuffer);
|
||||
@@ -330,8 +331,9 @@ std::size_t odbc_statement_backend::column_size(int colNum)
|
||||
|
||||
if (is_odbc_error(rc))
|
||||
{
|
||||
throw odbc_soci_error(SQL_HANDLE_STMT, hstmt_,
|
||||
"column size");
|
||||
std::ostringstream ss;
|
||||
ss << "getting size of column at position " << colNum;
|
||||
throw odbc_soci_error(SQL_HANDLE_STMT, hstmt_, ss.str());
|
||||
}
|
||||
|
||||
return colSize;
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
###############################################################################
|
||||
#
|
||||
# This file is part of CMake configuration for SOCI library
|
||||
#
|
||||
# Copyright (C) 2010 Mateusz Loskot <mateusz@loskot.net>
|
||||
# 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)
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
if (WIN32)
|
||||
# MDBTools driver seems unreliable
|
||||
soci_backend_test(
|
||||
NAME access
|
||||
BACKEND ODBC
|
||||
SOURCE test-odbc-access.cpp
|
||||
CONNSTR "test-access.dsn")
|
||||
|
||||
# We have no means to test SQL Server at travis-ci.org
|
||||
soci_backend_test(
|
||||
NAME mssql
|
||||
BACKEND ODBC
|
||||
SOURCE test-odbc-mssql.cpp
|
||||
CONNSTR "test-mssql.dsn")
|
||||
endif()
|
||||
|
||||
soci_backend_test(
|
||||
NAME mysql
|
||||
BACKEND ODBC
|
||||
SOURCE test-odbc-mysql.cpp
|
||||
CONNSTR "test-mysql.dsn")
|
||||
|
||||
soci_backend_test(
|
||||
NAME postgresql
|
||||
BACKEND ODBC
|
||||
SOURCE test-odbc-postgresql.cpp
|
||||
CONNSTR "test-postgresql.dsn")
|
||||
|
||||
# TODO: DB2 backend is tested by Travis CI on dedicated VM, separate from ODBC,
|
||||
# in order to test DB2 with ODBC, it would be best to install DB2 driver only.
|
||||
if (NOT $ENV{TRAVIS})
|
||||
soci_backend_test(
|
||||
NAME db2
|
||||
BACKEND ODBC
|
||||
SOURCE test-odbc-db2.cpp
|
||||
CONNSTR "test-db2.dsn")
|
||||
endif()
|
||||
@@ -1,24 +0,0 @@
|
||||
# The following variable is specific to this backend and its correct
|
||||
# values might depend on your environment - feel free to set it accordingly.
|
||||
|
||||
ODBCINCLUDEDIR = -I/usr/include
|
||||
ODBCLIBDIR = -L/usr/lib
|
||||
ODBCLIBS = -lodbc -lodbcinst
|
||||
|
||||
# The rest of the Makefile is independent of the target environment.
|
||||
|
||||
COMPILER = g++
|
||||
CXXFLAGS = -Wall -pedantic -Wno-long-long
|
||||
INCLUDEDIRS = -I.. -I../../../core ${ODBCINCLUDEDIR}
|
||||
LIBDIRS = -L.. -L../../../core ${ODBCLIBDIR}
|
||||
LIBS = -lsoci_core -lsoci_odbc -ldl ${ODBCLIBS}
|
||||
|
||||
|
||||
test-odbc-mssql: test-odbc-mssql.cpp
|
||||
${COMPILER} -o $@ $? ${CXXFLAGS} ${INCLUDEDIRS} ${LIBDIRS} ${LIBS}
|
||||
|
||||
test-odbc-access: test-odbc-access.cpp
|
||||
${COMPILER} -o $@ $? ${CXXFLAGS} ${INCLUDEDIRS} ${LIBDIRS} ${LIBS}
|
||||
|
||||
clean :
|
||||
rm -f test-odbc-access.exe test-odbc-mssql.exe
|
||||
@@ -1,19 +0,0 @@
|
||||
ODBCINCLUDEDIR="C:\Program Files\Microsoft Platform SDK\Include"
|
||||
ODBCLIBDIR="C:\Program Files\Microsoft Platform SDK\Lib"
|
||||
|
||||
COMPILER = cl
|
||||
CXXFLAGS = /nologo /EHsc
|
||||
CXXFLAGSSO = $(CXXFLAGS)
|
||||
INCLUDEDIRS = /I.. /I..\..\..\core /I..\..\..\core\test /I$(ODBCINCLUDEDIR)
|
||||
LIBS = ..\..\..\core\soci-core.lib ..\soci-odbc.lib $(ODBCLIBDIR)\uuid.lib $(ODBCLIBDIR)\odbc32.lib
|
||||
|
||||
mssql: test-odbc-mssql.cpp
|
||||
$(COMPILER) $? $(CXXFLAGS) $(INCLUDEDIRS) $(LIBS)
|
||||
|
||||
access: test-odbc-access.cpp
|
||||
$(COMPILER) $? $(CXXFLAGS) $(INCLUDEDIRS) $(LIBS)
|
||||
|
||||
clean:
|
||||
del *.exe
|
||||
del *.obj
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
[ODBC]
|
||||
DRIVER=Microsoft Access Driver (*.mdb)
|
||||
UID=admin
|
||||
UserCommitSync=Yes
|
||||
Threads=3
|
||||
SafeTransactions=0
|
||||
PageTimeout=5
|
||||
MaxScanRows=8
|
||||
MaxBufferSize=2048
|
||||
FIL=MS Access
|
||||
DriverId=25
|
||||
DefaultDir=.\
|
||||
DBQ=.\soci_test.mdb
|
||||
@@ -1,8 +0,0 @@
|
||||
[ODBC]
|
||||
DRIVER=SQL Native Client
|
||||
UID=David
|
||||
DATABASE=soci_test
|
||||
WSID=NANO
|
||||
APP=Microsoft Data Access Components
|
||||
Trusted_Connection=Yes
|
||||
SERVER=localhost\SQLEXPRESS
|
||||
@@ -1,4 +0,0 @@
|
||||
[ODBC]
|
||||
DRIVER=MySQL
|
||||
DATABASE=soci_test
|
||||
OPTION=0
|
||||
@@ -1,155 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton, David Courtney
|
||||
// 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 "soci.h"
|
||||
#include "soci-odbc.h"
|
||||
#include "common-tests.h"
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
#include <ctime>
|
||||
#include <cmath>
|
||||
|
||||
using namespace soci;
|
||||
using namespace soci::tests;
|
||||
|
||||
std::string connectString;
|
||||
backend_factory const &backEnd = *soci::factory_odbc();
|
||||
|
||||
// DDL Creation objects for common tests
|
||||
struct table_creator_one : public table_creator_base
|
||||
{
|
||||
table_creator_one(session & sql)
|
||||
: table_creator_base(sql)
|
||||
{
|
||||
sql << "create table soci_test(id integer, val integer, c char, "
|
||||
"str varchar(20), sh integer, ul number, d float, "
|
||||
"tm timestamp, i1 integer, i2 integer, i3 integer, "
|
||||
"name varchar(20))";
|
||||
}
|
||||
};
|
||||
|
||||
struct table_creator_two : public table_creator_base
|
||||
{
|
||||
table_creator_two(session & sql)
|
||||
: table_creator_base(sql)
|
||||
{
|
||||
sql << "create table soci_test(num_float float, num_int integer,"
|
||||
" name varchar(20), sometime datetime, chr char)";
|
||||
}
|
||||
};
|
||||
|
||||
struct table_creator_three : public table_creator_base
|
||||
{
|
||||
table_creator_three(session & sql)
|
||||
: table_creator_base(sql)
|
||||
{
|
||||
sql << "create table soci_test(name varchar(100) not null, "
|
||||
"phone varchar(15))";
|
||||
}
|
||||
};
|
||||
|
||||
struct table_creator_for_get_affected_rows : table_creator_base
|
||||
{
|
||||
table_creator_for_get_affected_rows(session & sql)
|
||||
: table_creator_base(sql)
|
||||
{
|
||||
sql << "create table soci_test(val integer)";
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// Support for SOCI Common Tests
|
||||
//
|
||||
|
||||
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(session& s) const
|
||||
{
|
||||
return new table_creator_one(s);
|
||||
}
|
||||
|
||||
table_creator_base * table_creator_2(session& s) const
|
||||
{
|
||||
return new table_creator_two(s);
|
||||
}
|
||||
|
||||
table_creator_base * table_creator_3(session& s) const
|
||||
{
|
||||
return new table_creator_three(s);
|
||||
}
|
||||
|
||||
table_creator_base * table_creator_4(session& s) const
|
||||
{
|
||||
return new table_creator_for_get_affected_rows(s);
|
||||
}
|
||||
|
||||
std::string fromDual(std::string const &sql) const
|
||||
{
|
||||
return sql;
|
||||
}
|
||||
|
||||
std::string toDate(std::string const &datdt_string) const
|
||||
{
|
||||
return "#" + datdt_string + "#";
|
||||
}
|
||||
|
||||
std::string to_date_time(std::string const &datdt_string) const
|
||||
{
|
||||
return "#" + datdt_string + "#";
|
||||
}
|
||||
};
|
||||
|
||||
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 asser()-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];
|
||||
}
|
||||
else
|
||||
{
|
||||
connectString = "FILEDSN=./test-access.dsn";
|
||||
}
|
||||
try
|
||||
{
|
||||
std::cout << "\nSOCI ODBC with MS Access Tests:\n\n";
|
||||
|
||||
test_context tc(backEnd, connectString);
|
||||
common_tests tests(tc);
|
||||
tests.run();
|
||||
|
||||
std::cout << "\nOK, all tests passed.\n\n";
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
catch (soci::odbc_soci_error const & e)
|
||||
{
|
||||
std::cout << "ODBC Error Code: " << e.odbc_error_code() << std::endl
|
||||
<< "Native Error Code: " << e.native_error_code() << std::endl
|
||||
<< "SOCI Message: " << e.what() << std::endl
|
||||
<< "ODBC Message: " << e.odbc_error_message() << std::endl;
|
||||
}
|
||||
catch (std::exception const & e)
|
||||
{
|
||||
std::cout << "STD::EXECEPTION " << e.what() << '\n';
|
||||
}
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
@@ -1,306 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton, David Courtney
|
||||
// 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 "soci.h"
|
||||
#include "soci-odbc.h"
|
||||
#include "common-tests.h"
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
#include <ctime>
|
||||
#include <cmath>
|
||||
|
||||
using namespace soci;
|
||||
using namespace soci::tests;
|
||||
|
||||
std::string connectString;
|
||||
backend_factory const &backEnd = *soci::factory_odbc();
|
||||
|
||||
// DDL Creation objects for common tests
|
||||
struct table_creator_one : public table_creator_base
|
||||
{
|
||||
table_creator_one(session & sql)
|
||||
: table_creator_base(sql)
|
||||
{
|
||||
sql << "CREATE TABLE SOCI_TEST(ID INTEGER, VAL SMALLINT, C CHAR, STR VARCHAR(20), SH SMALLINT, UL NUMERIC(20), D DOUBLE, "
|
||||
"TM TIMESTAMP(9), I1 INTEGER, I2 INTEGER, I3 INTEGER, NAME VARCHAR(20))";
|
||||
}
|
||||
};
|
||||
|
||||
struct table_creator_two : public table_creator_base
|
||||
{
|
||||
table_creator_two(session & sql)
|
||||
: table_creator_base(sql)
|
||||
{
|
||||
sql << "CREATE TABLE SOCI_TEST(NUM_FLOAT DOUBLE, NUM_INT INTEGER, NAME VARCHAR(20), SOMETIME TIMESTAMP, CHR CHAR)";
|
||||
}
|
||||
};
|
||||
|
||||
struct table_creator_three : public table_creator_base
|
||||
{
|
||||
table_creator_three(session & sql)
|
||||
: table_creator_base(sql)
|
||||
{
|
||||
sql << "CREATE TABLE SOCI_TEST(NAME VARCHAR(100) NOT NULL, PHONE VARCHAR(15))";
|
||||
}
|
||||
};
|
||||
|
||||
struct table_creator_for_get_affected_rows : table_creator_base
|
||||
{
|
||||
table_creator_for_get_affected_rows(session & sql)
|
||||
: table_creator_base(sql)
|
||||
{
|
||||
sql << "CREATE TABLE SOCI_TEST(VAL INTEGER)";
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// Support for SOCI Common Tests
|
||||
//
|
||||
|
||||
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(session& s) const
|
||||
{
|
||||
return new table_creator_one(s);
|
||||
}
|
||||
|
||||
table_creator_base * table_creator_2(session& s) const
|
||||
{
|
||||
return new table_creator_two(s);
|
||||
}
|
||||
|
||||
table_creator_base * table_creator_3(session& s) const
|
||||
{
|
||||
return new table_creator_three(s);
|
||||
}
|
||||
|
||||
table_creator_base * table_creator_4(session& s) const
|
||||
{
|
||||
return new table_creator_for_get_affected_rows(s);
|
||||
}
|
||||
|
||||
std::string to_date_time(std::string const &datdt_string) const
|
||||
{
|
||||
return "\'" + datdt_string + "\'";
|
||||
}
|
||||
};
|
||||
|
||||
struct table_creator_bigint : table_creator_base
|
||||
{
|
||||
table_creator_bigint(session & sql)
|
||||
: table_creator_base(sql)
|
||||
{
|
||||
sql << "CREATE TABLE SOCI_TEST (VAL BIGINT)";
|
||||
}
|
||||
};
|
||||
|
||||
void test_odbc_db2_long_long()
|
||||
{
|
||||
const int num_recs = 100;
|
||||
session sql(backEnd, connectString);
|
||||
table_creator_bigint table(sql);
|
||||
|
||||
{
|
||||
long long n;
|
||||
statement st = (sql.prepare <<
|
||||
"INSERT INTO SOCI_TEST (VAL) VALUES (:val)", use(n));
|
||||
for (int i = 0; i < num_recs; i++)
|
||||
{
|
||||
n = 1000000000LL + i;
|
||||
st.execute();
|
||||
}
|
||||
}
|
||||
{
|
||||
long long n2;
|
||||
statement st = (sql.prepare <<
|
||||
"SELECT VAL FROM SOCI_TEST ORDER BY VAL", into(n2));
|
||||
st.execute();
|
||||
for (int i = 0; i < num_recs; i++)
|
||||
{
|
||||
st.fetch();
|
||||
assert(n2 == 1000000000LL + i);
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "test odbc_db2_long_long passed" << std::endl;
|
||||
}
|
||||
|
||||
void test_odbc_db2_unsigned_long_long()
|
||||
{
|
||||
const int num_recs = 100;
|
||||
session sql(backEnd, connectString);
|
||||
table_creator_bigint table(sql);
|
||||
|
||||
{
|
||||
unsigned long long n;
|
||||
statement st = (sql.prepare <<
|
||||
"INSERT INTO SOCI_TEST (VAL) VALUES (:val)", use(n));
|
||||
for (int i = 0; i < num_recs; i++)
|
||||
{
|
||||
n = 1000000000LL + i;
|
||||
st.execute();
|
||||
}
|
||||
}
|
||||
{
|
||||
unsigned long long n2;
|
||||
statement st = (sql.prepare <<
|
||||
"SELECT VAL FROM SOCI_TEST ORDER BY VAL", into(n2));
|
||||
st.execute();
|
||||
for (int i = 0; i < num_recs; i++)
|
||||
{
|
||||
st.fetch();
|
||||
assert(n2 == 1000000000LL + i);
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "test odbc_db2_unsigned_long_long passed" << std::endl;
|
||||
}
|
||||
|
||||
void test_odbc_db2_long_long_vector()
|
||||
{
|
||||
const std::size_t num_recs = 100;
|
||||
session sql(backEnd, connectString);
|
||||
table_creator_bigint table(sql);
|
||||
|
||||
{
|
||||
std::vector<long long> v(num_recs);
|
||||
for (std::size_t i = 0; i < num_recs; i++)
|
||||
{
|
||||
v[i] = 1000000000LL + i;
|
||||
}
|
||||
|
||||
sql << "INSERT INTO SOCI_TEST (VAL) VALUES (:bi)", use(v);
|
||||
}
|
||||
{
|
||||
std::size_t recs = 0;
|
||||
|
||||
std::vector<long long> v(num_recs / 2 + 1);
|
||||
statement st = (sql.prepare <<
|
||||
"SELECT VAL FROM SOCI_TEST ORDER BY VAL", into(v));
|
||||
st.execute();
|
||||
while (true)
|
||||
{
|
||||
if (!st.fetch())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
const std::size_t vsize = v.size();
|
||||
for (std::size_t i = 0; i < vsize; i++)
|
||||
{
|
||||
assert(v[i] == 1000000000LL +
|
||||
static_cast<long long>(recs));
|
||||
recs++;
|
||||
}
|
||||
}
|
||||
assert(recs == num_recs);
|
||||
}
|
||||
|
||||
std::cout << "test odbc_db2_long_long_vector passed" << std::endl;
|
||||
}
|
||||
|
||||
void test_odbc_db2_unsigned_long_long_vector()
|
||||
{
|
||||
const std::size_t num_recs = 100;
|
||||
session sql(backEnd, connectString);
|
||||
table_creator_bigint table(sql);
|
||||
|
||||
{
|
||||
std::vector<unsigned long long> v(num_recs);
|
||||
for (std::size_t i = 0; i < num_recs; i++)
|
||||
{
|
||||
v[i] = 1000000000LL + i;
|
||||
}
|
||||
|
||||
sql << "INSERT INTO SOCI_TEST (VAL) VALUES (:bi)", use(v);
|
||||
}
|
||||
{
|
||||
std::size_t recs = 0;
|
||||
|
||||
std::vector<unsigned long long> v(num_recs / 2 + 1);
|
||||
statement st = (sql.prepare <<
|
||||
"SELECT VAL FROM SOCI_TEST ORDER BY VAL", into(v));
|
||||
st.execute();
|
||||
while (true)
|
||||
{
|
||||
if (!st.fetch())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
const std::size_t vsize = v.size();
|
||||
for (std::size_t i = 0; i < vsize; i++)
|
||||
{
|
||||
assert(v[i] == 1000000000LL +
|
||||
static_cast<unsigned long long>(recs));
|
||||
recs++;
|
||||
}
|
||||
}
|
||||
assert(recs == num_recs);
|
||||
}
|
||||
|
||||
std::cout << "test odbc_db2_unsigned_long_long_vector passed" << std::endl;
|
||||
}
|
||||
|
||||
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 asser()-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];
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << std::endl <<
|
||||
"usage: test-odbc-db2 \"DSN=<db>;Uid=<user>;Pwd=<password>\"" <<
|
||||
std::endl << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
try
|
||||
{
|
||||
std::cout << "\nSOCI ODBC with DB2 Tests:\n\n";
|
||||
|
||||
test_context tc(backEnd, connectString);
|
||||
common_tests tests(tc);
|
||||
tests.run();
|
||||
|
||||
std::cout << "\nSOCI DB2 Specific Tests:\n\n";
|
||||
test_odbc_db2_long_long();
|
||||
test_odbc_db2_unsigned_long_long();
|
||||
test_odbc_db2_long_long_vector();
|
||||
test_odbc_db2_unsigned_long_long_vector();
|
||||
|
||||
std::cout << "\nOK, all tests passed.\n\n";
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
catch (soci::odbc_soci_error const & e)
|
||||
{
|
||||
std::cout << "ODBC Error Code: " << e.odbc_error_code() << std::endl
|
||||
<< "Native Error Code: " << e.native_error_code() << std::endl
|
||||
<< "SOCI Message: " << e.what() << std::endl
|
||||
<< "ODBC Message: " << e.odbc_error_message() << std::endl;
|
||||
}
|
||||
catch (std::exception const & e)
|
||||
{
|
||||
std::cout << "STD::EXECEPTION " << e.what() << '\n';
|
||||
}
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
@@ -1,148 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton, David Courtney
|
||||
// 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 "soci.h"
|
||||
#include "soci-odbc.h"
|
||||
#include "common-tests.h"
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
#include <ctime>
|
||||
#include <cmath>
|
||||
|
||||
using namespace soci;
|
||||
using namespace soci::tests;
|
||||
|
||||
std::string connectString;
|
||||
backend_factory const &backEnd = *soci::factory_odbc();
|
||||
|
||||
// DDL Creation objects for common tests
|
||||
struct table_creator_one : public table_creator_base
|
||||
{
|
||||
table_creator_one(session & sql)
|
||||
: table_creator_base(sql)
|
||||
{
|
||||
sql << "create table soci_test(id integer, val integer, c char, "
|
||||
"str varchar(20), sh smallint, ul numeric(20), d float, "
|
||||
"tm datetime, i1 integer, i2 integer, i3 integer, "
|
||||
"name varchar(20))";
|
||||
}
|
||||
};
|
||||
|
||||
struct table_creator_two : public table_creator_base
|
||||
{
|
||||
table_creator_two(session & sql)
|
||||
: table_creator_base(sql)
|
||||
{
|
||||
sql << "create table soci_test(num_float float, num_int integer,"
|
||||
" name varchar(20), sometime datetime, chr char)";
|
||||
}
|
||||
};
|
||||
|
||||
struct table_creator_three : public table_creator_base
|
||||
{
|
||||
table_creator_three(session & sql)
|
||||
: table_creator_base(sql)
|
||||
{
|
||||
sql << "create table soci_test(name varchar(100) not null, "
|
||||
"phone varchar(15))";
|
||||
}
|
||||
};
|
||||
|
||||
struct table_creator_for_get_affected_rows : table_creator_base
|
||||
{
|
||||
table_creator_for_get_affected_rows(session & sql)
|
||||
: table_creator_base(sql)
|
||||
{
|
||||
sql << "create table soci_test(val integer)";
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// Support for SOCI Common Tests
|
||||
//
|
||||
|
||||
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(session& s) const
|
||||
{
|
||||
return new table_creator_one(s);
|
||||
}
|
||||
|
||||
table_creator_base* table_creator_2(session& s) const
|
||||
{
|
||||
return new table_creator_two(s);
|
||||
}
|
||||
|
||||
table_creator_base* table_creator_3(session& s) const
|
||||
{
|
||||
return new table_creator_three(s);
|
||||
}
|
||||
|
||||
table_creator_base * table_creator_4(session& s) const
|
||||
{
|
||||
return new table_creator_for_get_affected_rows(s);
|
||||
}
|
||||
|
||||
std::string to_date_time(std::string const &datdt_string) const
|
||||
{
|
||||
return "convert(datetime, \'" + datdt_string + "\', 120)";
|
||||
}
|
||||
};
|
||||
|
||||
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 asser()-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];
|
||||
}
|
||||
else
|
||||
{
|
||||
connectString = "FILEDSN=./test-mssql.dsn";
|
||||
}
|
||||
try
|
||||
{
|
||||
std::cout << "\nSOCI ODBC with MS SQL Server Tests:\n\n";
|
||||
|
||||
test_context tc(backEnd, connectString);
|
||||
common_tests tests(tc);
|
||||
tests.run();
|
||||
|
||||
std::cout << "\nOK, all tests passed.\n\n";
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
catch (soci::odbc_soci_error const & e)
|
||||
{
|
||||
std::cout << "ODBC Error Code: " << e.odbc_error_code() << std::endl
|
||||
<< "Native Error Code: " << e.native_error_code() << std::endl
|
||||
<< "SOCI Message: " << e.what() << std::endl
|
||||
<< "ODBC Message: " << e.odbc_error_message() << std::endl;
|
||||
}
|
||||
catch (soci::soci_error const & e)
|
||||
{
|
||||
std::cout << "SOCIERROR: " << e.what() << '\n';
|
||||
}
|
||||
catch (std::exception const & e)
|
||||
{
|
||||
std::cout << "STD::EXECEPTION " << e.what() << '\n';
|
||||
}
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
@@ -1,144 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton, David Courtney
|
||||
// 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 "soci.h"
|
||||
#include "soci-odbc.h"
|
||||
#include "common-tests.h"
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
#include <ctime>
|
||||
#include <cmath>
|
||||
|
||||
using namespace soci;
|
||||
using namespace soci::tests;
|
||||
|
||||
std::string connectString;
|
||||
backend_factory const &backEnd = *soci::factory_odbc();
|
||||
|
||||
// DDL Creation objects for common tests
|
||||
struct table_creator_one : public table_creator_base
|
||||
{
|
||||
table_creator_one(session & sql)
|
||||
: table_creator_base(sql)
|
||||
{
|
||||
sql << "create table soci_test(id integer, val integer, c char, "
|
||||
"str varchar(20), sh int2, ul numeric(20), d float8, "
|
||||
"tm datetime, i1 integer, i2 integer, i3 integer, "
|
||||
"name varchar(20))";
|
||||
}
|
||||
};
|
||||
|
||||
struct table_creator_two : public table_creator_base
|
||||
{
|
||||
table_creator_two(session & sql)
|
||||
: table_creator_base(sql)
|
||||
{
|
||||
sql << "create table soci_test(num_float float8, num_int integer,"
|
||||
" name varchar(20), sometime datetime, chr char)";
|
||||
}
|
||||
};
|
||||
|
||||
struct table_creator_three : public table_creator_base
|
||||
{
|
||||
table_creator_three(session & sql)
|
||||
: table_creator_base(sql)
|
||||
{
|
||||
sql << "create table soci_test(name varchar(100) not null, "
|
||||
"phone varchar(15))";
|
||||
}
|
||||
};
|
||||
|
||||
struct table_creator_for_get_affected_rows : table_creator_base
|
||||
{
|
||||
table_creator_for_get_affected_rows(session & sql)
|
||||
: table_creator_base(sql)
|
||||
{
|
||||
sql << "create table soci_test(val integer)";
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// Support for SOCI Common Tests
|
||||
//
|
||||
|
||||
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(session& s) const
|
||||
{
|
||||
return new table_creator_one(s);
|
||||
}
|
||||
|
||||
table_creator_base * table_creator_2(session& s) const
|
||||
{
|
||||
return new table_creator_two(s);
|
||||
}
|
||||
|
||||
table_creator_base * table_creator_3(session& s) const
|
||||
{
|
||||
return new table_creator_three(s);
|
||||
}
|
||||
|
||||
table_creator_base * table_creator_4(session& s) const
|
||||
{
|
||||
return new table_creator_for_get_affected_rows(s);
|
||||
}
|
||||
|
||||
std::string to_date_time(std::string const &datdt_string) const
|
||||
{
|
||||
return "\'" + datdt_string + "\'";
|
||||
}
|
||||
};
|
||||
|
||||
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 asser()-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];
|
||||
}
|
||||
else
|
||||
{
|
||||
connectString = "FILEDSN=./test-mysql.dsn";
|
||||
}
|
||||
try
|
||||
{
|
||||
std::cout << "\nSOCI ODBC with MySQL Tests:\n\n";
|
||||
|
||||
test_context tc(backEnd, connectString);
|
||||
common_tests tests(tc);
|
||||
tests.run();
|
||||
|
||||
std::cout << "\nOK, all tests passed.\n\n";
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
catch (soci::odbc_soci_error const & e)
|
||||
{
|
||||
std::cout << "ODBC Error Code: " << e.odbc_error_code() << std::endl
|
||||
<< "Native Error Code: " << e.native_error_code() << std::endl
|
||||
<< "SOCI Message: " << e.what() << std::endl
|
||||
<< "ODBC Message: " << e.odbc_error_message() << std::endl;
|
||||
}
|
||||
catch (std::exception const & e)
|
||||
{
|
||||
std::cout << "STD::EXECEPTION " << e.what() << '\n';
|
||||
}
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
@@ -1,146 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton, David Courtney
|
||||
// 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 "soci.h"
|
||||
#include "soci-odbc.h"
|
||||
#include "common-tests.h"
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
#include <ctime>
|
||||
#include <cmath>
|
||||
|
||||
using namespace soci;
|
||||
using namespace soci::tests;
|
||||
|
||||
std::string connectString;
|
||||
backend_factory const &backEnd = *soci::factory_odbc();
|
||||
|
||||
// DDL Creation objects for common tests
|
||||
struct table_creator_one : public table_creator_base
|
||||
{
|
||||
table_creator_one(session & sql)
|
||||
: table_creator_base(sql)
|
||||
{
|
||||
sql << "create table soci_test(id integer, val integer, c char, "
|
||||
"str varchar(20), sh int2, ul numeric(20), d float8, "
|
||||
"tm timestamp, i1 integer, i2 integer, i3 integer, "
|
||||
"name varchar(20))";
|
||||
}
|
||||
};
|
||||
|
||||
struct table_creator_two : public table_creator_base
|
||||
{
|
||||
table_creator_two(session & sql)
|
||||
: table_creator_base(sql)
|
||||
{
|
||||
sql << "create table soci_test(num_float float8, num_int integer,"
|
||||
" name varchar(20), sometime timestamp, chr char)";
|
||||
}
|
||||
};
|
||||
|
||||
struct table_creator_three : public table_creator_base
|
||||
{
|
||||
table_creator_three(session & sql)
|
||||
: table_creator_base(sql)
|
||||
{
|
||||
sql << "create table soci_test(name varchar(100) not null, "
|
||||
"phone varchar(15))";
|
||||
}
|
||||
};
|
||||
|
||||
struct table_creator_for_get_affected_rows : table_creator_base
|
||||
{
|
||||
table_creator_for_get_affected_rows(session & sql)
|
||||
: table_creator_base(sql)
|
||||
{
|
||||
sql << "create table soci_test(val integer)";
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// Support for SOCI Common Tests
|
||||
//
|
||||
|
||||
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(session& s) const
|
||||
{
|
||||
return new table_creator_one(s);
|
||||
}
|
||||
|
||||
table_creator_base * table_creator_2(session& s) const
|
||||
{
|
||||
return new table_creator_two(s);
|
||||
}
|
||||
|
||||
table_creator_base * table_creator_3(session& s) const
|
||||
{
|
||||
return new table_creator_three(s);
|
||||
}
|
||||
|
||||
table_creator_base * table_creator_4(session& s) const
|
||||
{
|
||||
return new table_creator_for_get_affected_rows(s);
|
||||
}
|
||||
|
||||
std::string to_date_time(std::string const &datdt_string) const
|
||||
{
|
||||
return "timestamptz(\'" + datdt_string + "\')";
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
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 asser()-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];
|
||||
}
|
||||
else
|
||||
{
|
||||
connectString = "FILEDSN=./test-postgresql.dsn";
|
||||
}
|
||||
try
|
||||
{
|
||||
std::cout << "\nSOCI ODBC with PostgreSQL Tests:\n\n";
|
||||
|
||||
test_context tc(backEnd, connectString);
|
||||
common_tests tests(tc);
|
||||
tests.run();
|
||||
|
||||
std::cout << "\nOK, all tests passed.\n\n";
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
catch (soci::odbc_soci_error const & e)
|
||||
{
|
||||
std::cout << "ODBC Error Code: " << e.odbc_error_code() << std::endl
|
||||
<< "Native Error Code: " << e.native_error_code() << std::endl
|
||||
<< "SOCI Message: " << e.what() << std::endl
|
||||
<< "ODBC Message: " << e.odbc_error_message() << std::endl;
|
||||
}
|
||||
catch (std::exception const & e)
|
||||
{
|
||||
std::cout << "STD::EXECEPTION " << e.what() << '\n';
|
||||
}
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
[ODBC]
|
||||
Description=DSN for SOCI ODBC connection to PostgreSQL
|
||||
Driver=PostgreSQL ANSI
|
||||
Server=localhost
|
||||
Port=5432
|
||||
Database=soci_test
|
||||
UID=postgres
|
||||
PWD=
|
||||
@@ -6,9 +6,10 @@
|
||||
//
|
||||
|
||||
#define SOCI_ODBC_SOURCE
|
||||
#include "soci-odbc.h"
|
||||
#include <soci-platform.h>
|
||||
#include <cassert>
|
||||
#include "soci/soci-platform.h"
|
||||
#include "soci/odbc/soci-odbc.h"
|
||||
#include "soci-mktime.h"
|
||||
#include "soci-static-assert.h"
|
||||
#include <cctype>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
@@ -55,7 +56,7 @@ void odbc_vector_into_type_backend::define_by_pos(
|
||||
{
|
||||
odbcType_ = SQL_C_SLONG;
|
||||
size = sizeof(SQLINTEGER);
|
||||
assert(sizeof(SQLINTEGER) == sizeof(int));
|
||||
SOCI_STATIC_ASSERT(sizeof(SQLINTEGER) == sizeof(int));
|
||||
std::vector<int> *vp = static_cast<std::vector<int> *>(data);
|
||||
std::vector<int> &v(*vp);
|
||||
prepare_indicators(v.size());
|
||||
@@ -177,13 +178,14 @@ void odbc_vector_into_type_backend::define_by_pos(
|
||||
case x_blob: break; // not supported
|
||||
}
|
||||
|
||||
SQLRETURN rc
|
||||
SQLRETURN rc
|
||||
= SQLBindCol(statement_.hstmt_, static_cast<SQLUSMALLINT>(position++),
|
||||
odbcType_, static_cast<SQLPOINTER>(data), size, indHolders_);
|
||||
if (is_odbc_error(rc))
|
||||
{
|
||||
throw odbc_soci_error(SQL_HANDLE_STMT, statement_.hstmt_,
|
||||
"vector into type define by pos");
|
||||
std::ostringstream ss;
|
||||
ss << "binding output vector column #" << position;
|
||||
throw odbc_soci_error(SQL_HANDLE_STMT, statement_.hstmt_, ss.str());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -238,20 +240,10 @@ void odbc_vector_into_type_backend::post_fetch(bool gotData, indicator *ind)
|
||||
std::size_t const vsize = v.size();
|
||||
for (std::size_t i = 0; i != vsize; ++i)
|
||||
{
|
||||
std::tm t;
|
||||
|
||||
TIMESTAMP_STRUCT * ts = reinterpret_cast<TIMESTAMP_STRUCT*>(pos);
|
||||
t.tm_isdst = -1;
|
||||
t.tm_year = ts->year - 1900;
|
||||
t.tm_mon = ts->month - 1;
|
||||
t.tm_mday = ts->day;
|
||||
t.tm_hour = ts->hour;
|
||||
t.tm_min = ts->minute;
|
||||
t.tm_sec = ts->second;
|
||||
|
||||
// normalize and compute the remaining fields
|
||||
std::mktime(&t);
|
||||
v[i] = t;
|
||||
details::mktime_from_ymdhms(v[i],
|
||||
ts->year, ts->month, ts->day,
|
||||
ts->hour, ts->minute, ts->second);
|
||||
pos += colSize_;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
//
|
||||
|
||||
#define SOCI_ODBC_SOURCE
|
||||
#include "soci-odbc.h"
|
||||
#include <soci-platform.h>
|
||||
#include <cassert>
|
||||
#include "soci/soci-platform.h"
|
||||
#include "soci/odbc/soci-odbc.h"
|
||||
#include "soci-static-assert.h"
|
||||
#include <cctype>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
@@ -57,7 +57,7 @@ void odbc_vector_use_type_backend::prepare_for_bind(void *&data, SQLUINTEGER &si
|
||||
sqlType = SQL_INTEGER;
|
||||
cType = SQL_C_SLONG;
|
||||
size = sizeof(SQLINTEGER);
|
||||
assert(sizeof(SQLINTEGER) == sizeof(int));
|
||||
SOCI_STATIC_ASSERT(sizeof(SQLINTEGER) == sizeof(int));
|
||||
std::vector<int> *vp = static_cast<std::vector<int> *>(data);
|
||||
std::vector<int> &v(*vp);
|
||||
prepare_indicators(v.size());
|
||||
@@ -230,8 +230,9 @@ void odbc_vector_use_type_backend::bind_helper(int &position, void *data, exchan
|
||||
|
||||
if (is_odbc_error(rc))
|
||||
{
|
||||
throw odbc_soci_error(SQL_HANDLE_STMT, statement_.hstmt_,
|
||||
"Error while binding value to column");
|
||||
std::ostringstream ss;
|
||||
ss << "binding input vector parameter #" << position;
|
||||
throw odbc_soci_error(SQL_HANDLE_STMT, statement_.hstmt_, ss.str());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,9 +10,6 @@
|
||||
###############################################################################
|
||||
soci_backend(Oracle
|
||||
DEPENDS Oracle
|
||||
HEADERS soci-oracle.h error.h
|
||||
DESCRIPTION "SOCI backend for Oracle 10+"
|
||||
AUTHORS "Maciej Sobczak, Stephen Hutton"
|
||||
MAINTAINERS "Maciej Sobczak")
|
||||
|
||||
add_subdirectory(test)
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
# The following variable is specific to this backend and its correct
|
||||
# values might depend on your environment - feel free to set it accordingly.
|
||||
|
||||
ORACLEINCLUDEDIR = -I/usr/lib/oracle/xe/app/oracle/product/10.2.0/server/rdbms/public
|
||||
ORACLEINCLUDEDIR = -I${ORACLE_HOME}/rdbms/public
|
||||
|
||||
# The rest of the Makefile is indepentent of the target environment.
|
||||
|
||||
COMPILER = g++
|
||||
CXXFLAGS = -Wall -pedantic -Wno-long-long
|
||||
CXXFLAGSSO = ${CXXFLAGS} -fPIC
|
||||
INCLUDEDIRS = -I../../core ${ORACLEINCLUDEDIR}
|
||||
INCLUDEDIRS = -I../../../include -I../../../include/private ${ORACLEINCLUDEDIR}
|
||||
|
||||
OBJECTS = blob.o factory.o row-id.o session.o standard-into-type.o \
|
||||
standard-use-type.o statement.o vector-into-type.o vector-use-type.o \
|
||||
@@ -22,9 +22,9 @@ libsoci_oracle.a : ${OBJECTS}
|
||||
ar rv $@ $?
|
||||
rm *.o
|
||||
|
||||
soci-oracle.o : soci-oracle.cpp
|
||||
soci-oracle.o : soci-oracle.cpp
|
||||
${COMPILER} -c $? ${CXXFLAGS} ${INCLUDEDIRS}
|
||||
|
||||
|
||||
blob.o : blob.cpp
|
||||
${COMPILER} -c $? ${CXXFLAGS} ${INCLUDEDIRS}
|
||||
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#include "soci-oracle.h"
|
||||
#include "soci/oracle/soci-oracle.h"
|
||||
#include "error.h"
|
||||
#include "statement.h"
|
||||
#include "soci/statement.h"
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
#include <cstdio>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
//
|
||||
|
||||
#define SOCI_ORACLE_SOURCE
|
||||
#include "soci-oracle.h"
|
||||
#include "soci/oracle/soci-oracle.h"
|
||||
#include "error.h"
|
||||
#include <limits>
|
||||
#include <sstream>
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#ifndef SOCI_ORACLE_ERROR_H_INCLUDED
|
||||
#define SOCI_ORACLE_ERROR_H_INCLUDED
|
||||
|
||||
#include "soci-oracle.h"
|
||||
#include "soci/oracle/soci-oracle.h"
|
||||
|
||||
namespace soci
|
||||
{
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user