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 &amp; 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:
Nik Bougalis
2015-08-18 08:43:51 -07:00
parent 9708a12607
commit caab155a00
386 changed files with 26285 additions and 19139 deletions

15
.gitignore vendored
View File

@@ -1,5 +1,6 @@
# General
*.swp
*.kate-swp
tags
tmp
@@ -8,6 +9,16 @@ _build*
src/_build*
src/build
# Files generated by CMake
Makefile
src/core/soci_backends_config.h
# ... and the rest of CMake spam
CMakeFiles/
CMakeCache.txt
CTestTestfile.cmake
cmake_install.cmake
# Visual Studio
*.opensdf
*.sdf
@@ -22,3 +33,7 @@ src/build
*.creator*
*.files
*.includes
CMakeLists.txt.user
# Eclipse
/.project

View File

@@ -14,15 +14,20 @@ services:
- postgresql
env:
matrix:
- SOCI_TRAVIS_BACKEND=db2
- SOCI_TRAVIS_BACKEND=empty
- SOCI_TRAVIS_BACKEND=firebird
- SOCI_TRAVIS_BACKEND=mysql
- SOCI_TRAVIS_BACKEND=odbc
- SOCI_TRAVIS_BACKEND=oracle
- SOCI_TRAVIS_BACKEND=postgresql
- SOCI_TRAVIS_BACKEND=sqlite3
- SOCI_TRAVIS_BACKEND=db2
- SOCI_TRAVIS_BACKEND=empty
- SOCI_TRAVIS_BACKEND=firebird
- SOCI_TRAVIS_BACKEND=mysql
- SOCI_TRAVIS_BACKEND=odbc
- SOCI_TRAVIS_BACKEND=oracle CFLAGS=-m32 CXXFLAGS=-m32 WITH_BOOST=OFF
- SOCI_TRAVIS_BACKEND=postgresql
- SOCI_TRAVIS_BACKEND=postgression
- SOCI_TRAVIS_BACKEND=sqlite3
matrix:
fast_finish: true
allow_failures:
- env: SOCI_TRAVIS_BACKEND=postgression
before_install: ./bin/ci/before_install.sh
before_script: ./bin/ci/before_script.sh
@@ -32,8 +37,8 @@ notifications:
email:
recipients:
- soci-devel@lists.sourceforge.net
on_success: change # [always|never|change] # default: change
on_failure: always # [always|never|change] # default: always
on_success: change # [always|never|change] # default: change
on_failure: always # [always|never|change] # default: always
irc:
channels:

View File

@@ -19,6 +19,8 @@ Viacheslav Naydenov
We would like to thank you for your contributions
- they allowed us to improve the quality of the SOCI library:
Adesmier
Alex Volanis
Andrey Belobrov
Andrey Utkin
Andriy Gapon
@@ -52,6 +54,7 @@ Matt Arsenault
Matthieu Kermagoret
Michael Davidsaver
Mika Fischer
pacocamberos
Paul Bondo
Petr Vanek
Philip Pemberton
@@ -69,5 +72,7 @@ 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!
There are a lot of people that help to drive SOCI project forward,
if we have forgot to mention someone in here,
if you would like to be listed by name instead of GitHub username,
send us an email!

View File

@@ -1,10 +1,55 @@
This file contains the history of changes in the SOCI library.
---
Version 4.0.0 differs from 3.2.x in the following ways:
- Provide context of the failure in soci_error::what() which now returns a
longer and more useful message. Use the new get_error_message() method to get
just the brief error message which used to be returned by what().
- Firebird
-- Add SOCI_FIREBIRD_EMBEDDED option to allow building with embedded library.
-- Throw an exception instead of truncating too long VARCHAR columns values.
- ODBC/MS SQL
-- Fix inserting strings of length greater than 8000 bytes into database.
- Oracle
-- Use SQLT_BDOUBLE for floating point values instead of SQLT_FLT.
---
Version 3.2.3 differs from 3.2.2 in the following ways:
- Improved Boost Tuple & Fusion integration by using boost::fusion::foreach
to reference each member of a sequence. Breaks compatibility with Boost 1.35 (2008).
- Fixed linker error when building 64-bit target with Visual Studio.
- Fixed several issues with building using Cygwin and MinGW.
- Clarified documentation and examples on bulk operations.
- MySQL
-- Fixed building against MySQL 3.23.
- ODBC
- Improve readability of ODBC error messages.
- Fixed CMake configuration of ODBC backend for Visual Studio 64-bit targets.
- Oracle
-- We've had to disable Oracle target in the Travis CI configuration until we
figure out how to setup Oracle on Travis CI directly.
Therefore, this release hasn't been extensively tested against Oracle.
- PostgreSQL
-- Added support for UUID column type (tests and docs updated).
- SQLite3
-- Added sqlite3_soci_error exception as subclass of soci_error to provide useful
exposure of specific SQLite3 error codes (tests and docs updated).
---
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
- 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
@@ -77,7 +122,7 @@ Version 3.2.1 differs from 3.2.0 in the following ways:
---
Version 3.2.0 differs from 3.1.0 in the following ways:
- SOCI is now organization at GitHub
- 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
@@ -124,7 +169,7 @@ Version 3.2.0 differs from 3.1.0 in the following ways:
-- 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 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
@@ -297,7 +342,7 @@ Version 2.0.1 differs from 2.0.0 in the following ways:
- 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
Values::set<T>() and Values::get<T>() are called where T is a
TypeConversion-based type.
---

159
CMakeLists.txt Normal file
View File

@@ -0,0 +1,159 @@
###############################################################################
#
# This file is part of CMake configuration for SOCI library
#
# Copyright (C) 2009-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)
include(SociConfig)
colormsg(_HIBLUE_ "Configuring SOCI:")
###############################################################################
# SOCI version information
###############################################################################
include(SociVersion)
# The version here should be in sync with the one in include/soci/version.h.
soci_version(MAJOR 4 MINOR 0 PATCH 0)
###############################################################################
# Build features and variants
##############################################################################
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)
# from SociConfig.cmake
boost_report_value(SOCI_CXX_C11)
# 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_TARGET)
set(SOCI_CORE_TARGET_STATIC)
set(SOCI_CORE_DEPS_LIBS)
include(SociDependencies)
get_property(SOCI_INCLUDE_DIRS DIRECTORY ${CMAKE_SOURCE_DIR}
PROPERTY INCLUDE_DIRECTORIES)
if(Threads_FOUND)
list(APPEND SOCI_CORE_DEPS_LIBS ${CMAKE_THREAD_LIBS_INIT})
else()
message(FATAL_ERROR "No thread library found")
endif()
if(NOT MSVC)
set(DL_FIND_QUIETLY TRUE)
find_package(DL)
if(DL_FOUND)
list(APPEND SOCI_CORE_DEPS_LIBS ${DL_LIBRARY})
set_directory_properties(PROPERTIES INCLUDE_DIRECTORIES ${DL_INCLUDE_DIR})
add_definitions(-DHAVE_DL=1)
endif()
else() #MSVC
# This flag enables multi process compiling for Visual Studio 2005 and above
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
endif()
if(Boost_FOUND)
get_property(SOCI_COMPILE_DEFINITIONS
DIRECTORY ${CMAKE_SOURCE_DIR}
PROPERTY COMPILE_DEFINITIONS)
list(APPEND SOCI_COMPILE_DEFINITIONS "HAVE_BOOST=1")
if(Boost_DATE_TIME_FOUND)
list(APPEND SOCI_CORE_DEPS_LIBS ${Boost_DATE_TIME_LIBRARY})
list(APPEND SOCI_COMPILE_DEFINITIONS "HAVE_BOOST_DATE_TIME=1")
endif()
list(APPEND SOCI_INCLUDE_DIRS ${Boost_INCLUDE_DIRS})
list(APPEND SOCI_CORE_INCLUDE_DIRS ${Boost_INCLUDE_DIRS})
set_directory_properties(PROPERTY COMPILE_DEFINITIONS "${SOCI_COMPILE_DEFINITIONS}")
set_property(DIRECTORY ${SOCI_SOURCE_DIR}
PROPERTY COMPILE_DEFINITIONS "${SOCI_COMPILE_DEFINITIONS}")
endif()
list(APPEND SOCI_INCLUDE_DIRS ${CMAKE_CURRENT_BINARY_DIR})
set_property(DIRECTORY ${CMAKE_SOURCE_DIR}
PROPERTY
INCLUDE_DIRECTORIES ${SOCI_INCLUDE_DIRS})
###############################################################################
# Installation
###############################################################################
if(NOT DEFINED SOCI_LIBDIR)
if(APPLE OR CMAKE_SIZEOF_VOID_P EQUAL 4)
set(SOCI_LIBDIR "lib")
else()
set(SOCI_LIBDIR "lib64")
endif()
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}/include)
add_subdirectory(src)
add_subdirectory(tests)
message(STATUS "")

View File

@@ -6,7 +6,7 @@ Website: http://soci.sourceforge.net
GitHub hosts SOCI source code repository, issues tracker and wiki:
https://github.com/SOCI
Downloads and mailing lists at
Downloads and mailing lists at
http://sourceforge.net/projects/soci/
Travis CI service at https://travis-ci.org/SOCI/soci
@@ -23,18 +23,18 @@ Requirements
Core:
* C++ compiler
* Boost C++ Libraries (optional, headers only)
* Boost C++ Libraries (optional, headers and Boost.DateTime)
Backend specific client libraries for:
* DB2
* Firebird
* MySQL
* ODBC andwith specific database driver
* ODBC with specific database driver
* Oracle
* PostgreSQL
* SQLite 3
See documentation at http://soci.sourceforge.net for details
See documentation at http://soci.sourceforge.net for details
Brief History
-------------

View File

@@ -75,7 +75,7 @@ Additional pair based val/indicator interface?
Consolidate iteration methods?
most radical: do we still need Statement::fetch()? into()?
(Rowset<Row> can currently be used for any query, supports indicators,
defaults, and no need to check for eNodata)
defaults, and no need to check for eNodata)
---
ColumnProperties() more logically belongs to Rowset than to Row
@@ -121,7 +121,7 @@ Sub-concepts:
- joins are tricky
- boolean operators (<,>,=,<=,=> and <>) and WHERE-like clause support as a query
rowset<Row> rs = (s.prepare << "age > 28") // rows where field 'age' is less than 28
rowset<Row> rs = (s.prepare << "age <> 28") // rows where field 'age' is less or more than 28
rowset<Row> rs = (s.prepare << "firstname='John' AND age > 28") // multi-fields combined queries

View File

@@ -1,4 +1,4 @@
#!/bin/bash -e
#!/bin/bash
# Run before_install actions for SOCI build at travis-ci.org
#
# Copyright (c) 2013 Mateusz Loskot <mateusz@loskot.net>
@@ -6,8 +6,14 @@
source ${TRAVIS_BUILD_DIR}/bin/ci/common.sh
sudo apt-key adv --recv-keys --keyserver keyserver.ubuntu.com 16126D3A3E5C1192
sudo apt-get update -qq
sudo apt-get install -qq libboost-dev libboost-date-time-dev
sudo add-apt-repository -y ppa:apt-fast/stable
sudo apt-get update -qq -y
sudo apt-get install -qq -y apt-fast
sudo apt-fast update -qq -y
sudo apt-fast install -qq -y libboost-dev libboost-date-time-dev
before_install="${TRAVIS_BUILD_DIR}/bin/ci/before_install_${SOCI_TRAVIS_BACKEND}.sh"
[ -x ${before_install} ] && ${before_install} || echo "nothing to run"
if [ -x ${before_install} ]; then
echo "Running ${before_install}"
${before_install}
fi

View File

@@ -8,7 +8,7 @@ source ${TRAVIS_BUILD_DIR}/bin/ci/common.sh
sudo apt-get install -qq firebird2.5-super firebird2.5-dev
# Configure Firebird server
# See: Non-interactive setup for travis-ci.org
# See: Non-interactive setup for travis-ci.org
# http://tech.groups.yahoo.com/group/firebird-support/message/120883
#sudo dpkg-reconfigure -f noninteractive firebird2.5-super
sudo sed /ENABLE_FIREBIRD_SERVER=/s/no/yes/ -i /etc/default/firebird2.5

View File

@@ -1,15 +1,123 @@
#!/bin/bash -e
# Install Oracle client libraries for SOCI at travis-ci.org
#!/bin/bash
# Script performs non-interactive installation of Oracle XE 10g on Debian
#
# Copyright (c) 2013 Mateusz Loskot <mateusz@loskot.net>
# Based on oracle10g-update.sh from HTSQL project:
# https://bitbucket.org/prometheus/htsql
#
# Modified by Mateusz Loskot <mateusz@loskot.net>
# Changes:
# - Add fake swap support (backup /usr/bin/free manually anyway!)
# - Increase Oracle XE's PROCESSES parameter to value from range 100-200.
# Required to prevent random ORA-12520 errors while running tests.
#
# Modified by Peter Butkovic <butkovic@gmail.com> to enable i386 install on amd64 architecture (precise 64)
# based on: http://www.ubuntugeek.com/how-to-install-oracle-10g-xe-in-64-bit-ubuntu.html
#
# set -ex
source ${TRAVIS_BUILD_DIR}/bin/ci/common.sh
sudo apt-get install -qq tar bzip2 libaio1
#
# Utilities
#
function free_backup()
{
# Multiple copies to be on safe side
sudo cp /usr/bin/free /root
sudo mv /usr/bin/free /usr/bin/free.original
}
wget http://brzuchol.loskot.net/software/oracle/instantclient_11_2-linux-x64-mloskot.tar.bz2
tar -jxf instantclient_11_2-linux-x64-mloskot.tar.bz2
sudo mkdir -p /opt
sudo mv instantclient_11_2 /opt
sudo ln -s ${ORACLE_HOME}/libclntsh.so.11.1 ${ORACLE_HOME}/libclntsh.so
sudo ln -s ${ORACLE_HOME}/libocci.so.11.1 ${ORACLE_HOME}/libocci.so
function free_restore()
{
sudo cp /usr/bin/free.original /usr/bin/free
}
# Install fake free
# http://www.axelog.de/2010/02/7-oracle-ee-refused-to-install-into-openvz/
free_backup
sudo tee /usr/bin/free <<EOF > /dev/null
#!/bin/sh
cat <<__eof
total used free shared buffers cached
Mem: 1048576 327264 721312 0 0 0
-/+ buffers/cache: 327264 721312
Swap: 2000000 0 2000000
__eof
exit
EOF
sudo chmod 755 /usr/bin/free
#
# ok, bc, is the dependency that is required by DB2 as well => let's remove it from oracle xe dependencies and provide 64bit one only
#
# Install the Oracle 10g dependant packages
sudo apt-fast install -qq -y --force-yes libc6:i386
# travis needs the "apt-transport-https" to enable https transport
sudo apt-fast install -qq -y bc apt-transport-https
# add Oracle repo + key (please note https is a must here, otherwise "apt-get update" fails for this repo with the "Undetermined error")
sudo bash -c 'echo "deb https://oss.oracle.com/debian/ unstable main non-free" >/etc/apt/sources.list.d/oracle.list'
wget -q https://oss.oracle.com/el4/RPM-GPG-KEY-oracle -O- | sudo apt-key add -
sudo apt-fast update -qq -y
# only download the package, to manually install afterwards
sudo apt-fast install -qq -y --force-yes -d oracle-xe-universal:i386
sudo apt-fast install -qq -y --force-yes libaio:i386
# remove key + repo (to prevent failures on next updates)
sudo apt-key del B38A8516
sudo bash -c 'rm -rf /etc/apt/sources.list.d/oracle.list'
sudo apt-fast update -qq -y
sudo apt-get autoremove -qq
# remove bc from the dependencies of the oracle-xe-universal package (to keep 64bit one installed)
mkdir /tmp/oracle_unpack
dpkg-deb -x /var/cache/apt/archives/oracle-xe-universal_10.2.0.1-1.1_i386.deb /tmp/oracle_unpack
cd /tmp/oracle_unpack
dpkg-deb --control /var/cache/apt/archives/oracle-xe-universal_10.2.0.1-1.1_i386.deb
sed -i "s/,\ bc//g" /tmp/oracle_unpack/DEBIAN/control
mkdir /tmp/oracle_repack
dpkg -b /tmp/oracle_unpack /tmp/oracle_repack/oracle-xe-universal_fixed_10.2.0.1-1.1_i386.deb
# install Oracle 10g with the fixed dependencies, to prevent i386/amd64 conflicts on bc package
sudo dpkg -i --force-architecture /tmp/oracle_repack/oracle-xe-universal_fixed_10.2.0.1-1.1_i386.deb
# Fix the problem when the configuration script eats the last
# character of the password if it is 'n': replace IFS="\n" with IFS=$'\n'.
sudo sed -i -e s/IFS=\"\\\\n\"/IFS=\$\'\\\\n\'/ /etc/init.d/oracle-xe
# Configure the server; provide the answers for the following questions:
# The HTTP port for Oracle Application Express: 8080
# A port for the database listener: 1521
# The password for the SYS and SYSTEM database accounts: admin
# Start the server on boot: yes
sudo /etc/init.d/oracle-xe configure <<END
8080
1521
admin
admin
y
END
# Load Oracle environment variables so that we could run `sqlplus`.
. /usr/lib/oracle/xe/app/oracle/product/10.2.0/server/bin/oracle_env.sh
# Increase the number of connections.
echo "ALTER SYSTEM SET PROCESSES=200 SCOPE=SPFILE;" | \
sqlplus -S -L sys/admin AS SYSDBA
# need to restart, to apply connection number update
sudo /etc/init.d/oracle-xe restart
# Set Oracle environment variables on login.
# NOTE, mloskot: On Travis CI, fails with Permission denied
#sudo cat <<END >>/root/.bashrc
#. /usr/lib/oracle/xe/app/oracle/product/10.2.0/server/bin/oracle_env.sh
#END
free_restore
# Install development toolset for 32-bit for Travis CI 64-bit
sudo apt-fast install -qq -y g++-multilib

View File

@@ -1,4 +1,4 @@
#!/bin/bash -e
#!/bin/bash
# Run before_script actions for SOCI build at travis-ci.org
#
# Copyright (c) 2013 Mateusz Loskot <mateusz@loskot.net>
@@ -6,4 +6,7 @@
source ${TRAVIS_BUILD_DIR}/bin/ci/common.sh
before_script="${TRAVIS_BUILD_DIR}/bin/ci/before_script_${SOCI_TRAVIS_BACKEND}.sh"
[ -x ${before_script} ] && ${before_script} || echo "nothing to run"
if [ -x ${before_script} ]; then
echo "Running ${before_script}"
${before_script}
fi

View File

@@ -7,5 +7,5 @@ source ${TRAVIS_BUILD_DIR}/bin/ci/common.sh
mysql --version
mysql -e 'create database soci_test;'
psql --version
psql --version
psql -c 'create database soci_test;' -U postgres

45
bin/ci/before_script_oracle.sh Executable file
View File

@@ -0,0 +1,45 @@
#!/bin/bash
# Sets up environment for p6psy backend Oracle at travis-ci.org
#
# Copyright (c) 2013 Peter Butkovic <butkovic@gmail.com>
#
# Modified by Mateusz Loskot <mateusz@loskot.net>
# Changes:
# - Check connection as user for testing
#
# for some reason the file is not found any more here => creating user in install script
# Load Oracle environment variables so that we could run `sqlplus`.
. /usr/lib/oracle/xe/app/oracle/product/10.2.0/server/bin/oracle_env.sh
echo "ORACLE_HOME=${ORACLE_HOME}"
echo "ORACLE_SID=${ORACLE_SID}"
# create user for testing
echo "CREATE USER travis IDENTIFIED BY travis;" | \
sqlplus -S -L sys/admin AS SYSDBA
echo "grant connect, resource to travis;" | \
sqlplus -S -L sys/admin AS SYSDBA
echo "grant create session, alter any procedure to travis;" | \
sqlplus -S -L sys/admin AS SYSDBA
# to enable xa recovery, see: https://community.oracle.com/thread/378954
echo "grant select on sys.dba_pending_transactions to travis;" | \
sqlplus -S -L sys/admin AS SYSDBA
echo "grant select on sys.pending_trans$ to travis;" | \
sqlplus -S -L sys/admin AS SYSDBA
echo "grant select on sys.dba_2pc_pending to travis;" | \
sqlplus -S -L sys/admin AS SYSDBA
echo "grant execute on sys.dbms_system to travis;" | \
sqlplus -S -L sys/admin AS SYSDBA
# increase default=40 value of processes to prevent ORA-12520 failures while testing
echo "alter system set processes=100 scope=spfile;" | \
sqlplus -S -L sys/admin AS SYSDBA
# check connection as user for testing
echo "Connecting using travis/travis@XE"
echo "SELECT * FROM product_component_version;" | \
sqlplus -S -L travis/travis@XE

View File

@@ -5,5 +5,5 @@
#
source ${TRAVIS_BUILD_DIR}/bin/ci/common.sh
psql --version
psql --version
psql -c 'create database soci_test;' -U postgres

View File

@@ -15,8 +15,6 @@ if [[ -f /sys/devices/system/cpu/online ]]; then
# Calculates 1.5 times physical threads
TCI_NUMTHREADS=$(( ( $(cut -f 2 -d '-' /sys/devices/system/cpu/online) + 1 ) * 15 / 10 ))
fi
export ORACLE_HOME=/opt/instantclient_11_2
export LD_LIBRARY_PATH=${ORACLE_HOME}:${LD_LIBRARY_PATH}
#
# Functions
#
@@ -27,10 +25,10 @@ tmstamp()
run_make()
{
[ $TCI_NUMTHREADS -gt 0 ] && make -j $TCI_NUMTHREADS ] || make
[ $TCI_NUMTHREADS -gt 0 ] && make -j $TCI_NUMTHREADS || make
}
run_test()
{
ctest -V --output-on-failure .
ctest -V --output-on-failure "$@" .
}

14
bin/ci/oracle.sh Normal file
View File

@@ -0,0 +1,14 @@
# Definitions used by SOCI when building Oracle backend at travis-ci.org
#
# Copyright (c) 2015 Vadim Zeitlin <vz-soci@zeitlins.org>
#
# Notice that this file is not executable, it is supposed to be sourced from
# the other files.
# Load Oracle environment variables
. /usr/lib/oracle/xe/app/oracle/product/10.2.0/server/bin/oracle_env.sh
echo "ORACLE_HOME=${ORACLE_HOME}"
echo "ORACLE_SID=${ORACLE_SID}"
LD_LIBRARY_PATH=${ORACLE_HOME}:${LD_LIBRARY_PATH}
export LD_LIBRARY_PATH

View File

@@ -1,4 +1,4 @@
#!/bin/bash -e
#!/bin/bash
# Run test script actions for SOCI build at travis-ci.org
#
# Copyright (c) 2013 Mateusz Loskot <mateusz@loskot.net>
@@ -6,9 +6,11 @@
source ${TRAVIS_BUILD_DIR}/bin/ci/common.sh
# prepare build directory
builddir="${TRAVIS_BUILD_DIR}/src/_build"
builddir="${TRAVIS_BUILD_DIR}/_build"
mkdir -p ${builddir}
cd ${builddir}
# build and run tests
${TRAVIS_BUILD_DIR}/bin/ci/script_${SOCI_TRAVIS_BACKEND}.sh
SCRIPT=${TRAVIS_BUILD_DIR}/bin/ci/script_${SOCI_TRAVIS_BACKEND}.sh
echo "Running ${SCRIPT}"
${SCRIPT}

View File

@@ -7,6 +7,7 @@
source ${TRAVIS_BUILD_DIR}/bin/ci/common.sh
cmake \
-DCMAKE_VERBOSE_MAKEFILE=ON \
-DSOCI_TESTS=ON \
-DSOCI_STATIC=OFF \
-DSOCI_DB2=ON \
@@ -18,7 +19,7 @@ cmake \
-DSOCI_POSTGRESQL=OFF \
-DSOCI_SQLITE3=OFF \
-DSOCI_DB2_TEST_CONNSTR:STRING="DSN=SOCITEST\;Uid=db2inst1\;Pwd=db2inst1" \
..
..
run_make
run_test

View File

@@ -6,6 +6,7 @@
source ${TRAVIS_BUILD_DIR}/bin/ci/common.sh
cmake \
-DCMAKE_VERBOSE_MAKEFILE=ON \
-DSOCI_TESTS=ON \
-DSOCI_STATIC=OFF \
-DSOCI_DB2=OFF \

View File

@@ -6,6 +6,7 @@
source ${TRAVIS_BUILD_DIR}/bin/ci/common.sh
cmake \
-DCMAKE_VERBOSE_MAKEFILE=ON \
-DSOCI_TESTS=ON \
-DSOCI_STATIC=OFF \
-DSOCI_DB2=OFF \
@@ -17,7 +18,7 @@ cmake \
-DSOCI_POSTGRESQL=OFF \
-DSOCI_SQLITE3=OFF \
-DSOCI_FIREBIRD_TEST_CONNSTR:STRING="service=LOCALHOST:/tmp/soci_test.fdb user=SYSDBA password=masterkey" \
..
..
run_make
run_test

View File

@@ -6,6 +6,7 @@
source ${TRAVIS_BUILD_DIR}/bin/ci/common.sh
cmake \
-DCMAKE_VERBOSE_MAKEFILE=ON \
-DSOCI_TESTS=ON \
-DSOCI_STATIC=OFF \
-DSOCI_DB2=OFF \
@@ -17,7 +18,7 @@ cmake \
-DSOCI_POSTGRESQL=OFF \
-DSOCI_SQLITE3=OFF \
-DSOCI_MYSQL_TEST_CONNSTR:STRING="db=soci_test" \
..
..
run_make
run_test

View File

@@ -5,7 +5,14 @@
#
source ${TRAVIS_BUILD_DIR}/bin/ci/common.sh
ODBC_TEST=${PWD}/../tests/odbc
if test ! -d ${ODBC_TEST}; then
echo "ERROR: '${ODBC_TEST}' directory not found"
exit 1
fi
cmake \
-DCMAKE_VERBOSE_MAKEFILE=ON \
-DSOCI_TESTS=ON \
-DSOCI_STATIC=OFF \
-DSOCI_DB2=OFF \
@@ -16,9 +23,11 @@ cmake \
-DSOCI_ORACLE=OFF \
-DSOCI_POSTGRESQL=OFF \
-DSOCI_SQLITE3=OFF \
-DSOCI_ODBC_TEST_POSTGRESQL_CONNSTR="FILEDSN=${PWD}/../backends/odbc/test/test-postgresql.dsn;" \
-DSOCI_ODBC_TEST_MYSQL_CONNSTR="FILEDSN=${PWD}/../backends/odbc/test/test-mysql.dsn;" \
-DSOCI_ODBC_TEST_POSTGRESQL_CONNSTR="FILEDSN=${ODBC_TEST}/test-postgresql.dsn;" \
-DSOCI_ODBC_TEST_MYSQL_CONNSTR="FILEDSN=${ODBC_TEST}/test-mysql.dsn;" \
..
run_make
run_test
# Exclude the test which can't be run as there is no MS SQL server available.
run_test -E soci_odbc_test_mssql

View File

@@ -4,15 +4,11 @@
# Copyright (c) 2013 Mateusz Loskot <mateusz@loskot.net>
#
source ${TRAVIS_BUILD_DIR}/bin/ci/common.sh
if [ "${CXX}" == "g++" ]
then
ORACLE_USER="soci_tester"
else
ORACLE_USER="soci_tester1"
fi
source ${TRAVIS_BUILD_DIR}/bin/ci/oracle.sh
cmake \
-DCMAKE_VERBOSE_MAKEFILE=ON \
-DWITH_BOOST=OFF \
-DSOCI_TESTS=ON \
-DSOCI_STATIC=OFF \
-DSOCI_DB2=OFF \
@@ -23,8 +19,8 @@ cmake \
-DSOCI_ORACLE=ON \
-DSOCI_POSTGRESQL=OFF \
-DSOCI_SQLITE3=OFF \
-DSOCI_ORACLE_TEST_CONNSTR:STRING="service=brzuchol.loskot.net user=${ORACLE_USER} password=soci_secret" \
..
-DSOCI_ORACLE_TEST_CONNSTR:STRING="service=XE user=travis password=travis" \
..
run_make
run_test

View File

@@ -6,6 +6,7 @@
source ${TRAVIS_BUILD_DIR}/bin/ci/common.sh
cmake \
-DCMAKE_VERBOSE_MAKEFILE=ON \
-DSOCI_TESTS=ON \
-DSOCI_STATIC=OFF \
-DSOCI_DB2=OFF \
@@ -17,7 +18,7 @@ cmake \
-DSOCI_POSTGRESQL=ON \
-DSOCI_SQLITE3=OFF \
-DSOCI_POSTGRESQL_TEST_CONNSTR:STRING="dbname=soci_test user=postgres" \
..
..
run_make
run_test

47
bin/ci/script_postgression.sh Executable file
View File

@@ -0,0 +1,47 @@
#!/bin/bash -e
# Builds and tests SOCI backend PostgreSQL at travis-ci.org
#
# Copyright (C) 2014 Vadim Zeitlin
# Copyright (C) 2015 Mateusz Loskot <mateusz@loskot.net>
#
source ${TRAVIS_BUILD_DIR}/bin/ci/common.sh
# Get Postgression's PostgreSQL connection parameters as URI
SOCI_POSTGRESQL_CONNSTR=$(curl http://api.postgression.com)
# or old-style conninfo string, both should work.
#SOCI_POSTGRESQL_CONNSTR=$(curl http://api.postgression.com | \
#sed 's|postgres://\([^:]\+\):\([^@]\+\)@\([^:]\+\):\([0-9]\+\)/\(.*\)|user=\1 password=\2 host=\3 port=\4 dbname=\5|')
# Before proceeding with build, check Postgression availability
echo $SOCI_POSTGRESQL_CONNSTR | grep NO_DATABASES_AVAILABLE
if [ $? -eq 0 ];then
echo ${SOCI_POSTGRESQL_CONNSTR}
exit 1
fi
echo "Postgression connection parameters: $SOCI_POSTGRESQL_CONNSTR"
echo "PostgreSQL client version:"
psql --version
# WARNING: Somehow, connecting to Postgression service with psql
# seems to terminate Travis CI session preventing the job to
# continue with build and tests.
#psql -c 'select version();' "$SOCI_POSTGRESQL_CONNSTR"
cmake \
-DCMAKE_VERBOSE_MAKEFILE=ON \
-DSOCI_TESTS=ON \
-DSOCI_STATIC=OFF \
-DSOCI_DB2=OFF \
-DSOCI_EMPTY=OFF \
-DSOCI_FIREBIRD=OFF \
-DSOCI_MYSQL=OFF \
-DSOCI_ODBC=OFF \
-DSOCI_ORACLE=OFF \
-DSOCI_POSTGRESQL=ON \
-DSOCI_SQLITE3=OFF \
-DSOCI_POSTGRESQL_TEST_CONNSTR:STRING="$SOCI_POSTGRESQL_CONNSTR" \
..
run_make
run_test

View File

@@ -6,6 +6,7 @@
source ${TRAVIS_BUILD_DIR}/bin/ci/common.sh
cmake \
-DCMAKE_VERBOSE_MAKEFILE=ON \
-DSOCI_TESTS=ON \
-DSOCI_STATIC=OFF \
-DSOCI_DB2=OFF \

View File

@@ -28,7 +28,7 @@ function free_restore()
# Install fake free
# http://www.axelog.de/2010/02/7-oracle-ee-refused-to-install-into-openvz/
free_backup
cat <<EOF >> /usr/bin/free
cat <<EOF >> /usr/bin/free
#!/bin/sh
cat <<__eof
total used free shared buffers cached

View File

@@ -1,2 +0,0 @@
This directory is dedicated for:
- other building systems contributed by SOCI team and users

View File

@@ -1,37 +0,0 @@
proc buildCore {} {
global CXXFLAGS
puts "building static core"
set cwd [pwd]
cd "../../src/core"
foreach cppFile [glob "*.cpp"] {
execute "g++ -c $cppFile $CXXFLAGS"
}
execute "ar cr libsoci_core.a [glob *.o]"
cd $cwd
eval exec mkdir -p "lib"
execute "cp ../../src/core/libsoci_core.a lib"
eval exec mkdir -p "include"
execute "cp [glob ../../src/core/*.h] include"
}
proc buildCoreSo {} {
global CXXFLAGS SHARED
puts "building shared core"
set cwd [pwd]
cd "../../src/core"
foreach cppFile [glob "*.cpp"] {
execute "g++ -c $cppFile $CXXFLAGS -fPIC"
}
execute "g++ $SHARED -o libsoci_core.so [glob *.o]"
cd $cwd
eval exec mkdir -p "lib"
execute "cp ../../src/core/libsoci_core.so lib"
eval exec mkdir -p "include"
execute "cp [glob ../../src/core/*.h] include"
}

View File

@@ -1,142 +0,0 @@
source "local/parameters.tcl"
proc findMySQL {} {
global mysqlInclude mysqlLib
# candidate directories for local MySQL:
set includeDirs {
"/usr/local/include/mysql"
"/usr/include/mysql"
"/usr/local/include"
"/usr/include"
"/opt/local/include"
}
set libDirs {
"/usr/local/lib/mysql"
"/usr/lib/mysql"
"/usr/local/lib"
"/usr/lib"
"/opt/local/lib"
}
if [info exists mysqlInclude] {
set includeDirs [list $mysqlInclude]
}
if [info exists mysqlLib] {
set libDirs [list $mysqlLib]
}
set includeDir ""
foreach I $includeDirs {
set header "${I}/mysql.h"
if {[file exists $header]} {
set includeDir $I
break
}
}
if {$includeDir == ""} {
return {}
}
set libDir ""
foreach L $libDirs {
set libraryA "${L}/libmysqlclient.a"
set librarySo "${L}/libmysqlclient.so"
if {[file exists $libraryA] || [file exists $librarySo]} {
set libDir $L
break
}
}
if {$libDir == ""} {
return {}
}
return [list $includeDir $libDir]
}
proc buildMySQL {} {
global CXXFLAGS
puts "building static MySQL"
set dirs [findMySQL]
if {$dirs == {}} {
puts "cannot find MySQL library files, skipping this target"
return
}
set includeDir [lindex $dirs 0]
set libDir [lindex $dirs 1]
set cwd [pwd]
cd "../../src/backends/mysql"
foreach cppFile [glob "*.cpp"] {
execute "g++ -c $cppFile $CXXFLAGS -I../../core -I${includeDir}"
}
execute "ar cr libsoci_mysql.a [glob *.o]"
cd $cwd
eval exec mkdir -p "lib"
execute "cp ../../src/backends/mysql/libsoci_mysql.a lib"
eval exec mkdir -p "include"
execute "cp ../../src/backends/mysql/soci-mysql.h include"
}
proc buildMySQLSo {} {
global CXXFLAGS SHARED
puts "building shared MySQL"
set dirs [findMySQL]
if {$dirs == {}} {
puts "cannot find MySQL library files, skipping this target"
return
}
set includeDir [lindex $dirs 0]
set libDir [lindex $dirs 1]
set cwd [pwd]
cd "../../src/backends/mysql"
foreach cppFile [glob "*.cpp"] {
execute "g++ -c $cppFile $CXXFLAGS -fPIC -I../../core -I${includeDir}"
}
execute "g++ $SHARED -o libsoci_mysql.so [glob *.o] -L${libDir} -lmysqlclient -lz"
cd $cwd
eval exec mkdir -p "lib"
execute "cp ../../src/backends/mysql/libsoci_mysql.so lib"
eval exec mkdir -p "include"
execute "cp ../../src/backends/mysql/soci-mysql.h include"
}
proc buildMySQLTest {} {
global CXXTESTFLAGS LDL
puts "building MySQL test"
set dirs [findMySQL]
if {$dirs == {}} {
puts "cannot find MySQL library files, skipping this target"
return
}
set includeDir [lindex $dirs 0]
set libDir [lindex $dirs 1]
set dirs [findBoost]
if {$dirs == {}} {
puts "cannot find Boost library files, skipping this target"
return
}
set boostIncludeDir [lindex $dirs 0]
set boostLibDir [lindex $dirs 1]
set cwd [pwd]
cd "../../src/backends/mysql/test"
execute "g++ test-mysql.cpp -o test-mysql $CXXTESTFLAGS -I.. -I../../../core -I../../../core/test -I${includeDir} -I${boostIncludeDir} -L../../../../build/unix/lib -L${libDir} -L${boostLibDir} -lsoci_core -lsoci_mysql -lboost_date_time ${LDL} -lmysqlclient -lz"
cd $cwd
eval exec mkdir -p "tests"
execute "cp ../../src/backends/mysql/test/test-mysql tests"
}

View File

@@ -1,120 +0,0 @@
proc findOracle {} {
global env oracleInclude oracleLib
if {[info exists oracleInclude] &&
[info exists oracleLib]} {
set includeDir $oracleInclude
set libDir $oracleLib
} else {
if {[info exists env(ORACLE_HOME)] == 0} {
puts "The ORACLE_HOME variable is not set."
return {}
}
set ORACLE_HOME $env(ORACLE_HOME)
set includeDir [file join $ORACLE_HOME "rdbms/public"]
set header [file join $includeDir "oci.h"]
if {[file exists $header] == 0} {
puts "ORACLE_HOME is strange."
return {}
}
set libDir [file join $ORACLE_HOME "lib"]
set libraryA [file join $libDir "libclntsh.a"]
set librarySo [file join $libDir "libclntsh.so"]
if {([file exists $libraryA] == 0) && ([file exists $librarySo] == 0)} {
puts "ORACLE_HOME is strange."
return {}
}
}
return [list $includeDir $libDir]
}
proc buildOracle {} {
global CXXFLAGS
puts "building static Oracle"
set dirs [findOracle]
if {$dirs == {}} {
puts "cannot find Oracle library files, skipping this target"
return
}
set includeDir [lindex $dirs 0]
set libDir [lindex $dirs 1]
set cwd [pwd]
cd "../../src/backends/oracle"
foreach cppFile [glob "*.cpp"] {
execute "g++ -c $cppFile $CXXFLAGS -I../../core -I${includeDir}"
}
execute "ar cr libsoci_oracle.a [glob *.o]"
cd $cwd
eval exec mkdir -p "lib"
execute "cp ../../src/backends/oracle/libsoci_oracle.a lib"
eval exec mkdir -p "include"
execute "cp ../../src/backends/oracle/soci-oracle.h include"
}
proc buildOracleSo {} {
global CXXFLAGS SHARED
puts "building shared Oracle"
set dirs [findOracle]
if {$dirs == {}} {
puts "cannot find Oracle library files, skipping this target"
return
}
set includeDir [lindex $dirs 0]
set libDir [lindex $dirs 1]
set cwd [pwd]
cd "../../src/backends/oracle"
foreach cppFile [glob "*.cpp"] {
execute "g++ -c $cppFile $CXXFLAGS -fPIC -I../../core -I${includeDir}"
}
execute "g++ $SHARED -o libsoci_oracle.so [glob *.o] -L${libDir} -lclntsh -lnnz10"
cd $cwd
eval exec mkdir -p "lib"
execute "cp ../../src/backends/oracle/libsoci_oracle.so lib"
eval exec mkdir -p "include"
execute "cp ../../src/backends/oracle/soci-oracle.h include"
}
proc buildOracleTest {} {
global CXXTESTFLAGS LDL
puts "building Oracle test"
set dirs [findOracle]
if {$dirs == {}} {
puts "cannot find Oracle library files, skipping this target"
return
}
set includeDir [lindex $dirs 0]
set libDir [lindex $dirs 1]
set dirs [findBoost]
if {$dirs == {}} {
puts "cannot find Boost library files, skipping this target"
return
}
set boostIncludeDir [lindex $dirs 0]
set boostLibDir [lindex $dirs 1]
set cwd [pwd]
cd "../../src/backends/oracle/test"
execute "g++ test-oracle.cpp -o test-oracle $CXXTESTFLAGS -I.. -I../../../core -I../../../core/test -I${includeDir} -I${boostIncludeDir} -L../../../../build/unix/lib -L${libDir} -L${boostLibDir} -lsoci_core -lsoci_oracle -lboost_date_time ${LDL} -lclntsh -lnnz10"
cd $cwd
eval exec mkdir -p "tests"
execute "cp ../../src/backends/oracle/test/test-oracle tests"
}

View File

@@ -1,148 +0,0 @@
proc findPostgreSQL {} {
global postgresqlInclude postgresqlLib
# candidate directories for local PostgreSQL:
set includeDirs {
"/usr/local/pgsql/include"
"/usr/local/postgresql/include"
"/usr/local/include/pgsql"
"/usr/local/include/postgresql"
"/usr/include/pgsql"
"/usr/include/postgresql"
"/usr/local/include"
"/usr/include"
"/opt/local/include"
}
set libDirs {
"/usr/local/pgsql/lib"
"/usr/local/postgresql/lib"
"/usr/local/lib/pgsql"
"/usr/local/lib/postgresql"
"/usr/lib/pgsql"
"/usr/lib/postgresql"
"/usr/local/lib"
"/usr/lib"
"/opt/local/lib"
}
if [info exists postgresqlInclude] {
set includeDirs [list $postgresqlInclude]
}
if [info exists postgresqlLib] {
set libDirs [list $postgresqlLib]
}
set includeDir ""
foreach I $includeDirs {
set header "${I}/libpq/libpq-fs.h"
if {[file exists $header]} {
set includeDir $I
break
}
}
if {$includeDir == ""} {
return {}
}
set libDir ""
foreach L $libDirs {
set libraryA "${L}/libpq.a"
set librarySo "${L}/libpq.so"
if {[file exists $libraryA] || [file exists $librarySo]} {
set libDir $L
break
}
}
if {$libDir == ""} {
return {}
}
return [list $includeDir $libDir]
}
proc buildPostgreSQL {} {
global CXXFLAGS
puts "building static PostgreSQL"
set dirs [findPostgreSQL]
if {$dirs == {}} {
puts "cannot find PostgreSQL library files, skipping this target"
return
}
set includeDir [lindex $dirs 0]
set libDir [lindex $dirs 1]
set cwd [pwd]
cd "../../src/backends/postgresql"
foreach cppFile [glob "*.cpp"] {
execute "g++ -c $cppFile $CXXFLAGS -I../../core -I${includeDir}"
}
execute "ar cr libsoci_postgresql.a [glob *.o]"
cd $cwd
eval exec mkdir -p "lib"
execute "cp ../../src/backends/postgresql/libsoci_postgresql.a lib"
eval exec mkdir -p "include"
execute "cp ../../src/backends/postgresql/soci-postgresql.h include"
}
proc buildPostgreSQLSo {} {
global CXXFLAGS SHARED
puts "building shared PostgreSQL"
set dirs [findPostgreSQL]
if {$dirs == {}} {
puts "cannot find PostgreSQL library files, skipping this target"
return
}
set includeDir [lindex $dirs 0]
set libDir [lindex $dirs 1]
set cwd [pwd]
cd "../../src/backends/postgresql"
foreach cppFile [glob "*.cpp"] {
execute "g++ -c $cppFile $CXXFLAGS -fPIC -I../../core -I${includeDir}"
}
execute "g++ $SHARED -o libsoci_postgresql.so [glob *.o] -L${libDir} -lpq"
cd $cwd
eval exec mkdir -p "lib"
execute "cp ../../src/backends/postgresql/libsoci_postgresql.so lib"
eval exec mkdir -p "include"
execute "cp ../../src/backends/postgresql/soci-postgresql.h include"
}
proc buildPostgreSQLTest {} {
global CXXTESTFLAGS LDL
puts "building PostgreSQL test"
set dirs [findPostgreSQL]
if {$dirs == {}} {
puts "cannot find PostgreSQL library files, skipping this target"
return
}
set includeDir [lindex $dirs 0]
set libDir [lindex $dirs 1]
set dirs [findBoost]
if {$dirs == {}} {
puts "cannot find Boost library files, skipping this target"
return
}
set boostIncludeDir [lindex $dirs 0]
set boostLibDir [lindex $dirs 1]
set cwd [pwd]
cd "../../src/backends/postgresql/test"
execute "g++ test-postgresql.cpp -o test-postgresql $CXXTESTFLAGS -I.. -I../../../core -I../../../core/test -I${includeDir} -I${boostIncludeDir} -L../../../../build/unix/lib -L${libDir} -L${boostLibDir} -lsoci_core -lsoci_postgresql -lboost_date_time ${LDL} -lpq"
cd $cwd
eval exec mkdir -p "tests"
execute "cp ../../src/backends/postgresql/test/test-postgresql tests"
}

View File

@@ -1,142 +0,0 @@
proc findSqlite3 {} {
global Sqlite3Include Sqlite3Lib
# candidate directories for local sqlite3:
set includeDirs {
"/usr/local/include"
"/usr/include"
"/opt/local/include"
}
set libDirs {
"/usr/local/lib"
"/usr/lib"
"/opt/local/lib"
}
if [info exists Sqlite3Include] {
set includeDirs [list $Sqlite3Include]
}
if [info exists Sqlite3Lib] {
set libDirs [list $Sqlite3Lib]
}
set includeDir ""
foreach I $includeDirs {
set header "${I}/sqlite3.h"
if {[file exists $header]} {
set includeDir $I
break
}
}
if {$includeDir == ""} {
return {}
}
set libDir ""
foreach L $libDirs {
set libraryA "${L}/libsqlite3.a"
set librarySo "${L}/libsqlite3.so"
set libraryDl "${L}/libsqlite3.dylib"
if {[file exists $libraryA] || [file exists $librarySo] || [file exists $libraryDl]} {
set libDir $L
break
}
}
if {$libDir == ""} {
return {}
}
return [list $includeDir $libDir]
}
proc buildSqlite3 {} {
global CXXFLAGS tcl_platform
puts "building static Sqlite3"
set dirs [findSqlite3]
if {$dirs == {}} {
puts "cannot find Sqlite3 library files, skipping this target"
return
}
set includeDir [lindex $dirs 0]
set libDir [lindex $dirs 1]
set cwd [pwd]
cd "../../src/backends/sqlite3"
foreach cppFile [glob "*.cpp"] {
execute "g++ -c $cppFile $CXXFLAGS -I../../core -I${includeDir}"
}
execute "ar cr libsoci_sqlite3.a [glob *.o]"
if {$tcl_platform(os) == "Darwin"} {
# special case for Mac OS X
execute "ranlib libsoci_sqlite3.a"
}
cd $cwd
eval exec mkdir -p "lib"
execute "cp ../../src/backends/sqlite3/libsoci_sqlite3.a lib"
eval exec mkdir -p "include"
execute "cp ../../src/backends/sqlite3/soci-sqlite3.h include"
}
proc buildSqlite3So {} {
global CXXFLAGS SHARED
puts "building shared Sqlite3"
set dirs [findSqlite3]
if {$dirs == {}} {
puts "cannot find Sqlite3 library files, skipping this target"
return
}
set includeDir [lindex $dirs 0]
set libDir [lindex $dirs 1]
set cwd [pwd]
cd "../../src/backends/sqlite3"
foreach cppFile [glob "*.cpp"] {
execute "g++ -c $cppFile $CXXFLAGS -fPIC -I../../core -I${includeDir}"
}
execute "g++ $SHARED -o libsoci_sqlite3.so [glob *.o] -L${libDir} -lsqlite3"
cd $cwd
eval exec mkdir -p "lib"
execute "cp ../../src/backends/sqlite3/libsoci_sqlite3.so lib"
eval exec mkdir -p "include"
execute "cp ../../src/backends/sqlite3/soci-sqlite3.h include"
}
proc buildSqlite3Test {} {
global CXXTESTFLAGS LDL
puts "building Sqlite3 test"
set dirs [findSqlite3]
if {$dirs == {}} {
puts "cannot find Sqlite3 library files, skipping this target"
return
}
set includeDir [lindex $dirs 0]
set libDir [lindex $dirs 1]
set dirs [findBoost]
if {$dirs == {}} {
puts "cannot find Boost library files, skipping this target"
return
}
set boostIncludeDir [lindex $dirs 0]
set boostLibDir [lindex $dirs 1]
set cwd [pwd]
cd "../../src/backends/sqlite3/test"
execute "g++ test-sqlite3.cpp -o test-sqlite3 $CXXTESTFLAGS -I.. -I../../../core -I../../../core/test -I${includeDir} -I${boostIncludeDir} -L../../../../build/unix/lib -L${libDir} -L${boostLibDir} -lsoci_core -lsoci_sqlite3 -lboost_date_time ${LDL} -lsqlite3"
cd $cwd
eval exec mkdir -p "tests"
execute "cp ../../src/backends/sqlite3/test/test-sqlite3 tests"
}

View File

@@ -1,87 +0,0 @@
#!/usr/bin/tclsh
# some common compilation settings if you need to change them:
if [info exists env(CXXFLAGS)] {
set CXXFLAGS $env(CXXFLAGS)
} else {
set CXXFLAGS "-Wall -pedantic -Wno-long-long -O2"
}
set CXXTESTFLAGS "-O2"
if {$tcl_platform(os) == "Darwin"} {
# special case for Mac OS X
set SHARED "-dynamiclib -flat_namespace -undefined suppress"
} else {
set SHARED "-shared"
}
if {$tcl_platform(os) == "FreeBSD"} {
# FreeBSD does not have the libdl library, it is part of libc.
set LDL ""
} else {
set LDL "-ldl"
}
source "execute.tcl"
source "find-boost.tcl"
source "build-core.tcl"
source "build-oracle.tcl"
source "build-postgresql.tcl"
source "build-mysql.tcl"
proc printUsageAndExit {} {
puts "Usage:"
puts "$ ./build.tcl list-of-targets"
puts ""
puts "list of targets can contain any of:"
puts "core - the core part of the library (static version)"
puts "core-so - the core part of the library (shared version)"
puts "oracle - the static Oracle backend"
puts "oracle-so - the shared Oracle backend"
puts " Note: before building Oracle backend"
puts " set the ORACLE_HOME variable properly."
puts "postgresql - the static PostgreSQL backend"
puts "postgresql-so - the shared PostgreSQL backend"
puts "mysql - the static MySQL backend"
puts "mysql-so - the shared MySQL backend"
puts ""
puts "oracle-test - the test for Oracle"
puts "postgresql-test - the test for PostgreSQL"
puts "mysql-test - the test for MySQL"
puts " Note: build static core and backends first."
puts ""
puts "Examples:"
puts ""
puts "$ ./build.tcl core mysql"
puts ""
puts "$ ./build.tcl core postgresql postgresql-test"
puts ""
puts "After successful build the results are in include, lib and test directories."
puts "Move/copy the contents of these directories wherever you want."
exit
}
if {$argc == 0 || $argv == "--help"} {
printUsageAndExit
}
foreach target $argv {
switch -exact $target {
core buildCore
core-so buildCoreSo
oracle buildOracle
oracle-so buildOracleSo
oracle-test buildOracleTest
postgresql buildPostgreSQL
postgresql-so buildPostgreSQLSo
postgresql-test buildPostgreSQLTest
mysql buildMySQL
mysql-so buildMySQLSo
mysql-test buildMySQLTest
default {
puts "unknown target $target - skipping"
}
}
}

View File

@@ -1,14 +0,0 @@
proc execute {command} {
puts $command
set result [catch {eval exec $command "2>@ stdout"} output]
if {$result != 0} {
puts "The last command did not execute properly:"
puts $output
puts "Please contact the SOCI team."
exit
} else {
if {$output != ""} {
puts $output
}
}
}

View File

@@ -1,47 +0,0 @@
proc findBoost {} {
global rootBoost
# candidate directories for local Boost:
set includeDirs {
"/usr/local/include"
"/usr/include"
"/opt/local/include"
}
set libDirs {
"/usr/local/lib"
"/usr/lib"
"/opt/local/lib"
}
if [info exists rootBoost] {
set includeDirs [list $rootBoost]
set libDirs [list $rootBoost]
}
set includeDir ""
foreach I $includeDirs {
set header "${I}/boost/version.hpp"
if {[file exists $header]} {
set includeDir $I
break
}
}
if {$includeDir == ""} {
return {}
}
set libDir ""
foreach L $libDirs {
set libraryA "${L}/libboost_date_time.a"
set librarySo "${L}/libboost_date_time.so"
if {[file exists $libraryA] || [file exists $librarySo]} {
set libDir $L
break
}
}
if {$libDir == ""} {
return {}
}
return [list $includeDir $libDir]
}

View File

@@ -1,74 +0,0 @@
set headerInstallPrefix "/usr/local/include/soci"
set libInstallPrefix "/usr/local/lib"
set sociVersion "3.0.0"
set sociMajor "3"
source "execute.tcl"
source "local/parameters.tcl"
if [info exists env(DESTDIR)] {
set DESTDIR $env(DESTDIR)
set headerInstallPrefix [file normalize ${DESTDIR}/${headerInstallPrefix}]
set libInstallPrefix [file normalize ${DESTDIR}/${libInstallPrefix}]
}
set uninstallFile [open "local/uninstall.sh" "w"]
if {[file exists $headerInstallPrefix] == 0} {
execute "mkdir -p $headerInstallPrefix"
puts $uninstallFile "rm -rf $headerInstallPrefix"
}
foreach header [glob "include/*"] {
set tail [file tail $header]
puts "copying $tail to ${headerInstallPrefix}"
execute "cp $header $headerInstallPrefix"
puts $uninstallFile "rm -f ${headerInstallPrefix}/${tail}"
}
if {[file exists $libInstallPrefix] == 0} {
execute "mkdir -p $libInstallPrefix"
puts $uninstallFile "rm -rf $libInstallPrefix"
}
foreach lib [glob "lib/*.a"] {
set tail [file tail $lib]
puts "copying $tail to ${libInstallPrefix}"
execute "cp $lib $libInstallPrefix"
puts $uninstallFile "rm -f ${libInstallPrefix}/${tail}"
}
set buildDir [pwd]
cd $libInstallPrefix
foreach lib [glob "${buildDir}/lib/*.so"] {
set rootName [file rootname [file tail $lib]]
set targetName "${rootName}-${sociVersion}.so"
set majorLink "${rootName}-${sociMajor}.so"
set link "${rootName}.so"
puts "copying [file tail $lib] to ${targetName}"
execute "cp $lib $targetName"
puts $uninstallFile "rm -f ${libInstallPrefix}/${targetName}"
puts "creating link ${majorLink}"
execute "ln -s $targetName [file tail $majorLink]"
puts $uninstallFile "rm -f ${libInstallPrefix}/${majorLink}"
puts "creating ${link}"
execute "ln -s $targetName [file tail $link]"
puts $uninstallFile "rm -f ${libInstallPrefix}/${link}"
}
close $uninstallFile
puts "ldconfig ${libInstallPrefix}"
catch { eval exec "ldconfig ${libInstallPrefix}" }
puts ""
puts ""
puts "Hint: the shared libraries were installed in $libInstallPrefix"
puts "- If you use dynamically loaded backends, then you might need to set"
puts " the SOCI_BACKENDS_PATH variable accordingly."
puts ""
puts "Hint: to remove all installed files and links run make uninstall"
puts ""

View File

@@ -1,60 +0,0 @@
set paramsFile [open "local/parameters"]
set tclParamsFile [open "local/parameters.tcl" "w"]
set line [gets $paramsFile]
while {![eof $paramsFile]} {
set pair [split $line "="]
if {[llength $pair] == 2} {
set name [lindex $pair 0]
set value [lindex $pair 1]
switch -exact -- $name {
--include-prefix {
puts $tclParamsFile "set headerInstallPrefix $value"
puts "setting prefix for SOCI headers to $value"
}
--lib-prefix {
puts $tclParamsFile "set libInstallPrefix $value"
puts "setting prefix for SOCI libraries to $value"
}
--mysql-include {
puts $tclParamsFile "set mysqlInclude $value"
puts "setting include directory for MySQL to $value"
}
--mysql-lib {
puts $tclParamsFile "set mysqlLib $value"
puts "setting lib directory for MySQL to $value"
}
--oracle-include {
puts $tclParamsFile "set oracleInclude $value"
puts "setting include directory for Oracle to $value"
}
--oracle-lib {
puts $tclParamsFile "set oracleLib $value"
puts "setting lib directory for Oracle to $value"
}
--postgresql-include {
puts $tclParamsFile "set postgresqlInclude $value"
puts "setting include directory for PostgreSQL to $value"
}
--postgresql-lib {
puts $tclParamsFile "set postgresqlLib $value"
puts "setting lib directory for PostgreSQL to $value"
}
--boost-include {
puts $tclParamsFile "set boostInclude $value"
puts "setting Boost include directory to $value"
}
--boost-lib {
puts $tclParamsFile "set boostLib $value"
puts "setting Boost lib directory to $value"
}
default {
puts "unknown option: $name : skipping it!"
}
}
}
set line [gets $paramsFile]
}
close $paramsFile
close $tclParamsFile

View File

@@ -1,14 +1,14 @@
################################################################################
# SociBackend.cmake - part of CMake configuration of SOCI library
################################################################################
# Copyright (C) 2010 Mateusz Loskot <mateusz@loskot.net>
# Copyright (C) 2010-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)
################################################################################
# Macros in this module:
#
#
# soci_backend
# - defines project of a database backend for SOCI library
#
@@ -16,10 +16,47 @@
# - defines test project of a database backend for SOCI library
################################################################################
macro(soci_backend_deps_found NAME DEPS SUCCESS)
#message(STATUS "DEPS=${DEPS}")
# Determine required dependencies
set(DEPS_INCLUDE_DIRS)
set(DEPS_LIBRARIES)
set(DEPS_DEFS)
set(DEPS_NOT_FOUND)
# CMake 2.8+ syntax only:
#foreach(dep IN LISTS DEPS)
foreach(dep ${DEPS})
soci_check_package_found(${dep} DEPEND_FOUND)
if(NOT DEPEND_FOUND)
list(APPEND DEPS_NOT_FOUND ${dep})
else()
string(TOUPPER "${dep}" DEPU)
list(APPEND DEPS_INCLUDE_DIRS ${${DEPU}_INCLUDE_DIR})
list(APPEND DEPS_INCLUDE_DIRS ${${DEPU}_INCLUDE_DIRS})
list(APPEND DEPS_LIBRARIES ${${DEPU}_LIBRARIES})
list(APPEND DEPS_DEFS HAVE_${DEPU}=1)
endif()
endforeach()
list(LENGTH DEPS_NOT_FOUND NOT_FOUND_COUNT)
if (NOT_FOUND_COUNT GREATER 0)
set(${SUCCESS} False)
else()
set(${NAME}_DEPS_INCLUDE_DIRS ${DEPS_INCLUDE_DIRS})
set(${NAME}_DEPS_LIBRARIES ${DEPS_LIBRARIES})
set(${NAME}_DEPS_DEFS ${DEPS_DEFS})
set(${SUCCESS} True)
endif()
#message(STATUS "soci_backend_deps_found: ${SUCCESS}=${${SUCCESS}}")
endmacro()
# Defines project of a database backend for SOCI library
#
# soci_backend(backendname
# HEADERS header1 header2
# DEPENDS dependency1 dependency2
# DESCRIPTION description
# AUTHORS author1 author2
@@ -27,7 +64,7 @@
#
macro(soci_backend NAME)
parse_arguments(THIS_BACKEND
"HEADERS;DEPENDS;DESCRIPTION;AUTHORS;MAINTAINERS;"
"DEPENDS;DESCRIPTION;AUTHORS;MAINTAINERS;"
""
${ARGN})
@@ -43,36 +80,13 @@ macro(soci_backend NAME)
option(${THIS_BACKEND_OPTION}
"Attempt to build ${PROJECT_NAME} backend for ${NAME}" ON)
# Determine required dependencies
set(THIS_BACKEND_DEPENDS_INCLUDE_DIRS)
set(THIS_BACKEND_DEPENDS_LIBRARIES)
set(THIS_BACKEND_DEPENDS_DEFS)
set(DEPENDS_NOT_FOUND)
# CMake 2.8+ syntax only:
#foreach(dep IN LISTS THIS_BACKEND_DEPENDS)
foreach(dep ${THIS_BACKEND_DEPENDS})
soci_check_package_found(${dep} DEPEND_FOUND)
if(NOT DEPEND_FOUND)
list(APPEND DEPENDS_NOT_FOUND ${dep})
else()
string(TOUPPER "${dep}" DEPU)
list(APPEND THIS_BACKEND_DEPENDS_INCLUDE_DIRS ${${DEPU}_INCLUDE_DIR})
list(APPEND THIS_BACKEND_DEPENDS_INCLUDE_DIRS ${${DEPU}_INCLUDE_DIRS})
list(APPEND THIS_BACKEND_DEPENDS_LIBRARIES ${${DEPU}_LIBRARIES})
list(APPEND THIS_BACKEND_DEPENDS_DEFS -DHAVE_${DEPU}=1)
endif()
endforeach()
list(LENGTH DEPENDS_NOT_FOUND NOT_FOUND_COUNT)
if (NOT_FOUND_COUNT GREATER 0)
soci_backend_deps_found(${NAMEU} "${THIS_BACKEND_DEPENDS}" ${NAMEU}_DEPS_FOUND)
if(NOT ${NAMEU}_DEPS_FOUND)
colormsg(_RED_ "WARNING:")
colormsg(RED "Some required dependencies of ${NAME} backend not found:")
if (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} LESS 2.8)
if(${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} LESS 2.8)
foreach(dep ${DEPENDS_NOT_FOUND})
colormsg(RED " ${dep}")
endforeach()
@@ -87,43 +101,56 @@ macro(soci_backend NAME)
set(${THIS_BACKEND_OPTION} OFF)
else(NOT_FOUND_COUNT GREATER 0)
else()
if(${THIS_BACKEND_OPTION})
# Backend-specific include directories
list(APPEND THIS_BACKEND_DEPENDS_INCLUDE_DIRS ${SOCI_SOURCE_DIR}/core)
set_directory_properties(PROPERTIES INCLUDE_DIRECTORIES
"${THIS_BACKEND_DEPENDS_INCLUDE_DIRS}")
get_directory_property(THIS_INCLUDE_DIRS INCLUDE_DIRECTORIES)
get_directory_property(THIS_COMPILE_DEFS COMPILE_DEFINITIONS)
# Backend-specific preprocessor definitions
add_definitions(${THIS_BACKEND_DEPENDS_DEFS})
# Backend-specific depedencies
set(THIS_BACKEND_DEPENDS_INCLUDE_DIRS ${${NAMEU}_DEPS_INCLUDE_DIRS})
set(THIS_BACKEND_DEPENDS_LIBRARIES ${${NAMEU}_DEPS_LIBRARIES})
set(THIS_BACKEND_DEPENDS_DEFS ${${NAMEU}_DEPS_DEFS})
# Backend installable headers and sources
if (NOT THIS_BACKEND_HEADERS)
file(GLOB THIS_BACKEND_HEADERS *.h)
endif()
file(GLOB THIS_BACKEND_SOURCES *.cpp)
set(THIS_BACKEND_HEADERS_VAR SOCI_${NAMEU}_HEADERS)
set(${THIS_BACKEND_HEADERS_VAR} ${THIS_BACKEND_HEADERS})
# Collect include directories
list(APPEND THIS_INCLUDE_DIRS ${SOCI_SOURCE_DIR}/include/private)
list(APPEND THIS_INCLUDE_DIRS ${THIS_BACKEND_DEPENDS_INCLUDE_DIRS})
# Collect compile definitions
list(APPEND THIS_COMPILE_DEFS ${THIS_BACKEND_DEPENDS_DEFS})
# Group source files for IDE source explorers (e.g. Visual Studio)
source_group("Header Files" FILES ${THIS_BACKEND_HEADERS})
source_group("Source Files" FILES ${THIS_BACKEND_SOURCES})
source_group("CMake Files" FILES CMakeLists.txt)
set_directory_properties(PROPERTIES
INCLUDE_DIRECTORIES "${THIS_INCLUDE_DIRS}"
COMPILE_DEFINITIONS "${THIS_COMPILE_DEFS}")
# Backend target
set(THIS_BACKEND_VAR SOCI_${NAMEU})
set(THIS_BACKEND_TARGET ${PROJECTNAMEL}_${NAMEL})
set(THIS_BACKEND_TARGET_VAR SOCI_${NAMEU}_TARGET)
set(THIS_BACKEND_TARGET_VAR ${THIS_BACKEND_VAR}_TARGET)
set(${THIS_BACKEND_TARGET_VAR} ${THIS_BACKEND_TARGET})
soci_target_output_name(${THIS_BACKEND_TARGET} ${THIS_BACKEND_TARGET_VAR}_OUTPUT_NAME)
set(THIS_BACKEND_TARGET_OUTPUT_NAME ${${THIS_BACKEND_TARGET_VAR}_OUTPUT_NAME})
set(THIS_BACKEND_TARGET_OUTPUT_NAME_VAR ${THIS_BACKEND_TARGET_VAR}_OUTPUT_NAME)
soci_target_output_name(${THIS_BACKEND_TARGET} ${THIS_BACKEND_VAR}_OUTPUT_NAME)
set(THIS_BACKEND_OUTPUT_NAME ${${THIS_BACKEND_VAR}_OUTPUT_NAME})
set(THIS_BACKEND_OUTPUT_NAME_VAR ${THIS_BACKEND_VAR}_OUTPUT_NAME)
set(${THIS_BACKEND_VAR}_COMPILE_DEFINITIONS ${THIS_COMPILE_DEFS})
set(THIS_BACKEND_COMPILE_DEFINITIONS_VAR ${THIS_BACKEND_VAR}_COMPILE_DEFINITIONS)
set(${THIS_BACKEND_VAR}_INCLUDE_DIRECTORIES ${THIS_INCLUDE_DIRS})
set(THIS_BACKEND_INCLUDE_DIRECTORIES_VAR ${THIS_BACKEND_VAR}_INCLUDE_DIRECTORIES)
# Backend installable headers and sources
file(GLOB THIS_BACKEND_HEADERS ${SOCI_SOURCE_DIR}/include/soci/${NAMEL}/*.h)
file(GLOB THIS_BACKEND_SOURCES *.cpp)
set(THIS_BACKEND_HEADERS_VAR SOCI_${NAMEU}_HEADERS)
set(${THIS_BACKEND_HEADERS_VAR} ${THIS_BACKEND_HEADERS})
# Group source files for IDE source explorers (e.g. Visual Studio)
source_group("Header Files" FILES ${THIS_BACKEND_HEADERS})
source_group("Source Files" FILES ${THIS_BACKEND_SOURCES})
source_group("CMake Files" FILES CMakeLists.txt)
# TODO: Extract as macros: soci_shared_lib_target and soci_static_lib_target --mloskot
# Shared library target
if (SOCI_SHARED)
add_library(${THIS_BACKEND_TARGET}
@@ -132,19 +159,25 @@ macro(soci_backend NAME)
${THIS_BACKEND_HEADERS})
target_link_libraries(${THIS_BACKEND_TARGET}
${SOCI_CORE_TARGET}
${THIS_BACKEND_DEPENDS_LIBRARIES})
${SOCI_CORE_TARGET}
${THIS_BACKEND_DEPENDS_LIBRARIES})
if(WIN32)
set_target_properties(${THIS_BACKEND_TARGET}
set_target_properties(${THIS_BACKEND_TARGET}
PROPERTIES
OUTPUT_NAME ${THIS_BACKEND_TARGET_OUTPUT_NAME}
OUTPUT_NAME ${THIS_BACKEND_OUTPUT_NAME}
DEFINE_SYMBOL SOCI_DLL)
else()
set_target_properties(${THIS_BACKEND_TARGET}
set_target_properties(${THIS_BACKEND_TARGET}
PROPERTIES
SOVERSION ${${PROJECT_NAME}_SOVERSION}
INSTALL_NAME_DIR ${CMAKE_INSTALL_PREFIX}/lib)
if(APPLE)
set_target_properties(${THIS_BACKEND_TARGET}
PROPERTIES
LINK_FLAGS "-Wl,-flat_namespace -Wl,-undefined -Wl,suppress")
endif()
endif()
set_target_properties(${THIS_BACKEND_TARGET}
@@ -154,7 +187,7 @@ macro(soci_backend NAME)
endif()
# Static library target
if (SOCI_STATIC)
if(SOCI_STATIC)
set(THIS_BACKEND_TARGET_STATIC ${THIS_BACKEND_TARGET}_static)
add_library(${THIS_BACKEND_TARGET_STATIC}
@@ -162,46 +195,50 @@ macro(soci_backend NAME)
${THIS_BACKEND_SOURCES}
${THIS_BACKEND_HEADERS})
# Still need to link the libraries for tests to work
target_link_libraries (${THIS_BACKEND_TARGET_STATIC}
${THIS_BACKEND_DEPENDS_LIBRARIES}
)
set_target_properties(${THIS_BACKEND_TARGET_STATIC}
PROPERTIES
OUTPUT_NAME ${THIS_BACKEND_TARGET_OUTPUT_NAME}
PREFIX "lib"
CLEAN_DIRECT_OUTPUT 1)
PROPERTIES
OUTPUT_NAME ${THIS_BACKEND_OUTPUT_NAME}
PREFIX "lib"
CLEAN_DIRECT_OUTPUT 1)
endif()
# Backend installation
install(FILES ${THIS_BACKEND_HEADERS}
DESTINATION
${INCLUDEDIR}/${PROJECTNAMEL}/${NAMEL})
DESTINATION
${INCLUDEDIR}/${PROJECTNAMEL}/${NAMEL})
if (SOCI_SHARED)
install(TARGETS ${THIS_BACKEND_TARGET}
RUNTIME DESTINATION ${BINDIR}
LIBRARY DESTINATION ${LIBDIR}
ARCHIVE DESTINATION ${LIBDIR})
RUNTIME DESTINATION ${BINDIR}
LIBRARY DESTINATION ${LIBDIR}
ARCHIVE DESTINATION ${LIBDIR})
endif()
if (SOCI_SHARED)
install(TARGETS ${THIS_BACKEND_TARGET_STATIC}
RUNTIME DESTINATION ${BINDIR}
LIBRARY DESTINATION ${LIBDIR}
ARCHIVE DESTINATION ${LIBDIR})
RUNTIME DESTINATION ${BINDIR}
LIBRARY DESTINATION ${LIBDIR}
ARCHIVE DESTINATION ${LIBDIR})
endif()
else()
colormsg(HIRED "${NAME}" RED "backend disabled, since")
endif()
else()
colormsg(HIRED "${NAME}" RED "backend disabled, since")
endif()
endif(NOT_FOUND_COUNT GREATER 0)
endif()
boost_report_value(${THIS_BACKEND_OPTION})
if(${THIS_BACKEND_OPTION})
boost_report_value(${THIS_BACKEND_TARGET_VAR})
boost_report_value(${THIS_BACKEND_TARGET_OUTPUT_NAME_VAR})
boost_report_value(${THIS_BACKEND_HEADERS_VAR})
soci_report_directory_property(COMPILE_DEFINITIONS)
boost_report_value(${THIS_BACKEND_OUTPUT_NAME_VAR})
boost_report_value(${THIS_BACKEND_COMPILE_DEFINITIONS_VAR})
boost_report_value(${THIS_BACKEND_INCLUDE_DIRECTORIES_VAR})
endif()
# LOG
@@ -212,7 +249,6 @@ macro(soci_backend NAME)
#message("DESCRIPTION: ${THIS_BACKEND_DESCRIPTION}")
#message("AUTHORS: ${THIS_BACKEND_AUTHORS}")
#message("MAINTAINERS: ${THIS_BACKEND_MAINTAINERS}")
#message("HEADERS: ${THIS_BACKEND_HEADERS}")
#message("SOURCES: ${THIS_BACKEND_SOURCES}")
#message("DEPENDS_LIBRARIES: ${THIS_BACKEND_DEPENDS_LIBRARIES}")
#message("DEPENDS_INCLUDE_DIRS: ${THIS_BACKEND_DEPENDS_INCLUDE_DIRS}")
@@ -243,7 +279,7 @@ endfunction(soci_backend_test_create_vcxproj_user)
#
# soci_backend_test(BACKEND mybackend SOURCE mytest1.cpp
# NAME mytest1
# CONNSTR "my test connection"
# CONNSTR "my test connection"
# DEPENDS library1 library2)
#
macro(soci_backend_test)
@@ -260,90 +296,90 @@ macro(soci_backend_test)
# Test name
if(THIS_TEST_NAME)
string(TOUPPER "${THIS_TEST_NAME}" NAMEU)
set(TEST_FULL_NAME SOCI_${BACKENDU}_TEST_${NAMEU})
else()
set(TEST_FULL_NAME SOCI_${BACKENDU}_TEST)
string(TOUPPER "${THIS_TEST_NAME}" NAMEU)
set(TEST_FULL_NAME SOCI_${BACKENDU}_TEST_${NAMEU})
else()
set(TEST_FULL_NAME SOCI_${BACKENDU}_TEST)
endif()
string(TOLOWER "${TEST_FULL_NAME}" TEST_TARGET)
string(TOUPPER "${TEST_FULL_NAME}" NAMEU)
soci_backend_deps_found(${NAMEU} "${THIS_TEST_DEPENDS}" ${NAMEU}_DEPS_FOUND)
if(${NAMEU}_DEPS_FOUND)
get_directory_property(THIS_INCLUDE_DIRS INCLUDE_DIRECTORIES)
get_directory_property(THIS_COMPILE_DEFS COMPILE_DEFINITIONS)
set(THIS_TEST_DEPENDS_INCLUDE_DIRS ${${NAMEU}_DEPS_INCLUDE_DIRS})
set(THIS_TEST_DEPENDS_LIBRARIES ${${NAMEU}_DEPS_LIBRARIES})
set(THIS_TEST_DEPENDS_DEFS ${${NAMEU}_DEPS_DEFS})
list(APPEND THIS_INCLUDE_DIRS ${THIS_TEST_DEPENDS_INCLUDE_DIRS})
list(APPEND THIS_COMPILE_DEFS ${THIS_TEST_DEPENDS_DEFS})
set_directory_properties(PROPERTIES
INCLUDE_DIRECTORIES "${THIS_INCLUDE_DIRS}"
COMPILE_DEFINITIONS "${THIS_COMPILE_DEFS}")
else()
colormsg(_RED_ "WARNING:")
colormsg(RED "Some dependencies of ${THIS_TEST_BACKEND} test not found")
endif()
set(TEST_CONNSTR_VAR ${TEST_FULL_NAME}_CONNSTR)
set(${TEST_CONNSTR_VAR} ""
CACHE STRING "Connection string for ${BACKENDU} test")
if(NOT ${TEST_CONNSTR_VAR} AND THIS_TEST_CONNSTR)
set(${TEST_CONNSTR_VAR} ${THIS_TEST_CONNSTR})
endif()
boost_report_value(${TEST_CONNSTR_VAR})
include_directories(${SOCI_SOURCE_DIR}/core/test)
include_directories(${SOCI_SOURCE_DIR}/backends/${BACKENDL})
if( SOCI_SHARED )
# Shared libraries test
add_executable(${TEST_TARGET} ${THIS_TEST_SOURCE})
# TODO: Find more generic way of adding Boost to core and backend tests only.
# Ideally, from within Boost.cmake.
set(SOCI_TEST_DEPENDENCIES)
if(Boost_FOUND)
include_directories(${Boost_INCLUDE_DIRS})
if(Boost_DATE_TIME_FOUND)
set(SOCI_TEST_DEPENDENCIES ${Boost_DATE_TIME_LIBRARY})
add_definitions(-DHAVE_BOOST_DATE_TIME=1)
endif()
endif()
target_link_libraries(${TEST_TARGET}
${SOCI_CORE_DEPS_LIBS}
${THIS_TEST_DEPENDS_LIBRARIES}
soci_core
soci_${BACKENDL})
string(TOLOWER "${TEST_FULL_NAME}" TEST_TARGET)
add_test(${TEST_TARGET}
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_TARGET}
${${TEST_CONNSTR_VAR}})
set(TEST_HEADERS ${PROJECT_SOURCE_DIR}/core/test/common-tests.h)
soci_backend_test_create_vcxproj_user(${TEST_TARGET} "\"${${TEST_CONNSTR_VAR}}\"")
# Shared libraries test
add_executable(${TEST_TARGET} ${TEST_HEADERS} ${THIS_TEST_SOURCE})
target_link_libraries(${TEST_TARGET}
${SOCI_CORE_TARGET}
${SOCI_${BACKENDU}_TARGET}
${${BACKENDU}_LIBRARIES}
${SOCI_TEST_DEPENDENCIES})
add_test(${TEST_TARGET}
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_TARGET}
${${TEST_CONNSTR_VAR}})
soci_backend_test_create_vcxproj_user(${TEST_TARGET} "\"${${TEST_CONNSTR_VAR}}\"")
# Ask make check to try to build tests first before executing them
add_dependencies(check ${TEST_TARGET})
endif(SOCI_SHARED)
# Static libraries test
if(SOCI_STATIC)
set(TEST_TARGET_STATIC ${TEST_TARGET}_static)
add_executable(${TEST_TARGET_STATIC} ${TEST_HEADERS} ${THIS_TEST_SOURCE})
add_executable(${TEST_TARGET_STATIC} ${THIS_TEST_SOURCE})
target_link_libraries(${TEST_TARGET_STATIC}
${SOCI_CORE_TARGET_STATIC}
${SOCI_${BACKENDU}_TARGET}_static
${${BACKENDU}_LIBRARIES}
${SOCI_CORE_STATIC_DEPENDENCIES}
${SOCI_TEST_DEPENDENCIES})
${SOCI_CORE_DEPS_LIBS}
${THIS_TEST_DEPENDS_LIBRARIES}
soci_core_static
soci_${BACKENDL}_static)
add_test(${TEST_TARGET_STATIC}
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_TARGET_STATIC}
${${TEST_CONNSTR_VAR}})
soci_backend_test_create_vcxproj_user(${TEST_TARGET_STATIC} "\"${${TEST_CONNSTR_VAR}}\"")
# Ask make check to try to build tests first before executing them
add_dependencies(check ${TEST_TARGET_STATIC})
endif(SOCI_STATIC)
# Ask make check to try to build tests first before executing them
add_dependencies(check ${TEST_TARGET} ${TEST_TARGET_STATIC})
# Group source files for IDE source explorers (e.g. Visual Studio)
source_group("Header Files" FILES ${TEST_HEADERS})
source_group("Source Files" FILES ${THIS_TEST_SOURCE})
source_group("CMake Files" FILES CMakeLists.txt)
endif()
# LOG
#message("NAME=${NAME}")
#message("THIS_TEST_NAME=${THIS_TEST_NAME}")
#message("THIS_TEST_BACKEND=${THIS_TEST_BACKEND}")
#message("THIS_TEST_CONNSTR=${THIS_TEST_CONNSTR}")
#message("THIS_TEST_SOURCE=${THIS_TEST_SOURCE}")
#message("THIS_TEST_OPTION=${THIS_TEST_OPTION}")
endmacro()

View File

@@ -8,6 +8,28 @@
# http://www.boost.org/LICENSE_1_0.txt)
################################################################################
include(CheckCXXSymbolExists)
if(WIN32)
check_cxx_symbol_exists("_M_AMD64" "" SOCI_TARGET_ARCH_X64)
if(NOT RTC_ARCH_X64)
check_cxx_symbol_exists("_M_IX86" "" SOCI_TARGET_ARCH_X86)
endif(NOT RTC_ARCH_X64)
# add check for arm here
# see http://msdn.microsoft.com/en-us/library/b0084kay.aspx
else(WIN32)
check_cxx_symbol_exists("__i386__" "" SOCI_TARGET_ARCH_X86)
check_cxx_symbol_exists("__x86_64__" "" SOCI_TARGET_ARCH_X64)
check_cxx_symbol_exists("__arm__" "" SOCI_TARGET_ARCH_ARM)
endif(WIN32)
#
# C++11 Option
#
set (SOCI_CXX_C11 OFF CACHE BOOL "Build to the C++11 standard")
#
# Force compilation flags and set desired warnings level
#
@@ -19,35 +41,43 @@ if (MSVC)
add_definitions(-D_CRT_NONSTDC_NO_WARNING)
add_definitions(-D_SCL_SECURE_NO_WARNINGS)
endif()
if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
endif()
else()
set(SOCI_GCC_CLANG_COMMON_FLAGS
"-pedantic -ansi -Wall -Wpointer-arith -Wcast-align -Wcast-qual -Wfloat-equal -Wredundant-decls -Wno-long-long")
"-pedantic -Werror -Wall -Wpointer-arith -Wcast-align -Wcast-qual -Wfloat-equal -Wredundant-decls -Wno-long-long")
if (SOCI_CXX_C11)
set(SOCI_CXX_VERSION_FLAGS "-std=c++11")
add_definitions(-DSOCI_CXX_C11)
else()
set(SOCI_CXX_VERSION_FLAGS "-std=gnu++98")
endif()
if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC ${SOCI_GCC_CLANG_COMMON_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC ${SOCI_GCC_CLANG_COMMON_FLAGS} ${SOCI_CXX_VERSION_FLAGS} ")
if (CMAKE_COMPILER_IS_GNUCXX)
if (CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++98")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++98")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-variadic-macros")
endif()
endif()
elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" OR "${CMAKE_CXX_COMPILER}" MATCHES "clang")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${SOCI_GCC_CLANG_COMMON_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${SOCI_GCC_CLANG_COMMON_FLAGS} ${SOCI_CXX_VERSION_FLAGS}")
else()
message(FATAL_ERROR "CMake is unable to recognize compilation toolset to build SOCI for you!")
message(WARNING "Unknown toolset - using default flags to build SOCI")
endif()
endif()

View File

@@ -11,7 +11,7 @@
# http://www.boost.org/LICENSE_1_0.txt)
################################################################################
# Macros in this module:
#
#
# soci_backend - defines a database backend for SOCI library
#
################################################################################
@@ -19,6 +19,10 @@
#
# List of SOCI dependncies
#
set(SOCI_CORE_DEPENDENCIES
Threads
Boost)
set(SOCI_BACKENDS_DB_DEPENDENCIES
MySQL
ODBC
@@ -28,13 +32,13 @@ set(SOCI_BACKENDS_DB_DEPENDENCIES
Firebird
DB2)
set(SOCI_BACKENDS_ALL_DEPENDENCIES
Boost
set(SOCI_ALL_DEPENDENCIES
${SOCI_CORE_DEPENDENCIES}
${SOCI_BACKENDS_DB_DEPENDENCIES})
#
# Perform checks
#
#
colormsg(_HIBLUE_ "Looking for SOCI dependencies:")
macro(boost_external_report NAME)
@@ -46,7 +50,7 @@ macro(boost_external_report NAME)
list(REMOVE_AT VARNAMES 0)
# Test both, given original name and uppercase version too
if(NOT SUCCESS)
if(NOT SUCCESS)
string(TOUPPER ${NAME} VARNAME)
set(SUCCESS ${${VARNAME}_FOUND})
if(NOT SUCCESS)
@@ -69,7 +73,7 @@ option(WITH_VALGRIND "Run tests under valgrind" OFF)
#
# Detect available dependencies
#
foreach(external ${SOCI_BACKENDS_ALL_DEPENDENCIES})
foreach(external ${SOCI_ALL_DEPENDENCIES})
string(TOUPPER "${external}" EXTERNAL)
option(WITH_${EXTERNAL} "Attempt to find and configure ${external}" ON)
if(WITH_${EXTERNAL})

View File

@@ -5,7 +5,7 @@
################################################################################
# Copyright (C) 2007 Douglas Gregor <doug.gregor@gmail.com>
# Copyright (C) 2007 Troy Straszheim
# Copyright (C) 2010 Mateusz Loskot <mateusz@loskot.net>
# Copyright (C) 2010-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
@@ -29,7 +29,7 @@
# occurs within a list of strings:
#
# list_contains(result string_to_find arg1 arg2 arg3 ... argn)
#
#
# This macro sets the variable named by result equal to TRUE if
# string_to_find is found anywhere in the following arguments.
macro(list_contains var value)
@@ -63,16 +63,16 @@ endmacro(cdr)
# list of names, and the third argument is a list of options. Both of
# these lists should be quoted. The rest of parse_arguments are
# arguments from another macro to be parsed.
#
# parse_arguments(prefix arg_names options arg1 arg2...)
#
#
# parse_arguments(prefix arg_names options arg1 arg2...)
#
# For each item in options, parse_arguments will create a variable with
# that name, prefixed with prefix_. So, for example, if prefix is
# MY_MACRO and options is OPTION1;OPTION2, then parse_arguments will
# create the variables MY_MACRO_OPTION1 and MY_MACRO_OPTION2. These
# variables will be set to true if the option exists in the command line
# or false otherwise.
#
#
# For each item in arg_names, parse_arguments will create a variable
# with that name, prefixed with prefix_. Each variable will be filled
# with the arguments that occur after the given arg_name is encountered
@@ -109,8 +109,8 @@ macro(parse_arguments prefix arg_names option_names)
set(${prefix}_${current_arg_name} ${current_arg_list})
endmacro(parse_arguments)
# Perform a reverse topological sort on the given LIST.
#
# Perform a reverse topological sort on the given LIST.
#
# topological_sort(my_list "MY_" "_EDGES")
#
# LIST is the name of a variable containing a list of elements to be
@@ -132,7 +132,7 @@ endmacro(parse_arguments)
# using the following variables:
#
# MY_A_EDGES b
# MY_B_EDGES
# MY_B_EDGES
# MY_C_EDGES a b
#
# With the involcation of topological_sort shown above and these
@@ -153,7 +153,7 @@ function(topological_sort LIST PREFIX SUFFIX)
# search from where.
if (NOT FOUND_${UPPER_VERTEX})
# Push this vertex onto the stack with all of its outgoing edges
string(REPLACE ";" " " NEW_ELEMENT
string(REPLACE ";" " " NEW_ELEMENT
"${VERTEX};${${PREFIX}${UPPER_VERTEX}${SUFFIX}}")
list(APPEND STACK ${NEW_ELEMENT})
@@ -191,14 +191,14 @@ function(topological_sort LIST PREFIX SUFFIX)
# Push the remaining edges for the current vertex onto the
# stack
string(REPLACE ";" " " NEW_ELEMENT
string(REPLACE ";" " " NEW_ELEMENT
"${SOURCE};${OUT_EDGES}")
list(APPEND STACK ${NEW_ELEMENT})
# Setup the new source and outgoing edges
set(SOURCE ${TARGET})
string(TOUPPER ${SOURCE} UPPER_SOURCE)
set(OUT_EDGES
set(OUT_EDGES
${${PREFIX}${UPPER_SOURCE}${SUFFIX}})
endif(NOT FOUND_${UPPER_TARGET})
@@ -275,19 +275,19 @@ function (colormsg)
message(STATUS ${str})
endfunction()
# colormsg("Colors:"
# WHITE "white" GRAY "gray" GREEN "green"
# RED "red" YELLOW "yellow" BLUE "blue" MAG "mag" CYAN "cyan"
# _WHITE_ "white" _GRAY_ "gray" _GREEN_ "green"
# _RED_ "red" _YELLOW_ "yellow" _BLUE_ "blue" _MAG_ "mag" _CYAN_ "cyan"
# _HIWHITE_ "white" _HIGRAY_ "gray" _HIGREEN_ "green"
# _HIRED_ "red" _HIYELLOW_ "yellow" _HIBLUE_ "blue" _HIMAG_ "mag" _HICYAN_ "cyan"
# HIWHITE "white" HIGRAY "gray" HIGREEN "green"
# HIRED "red" HIYELLOW "yellow" HIBLUE "blue" HIMAG "mag" HICYAN "cyan"
# colormsg("Colors:"
# WHITE "white" GRAY "gray" GREEN "green"
# RED "red" YELLOW "yellow" BLUE "blue" MAG "mag" CYAN "cyan"
# _WHITE_ "white" _GRAY_ "gray" _GREEN_ "green"
# _RED_ "red" _YELLOW_ "yellow" _BLUE_ "blue" _MAG_ "mag" _CYAN_ "cyan"
# _HIWHITE_ "white" _HIGRAY_ "gray" _HIGREEN_ "green"
# _HIRED_ "red" _HIYELLOW_ "yellow" _HIBLUE_ "blue" _HIMAG_ "mag" _HICYAN_ "cyan"
# HIWHITE "white" HIGRAY "gray" HIGREEN "green"
# HIRED "red" HIYELLOW "yellow" HIBLUE "blue" HIMAG "mag" HICYAN "cyan"
# "right?")
#
# pretty-prints the value of a variable so that the
# pretty-prints the value of a variable so that the
# equals signs align
#
function(boost_report_value NAME)
@@ -296,7 +296,7 @@ function(boost_report_value NAME)
#message(STATUS "boost_report_value: NAME=${NAME} (${varlen})")
#message(STATUS "boost_report_value: \${NAME}=${${NAME}}")
math(EXPR padding_len 40-${varlen})
string(SUBSTRING " "
string(SUBSTRING " "
0 ${padding_len} varpadding)
colormsg("${NAME}${varpadding} = ${${NAME}}")
endfunction()
@@ -309,16 +309,16 @@ function(trace NAME)
0 ${padding_len} varpadding)
message("${NAME} ${varpadding} ${${NAME}}")
endif()
endfunction()
endfunction()
#
# pretty-prints the value of a variable so that the
# pretty-prints the value of a variable so that the
# equals signs align
#
function(boost_report_pretty PRETTYNAME VARNAME)
string(LENGTH "${PRETTYNAME}" varlen)
math(EXPR padding_len 30-${varlen})
string(SUBSTRING " "
string(SUBSTRING " "
0 ${padding_len} varpadding)
message(STATUS "${PRETTYNAME}${varpadding} = ${${VARNAME}}")
endfunction()
@@ -348,7 +348,7 @@ macro(soci_check_package_found NAME SUCCESS)
set(VARNAME_SUCCESS ${${VARNAME}_FOUND})
# Test both, given original name and uppercase version too
if(VARNAME_SUCCESS)
if(VARNAME_SUCCESS)
set(${SUCCESS} TRUE)
else()
string(TOUPPER ${NAME} VARNAME)
@@ -357,15 +357,17 @@ macro(soci_check_package_found NAME SUCCESS)
set(${SUCCESS} TRUE)
endif()
endif()
#message(STATUS "soci_check_package_found: ${SUCCESS}=${${SUCCESS}}")
endmacro()
#
# Pretty-print of given property of current directory.
#
macro(soci_report_directory_property PROPNAME)
function(soci_report_directory_property PROPNAME)
get_directory_property(${PROPNAME} ${PROPNAME})
boost_report_value(${PROPNAME})
endmacro()
endfunction()
#
# Scans the current directory and returns a list of subdirectories.

View File

@@ -8,7 +8,7 @@
# http://www.boost.org/LICENSE_1_0.txt)
################################################################################
# Macros in this module:
#
#
# soci_version - defines version information for SOCI library
#
################################################################################

View File

@@ -1,10 +1,9 @@
set(Boost_FIND_QUIETLY TRUE)
set(Boost_USE_STATIC_LIBS ON)
set(Boost_USE_MULTITHREADED ON)
find_package(Boost 1.33.1 COMPONENTS date_time)
if (NOT Boost_date_time_FOUND)
if (NOT Boost_DATE_TIME_FOUND)
find_package(Boost 1.33.1)
endif()

View File

@@ -0,0 +1,9 @@
option(SOCI_FIREBIRD_EMBEDDED "Use embedded library in Firebird backend" OFF)
boost_report_value(SOCI_FIREBIRD_EMBEDDED)
set(Firebird_FIND_QUIETLY TRUE)
find_package(Firebird)
boost_external_report(Firebird INCLUDE_DIR LIBRARIES VERSION)

View File

@@ -0,0 +1,5 @@
set(MySQL_FIND_QUIETLY TRUE)
find_package(MySQL)
boost_external_report(MySQL INCLUDE_DIR LIBRARIES)

View File

@@ -0,0 +1,4 @@
set(Threads_FIND_QUIETLY TRUE)
find_package(Threads)
boost_report_value(CMAKE_THREAD_LIBS_INIT)

View File

@@ -26,7 +26,7 @@ if(UNIX)
else()
set(DB2_LIBDIRS "lib64")
endif()
set(DB2_FIND_INCLUDE_PATHS)
set(DB2_FIND_LIB_PATHS)
foreach(db2_install_path ${DB2_INSTALL_PATHS})
@@ -45,10 +45,10 @@ if(UNIX)
endforeach(db2_install_path)
elseif(WIN32)
if (CMAKE_CL_64) # 64-bit build, DB2 64-bit installed
set(DB2_FIND_INCLUDE_PATHS $ENV{ProgramW6432}/IBM/SQLLIB/include)
set(DB2_FIND_INCLUDE_PATHS $ENV{ProgramW6432}/IBM/SQLLIB/include)
set(DB2_FIND_LIB_PATHS $ENV{ProgramW6432}/IBM/SQLLIB/lib)
else() # 32-bit build, DB2 64-bit or DB2 32-bit installed
if(EXISTS "$ENV{ProgramW6432}/IBM/SQLLIB/lib")
# On 64-bit Windows with DB2 64-bit installed:
# LIB environment points to {DB2}/IBM/SQLLIB/lib with64-bit db2api.lib,
@@ -56,8 +56,8 @@ elseif(WIN32)
set(DB2_FIND_LIB_NO_LIB NO_SYSTEM_ENVIRONMENT_PATH)
endif()
set(DB2_FIND_INCLUDE_PATHS
set(DB2_FIND_INCLUDE_PATHS
$ENV{ProgramW6432}/IBM/SQLLIB/include
$ENV{ProgramFiles}/IBM/SQLLIB/include)
set(DB2_FIND_LIB_PATHS
@@ -84,10 +84,6 @@ endif()
if(DB2_INCLUDE_DIR AND DB2_LIBRARY_DIR)
set(DB2_FOUND TRUE)
include_directories(${DB2_INCLUDE_DIR})
link_directories(${DB2_LIBRARY_DIR})
endif()
set(DB2_LIBRARIES ${DB2_LIBRARY})

View File

@@ -14,10 +14,15 @@ find_path(FIREBIRD_INCLUDE_DIR ibase.h
$ENV{ProgramFiles}/Firebird/*/include
)
if(SOCI_FIREBIRD_EMBEDDED)
set(FIREBIRD_LIB_NAMES fbembed)
else()
set(FIREBIRD_LIB_NAMES fbclient fbclient_ms)
endif()
find_library(FIREBIRD_LIBRARIES
NAMES
fbclient
fbclient_ms
${FIREBIRD_LIB_NAMES}
PATHS
/usr/lib
$ENV{ProgramFiles}/Firebird/*/lib

View File

@@ -23,6 +23,7 @@ if(WIN32)
$ENV{MYSQL_DIR}/include
$ENV{ProgramFiles}/MySQL/*/include
$ENV{SystemDrive}/MySQL/*/include
$ENV{ProgramW6432}/MySQL/*/include
)
else(WIN32)
find_path(MYSQL_INCLUDE_DIR mysql.h
@@ -54,41 +55,30 @@ if(WIN32)
endif(CMAKE_BUILD_TYPE_TOLOWER MATCHES "debug")
# find_library(MYSQL_LIBRARIES NAMES mysqlclient
find_library(MYSQL_LIBRARIES NAMES libmysql
PATHS
set(MYSQL_LIB_PATHS
$ENV{MYSQL_DIR}/lib/${binary_dist}
$ENV{MYSQL_DIR}/libmysql/${build_dist}
$ENV{MYSQL_DIR}/client/${build_dist}
$ENV{ProgramFiles}/MySQL/*/lib/${binary_dist}
$ENV{SystemDrive}/MySQL/*/lib/${binary_dist}
$ENV{MYSQL_DIR}/lib/opt
$ENV{MYSQL_DIR}/client/release
$ENV{ProgramFiles}/MySQL/*/lib/opt
$ENV{SystemDrive}/MySQL/*/lib/opt
$ENV{ProgramW6432}/MySQL/*/lib
)
find_library(MYSQL_LIBRARIES NAMES mysqlclient libmysql
PATHS
${MYSQL_LIB_PATHS}
)
else(WIN32)
# find_library(MYSQL_LIBRARIES NAMES mysqlclient
find_library(MYSQL_LIBRARIES NAMES libmysql
PATHS
set(MYSQL_LIB_PATHS
$ENV{MYSQL_DIR}/libmysql_r/.libs
$ENV{MYSQL_DIR}/lib
$ENV{MYSQL_DIR}/lib/mysql
/usr/local/mysql/lib
/opt/mysql/mysql/lib
PATH_SUFFIXES
mysql
)
endif(WIN32)
if(WIN32)
set(MYSQL_LIB_PATHS
$ENV{MYSQL_DIR}/lib/opt
$ENV{MYSQL_DIR}/client/release
$ENV{ProgramFiles}/MySQL/*/lib/opt
$ENV{SystemDrive}/MySQL/*/lib/opt
)
find_library(MYSQL_LIBRARIES NAMES mysqlclient
PATHS
${MYSQL_LIB_PATHS}
)
else(WIN32)
set(MYSQL_LIB_PATHS
$ENV{MYSQL_DIR}/libmysql_r/.libs
$ENV{MYSQL_DIR}/lib
$ENV{MYSQL_DIR}/lib/mysql

View File

@@ -1,13 +1,13 @@
#
#
# Find the ODBC driver manager includes and library.
#
#
# ODBC is an open standard for connecting to different databases in a
# semi-vendor-independent fashion. First you install the ODBC driver
# manager. Then you need a driver for each separate database you want
# to connect to (unless a generic one works). VTK includes neither
# the driver manager nor the vendor-specific drivers: you have to find
# those yourself.
#
#
# This module defines
# ODBC_INCLUDE_DIR, where to find sql.h
# ODBC_LIBRARIES, the libraries to link against to use ODBC
@@ -27,26 +27,31 @@ find_path(ODBC_INCLUDE_DIR sql.h
"C:/Program Files (x86)/Windows Kits/8.0/include/um"
"C:/Program Files (x86)/Microsoft SDKs/Windows/v7.0A/Include"
"C:/Program Files/ODBC/include"
"C:/Program Files/Microsoft SDKs/Windows/v7.0/include"
"C:/Program Files/Microsoft SDKs/Windows/v6.0a/include"
"C:/Program Files/Microsoft SDKs/Windows/v7.0/include"
"C:/Program Files/Microsoft SDKs/Windows/v6.0a/include"
"C:/ODBC/include"
DOC "Specify the directory containing sql.h."
)
find_library(ODBC_LIBRARY
NAMES iodbc odbc odbcinst odbc32
PATHS
/usr/lib
/usr/lib/odbc
/usr/local/lib
/usr/local/lib/odbc
/usr/local/odbc/lib
"C:/Program Files (x86)/Windows Kits/8.0/Lib/win8/um/x86/"
"C:/Program Files (x86)/Microsoft SDKs/Windows/v7.0A/Lib"
"C:/Program Files/ODBC/lib"
"C:/ODBC/lib/debug"
DOC "Specify the ODBC driver manager library here."
)
if(MSVC)
# msvc knows where to find sdk libs
set(ODBC_LIBRARY odbc32)
else()
find_library(ODBC_LIBRARY
NAMES iodbc odbc odbcinst odbc32
PATHS
/usr/lib
/usr/lib/odbc
/usr/local/lib
/usr/local/lib/odbc
/usr/local/odbc/lib
"C:/Program Files (x86)/Windows Kits/8.0/Lib/win8/um/x86/"
"C:/Program Files (x86)/Microsoft SDKs/Windows/v7.0A/Lib"
"C:/Program Files/ODBC/lib"
"C:/ODBC/lib/debug"
DOC "Specify the ODBC driver manager library here."
)
endif()
if(ODBC_LIBRARY)
if(ODBC_INCLUDE_DIR)

View File

@@ -0,0 +1,76 @@
###############################################################################
#
# CMake module to search for Oracle client library (OCI)
#
# On success, the macro sets the following variables:
# ORACLE_FOUND = if the library found
# ORACLE_LIBRARY = full path to the library
# ORACLE_LIBRARIES = full path to the library
# ORACLE_INCLUDE_DIR = where to find the library headers also defined,
# but not for general use are
# ORACLE_VERSION = version of library which was found, e.g. "1.2.5"
#
# Copyright (c) 2009-2013 Mateusz Loskot <mateusz@loskot.net>
#
# Developed with inspiration from Petr Vanek <petr@scribus.info>
# who wrote similar macro for TOra - http://torasql.com/
#
# Module source: http://github.com/mloskot/workshop/tree/master/cmake/
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
#
###############################################################################
# First check for CMAKE variable
if( NOT ORACLE_HOME )
# If ORACLE_HOME is not defined check for env var and if exists set from env var
if(EXISTS $ENV{ORACLE_HOME})
set(ORACLE_HOME $ENV{ORACLE_HOME})
endif(EXISTS $ENV{ORACLE_HOME})
endif(NOT ORACLE_HOME)
message(STATUS "ORACLE_HOME=${ORACLE_HOME}")
find_path(ORACLE_INCLUDE_DIR
NAMES oci.h
PATHS
${ORACLE_HOME}/rdbms/public
${ORACLE_HOME}/include
${ORACLE_HOME}/sdk/include # Oracle SDK
${ORACLE_HOME}/OCI/include) # Oracle XE on Windows
set(ORACLE_OCI_NAMES clntsh libclntsh oci) # Dirty trick might help on OSX, see issues/89
set(ORACLE_OCCI_NAMES libocci occi oraocci10 oraocci11 oraocci12)
set(ORACLE_NNZ_NAMES nnz10 libnnz10 nnz11 libnnz11 nnz12 libnnz12 ociw32)
set(ORACLE_LIB_DIR
${ORACLE_HOME}
${ORACLE_HOME}/lib
${ORACLE_HOME}/sdk/lib # Oracle SDK
${ORACLE_HOME}/sdk/lib/msvc
${ORACLE_HOME}/OCI/lib/msvc) # Oracle XE on Windows
find_library(ORACLE_OCI_LIBRARY
NAMES ${ORACLE_OCI_NAMES} PATHS ${ORACLE_LIB_DIR})
find_library(ORACLE_OCCI_LIBRARY
NAMES ${ORACLE_OCCI_NAMES} PATHS ${ORACLE_LIB_DIR})
find_library(ORACLE_NNZ_LIBRARY
NAMES ${ORACLE_NNZ_NAMES} PATHS ${ORACLE_LIB_DIR})
set(ORACLE_LIBRARY
${ORACLE_OCI_LIBRARY}
${ORACLE_OCCI_LIBRARY}
${ORACLE_NNZ_LIBRARY})
if(NOT WIN32)
set(ORACLE_LIBRARY ${ORACLE_LIBRARY} ${ORACLE_CLNTSH_LIBRARY})
endif(NOT WIN32)
set(ORACLE_LIBRARIES ${ORACLE_LIBRARY})
# Handle the QUIETLY and REQUIRED arguments and set ORACLE_FOUND to TRUE
# if all listed variables are TRUE
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(ORACLE DEFAULT_MSG ORACLE_LIBRARY ORACLE_INCLUDE_DIR)
mark_as_advanced(ORACLE_INCLUDE_DIR ORACLE_LIBRARY)

View File

@@ -31,7 +31,7 @@ if(PG_CONFIG)
exec_program(${PG_CONFIG}
ARGS "--includedir"
OUTPUT_VARIABLE PG_CONFIG_INCLUDEDIR)
OUTPUT_VARIABLE PG_CONFIG_INCLUDEDIR)
exec_program(${PG_CONFIG}
ARGS "--libdir"
@@ -53,7 +53,7 @@ find_path(POSTGRESQL_INCLUDE_DIR libpq-fe.h
find_library(POSTGRESQL_LIBRARIES NAMES pq libpq
PATHS
${PG_CONFIG_LIBDIR}
${PG_CONFIG_LIBDIR}
/usr/lib
/usr/local/lib
/usr/lib/postgresql

View File

@@ -46,7 +46,7 @@ find_library(SQLITE3_LIBRARY
${SQLITE_ROOT_DIR}/lib
$ENV{OSGEO4W_ROOT}/lib)
set(SQLITE3_LIBRARIES
set(SQLITE3_LIBRARIES
${SQLITE3_LIBRARIES}
${SQLITE3_LIBRARY})

View File

@@ -1,499 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en'>
<head>
<meta content="text/html; charset=ISO-8859-1" http-equiv="content-type" />
<link rel="stylesheet" type="text/css" href="style.css" />
<title>SOCI - backends</title>
</head>
<body>
<p class="banner">SOCI - The C++ Database Access Library</p>
<h2>Backends reference</h2>
<p>This part of the documentation is provided for those who want to
write (and contribute!) their own backends. It is anyway recommended
that authors of new backend see the code of some existing backend for
hints on how things are really done.</p>
<p>The backend interface is a set of base classes that the actual backends
are supposed to specialize. The main SOCI interface uses only the
interface and respecting the protocol (for example, the order of
function calls) described here. Note that both the interface and the
protocol were initially designed with the Oracle database in mind,
which means
that whereas it is quite natural with respect to the way Oracle API
(OCI) works, it might impose some implementation burden on other
backends, where things are done differently and therefore have to be
adjusted, cached, converted, etc.</p>
<p>The interface to the common SOCI interface is defined in the <code>core/soci-backend.h</code>
header file. This file is dissected below.</p>
<p>All names are defined in either <code>soci</code> or <code>soci::details</code>
namespace.</p>
<pre class="example">
// data types, as seen by the user
enum data_type
{
dt_string, dt_date, dt_double, dt_integer, dt_long_long, dt_unsigned_long_long
};
// the enum type for indicator variables
enum indicator { i_ok, i_null, i_truncated };
// data types, as used to describe exchange format
enum exchange_type
{
x_char,
x_stdstring,
x_short,
x_integer,
x_long_long,
x_unsigned_long_long,
x_double,
x_stdtm,
x_statement,
x_rowid,
x_blob
};
struct cstring_descriptor
{
cstring_descriptor(char * str, std::size_t bufSize)
: str_(str), bufSize_(bufSize) {}
char * str_;
std::size_t bufSize_;
};
// actually in error.h:
class soci_error : public std::runtime_error
{
public:
soci_error(std::string const &amp; msg);
};
</pre>
<p>The <code>data_type</code> enumeration type defines all types that
form the core type support for SOCI. The enum itself can be used by
clients when dealing with dynamic rowset description.</p>
<p>The <code>indicator</code> enumeration type defines all recognized <i>states</i> of data.
The <code>i_truncated</code>
state is provided for the case where the string is retrieved from the
database into the char buffer that is not long enough to hold the whole
value.</p>
<p>The <code>exchange_type</code> enumeration type defines all possible
types that can be used with the <code>into</code> and <code>use</code>
elements.</p>
<p>The <code>cstring_descriptor</code> is a helper class that allows to
store the address of <code>char</code> buffer together with its size.
The objects of this class are passed to the backend when the <code>x_cstring</code>
type is involved.</p>
<p>The <code>soci_error</code> class is an exception type used for
database-related (and
also usage-related) errors. The backends should throw exceptions of
this or derived type only.</p>
<pre class="example">
class standard_into_type_backend
{
public:
standard_into_type_backend() {}
virtual ~standard_into_type_backend() {}
virtual void define_by_pos(int&amp; position, void* data, exchange_type type) = 0;
virtual void pre_fetch() = 0;
virtual void post_fetch(bool gotData, bool calledFromFetch, indicator* ind) = 0;
virtual void clean_up() = 0;
};
</pre>
<p>The <code>standard_into_type_back_end</code> class implements the dynamic
interactions with the simple (non-bulk) <code>into</code> elements.
The objects of this class (or, rather, of the derived class implemented
by the actual backend) are created by the <code>statement</code>
object when the <code>into</code> element is bound - in terms of
lifetime management, <code>statement</code> is the master of this
class.</p>
<ul>
<li><code>define_by_pos</code> - Called when the <code>into</code>
element is bound, once and before the statement is executed. The <code>data</code>
pointer points to the variable used for <code>into</code> element (or
to the <code>cstring_descriptor</code> object, which is artificially
created when the plain <code>char</code> buffer is used for data
exchange). The <code>position</code> parameter is a "column number",
assigned by
the library. The backend should increase this parameter, according to
the number of fields actually taken (usually 1).</li>
<li><code>pre_fetch</code> - Called before each row is fetched.</li>
<li><code>post_fetch</code> - Called after each row is fetched. The <code>gotData</code>
parameter is <code>true</code> if the fetch operation really retrieved
some data and <code>false</code> otherwise; <code>calledFromFetch</code>
is <code>true</code> when the call is from the fetch operation and <code>false</code>
if it is from the execute operation (this is also the case for simple,
one-time queries). In particular, <code>(calledFromFetch &amp;&amp;
!gotData)</code> indicates that there is an end-of-rowset condition. <code>ind</code>
points to the indicator provided by the user, or is <code>NULL</code>,
if there is no indicator.</li>
<li><code>clean_up</code> - Called once when the statement is
destroyed.</li>
</ul>
<p>The intended use of <code>pre_fetch</code> and <code>post_fetch</code>
functions is to manage any internal buffer and/or data conversion for
each value retrieved from the database. If the given server supports
binary data transmission and the data format for the given type agrees
with what is used on the client machine, then these two functions need
not do anything; otherwise buffer management and data conversions
should go there.</p>
<pre class="example">
class vector_into_type_backend
{
public:
vector_into_type_backend() {}
virtual ~vector_into_type_backend() {}
virtual void define_by_pos(int&amp; position, void* data, exchange_type type) = 0;
virtual void pre_fetch() = 0;
virtual void post_fetch(bool gotData, indicator* ind) = 0;
virtual void resize(std::size_t sz) = 0;
virtual std::size_t size() = 0;
virtual void clean_up() = 0;
};
</pre>
<p>The <code>vector_into_type_back_end</code> has similar structure and
purpose as the previous one, but is used for vectors (bulk data
retrieval).</p>
<p>The <code>data</code> pointer points to the variable of type <code>std::vector&lt;T&gt;</code>
(and <i>not</i> to its internal buffer), <code>resize</code>
is supposed to really resize the user-provided vector and <code>size</code>
is supposed to return the current size of this vector.
The important difference with regard to the previous class is that <code>ind</code>
points (if not <code>NULL</code>) to the beginning of the <i>array</i> of indicators. The backend
should fill this array according to the actual state of the retrieved
data.</p>
<pre class="example">
class standard_use_type_backend
{
public:
virtual ~standard_use_type_backend() {}
virtual void bind_by_pos(int&amp; position,
void* data, exchange_type type, bool readOnly) = 0;
virtual void bind_by_name(std::string const&amp; name,
void* data, exchange_type type, bool readOnly) = 0;
virtual void pre_use(indicator const* ind) = 0;
virtual void post_use(bool gotData, indicator* ind) = 0;
virtual void clean_up() = 0;
};
</pre>
<p>The <code>standard_use_type_backend</code> implements the interactions
with the simple (non-bulk) <code>use</code> elements, created and
destroyed by the <code>statement</code> object.</p>
<ul>
<li><code>bind_by_pos</code> - Called for each <code>use</code>
element, once and before the statement is executed - for those <code>use</code>
elements that do not provide explicit names for parameter binding. The
meaning of parameters is same as in previous classes.</li>
<li><code>bind_by_name</code> - Called for those <code>use</code>
elements that provide the explicit name.</li>
<li><code>pre_use</code> - Called before the data is transmitted to
the server (this means before the statement is executed, which can
happen many times for the prepared statement). <code>ind</code> points
to the indicator provided by the user (or is <code>NULL</code>).</li>
<li><code>post_use</code> - Called after statement execution. <code>gotData</code>
and <code>ind</code> have the same meaning as in <code>standard_into_type_back_end::post_fetch</code>,
and this can be used by those backends whose respective servers support
two-way data exchange (like in/out parameters in stored procedures).</li>
</ul>
<p>The intended use for <code>pre_use</code> and <code>post_use</code>
methods is to manage any internal buffers and/or data conversion. They
can be called many times with the same statement.</p>
<pre class="example">
class vector_use_type_backend
{
public:
virtual ~vector_use_type_backend() {}
virtual void bind_by_pos(int&amp; position,
void* data, exchange_type type) = 0;
virtual void bind_by_name(std::string const&amp; name,
void* data, exchange_type type) = 0;
virtual void pre_use(indicator const* ind) = 0;
virtual std::size_t size() = 0;
virtual void clean_up() = 0;
};
</pre>
<p>Objects of this type (or rather of type derived from this one) are used
to implement interactions with user-provided vector (bulk) <code>use</code>
elements and are managed by the <code>statement</code> object.
The <code>data</code> pointer points to the whole vector object
provided by the user (and <i>not</i> to
its internal buffer); <code>ind</code> points to the beginning of the
array of indicators (or is <code>NULL</code>). The meaning of this
interface is analogous to those presented above.</p>
<pre class="example">
class statement_backend
{
public:
statement_backend() {}
virtual ~statement_backend() {}
virtual void alloc() = 0;
virtual void clean_up() = 0;
virtual void prepare(std::string const&amp; query, statement_type eType) = 0;
enum exec_fetch_result
{
ef_success,
ef_no_data
};
virtual exec_fetch_result execute(int number) = 0;
virtual exec_fetch_result fetch(int number) = 0;
virtual long long get_affected_rows() = 0;
virtual int get_number_of_rows() = 0;
virtual std::string rewrite_for_procedure_call(std::string const&amp; query) = 0;
virtual int prepare_for_describe() = 0;
virtual void describe_column(int colNum, data_type&amp; dtype,
std::string&amp; column_name) = 0;
virtual standard_into_type_backend* make_into_type_backend() = 0;
virtual standard_use_type_backend* make_use_type_backend() = 0;
virtual vector_into_type_backend* make_vector_into_type_backend() = 0;
virtual vector_use_type_backend* make_vector_use_type_backend() = 0;
};
</pre>
<p>The <code>statement_backend</code> type implements the internals of the
<code>statement</code> objects. The objects of this class are created by the <code>session</code>
object.</p>
<ul>
<li><code>alloc</code> - Called once to allocate everything that is
needed for the statement to work correctly.</li>
<li><code>clean_up</code> - Supposed to clean up the resources, called
once.</li>
<li><code>prepare</code> - Called once with the text of the SQL
query. For servers that support explicit query preparation, this is the
place to do it.</li>
<li><code>execute</code> - Called to execute the query; if number is
zero, the intent is not to exchange data with the user-provided objects
(<code>into</code> and <code>use</code> elements); positive values
mean the number of rows to exchange (more than 1 is used only for bulk
operations).</li>
<li><code>fetch</code> - Called to fetch next bunch of rows; number
is positive and determines the requested number of rows (more than 1 is
used only for bulk operations).</li>
<li><code>get_affected_rows</code> - Called to determine the actual
number of rows affected by data modifying statement.</li>
<li><code>get_number_of_rows</code> - Called to determine the actual
number of rows retrieved by the previous call to <code>execute</code>
or <code>fetch</code>.</li>
<li><code>rewrite_for_procedure_call</code> - Used when the <code>procedure</code>
is used instead of <code>statement</code>, to call the stored
procedure. This function should rewrite the SQL query (if necessary) to
the form that will allow to execute the given procedure.
</li>
<li><code>prepare_for_describe</code> - Called once when the <code>into</code>
element is used with the <code>row</code> type, which means that
dynamic rowset description should be performed. It is supposed to do
whatever is needed to later describe the column properties and should
return the number of columns.</li>
<li><code>describe_column</code> - Called once for each column (column
numbers - <code>colNum</code> - start from 1), should fill its
parameters according to the column properties.</li>
<li><code>make_into_type_backend</code>, <code>make_use_type_backend</code>,
<code>make_vector_into_type_backend</code>, <code>make_vector_use_type_backend</code>
- Called once for each <code>into</code> or <code>use</code> element,
to create the objects of appropriate classes (described above).</li>
</ul>
<p>Notes:</p>
<ol>
<li>Whether the query is executed using the simple one-time syntax or
is prepared, the <code>alloc</code>, <code>prepare</code> and <code>execute</code>
functions are always called, in this order.</li>
<li>All <code>into</code> and <code>use</code> elements are bound
(their <code>define_by_pos</code> or <code>bind_by_pos</code>/<code>bind_by_name</code>
functions are called) <i>between</i>
statement preparation and execution.
</li>
</ol>
<pre class="example">
class rowid_backend
{
public:
virtual ~rowid_backend() {}
};
</pre>
<p>The <code>rowid_backend</code> class is a hook for the backends to
provide their own state for the row identifier. It has no functions,
since the only portable interaction with the row identifier object is
to use it with <code>into</code> and <code>use</code> elements.</p>
<pre class="example">
class blob_backend
{
public:
virtual ~blob_backend() {}
virtual std::size_t get_len() = 0;
virtual std::size_t read(std::size_t offset, char * buf,
std::size_t toRead) = 0;
virtual std::size_t write(std::size_t offset, char const * buf,
std::size_t toWrite) = 0;
virtual std::size_t append(char const * buf, std::size_t toWrite) = 0;
virtual void trim(std::size_t newLen) = 0;
};
</pre>
<p>The <code>blob_backend</code> interface provides the entry points for
the <code>blob</code> methods.</p>
<pre class="example">
class session_backend
{
public:
virtual ~session_backend() {}
virtual void begin() = 0;
virtual void commit() = 0;
virtual void rollback() = 0;
virtual bool get_next_sequence_value(session&amp;, std::string const&amp;, long&amp;);
virtual bool get_last_insert_id(session&amp;, std::string const&amp;, long&amp;);
virtual std::string get_backend_name() const = 0;
virtual statement_backend * make_statement_backend() = 0;
virtual rowid_backend * make_rowid_backend() = 0;
virtual blob_backend * make_blob_backend() = 0;
};
</pre>
<p>The object of the class derived from <code>session_backend</code> implements the
internals of the <code>session</code> object.</p>
<ul>
<li><code>begin</code>, <code>commit</code>, <code>rollback</code>
- Forward-called when the same functions of <code>session</code> are
called by user.</li>
<li><code>get_next_sequence_value</code>, <code>get_last_insert_id</code>
- Called to retrieve sequences or auto-generated values and every backend should
define at least one of them to allow the code using auto-generated values to work.
</li>
<li><code>make_statement_backend</code>, <code>make_rowid_backend</code>,
<code>make_blob_backend</code> - Called to create respective
implementations for the <code>statement</code>, <code>rowid</code>
and <code>blob</code> classes.
</li>
</ul>
<pre class="example">
struct backend_factory
{
virtual ~backend_factory() {}
virtual details::session_backend * make_session(
std::string const&amp; connectString) const = 0;
};
</pre>
<p>The <code>backend_factory</code> is a base class for backend-provided
factory class that is able to create valid sessions. The <code>connectString</code>
parameter passed to <code>make_session</code> is provided here by the <code>session</code>
constructor and contains only the backend-related parameters, without the backend name
(if the dynamic backend loading is used).</p>
<p>The actual backend factory object is supposed to be provided by the
backend implementation and declared in its header file. In addition to this,
the <code>factory_ABC</code> function with the "C" calling convention
and returning the pointer to concrete factory object should be provided,
where <code>ABC</code> is the backend name.</p>
<p>The following example is taken from <code>soci-postgresql.h</code>,
which declares entities of the PostgreSQL backend:</p>
<pre class="example">
struct postgresql_backend_factory : backend_factory
{
virtual postgresql_session_backend* make_session(
std::string const&amp; connectString) const;
};
extern postgresql_backend_factory const postgresql;
extern "C"
{
// for dynamic backend loading
backend_factory const * factory_postgresql();
} // extern "C"
</pre>
<p>With the above declarations, it is enough to pass the <code>postgresql</code>
factory name to the constructor of the <code>session</code> object,
which will use this factory to create concrete implementations for any
other objects that
are needed, with the help of appropriate <code>make_XYZ</code>
functions. Alternatively, the <code>factory_postgresql</code> function will
be called automatically by the backend loader if the backend name is provided
at run-time instead.</p>
<p>Note that the backend source code is placed in the <code>backends/<i>name</i></code> directory (for example,
<code>backends/oracle</code>) and the test driver is in <code>backends/<i>name</i>/test</code>. There is also <code>backends/empty</code>
directory provided as a skeleton for development of new backends and
their tests. It is
recommended that all backends respect naming conventions by just
appending their name to the base-class names. The backend name used for
the global factory object should clearly identify the given
database engine, like <code>oracle</code>, <code>postgresql</code>, <code>mysql</code>,
and so on.</p>
<table class="foot-links" border="0" cellpadding="2" cellspacing="2">
<tr>
<td class="foot-link-left">
<a href="reference.html">Previous (Client reference)</a>
</td>
<td class="foot-link-right">
<a href="rationale.html">Next (Rationale FAQ)</a>
</td>
</tr>
</table>
<p class="copyright">Copyright &copy; 2013 Mateusz Loskot</p>
<p class="copyright">Copyright &copy; 2012 Vadim Zeitlin</p>
<p class="copyright">Copyright &copy; 2004-2006 Maciej Sobczak, Stephen Hutton</p>
</body>
</html>

View File

@@ -1,120 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<meta content="text/html; charset=ISO-8859-1" http-equiv="content-type" />
<link rel="stylesheet" type="text/css" href="../style.css" />
<title>SOCI - DB2 Backend Reference</title>
</head>
<body>
<p class="banner">SOCI - The C++ Database Access Library</p>
<h2>DB2 Backend Reference</h2>
<div class="navigation">
<a href="#prerequisites">Prerequisites</a><br />
<div class="navigation-indented">
<a href="#versions">Supported Versions</a><br />
<a href="#tested">Tested Platforms</a><br />
<a href="#required">Required Client Libraries</a><br />
</div>
<a href="#connecting">Connecting to the Database</a><br />
<a href="#support">SOCI Feature Support</a><br />
<div class="navigation-indented">
<a href="#dynamic">Dynamic Binding</a><br />
<a href="#bindingbyname">Binding by Name</a><br />
<a href="#bulk">Bulk Operations</a><br />
<a href="#transactions">Transactions</a><br />
<a href="#blob">BLOB Data Type</a><br />
<a href="#rowid">RowID Data Type</a><br />
<a href="#nested">Nested Statements</a><br />
<a href="#procedures">Stored Procedures</a><br />
</div>
<a href="#native">Accessing the Native Database API</a><br />
<a href="#extensions">Backend-specific Extensions</a><br />
<a href="#options">Configuration options</a><br />
</div>
<h3 id="prerequisites">Prerequisites</h3>
<h4 id="versions">Supported Versions</h4>
<p>The SOCI DB2 backend .</p>
<h4 id="tested">Tested Platforms</h4>
<table border="1" cellpadding="5" cellspacing="0">
<tbody>
<tr><th>DB2 version</th><th>Operating System</th><th>Compiler</th></tr>
<tr><td>-</td><td>Linux PPC64</td><td>GCC</td></tr>
<tr><td>9.1</td><td>Linux</td><td>GCC</td></tr>
<tr><td>9.5</td><td>Linux</td><td>GCC</td></tr>
<tr><td>9.7</td><td>Linux</td><td>GCC</td></tr>
<tr><td>10.1</td><td>Linux</td><td>GCC</td></tr>
<tr><td>10.1</td><td>Windows 8</td><td>Visual Studio 2012</td></tr>
</tbody>
</table>
<h4 id="required">Required Client Libraries</h4>
<p>The SOCI DB2 backend requires IBM DB2 Call Level Interface (CLI) library.</p>
<h4 id="connecting">Connecting to the Database</h4>
<p>On Unix, before using the DB2 backend please make sure, that you have sourced
DB2 profile into your environment:</p>
<pre>. ~/db2inst1/sqllib/db2profile</pre>
<p>To establish a connection to the DB2 database, create a session object
using the <code>DB2</code> backend factory together with the database file name:</p>
<pre class="example">
soci::session sql(soci::db2, "your DB2 connection string here");
</pre>
<h3 id="support">SOCI Feature Support</h3>
<h4 id="dynamic">Dynamic Binding</h4>
<p>TODO</p>
<h4 id="bindingbyname">Binding by Name</h4>
<p>TODO</p>
<h4 id="bulk">Bulk Operations</h4>
<p>Supported, but with caution as it hasn't been extensively tested.</p>
<h4 id="transactions">Transactions</h4>
<p>Currently, not supported.</p>
<h4 id="blob">BLOB Data Type</h4>
<p>Currently, not supported.</p>
<h4 id="nested">Nested Statements</h4>
<p>Nesting statements are not processed by SOCI in any special way and
they work as implemented by the DB2 database.</p>
<h4 id="procedures">Stored Procedures</h4>
<p>Stored procedures are supported, with <code>CALL</code> statement.</p>
<h3 id="native">Acessing the native database API</h3>
<p>TODO</p>
<h3 id="extensions">Backend-specific extensions</h3>
<p>None.</p>
<h3 id="options">Configuration options</h3>
<p>None</p>
<p class="copyright">Copyright &copy; 2013 Mateusz Loskot</p>
</body>
</html>

View File

@@ -1,240 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<meta content="text/html; charset=ISO-8859-1" http-equiv="content-type" />
<link rel="stylesheet" type="text/css" href="../style.css" />
<title>SOCI - Firebird Backend Reference</title>
</head>
<body>
<p class="banner">SOCI - The C++ Database Access Library</p>
<h2>Firebird Backend Reference</h2>
<div class="navigation">
<a href="#prerequisites">Prerequisites</a><br />
<div class="navigation-indented">
<a href="#versions">Supported Versions</a><br />
<a href="#tested">Tested Platforms</a><br />
<a href="#required">Required Client Libraries</a><br />
</div>
<a href="#connecting">Connecting to the Database</a><br />
<a href="#support">SOCI Feature Support</a><br />
<div class="navigation-indented">
<a href="#dynamic">Dynamic Binding</a><br />
<a href="#bindingbyname">Binding by Name</a><br />
<a href="#bulk">Bulk Operations</a><br />
<a href="#transactions">Transactions</a><br />
<a href="#blob">BLOB Data Type</a><br />
<a href="#rowid">RowID Data Type</a><br />
<a href="#nested">Nested Statements</a><br />
<a href="#procedures">Stored Procedures</a><br />
</div>
<a href="#native">Accessing the Native Database API</a><br />
<a href="#extensions">Backend-specific Extensions</a><br />
<div class="navigation-indented">
<a href="#firebird_soci_error">FirebirdSOCIError</a><br />
</div>
<a href="#options">Configuration options</a><br />
</div>
<h3 id="prerequisites">Prerequisites</h3>
<h4 id="versions">Supported Versions</h4>
<p>The SOCI Firebird backend is currently supported for use with Firebird 1.5.<br />
Other versions of Firebird may work as well, but they have not been tested by the SOCI team.</p>
<h4 id="tested">Tested Platforms</h4>
<table border="1" cellpadding="5" cellspacing="0">
<tbody>
<tr><th>Firebird version</th><th>Operating System</th><th>Compiler</th></tr>
<tr><td>1.5.2.4731</td><td>SunOS 5.10</td><td>g++ 3.4.3</td></tr>
<tr><td>1.5.2.4731</td><td>Windows XP</td><td>Visual C++ 8.0</td></tr>
<tr><td>1.5.3.4870</td><td>Windows XP</td><td>Visual C++ 8.0 Professional</td></tr>
</tbody>
</table>
<h4 id="required">Required Client Libraries</h4>
<p>The Firebird backend requires Firebird's <code>libfbclient</code> client library.</p>
<h4 id="connecting">Connecting to the Database</h4>
<p>To establish a connection to a Firebird database, create a Session object
using the firebird backend factory together with a connection string:</p>
<pre class="example">
BackEndFactory const &amp;backEnd = firebird;
Session sql(backEnd,
"service=/usr/local/firbird/db/test.fdb user=SYSDBA password=masterkey");
</pre>
<p>or simply:</p>
<pre class="example">
Session sql(firebird,
"service=/usr/local/firbird/db/test.fdb user=SYSDBA password=masterkey");
</pre>
<p>The set of parameters used in the connection string for Firebird is:</p>
<ul>
<li>service</li>
<li>user</li>
<li>password</li>
<li>role</li>
<li>charset</li>
</ul>
<p>The following parameters have to be provided as part of the connection string :
<i>service</i>, <i>user</i>, <i>password</i>. Role and charset parameters are optional.</p>
<p>Once you have created a <code>Session</code> object as shown above, you can use it to access the database, for example:</p>
<pre class="example">
int count;
sql &lt;&lt; "select count(*) from user_tables", into(count);
</pre>
<p>(See the <a href="../basics.html">SOCI basics</a> and <a href="../exchange.html">exchanging data</a> documentation for general information on using the <code>Session</code> class.)</p>
<h3 id="support">SOCI Feature Support</h3>
<h4 id="dynamic">Dynamic Binding</h4>
<p>The Firebird backend supports the use of the SOCI <code>Row</code> class, which facilitates retrieval of data whose type is not known at compile time.</p>
<p>When calling <code>Row::get&lt;T&gt;()</code>, the type you should pass as T depends upon the underlying database type. For the Firebird backend, this type mapping is:</p>
<table border="1" cellpadding="5" cellspacing="0">
<tbody>
<tr>
<th>Firebird Data Type</th>
<th>SOCI Data Type</th>
<th><code>Row::get&lt;T&gt;</code> specializations</th>
</tr>
<tr>
<td>numeric, decimal <br /><i>(where scale &gt; 0)</i></td>
<td><code>eDouble</code></td>
<td><code>double</code></td>
</tr>
<tr>
<td>numeric, decimal <sup>[<a href="#note1">1</a>]</sup><br /><i>(where scale = 0)</i></td>
<td><code>eInteger, eDouble</code></td>
<td><code>int, double</code></td>
</tr>
<tr>
<td>double precision, float</td>
<td><code>eDouble</code></td>
<td><code>double</code></td>
</tr>
<tr>
<td>smallint, integer</td>
<td><code>eInteger</code></td>
<td><code>int</code></td>
</tr>
<tr>
<td>char, varchar</td>
<td><code>eString</code></td>
<td><code>std::string</code></td>
</tr>
<tr>
<td>date, time, timestamp</td>
<td><code>eDate</code></td>
<td><code>std::tm</code><code></code></td>
</tr>
</tbody>
</table>
<p><a name="note1" />&nbsp;<sup>[1]</sup> &nbsp;There is also 64bit integer type for larger values which is
currently not supported.</p>
<p>(See the <a href="../exchange.html#dynamic">dynamic resultset binding</a> documentation for general information on using the <code>Row</code> class.)</p>
<h4 id="bindingbyname">Binding by Name</h4>
<p>In addition to <a href="../exchange.html#bind_position">binding by position</a>, the Firebird backend supports <a href="../exchange.html#bind_name">binding by name</a>, via an overload of the <code>use()</code> function:</p>
<pre class="example">
int id = 7;
sql &lt;&lt; "select name from person where id = :id", use(id, "id")
</pre>
<p>It should be noted that parameter binding by name is supported only by means of emulation, since the underlying API used by the backend doesn't provide this feature.</p>
<h4 id="bulk">Bulk Operations</h4>
<p>The Firebird backend has full support for SOCI's <a href="../statements.html#bulk">bulk operations</a> interface. This feature is also supported by emulation.</p>
<h4 id="transactions">Transactions</h4>
<p><a href="../statements.html#transactions">Transactions</a> are also fully
supported by the Firebird backend. In fact, there is always a transaction which is automatically commited in <code>Session's</code> destructor.
<br />See the <a href="#options">Configuration options</a> section for more details.</p>
<h4 id="blob">BLOB Data Type</h4>
<p>The Firebird backend supports working with data stored in columns of type Blob, via SOCI's <a href="../exchange.html#blob"><code>BLOB</code></a> class.</p>
<p>It should by noted, that entire Blob data is fetched from database to allow random read and write access.
This is because Firebird itself allows only writing to a new Blob or reading from existing one -
modifications of existing Blob means creating a new one. Firebird backend hides those details from user.</p>
<h4 id="rowid">RowID Data Type</h4>
<p>This feature is not supported by Firebird backend.</p>
<h4 id="nested">Nested Statements</h4>
<p>This feature is not supported by Firebird backend.</p>
<h4 id="procedures">Stored Procedures</h4>
<p>Firebird stored procedures can be executed by using SOCI's <a href="../statements.html#procedures">Procedure</a> class.</p>
<h3 id="native">Acessing the native database API</h3>
<p>SOCI provides access to underlying datbabase APIs via several getBackEnd() functions, as described in the <a href="../beyond.html">beyond SOCI</a> documentation.</p>
<p>The Firebird backend provides the following concrete classes for navite API access:</p>
<table border="1" cellpadding="5" cellspacing="0">
<tbody>
<tr>
<th>Accessor Function</th>
<th>Concrete Class</th>
</tr>
<tr>
<td><code>SessionBackEnd* Session::getBackEnd()</code></td>
<td><code>FirebirdSessionBackEnd</code></td>
</tr>
<tr>
<td><code>StatementBackEnd* Statement::getBackEnd()</code></td>
<td><code>FirebirdStatementBackEnd</code></td>
</tr>
<tr>
<td><code>BLOBBackEnd* BLOB::getBackEnd()</code></td>
<td><code>FirebirdBLOBBackEnd</code></td>
</tr>
<tr>
<td><code>RowIDBackEnd* RowID::getBackEnd()</code></td>
<td><code>FirebirdRowIDBackEnd</code></td>
</tr>
</tbody>
</table>
<h3 id="extensions">Backend-specific extensions</h3>
<h4 id="firebird_soci_error">FirebirdSOCIError</h4>
<p>The Firebird backend can throw instances of class <code>FirebirdSOCIError</code>,
which is publicly derived from <code>SOCIError</code> and has an
additional public <code>status_</code> member containing the Firebird status vector.</p>
<h3 id="options">Configuration options</h3>
<p>The Firebird backend recognize the following configuration macros :</p>
<ul>
<li><code>SOCI_FIREBIRD_NORESTARTTRANSACTION </code> -
Transactions will not be restarted automatically after commit() or rollback().
The default is to restart transactions.</li>
</ul>
<p class="copyright">Copyright &copy; 2004-2006 Maciej Sobczak, Stephen Hutton, Rafal Bobrowski</p>
</body>
</html>

View File

@@ -1,261 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en'>
<head>
<meta content="text/html; charset=ISO-8859-1" http-equiv="content-type" />
<link rel="stylesheet" type="text/css" href="../style.css" />
<title>SOCI - MySQL Backend Reference</title>
</head>
<body>
<p class="banner">SOCI - The C++ Database Access Library</p>
<h2>MySQL Backend Reference</h2>
<div class="navigation">
<a href="#prerequisites">Prerequisites</a><br />
<div class="navigation-indented">
<a href="#versions">Supported Versions</a><br />
<a href="#tested">Tested Platforms</a><br />
<a href="#required">Required Client Libraries</a><br />
</div>
<a href="#connecting">Connecting to the Database</a><br />
<a href="#support">SOCI Feature Support</a><br />
<div class="navigation-indented">
<a href="#dynamic">Dynamic Binding</a><br />
<a href="#bindingbyname">Binding by Name</a><br />
<a href="#bulk">Bulk Operations</a><br />
<a href="#transactions">Transactions</a><br />
<a href="#blob">BLOB Data Type</a><br />
<a href="#rowid">RowID Data Type</a><br />
<a href="#nested">Nested Statements</a><br />
<a href="#procedures">Stored Procedures</a><br />
</div>
<a href="#native">Accessing the Native Database API</a><br />
<a href="#extensions">Backend-specific Extensions</a><br />
<a href="#options">Configuration options</a><br />
</div>
<h3 id="prerequisites">Prerequisites</h3>
<h4 id="versions">Supported Versions</h4>
<p>The SOCI MySQL backend should in principle work with every version of MySQL 5.x.
Some of the features (transactions, stored functions) are not available when
MySQL server doesn't support them.</p>
<h4 id="tested">Tested Platforms</h4>
<table border="1" cellpadding="5" cellspacing="0">
<tbody>
<tr><th>MySQL version</th><th>Operating System</th><th>Compiler</th></tr>
<tr><td>5.5.28</td><td>OS X 10.8.2</td><td>Apple LLVM version 4.2
(clang-425.0.24)</td></tr>
<tr><td>5.0.96</td><td>Ubuntu 8.04.4 LTS (Hardy Heron)</td>
<td>g++ (GCC) 4.2.4 (Ubuntu 4.2.4-1ubuntu4)</td>
</tr>
</tbody>
</table>
<h4 id="required">Required Client Libraries</h4>
<p>The SOCI MySQL backend requires MySQL's <code>libmysqlclient</code>
client library.</p>
<p>Note that the SOCI library itself depends also on <code>libdl</code>, so the minimum set of libraries needed to compile a basic client program is:</p>
<pre class="example">
-lsoci_core -lsoci_mysql -ldl -lmysqlclient
</pre>
<h4 id="connecting">Connecting to the Database</h4>
<p>To establish a connection to a MySQL server, create a <code>session</code> object
using the <code>mysql</code> backend factory together with a connection
string:</p>
<pre class="example">
session sql(mysql, "db=test user=root password='Ala ma kota'");
// or:
session sql("mysql", "db=test user=root password='Ala ma kota'");
// or:
session sql("mysql://db=test user=root password='Ala ma kota'");
</pre>
<p>The set of parameters used in the connection string for MySQL is:</p>
<ul>
<li><code>dbname</code> or <code>db</code> or <code>service</code>
(required)</li>
<li><code>user</code></li>
<li><code>password</code> or <code>pass</code></li>
<li><code>host</code></li>
<li><code>port</code></li>
<li><code>unix_socket</code></li>
<li><code>sslca</code></li>
<li><code>sslcert</code></li>
<li><code>local_infile</code> - should be <code>0</code> or <code>1</code>,
<code>1</code> means <code>MYSQL_OPT_LOCAL_INFILE</code> will be set.</li>
<li><code>charset</code></li>
</ul>
<p>Once you have created a <code>session</code> object as shown above, you
can use it to access the database, for example:</p>
<pre class="example">
int count;
sql &lt;&lt; "select count(*) from invoices", into(count);
</pre>
<p>(See the <a href="../basics.html">SOCI basics</a> and <a href="../exchange.html">exchanging data</a> documentation for general information on using the <code>session</code> class.)</p>
<h3 id="support">SOCI Feature Support</h3>
<h4 id="dynamic">Dynamic Binding</h4>
<p>The MySQL backend supports the use of the SOCI <code>row</code> class,
which facilitates retrieval of data which type is not known at compile
time.</p>
<p>When calling <code>row::get&lt;T&gt;()</code>, the type you should pass
as <code>T</code> depends upon the underlying database type.<br/>
For the MySQL backend, this type mapping is:</p>
<table border="1" cellpadding="5" cellspacing="0">
<tbody>
<tr>
<th>MySQL Data Type</th>
<th>SOCI Data Type</th>
<th><code>row::get&lt;T&gt;</code> specializations</th>
</tr>
<tr>
<td>FLOAT, DOUBLE, DECIMAL and synonyms</td>
<td><code>dt_double</code></td>
<td><code>double</code></td>
</tr>
<tr>
<td>TINYINT, TINYINT UNSIGNED, SMALLINT, SMALLINT UNSIGNED, INT</td>
<td><code>dt_integer</code></td>
<td><code>int</code></td>
</tr>
<tr>
<td>INT UNSIGNED</td>
<td><code>dt_long_long</code></td>
<td><code>long long</code> or <code>unsigned</code></td>
</tr>
<tr>
<td>BIGINT</td>
<td><code>dt_long_long</code></td>
<td><code>long long</code></td>
</tr>
<tr>
<td>BIGINT UNSIGNED</td>
<td><code>dt_unsigned_long_long</code></td>
<td><code>unsigned long long</code></td>
</tr>
<tr>
<td>CHAR, VARCHAR, BINARY, VARBINARY, TINYBLOB, MEDIUMBLOB, BLOB,
LONGBLOB, TINYTEXT, MEDIUMTEXT, TEXT, LONGTEXT, ENUM</td>
<td><code>dt_string</code></td>
<td><code>std::string</code></td>
</tr>
<tr>
<td>TIMESTAMP (works only with MySQL >=&nbsp;5.0), DATE,
TIME, DATETIME</td>
<td><code>dt_date</code></td>
<td><code>std::tm</code><code></code></td>
</tr>
</tbody>
</table>
<p>(See the <a href="../exchange.html#dynamic">dynamic resultset binding</a> documentation for general information on using the <code>Row</code> class.)</p>
<h4 id="bindingbyname">Binding by Name</h4>
<p>In addition to <a href="../exchange.html#bind_position">binding by
position</a>, the MySQL backend supports
<a href="../exchange.html#bind_name">binding by name</a>, via an overload
of the <code>use()</code> function:</p>
<pre class="example">
int id = 7;
sql &lt;&lt; "select name from person where id = :id", use(id, "id")
</pre>
<p>It should be noted that parameter binding of any kind is supported
only by means of emulation, since the underlying API used by the backend
doesn't provide this feature.</p>
<h4 id="bulk">Bulk Operations</h4>
<p>The MySQL backend has full support for SOCI's <a href="../statements.html#bulk">bulk operations</a> interface. This feature is also supported
by emulation.</p>
<h4 id="transactions">Transactions</h4>
<p><a href="../statements.html#transactions">Transactions</a> are also
supported by the MySQL backend. Please note, however, that transactions
can only be used when the MySQL server supports them (it depends on
options used during the compilation of the server; typically, but not
always, servers >=4.0 support transactions and earlier versions do not)
and only with appropriate table types.
</p>
<h4 id="blob">BLOB Data Type</h4>
<p>SOCI <code>blob</code> interface is not supported by the MySQL backend.</p>
<p>Note that this does not mean you cannot use MySQL's <code>BLOB</code>
types. They can be selected using the usual SQL syntax and read into
<code>std::string</code> on the C++ side, so no special interface is
required.</p>
<h4 id="rowid">RowID Data Type</h4>
<p>The <code>rowid</code> functionality is not supported by the MySQL backend.</p>
<h4 id="nested">Nested Statements</h4>
<p>Nested statements are not supported by the MySQL backend.</p>
<h4 id="procedures">Stored Procedures</h4>
<p>MySQL version 5.0 and later supports two kinds of
stored routines: stored procedures and stored functions
(for details, please consult the
<a href="http://dev.mysql.com/doc/refman/5.0/en/stored-procedures.html">MySQL
documentation</a>). Stored functions can be executed by using
SOCI's <a href="../statements.html#procedures">procedure</a> class.
There is currently no support for stored procedures.</p>
<h3 id="native">Accessing the native database API</h3>
<p>SOCI provides access to underlying datbabase APIs via several <code>get_backend()</code> functions, as described in the <a href="../beyond.html">Beyond SOCI</a> documentation.</p>
<p>The MySQL backend provides the following concrete classes for native API access:</p>
<table border="1" cellpadding="5" cellspacing="0">
<tbody>
<tr>
<th>Accessor Function</th>
<th>Concrete Class</th>
</tr>
<tr>
<td><code>session_backend * session::get_backend()</code></td>
<td><code>mysql_session_backend</code></td>
</tr>
<tr>
<td><code>statement_backend * statement::get_backend()</code></td>
<td><code>mysql_statement_backend</code></td>
</tr>
</tbody>
</table>
<h3 id="extensions">Backend-specific extensions</h3>
<p>None.</p>
<h3 id="options">Configuration options</h3>
<p>None.</p>
<p class="copyright">Copyright &copy; 2004-2008 Maciej Sobczak, Stephen Hutton, Pawel Aleksander Fedorynski</p>
</body>
</html>

View File

@@ -1,288 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<meta content="text/html; charset=ISO-8859-1" http-equiv="content-type" />
<link rel="stylesheet" type="text/css" href="../style.css" />
<title>SOCI - ODBC Backend Reference</title>
</head>
<body>
<p class="banner">SOCI - The C++ Database Access Library</p>
<h2>ODBC Backend Reference</h2>
<div class="navigation">
<a href="#prerequisites">Prerequisites</a><br />
<div class="navigation-indented">
<a href="#versions">Supported Versions</a><br />
<a href="#tested">Tested Platforms</a><br />
<a href="#required">Required Client Libraries</a><br />
</div>
<a href="#connecting">Connecting to the Database</a><br />
<a href="#support">SOCI Feature Support</a><br />
<div class="navigation-indented">
<a href="#dynamic">Dynamic Binding</a><br />
<a href="#bindingbyname">Binding by Name</a><br />
<a href="#bulk">Bulk Operations</a><br />
<a href="#transactions">Transactions</a><br />
<a href="#blob">BLOB Data Type</a><br />
<a href="#rowid">RowID Data Type</a><br />
<a href="#nested">Nested Statements</a><br />
<a href="#procedures">Stored Procedures</a><br />
</div>
<a href="#native">Accessing the Native Database API</a><br />
<a href="#extensions">Backend-specific Extensions</a><br />
<div class="navigation-indented">
<a href="#odbc_soci_error">odbc_soci_error</a><br />
</div>
<a href="#options">Configuration options</a><br />
</div>
<h3 id="prerequisites">Prerequisites</h3>
<h4 id="versions">Supported Versions</h4>
<p>The SOCI ODBC backend is supported for use with ODBC 3.</p>
<h4 id="tested">Tested Platforms</h4>
<table border="1" cellpadding="5" cellspacing="0">
<tbody>
<tr><th>ODBC version</th><th>Operating System</th><th>Compiler</th></tr>
<tr><td>3</td><td>Linux (Ubuntu 12.04)</td><td>g++ 4.6.3</td></tr>
<tr><td>3</td><td>Linux (Ubuntu 12.04)</td><td>clang 3.2</td></tr>
<tr><td>3.8</td><td>Windows 8</td><td>Visual Studio 2012</td></tr>
<tr><td>3</td><td>Windows 7</td><td>Visual Studio 2010</td></tr>
<tr><td>3</td><td>Windows XP</td><td>Visual Studio 2005 (express)</td></tr>
<tr><td>3</td><td>Windows XP</td><td>Visual C++ 8.0 Professional</td></tr>
<tr><td>3</td><td>Windows XP</td><td>g++ 3.3.4 (Cygwin)</td></tr>
</tbody>
</table>
<h4 id="required">Required Client Libraries</h4>
<p>The SOCI ODBC backend requires the ODBC client library.</p>
<h4 id="connecting">Connecting to the Database</h4>
<p>To establish a connection to the ODBC database, create a Session object
using the <code>ODBC</code> backend factory together with a connection string:</p>
<pre class="example">
backend_factory const&amp; backEnd = odbc;
session sql(backEnd, "filedsn=c:\\my.dsn");
</pre>
<p>or simply:</p>
<pre class="example">
session sql(odbc, "filedsn=c:\\my.dsn");
</pre>
<p>The set of parameters used in the connection string for ODBC is the same as accepted by the <code><a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_d_4x4k.asp">SQLDriverConnect</a></code> function from the ODBC library.</p>
<p>Once you have created a <code>session</code> object as shown above, you can use it to access the database, for example:</p>
<pre class="example">
int count;
sql &lt;&lt; "select count(*) from invoices", into(count);
</pre>
<p>(See the <a href="../basics.html">SOCI basics</a> and <a href="../exchange.html">exchanging data</a> documentation for general information on using the <code>session</code> class.)</p>
<h3 id="support">SOCI Feature Support</h3>
<h4 id="dynamic">Dynamic Binding</h4>
<p>The ODBC backend supports the use of the SOCI <code>row</code> class, which facilitates retrieval of data whose type is not known at compile time.</p>
<p>When calling <code>row::get&lt;T&gt;()</code>, the type you should pass as T depends upon the underlying database type.<br/> For the ODBC backend, this type mapping is:</p>
<table border="1" cellpadding="5" cellspacing="0">
<tbody>
<tr>
<th>ODBC Data Type</th>
<th>SOCI Data Type</th>
<th><code>row::get&lt;T&gt;</code> specializations</th>
</tr>
<tr>
<td>SQL_DOUBLE
, SQL_DECIMAL
, SQL_REAL
, SQL_FLOAT
, SQL_NUMERIC
</td>
<td><code>dt_double</code></td>
<td><code>double</code></td>
</tr>
<tr>
<td>SQL_TINYINT
, SQL_SMALLINT
, SQL_INTEGER
, SQL_BIGINT</td>
<td><code>dt_integer</code></td>
<td><code>int</code></td>
</tr>
<tr>
<td>SQL_CHAR, SQL_VARCHAR</td>
<td><code>dt_string</code></td>
<td><code>std::string</code></td>
</tr>
<tr>
<td>SQL_TYPE_DATE
, SQL_TYPE_TIME
, SQL_TYPE_TIMESTAMP</td>
<td><code>dt_date</code></td>
<td><code>std::tm</code><code></code></td>
</tr>
</tbody>
</table>
<p>Not all ODBC drivers support all datatypes</p>
<p>(See the <a href="../exchange.html#dynamic">dynamic resultset binding</a> documentation for general information on using the <code>row</code> class.)</p>
<h4 id="bindingbyname">Binding by Name</h4>
<p>In addition to <a href="../exchange.html#bind_position">binding by position</a>, the ODBC backend supports <a href="../exchange.html#bind_name">binding by name</a>, via an overload of the <code>use()</code> function:</p>
<pre class="example">
int id = 7;
sql &lt;&lt; "select name from person where id = :id", use(id, "id")
</pre>
<p>Apart from the portable "colon-name" syntax above, which is achieved by rewriting the query string, the backend also supports the ODBC ? syntax:</p>
<pre class="example">
int i = 7;
int j = 8;
sql &lt;&lt; "insert into t(x, y) values(?, ?)", use(i), use(j);
</pre>
<h4 id="bulk">Bulk Operations</h4>
<p>The ODBC backend has support for SOCI's <a href="../statements.html#bulk">bulk operations</a> interface. Not all ODBC drivers support bulk operations, the following is a list of some tested backends:</p>
<table border="1" cellpadding="5" cellspacing="0">
<tbody>
<tr>
<th>ODBC Driver</th>
<th>Bulk Read</th>
<th>Bulk Insert</th>
</tr>
<tr>
<td>MS SQL Server 2005</td>
<td>YES</td>
<td>YES</td>
</tr>
<tr>
<td>MS Access 2003</td>
<td>YES</td>
<td>NO</td>
</tr>
<tr>
<td>PostgresQL 8.1</td>
<td>YES</td>
<td>YES</td>
</tr>
<tr>
<td>MySQL 4.1</td>
<td>NO</td>
<td>NO</td>
</tr>
</tbody>
</table>
<h4 id="transactions">Transactions</h4>
<p><a href="../statements.html#transactions">Transactions</a> are also fully supported by the ODBC backend, provided that they are supported by the underlying database.</p>
<h4 id="blob">BLOB Data Type</h4>
<p>Not currently supported</p>
<h4 id="rowid">RowID Data Type</h4>
<p>Not currently supported</p>
<h4 id="nested">Nested Statements</h4>
<p>Not currently supported</p>
<h4 id="procedures">Stored Procedures</h4>
<p>Not currently supported</p>
<h3 id="native">Acessing the native database API</h3>
<p>SOCI provides access to underlying datbabase APIs via several getBackEnd() functions, as described in the <a href="../beyond.html">beyond SOCI</a> documentation.</p>
<p>The ODBC backend provides the following concrete classes for navite API access:</p>
<table border="1" cellpadding="5" cellspacing="0">
<tbody>
<tr>
<th>Accessor Function</th>
<th>Concrete Class</th>
</tr>
<tr>
<td><code>session_backend* session::get_backend()</code></td>
<td><code>odbc_statement_backend</code></td>
</tr>
<tr>
<td><code>statement_backend* statement::get_backend()</code></td>
<td><code>odbc_statement_backend</code></td>
</tr>
<tr>
<td><code>rowid_backend* rowid::get_backend()</code></td>
<td><code>odbc_rowid_backend</code></td>
</tr>
</tbody>
</table>
<h3 id="extensions">Backend-specific extensions</h3>
<h4 id="odbc_soci_error">odbc_soci_error</h4>
<p>The ODBC backend can throw instances of class <code>odbc_soci_error</code>,
which is publicly derived from <code>soci_error</code> and has
additional public members containing the ODBC error code, the Native database
error code, and the message returned from ODBC:</p>
<pre class="example">
int main()
{
try
{
// regular code
}
catch (soci::odbc_soci_error const&amp; e)
{
cerr &lt;&lt; "ODBC Error Code: " &lt;&lt; e.odbc_error_code() &lt;&lt; endl
&lt;&lt; "Native Error Code: " &lt;&lt; e.native_error_code() &lt;&lt; endl
&lt;&lt; "SOCI Message: " &lt;&lt; e.what() &lt;&lt; std::endl
&lt;&lt; "ODBC Message: " &lt;&lt; e.odbc_error_message() &lt;&lt; endl;
}
catch (exception const &amp;e)
{
cerr &lt;&lt; "Some other error: " &lt;&lt; e.what() &lt;&lt; endl;
}
}
</pre>
<h4 id="get_connection_string">get_connection_string()</h4>
<p>The <code>odbc_session_backend</code> class provides <code>std::string get_connection_string() const</code> method
that returns fully expanded connection string as returned by the <code>SQLDriverConnect</code> function.</p>
<h3 id="options">Configuration options</h3>
<p>This backend supports <code>odbc_option_driver_complete</code> option which can be passed to it via <code>connection_parameters</code> class. The value of this option is passed to <code>SQLDriverConnect()</code> function as "driver completion" parameter and so must be one of <code>SQL_DRIVER_XXX</code> values, in the string form. The default value of this option is <code>SQL_DRIVER_PROMPT</code> meaning that the driver will query the user for the user name and/or the password if they are not stored together with the connection. If this is undesirable for some reason, you can use <code>SQL_DRIVER_NOPROMPT</code> value for this option to suppress showing the message box:</p>
<pre class="example">
connection_parameters parameters("odbc", "DSN=mydb");
parameters.set_option(odbc_option_driver_complete, "0" /* SQL_DRIVER_NOPROMPT */);
session sql(parameters);
</pre>
<p class="copyright">Copyright &copy; 2013 Mateusz Loskot</p>
<p class="copyright">Copyright &copy; 2004-2006 Maciej Sobczak, Stephen Hutton, David Courtney</p>
</body>
</html>

View File

@@ -1,260 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en'>
<head>
<meta content="text/html; charset=ISO-8859-1" http-equiv="content-type" />
<link rel="stylesheet" type="text/css" href="../style.css" />
<title>SOCI - Oracle Backend Reference</title>
</head>
<body>
<p class="banner">SOCI - The C++ Database Access Library</p>
<h2>Oracle Backend Reference</h2>
<div class="navigation">
<a href="#prerequisites">Prerequisites</a><br />
<div class="navigation-indented">
<a href="#versions">Supported Versions</a><br />
<a href="#tested">Tested Platforms</a><br />
<a href="#required">Required Client Libraries</a><br />
</div>
<a href="#connecting">Connecting to the Database</a><br />
<a href="#support">SOCI Feature Support</a><br />
<div class="navigation-indented">
<a href="#dynamic">Dynamic Binding</a><br />
<a href="#bindingbyname">Binding by Name</a><br />
<a href="#bulk">Bulk Operations</a><br />
<a href="#transactions">Transactions</a><br />
<a href="#blob">BLOB Data Type</a><br />
<a href="#rowid">RowID Data Type</a><br />
<a href="#nested">Nested Statements</a><br />
<a href="#procedures">Stored Procedures</a><br />
</div>
<a href="#native">Accessing the Native Database API</a><br />
<a href="#extensions">Backend-specific Extensions</a><br />
<div class="navigation-indented">
<a href="#oracle_soci_error">oracle_soci_error</a><br />
</div>
</div>
<h3 id="prerequisites">Prerequisites</h3>
<h4 id="versions">Supported Versions</h4>
<p>The SOCI Oracle backend is currently supported for use with Oracle 10 or later.<br />
Older versions of Oracle may work as well, but they have not been tested by the SOCI team.</p>
<h4 id="tested">Tested Platforms</h4>
<table border="1" cellpadding="5" cellspacing="0">
<tbody>
<tr><th>Oracle version</th><th>Operating System</th><th>Compiler</th></tr>
<tr><td>10.2.0 (XE)</td><td>RedHat 5</td><td>g++ 4.3</td></tr>
</tbody>
</table>
<h4 id="required">Required Client Libraries</h4>
<p>The SOCI Oracle backend requires Oracle's <code>libclntsh</code> client library.
Depending on the particular system, the <code>libnnz10</code> library might be needed as well.</p>
<p>Note that the SOCI library itself depends also on <code>libdl</code>, so the minimum set of libraries needed to compile a basic client program is:</p>
<pre class="example">
-lsoci_core -lsoci_oracle -ldl -lclntsh -lnnz10
</pre>
<h4 id="connecting">Connecting to the Database</h4>
<p>To establish a connection to an Oracle database, create a <code>session</code> object
using the oracle backend factory together with a connection string:</p>
<pre class="example">
session sql(oracle, "service=orcl user=scott password=tiger");
// or:
session sql("oracle", "service=orcl user=scott password=tiger");
// or:
session sql("oracle://service=orcl user=scott password=tiger");
</pre>
<p>The set of parameters used in the connection string for Oracle is:</p>
<ul>
<li><code>service</code></li>
<li><code>user</code></li>
<li><code>password</code></li>
<li><code>mode</code> (optional)</li>
</ul>
<p>The first 3 of these parameters have to be provided as part of the connection string.</p>
<p>The <code>mode</code> parameter allows to specify the connection mode and can be any of:</p>
<ul>
<li><code>default</code> (which is assumed if omitted)</li>
<li><code>sysdba</code></li>
<li><code>sysoper</code></li>
</ul>
<p>Once you have created a <code>session</code> object as shown above, you can use it to access the database, for example:</p>
<pre class="example">
int count;
sql &lt;&lt; "select count(*) from user_tables", into(count);
</pre>
<p>(See the <a href="../basics.html">SOCI basics</a> and <a href="../exchange.html">exchanging data</a> documentation for general information on using the <code>session</code> class.)</p>
<h3 id="support">SOCI Feature Support</h3>
<h4 id="dynamic">Dynamic Binding</h4>
<p>The Oracle backend supports the use of the SOCI <code>row</code> class, which facilitates retrieval of data which type is not known at compile time.</p>
<p>When calling <code>row::get&lt;T&gt;()</code>, the type you should pass as <code>T</code> depends upon the underlying database type.<br/> For the Oracle backend, this type mapping is:</p>
<table border="1" cellpadding="5" cellspacing="0">
<tbody>
<tr>
<th>Oracle Data Type</th>
<th>SOCI Data Type</th>
<th><code>row::get&lt;T&gt;</code> specializations</th>
</tr>
<tr>
<td>number <i>(where scale &gt; 0)</i></td>
<td><code>dt_double</code></td>
<td><code>double</code></td>
</tr>
<tr>
<td>number<br /><i>(where scale = 0 and precision &le; std::numeric_limits&lt;int&gt;::digits10)</i></td>
<td><code>dt_integer</code></td>
<td><code>int</code></td>
</tr>
<tr>
<td>number</td>
<td><code>dt_long_long</code></td>
<td><code>long long</code></td>
</tr>
<tr>
<td>char, varchar, varchar2</td>
<td><code>dt_string</code></td>
<td><code>std::string</code></td>
</tr>
<tr>
<td>date</td>
<td><code>dt_date</code></td>
<td><code>std::tm</code><code></code></td>
</tr>
</tbody>
</table>
<p>(See the <a href="../exchange.html#dynamic">dynamic resultset binding</a> documentation for general information on using the <code>row</code> class.)</p>
<h4 id="bindingbyname">Binding by Name</h4>
<p>In addition to <a href="../exchange.html#bind_position">binding by position</a>, the Oracle backend supports <a href="../exchange.html#bind_name">binding by name</a>, via an overload of the <code>use()</code> function:</p>
<pre class="example">
int id = 7;
sql &lt;&lt; "select name from person where id = :id", use(id, "id")
</pre>
<p>SOCI's use of ':' to indicate a value to be bound within a SQL string is consistant with the underlying Oracle client library syntax.</p>
<h4 id="bulk">Bulk Operations</h4>
<p>The Oracle backend has full support for SOCI's <a href="../statements.html#bulk">bulk operations</a> interface.</p>
<h4 id="transactions">Transactions</h4>
<p><a href="../statements.html#transactions">Transactions</a> are also fully supported by the Oracle backend,
although transactions with non-default isolation levels have to be managed by explicit SQL statements.</p>
<h4 id="blob">blob Data Type</h4>
<p>The Oracle backend supports working with data stored in columns of type Blob, via SOCI's <a href="../exchange.html#blob"><code>blob</code></a> class.</p>
<h4 id="rowid">rowid Data Type</h4>
<p>Oracle rowid's are accessible via SOCI's <a href="../reference.html#rowid"><code>rowid</code></a> class.</p>
<h4 id="nested">Nested Statements</h4>
<p>The Oracle backend supports selecting into objects of type <code>statement</code>, so that you may work with nested sql statements and PL/SQL cursors:</p>
<pre class="example">
statement stInner(sql);
statement stOuter = (sql.prepare &lt;&lt;
"select cursor(select name from person order by id)"
" from person where id = 1",
into(stInner));
stInner.exchange(into(name));
stOuter.execute();
stOuter.fetch();
while (stInner.fetch())
{
std::cout &lt;&lt; name &lt;&lt; '\n';
}
</pre>
<h4 id="procedures">Stored Procedures</h4>
<p>Oracle stored procedures can be executed by using SOCI's <a href="../statements.html#procedures"><code>procedure</code></a> class.</p>
<h3 id="native">Acessing the native database API</h3>
<p>SOCI provides access to underlying datbabase APIs via several <code>get_backend()</code> functions, as described in the <a href="../beyond.html">Beyond SOCI</a> documentation.</p>
<p>The Oracle backend provides the following concrete classes for navite API access:</p>
<table border="1" cellpadding="5" cellspacing="0">
<tbody>
<tr>
<th>Accessor Function</th>
<th>Concrete Class</th>
</tr>
<tr>
<td><code>session_backend * session::get_backend()</code></td>
<td><code>oracle_session_backend</code></td>
</tr>
<tr>
<td><code>statement_backend * statement::get_backend()</code></td>
<td><code>oracle_statement_backend</code></td>
</tr>
<tr>
<td><code>blob_backend * blob::get_backend()</code></td>
<td><code>oracle_blob_backend</code></td>
</tr>
<tr>
<td><code>rowid_backend * rowid::get_backend()</code></td>
<td><code>oracle_rowid_backend</code></td>
</tr>
</tbody>
</table>
<h3 id="extensions">Backend-specific extensions</h3>
<h4 id="oracle_soci_error">eracle=soci_error</h4>
<p>The Oracle backend can throw instances of class <code>oracle_soci_error</code>,
which is publicly derived from <code>soci_error</code> and has an
additional public <code>err_num_</code> member containing the Oracle error code:</p>
<pre class="example">
int main()
{
try
{
// regular code
}
catch (oracle_soci_error const &amp; e)
{
cerr &lt;&lt; "Oracle error: " &lt;&lt; e.err_num_
&lt;&lt; " " &lt;&lt; e.what() &lt;&lt; endl;
}
catch (exception const &amp;e)
{
cerr &lt;&lt; "Some other error: " &lt;&lt; e.what() &lt;&lt; endl;
}
}
</pre>
<p class="copyright">Copyright &copy; 2004-2008 Maciej Sobczak, Stephen Hutton</p>
</body>
</html>

View File

@@ -1,230 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en'>
<head>
<meta content="text/html; charset=ISO-8859-1" http-equiv="content-type" />
<link rel="stylesheet" type="text/css" href="../style.css" />
<title>SOCI - PostgreSQL Backend Reference</title>
</head>
<body>
<p class="banner">SOCI - The C++ Database Access Library</p>
<h2>PostgreSQL Backend Reference</h2>
<div class="navigation">
<a href="#prerequisites">Prerequisites</a><br />
<div class="navigation-indented">
<a href="#versions">Supported Versions</a><br />
<a href="#tested">Tested Platforms</a><br />
<a href="#required">Required Client Libraries</a><br />
</div>
<a href="#connecting">Connecting to the Database</a><br />
<a href="#support">SOCI Feature Support</a><br />
<div class="navigation-indented">
<a href="#dynamic">Dynamic Binding</a><br />
<a href="#bindingbyname">Binding by Name</a><br />
<a href="#bulk">Bulk Operations</a><br />
<a href="#transactions">Transactions</a><br />
<a href="#blob">BLOB Data Type</a><br />
<a href="#rowid">RowID Data Type</a><br />
<a href="#nested">Nested Statements</a><br />
<a href="#procedures">Stored Procedures</a><br />
</div>
<a href="#native">Accessing the Native Database API</a><br />
<a href="#extensions">Backend-specific Extensions</a><br />
<a href="#options">Configuration options</a><br />
</div>
<h3 id="prerequisites">Prerequisites</h3>
<h4 id="versions">Supported Versions</h4>
<p>The SOCI PostgreSQL backend is supported for use with PostgreSQL >= 7.3, although versions older than 8.0 will suffer from limited feature support. See below for details.</p>
<h4 id="tested">Tested Platforms</h4>
<table border="1" cellpadding="5" cellspacing="0">
<tbody>
<tr><th>PostgreSQL version</th><th>Operating System</th><th>Compiler</th></tr>
<tr><td>9.0</td><td>Mac OS X 10.6.6</td><td>g++ 4.2</td></tr>
<tr><td>8.4</td><td>FreeBSD 8.2</td><td>g++ 4.1</td></tr>
<tr><td>8.4</td><td>Debian 6</td><td>g++ 4.3</td></tr>
<tr><td>8.4</td><td>RedHat 5</td><td>g++ 4.3</td></tr>
</tbody>
</table>
<h4 id="required">Required Client Libraries</h4>
<p>The SOCI PostgreSQL backend requires PostgreSQL's <code>libpq</code> client library.</p>
<p>Note that the SOCI library itself depends also on <code>libdl</code>, so the minimum set of libraries needed to compile a basic client program is:</p>
<pre class="example">
-lsoci_core -lsoci_postgresql -ldl -lpq
</pre>
<h4 id="connecting">Connecting to the Database</h4>
<p>To establish a connection to the PostgreSQL database, create a <code>session</code> object
using the <code>postgresql</code> backend factory together with a connection string:</p>
<pre class="example">
session sql(postgresql, "dbname=mydatabase");
// or:
session sql("postgresql", "dbname=mydatabase");
// or:
session sql("postgresql://dbname=mydatabase");
</pre>
<p>The set of parameters used in the connection string for PostgreSQL is the same as accepted by the <code><a href="http://www.postgresql.org/docs/8.3/interactive/libpq.html#LIBPQ-CONNECT">PQconnectdb</a></code> function from the <code>libpq</code> library.</p>
<p>Once you have created a <code>session</code> object as shown above, you can use it to access the database, for example:</p>
<pre class="example">
int count;
sql &lt;&lt; "select count(*) from invoices", into(count);
</pre>
<p>(See the <a href="../basics.html">SOCI basics</a> and <a href="../exchange.html">exchanging data</a> documentation for general information on using the <code>session</code> class.)</p>
<h3 id="support">SOCI Feature Support</h3>
<h4 id="dynamic">Dynamic Binding</h4>
<p>The PostgreSQL backend supports the use of the SOCI <code>row</code> class, which facilitates retrieval of data whose type is not known at compile time.</p>
<p>When calling <code>row::get&lt;T&gt;()</code>, the type you should pass as <code>T</code> depends upon the underlying database type.<br/> For the PostgreSQL backend, this type mapping is:</p>
<table border="1" cellpadding="5" cellspacing="0">
<tbody>
<tr>
<th>PostgreSQL Data Type</th>
<th>SOCI Data Type</th>
<th><code>row::get&lt;T&gt;</code> specializations</th>
</tr>
<tr>
<td>numeric, real, double</td>
<td><code>dt_double</code></td>
<td><code>double</code></td>
</tr>
<tr>
<td>boolean, smallint, integer</td>
<td><code>dt_integer</code></td>
<td><code>int</code></td>
</tr>
<tr>
<td>int8</td>
<td><code>dt_long_long</code></td>
<td><code>long long</code></td>
</tr>
<tr>
<td>oid</td>
<td><code>dt_integer</code></td>
<td><code>unsigned long</code></td>
</tr>
<tr>
<td>char, varchar, text, cstring, bpchar</td>
<td><code>dt_string</code></td>
<td><code>std::string</code></td>
</tr>
<tr>
<td>abstime, reltime, date, time, timestamp, timestamptz, timetz</td>
<td><code>dt_date</code></td>
<td><code>std::tm</code><code></code></td>
</tr>
</tbody>
</table>
<p>(See the <a href="../exchange.html#dynamic">dynamic resultset binding</a> documentation for general information on using the <code>row</code> class.)</p>
<h4 id="bindingbyname">Binding by Name</h4>
<p>In addition to <a href="../exchange.html#bind_position">binding by position</a>, the PostgreSQL backend supports <a href="../exchange.html#bind_name">binding by name</a>, via an overload of the <code>use()</code> function:</p>
<pre class="example">
int id = 7;
sql &lt;&lt; "select name from person where id = :id", use(id, "id")
</pre>
<p>Apart from the portable "colon-name" syntax above, which is achieved by rewriting the query string, the backend also supports the PostgreSQL native numbered syntax:</p>
<pre class="example">
int i = 7;
int j = 8;
sql &lt;&lt; "insert into t(x, y) values($1, $2)", use(i), use(j);
</pre>
<p>The use of native syntax is not recommended, but can be nevertheless imposed by switching off the query rewriting. This can be achieved by defining the macro <code>SOCI_POSTGRESQL_NOBINDBYNAME</code> and it is actually necessary for PostgreSQL 7.3, in which case binding of use elements is not supported at all. See the <a href="#options">Configuration options</a> section for details.</p>
<h4 id="bulk">Bulk Operations</h4>
<p>The PostgreSQL backend has full support for SOCI's <a href="../statements.html#bulk">bulk operations</a> interface.</p>
<h4 id="transactions">Transactions</h4>
<p><a href="../statements.html#transactions">Transactions</a> are also fully supported by the PostgreSQL backend.</p>
<h4 id="blob">blob Data Type</h4>
<p>The PostgreSQL backend supports working with data stored in columns of type Blob, via SOCI's <a href="../exchange.html#blob"><code>blob</code></a> class with the exception that trimming is not supported.</p>
<h4 id="rowid">rowid Data Type</h4>
<p>The concept of row identifier (OID in PostgreSQL) is supported via SOCI's <a href="../reference.html#rowid">rowid</a> class.</p>
<h4 id="nested">Nested Statements</h4>
<p>Nested statements are not supported by PostgreSQL backend.</p>
<h4 id="procedures">Stored Procedures</h4>
<p>PostgreSQL stored procedures can be executed by using SOCI's <a href="../statements.html#procedures">procedure</a> class.</p>
<h3 id="native">Acessing the native database API</h3>
<p>SOCI provides access to underlying datbabase APIs via several <code>get_backend()</code> functions, as described in the <a href="../beyond.html">beyond SOCI</a> documentation.</p>
<p>The PostgreSQL backend provides the following concrete classes for navite API access:</p>
<table border="1" cellpadding="5" cellspacing="0">
<tbody>
<tr>
<th>Accessor Function</th>
<th>Concrete Class</th>
</tr>
<tr>
<td><code>session_backend * session::get_backend()</code></td>
<td><code>postgresql_session_backend</code></td>
</tr>
<tr>
<td><code>statement_backend * statement::get_backend()</code></td>
<td><code>postgresql_statement_backend</code></td>
</tr>
<tr>
<td><code>blob_backend * blob::get_backend()</code></td>
<td><code>postgresql_blob_backend</code></td>
</tr>
<tr>
<td><code>rowid_backend * rowid::get_backend()</code></td>
<td><code>postgresql_rowid_backend</code></td>
</tr>
</tbody>
</table>
<h3 id="extensions">Backend-specific extensions</h3>
<p>None.</p>
<h3 id="options">Configuration options</h3>
<p>To support older PostgreSQL versions, the following configuration macros are recognized:</p>
<ul>
<li><code>SOCI_POSTGRESQL_NOBINDBYNAME</code> - switches off the query rewriting.</li>
<li><code>SOCI_POSTGRESQL_NOPARAMS</code> - disables support for parameterized queries (binding of use elements), automatically imposes also the <code>SOCI_POSTGRESQL_NOBINDBYNAME</code> macro. It is necessary for PostgreSQL 7.3.</li>
<li><code>SOCI_POSTGRESQL_NOPREPARE</code> - disables support for separate query preparation, which in this backend is significant only in terms of optimization. It is necessary for PostgreSQL 7.3 and 7.4.</li>
</ul>
<p class="copyright">Copyright &copy; 2004-2008 Maciej Sobczak, Stephen Hutton</p>
</body>
</html>

View File

@@ -1,207 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<meta content="text/html; charset=ISO-8859-1" http-equiv="content-type" />
<link rel="stylesheet" type="text/css" href="../style.css" />
<title>SOCI - SQLite3 Backend Reference</title>
</head>
<body>
<p class="banner">SOCI - The C++ Database Access Library</p>
<h2>SQLite3 Backend Reference</h2>
<div class="navigation">
<a href="#prerequisites">Prerequisites</a><br />
<div class="navigation-indented">
<a href="#versions">Supported Versions</a><br />
<a href="#tested">Tested Platforms</a><br />
<a href="#required">Required Client Libraries</a><br />
</div>
<a href="#connecting">Connecting to the Database</a><br />
<a href="#support">SOCI Feature Support</a><br />
<div class="navigation-indented">
<a href="#dynamic">Dynamic Binding</a><br />
<a href="#bindingbyname">Binding by Name</a><br />
<a href="#bulk">Bulk Operations</a><br />
<a href="#transactions">Transactions</a><br />
<a href="#blob">BLOB Data Type</a><br />
<a href="#rowid">RowID Data Type</a><br />
<a href="#nested">Nested Statements</a><br />
<a href="#procedures">Stored Procedures</a><br />
</div>
<a href="#native">Accessing the Native Database API</a><br />
<a href="#extensions">Backend-specific Extensions</a><br />
<a href="#options">Configuration options</a><br />
</div>
<h3 id="prerequisites">Prerequisites</h3>
<h4 id="versions">Supported Versions</h4>
<p>The SOCI SQLite3 backend is supported for use with SQLite3 >= 3.1</p>
<h4 id="tested">Tested Platforms</h4>
<table border="1" cellpadding="5" cellspacing="0">
<tbody>
<tr><th>SQLite3 version</th><th>Operating System</th><th>Compiler</th></tr>
<tr><td>3.5.2</td><td>Mac OS X 10.5</td><td>g++ 4.0.1</td></tr>
<tr><td>3.1.3</td><td>Mac OS X 10.4</td><td>g++ 4.0.1</td></tr>
<tr><td>3.2.1</td><td>Linux i686 2.6.10-gentoo-r6</td><td>g++ 3.4.5</td></tr>
<tr><td>3.3.4</td><td>Ubuntu 5.1</td><td>g++ 4.0.2</td></tr>
<tr><td>3.3.4</td><td>Windows XP</td><td>(cygwin) g++ 3.3.4</td></tr>
<tr><td>3.3.4</td><td>Windows XP</td><td>Visual C++ 2005 Express Edition</td></tr>
<tr><td>3.3.8</td><td>Windows XP</td><td>Visual C++ 2005 Professional</td></tr>
<tr><td>3.4.0</td><td>Windows XP</td><td>(cygwin) g++ 3.4.4</td></tr>
<tr><td>3.4.0</td><td>Windows XP</td><td>Visual C++ 2005 Express Edition</td></tr>
</tbody>
</table>
<h4 id="required">Required Client Libraries</h4>
<p>The SOCI SQLite3 backend requires SQLite3's <code>libsqlite3</code> client library.</p>
<h4 id="connecting">Connecting to the Database</h4>
<p>To establish a connection to the SQLite3 database, create a Session object
using the <code>SQLite3</code> backend factory together with the database file name:</p>
<pre class="example">
session sql(sqlite3, "database_filename");
</pre>
<p>The only option for the connection string is the name of the file to use as a database.</p>
<p>Once you have created a <code>session</code> object as shown above, you can use it to access the database, for example:</p>
<pre class="example">
int count;
sql &lt;&lt; "select count(*) from invoices", into(count);
</pre>
<p>(See the <a href="../basics.html">SOCI basics</a> and <a href="../exchange.html">exchanging data</a> documentation for general information on using the <code>session</code> class.)</p>
<h3 id="support">SOCI Feature Support</h3>
<h4 id="dynamic">Dynamic Binding</h4>
<p>The SQLite3 backend supports the use of the SOCI <code>row</code> class, which facilitates retrieval of data whose type is not known at compile time.</p>
<p>When calling <code>row::get&lt;T&gt;()</code>, the type you should pass as T depends upon the underlying database type.</p>
<p>For the SQLite3 backend, this type mapping is complicated by the fact the SQLite3 does not enforce types <a href="#INTEGER_PRIMARY_KEY">*</a>, and makes no attempt to validate the type names used in table creation or alteration statements. SQLite3 will return the type as a string, SOCI will recognize the following strings and match them the corresponding SOCI types:</p>
<table border="1" cellpadding="5" cellspacing="0">
<tbody>
<tr>
<th>SQLite3 Data Type</th>
<th>SOCI Data Type</th>
<th><code>row::get&lt;T&gt;</code> specializations</th>
</tr>
<tr>
<td>*float*</td>
<td><code>dt_ouble</code></td>
<td><code>double</code></td>
</tr>
<tr>
<td>*int*</td>
<td><code>dt_integer</code></td>
<td><code>int</code></td>
</tr>
<tr>
<td>*char*</td>
<td><code>dt_string</code></td>
<td><code>std::string</code></td>
</tr>
<tr>
<td>*date*, *time*</td>
<td><code>dt_date</code></td>
<td><code>std::tm</code><code></code></td>
</tr>
</tbody>
</table>
<p id="INTEGER_PRIMARY_KEY">* There is one case where SQLite3 enforces type. If a column is declared as "integer primary key", then SQLite3 uses that as an alias to the internal ROWID column that exists for every table. Only integers are allowed in this column.</p>
<p>(See the <a href="../exchange.html#dynamic">dynamic resultset binding</a> documentation for general information on using the <code>row</code> class.)</p>
<h4 id="bindingbyname">Binding by Name</h4>
<p>In addition to <a href="../exchange.html#bind_position">binding by position</a>, the SQLite3 backend supports <a href="../exchange.html#bind_name">binding by name</a>, via an overload of the <code>use()</code> function:</p>
<pre class="example">
int id = 7;
sql &lt;&lt; "select name from person where id = :id", use(id, "id")
</pre>
<p>The backend also supports the SQLite3 native numbered syntax, "one or more literals can be replace by a parameter "?" or ":AAA" or "@AAA" or "$VVV" where AAA is an alphanumeric identifier and VVV is a variable name according to the syntax rules of the TCL programming language." <a href="http://www.sqlite.org/capi3ref.html#sqlite3_bind_int">[1]</a>:</p>
<pre class="example">
int i = 7;
int j = 8;
sql &lt;&lt; "insert into t(x, y) values(?, ?)", use(i), use(j);
</pre>
<h4 id="bulk">Bulk Operations</h4>
<p>The SQLite3 backend has full support for SOCI's <a href="../statements.html#bulk">bulk operations</a> interface. However, this support is emulated and is not native.</p>
<h4 id="transactions">Transactions</h4>
<p><a href="../statements.html#transactions">Transactions</a> are also fully supported by the SQLite3 backend.</p>
<h4 id="blob">BLOB Data Type</h4>
<p>The SQLite3 backend supports working with data stored in columns of type Blob, via SOCI's blob class. Because of SQLite3 general typelessness the column does not have to be declared any particular type.</p>
<h4 id="rowid">RowID Data Type</h4>
<p>In SQLite3 RowID is an integer. "Each entry in an SQLite table has a unique integer key called the "rowid". The rowid is always available as an undeclared column named ROWID, OID, or _ROWID_. If the table has a column of type INTEGER PRIMARY KEY then that column is another an alias for the rowid."<a href="http://www.sqlite.org/capi3ref.html#sqlite3_last_insert_rowid">[2]</a></p>
<h4 id="nested">Nested Statements</h4>
<p>Nested statements are not supported by SQLite3 backend.</p>
<h4 id="procedures">Stored Procedures</h4>
<p>Stored procedures are not supported by SQLite3 backend</p>
<h3 id="native">Acessing the native database API</h3>
<p>SOCI provides access to underlying datbabase APIs via several
<code>get_backend()</code> functions, as described in the
<a href="../beyond.html">beyond SOCI</a> documentation.</p>
<p>The SQLite3 backend provides the following concrete classes for navite API access:</p>
<table border="1" cellpadding="5" cellspacing="0">
<tbody>
<tr>
<th>Accessor Function</th>
<th>Concrete Class</th>
</tr>
<tr>
<td><code>session_backend* session::get_backend()</code></td>
<td><code>sqlie3_session_backend</code></td>
</tr>
<tr>
<td><code>statement_backend* statement::get_backend()</code></td>
<td><code>sqlite3_statement_backend</code></td>
</tr>
<tr>
<td><code>rowid_backend* rowid::get_backend()</code></td>
<td><code>sqlite3_rowid_backend</code></td>
</tr>
</tbody>
</table>
<h3 id="extensions">Backend-specific extensions</h3>
<p>None.</p>
<h3 id="options">Configuration options</h3>
<p>None</p>
<p class="copyright">Copyright &copy; 2004-2006 Maciej Sobczak, Stephen Hutton, David Courtney</p>
</body>
</html>

View File

@@ -1,174 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en'>
<head>
<meta content="text/html; charset=ISO-8859-1" http-equiv="content-type" />
<link rel="stylesheet" type="text/css" href="style.css" />
<title>SOCI - beyond standard SQL</title>
</head>
<body>
<p class="banner">SOCI - The C++ Database Access Library</p>
<h2>Beyond standard SQL</h2>
<p>Sometimes the standard SQL is not enough and database-specific syntax needs
to be used. When possible and practical, SOCI provides wrappers hiding the
differences between the backends and this section describes these wrappers.
And if this is still not enough, you can use the backend-specific methods
directly as described below.</p>
<h3>Getting the number of rows affected by an operation</h3>
<p>It can be useful to know how many rows were affected by the last SQL
statement, most often when using <tt>INSERT</tt>, <tt>UPDATE</tt> or
<tt>DELETE</tt>. SOCI provides <code>statement::get_affected_rows()</code>
method allowing to do this:</p>
<pre class="example">
statement st = (sql.prepare &lt;&lt; "update some_table ...");
st.execute(true);
if ( !st.get_affected_rows() )
{
... investigate why no rows were modified ...
}
</pre>
<div class="note">
<p><span class="note">Portability note:</span></p>
This method is currently not supported by the Oracle backend. It is however
supported when using Oracle database via ODBC backend.</p>
</div>
<h3 id="sequences">Working with sequences</h3>
<p>It is common to have auto-incrementing database fields or fields whose
value come from a sequence. In the latter case you need to retrieve the value
of the field for a new row before inserting it into the database. In the
former case, this is unnecessary but you may still want to know the value
generated by the database, e.g. to use it as a foreign key in another table.
So it would be useful to have a way to obtain the value of such a field.
But, of course, to make life of database programmers more interesting,
different products usually support either autoincrement fields or sequences
but not both -- and they use different syntaxes for them, too. SOCI tries to
help to deal with this unfortunate situation by providing two functions:
<code>session::get_next_sequence_value()</code> and
<code>session::get_last_insert_id</code>.</p>
<p>If you know which kind of database you use, you may use only one of them:
when working with sequences, the first one allows to generate the next value
in a sequence and when working with autoincrement fields, the second one
retrieves the last value generated for such a field for the given table.</p>
<p>However if you use multiple SOCI backends or even just a single ODBC
backend but support connecting to databases of different types, you actually
must use both of them in the following way to insert a row:</p>
<pre class="example">
long id;
statement st;
if ( sql.get_next_sequence_value("table_sequence", id) )
{
st &lt;&lt; "insert into table(id, f1, f2) values(:id, :f1, :f2)",
use(id), use(f1), use(f2);
}
else
{
// We're not using sequences, so don't specify the value,
// it will be automatically generated by the database on insert.
st &lt;&lt; "insert into table(f1, f2) value(:f1, :f2)",
use(f1), use(f2);
// If the ID used for the above row is needed later, get it:
if ( !sql.get_last_insert_id("table", id) )
... unexpected error, handle appropriately ...
}
</pre>
<div class="note">
<p><span class="note">Portability note:</span></p>
These methods are currently only implemented in Firebird and ODBC backends.</p>
</div>
<h3>Beyond SOCI API</h3>
<p>As the original name of the library (Simple Oracle Call Interface)
clearly stated, SOCI is intended to be a <i>simple</i> library, targeting the
majority of needs in regular C++ application. We do not claim that
<i>everything</i> can be done with SOCI and it was never the intent of the
library. What is important, though, is that the simplicity of the
library does <i>not</i> prevent the
client applications from reaching into the low-level specifics of each
database backend in order to achieve special configuration or
performance goals.</p>
<p>Most of the SOCI classes have the <code>getBackEnd</code> method,
which
returns the pointer to the actual backend object that implements the
given functionality. The knowledge of the actual backend allows the
client application to get access to all low-level details that are
involved.</p>
<pre class="example">
blob b(sql);
oracle_session_back_end * sessionBackEnd = static_cast&lt;oracle_session_back_end *&gt;(sql.get_back_end());
oracle_blob_back_end * blobBackEnd = static_cast&lt;oracle_blob_back_end *&gt;(b.get_back_end());
OCILobDisableBuffering(sessionBackEnd-&gt;svchp_, sessionBackEnd-&gt;errhp_, blobBackEnd-&gt;lobp_);
</pre>
<p>The above code creates the <code>blob</code> object and uses two calls
to the <code>get_back_end</code> function (on both the <code>session</code>
and the <code>blob</code> objects) to get access to the actual backend
objects. Assuming that it is the <code>"oracle"</code> backend which
is in use, the downcasts allow to access all relevant low-level handles
and use them in the call
to the <code>OCILobDisableBuffering</code> function. This way, the
BLOB handle was configured in a way that the SOCI library alone would
not allow.</p>
<pre class="example">
rowid rid(sql); // sql is a session object
sql &lt;&lt; "select oid from mytable where id = 7", into(rid);
postgresql_rowid_back_end * rbe = static_cast&lt;postgresql_rowid_back_end *&gt;(rid.get_back_end());
unsigned long oid = rbe-&gt;value_;
</pre>
<p>The above example retrieves the <code>rowid</code> ("something" that
identifies the
row in the table) from the table and uses the <code>get_back_end</code>
function to
extract the actual object that implements this functionality. Assuming
that it is the <code>"postgresql"</code> backend which is in use, the
downcast is
performed to use the <code>postgresql_rowid_back_end</code> interface to
get the actual
OID value that is a physical, low-level implementation of row
identifier on PostgreSQL databases.</p>
<p>In order for any of the above to compile, you have to explicitly <code>#include</code>
the appropriate backend's header file.</p>
<p>Please see the header file related to the given backend to learn what
low-level handles and descriptors are available.</p>
<table class="foot-links" border="0" cellpadding="2" cellspacing="2">
<tr>
<td class="foot-link-left">
<a href="statements.html">Previous (Interfaces)</a>
</td>
<td class="foot-link-right">
<a href="reference.html">Next (Client reference)</a>
</td>
</tr>
</table>
<p class="copyright">Copyright &copy; 2012 Vadim Zeitlin</p>
<p class="copyright">Copyright &copy; 2004-2006 Maciej Sobczak, Stephen Hutton</p>
</body>
</html>

View File

@@ -1,106 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en'>
<head>
<meta content="text/html; charset=ISO-8859-1" http-equiv="content-type" />
<link rel="stylesheet" type="text/css" href="style.css" />
<title>SOCI - integration with Boost</title>
</head>
<body>
<p class="banner">SOCI - The C++ Database Access Library</p>
<h2>Integration with Boost</h2>
<p>The SOCI user code can be easily integrated with the <a href="http://www.boost.org/" target="_blank">Boost library</a> thanks to the very flexible type conversion facility. There are three important Boost types that are supported out of the box.</p>
<h4>boost::optional&lt;T&gt;</h4>
<p><code>boost::optional&lt;T&gt;</code> provides an alternative way to support the null data condition and as such relieves the user from necessity to handle separate indicator values.</p>
<p>The <code>boost::optional&lt;T&gt;</code> objects can be used everywhere where the regular user provided
values are expected.</p>
<p>Example:</p>
<pre class="example">
boost::optional&lt;string&gt; name;
sql &lt;&lt; "select name from person where id = 7", into(name);
if (name.is_initialized())
{
// OK, the name was retrieved and is not-null
cout &lt;&lt; "The name is " &lt;&lt; name.get();
}
else
{
// the name is null
}
</pre>
<p>The <code>boost::optional&lt;T&gt;</code> objects are fully supported for both <code>into</code> and <code>use</code> elements, in both single and vector forms. They can be also used for user-defined data types.</p>
<h4>boost::tuple&lt;T1, ...&gt;</h4>
<p><code>boost::tuple&lt;T1, ...&gt;</code> allows to work with whole rows of information and in some cases can be more convenient to use than the more dynamically-oriented <code>row</code> type.</p>
<p>Example:</p>
<pre class="example">
boost::tuple&lt;string, string, int&gt; person;
sql &lt;&lt; "select name, phone, salary from persons where ...",
into(person);
</pre>
<p>Tuples are supported for both <code>into</code> and <code>use</code> elements. They can be used with <code>rowset</code> as well.</p>
<p>Tuples can be also composed with <code>boost::optional&lt;T&gt;</code>:</p>
<pre class="example">
boost::tuple&lt;string, boost::optional&lt;string&gt;, int&gt; person;
sql &lt;&lt; "select name, phone, salary from persons where ...",
into(person);
if (person.get&lt;1&gt;().is_initialized())
{
// the given person has a phone number
}
else
{
// this person does not have a phone number
}
</pre>
<h4>boost::fusion::vector&lt;T1, ...&gt;</h4>
<p>The <code>boost::fusion::vector</code> types are supported in the same way as tuples.</p>
<h4>boost::gregorian::date</h4>
<p>The <code>boost::gregorian::date</code> is provided as a conversion for base type <code>std::tm</code> and can be used as a replacement for it.</p>
<div class="note">
<p><span class="note">Optional integration:</span></p>
<p>The integration with Boost types is optional and <i>not</i> enabled by default, which means that SOCI can be compiled and used without any dependency on Boost.</p>
<p>In order to enable the support for any of the above types, the user needs to either include one of these headers:</p>
<pre class="example">
#include &lt;boost-optional.h&gt;
#include &lt;boost-tuple.h&gt;
#include &lt;boost-fusion.h&gt;
#include &lt;boost-gregorian-date.h&gt;
</pre>
<p>or to define the <code>SOCI_USE_BOOST</code> macro before including the <code>soci.h</code> main header file. Note that in this case the support for <code>boost::fusion::vector</code> is enabled only if the detected Boost version is at least 1.35.</p>
</div>
<table class="foot-links" border="0" cellpadding="2" cellspacing="2">
<tr>
<td class="foot-link-left">
<a href="statements.html">Previous (Multithreading)</a>
</td>
<td class="foot-link-right">
<a href="interfaces.html">Next (Interfaces)</a>
</td>
</tr>
</table>
<p class="copyright">Copyright &copy; 2004-2008 Maciej Sobczak, Stephen Hutton</p>
</body>
</html>

View File

@@ -1,142 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en'>
<head>
<meta content="text/html; charset=ISO-8859-1" http-equiv="content-type" />
<link rel="stylesheet" type="text/css" href="style.css" />
<title>SOCI - connections</title>
</head>
<body>
<p class="banner">SOCI - The C++ Database Access Library</p>
<h2>Connections and simple queries</h2>
<h3>Connecting to the database</h3>
<p>The <code>session</code> class encapsulates the database connection
and other backend-related details, which are common to all the
statements
that will be later executed. It has a couple of overloaded constructors.</p>
<p>The most basic one expects two parameters:
the requested backend factory object and the generic connection string,
which meaning is backend-dependent.</p>
<p>Example:</p>
<pre class="example">
session sql(oracle, "service=orcl user=scott password=tiger");
</pre>
<p>Another example might be:</p>
<pre class="example">
session sql(postgresql, "dbname=mydb");
</pre>
<p>Above, the <code>sql</code> object is a local (automatic) object
that encapsulates the connection.</p>
<p>This <code>session</code> constructor either connects successfully, or
throws an exception.</p>
<p>Another constructor allows to name backends at run-time and supports
the dynamically loadable backends, which have to be compiled as shared libraries. The usage is similar to the above, but instead of providing the factory object, the backend name is expected:</p>
<pre class="example">
session sql("postgresql", "dbname=mydb");
</pre>
<p>For convenience, the URL-like form that combines both the backend name with connection parameters is supported as well:</p>
<pre class="example">
session sql("postgresql://dbname=mydb");
</pre>
<p>The last two constructors described above try to locate the shared library with the name <code>libsoci_ABC.so</code> (or <code>libsoci_ABC.dll</code> on Windows), where ABC is the backend name. In the above examples, the expected library name will be <code>libsoci_postgresql.so</code> for Unix-like systems.</p>
<p>The most general form of the constructor takes a single object of <code>connection_parameters</code> type which contains a pointer to the backend to use, the connection string and also any connection options. Using this constructor is the only way to pass any non-default options to the backend. For example, to suppress any interactive prompts when using ODBC backend you could do:</p>
<pre class="example">
connection_parameters parameters("odbc", "DSN=mydb");
parameters.set_option(odbc_option_driver_complete, "0" /* SQL_DRIVER_NOPROMPT */);
session sql(parameters);
</pre>
Notice that you need to <code>#include &lt;soci-odbc.h&gt;</code> to obtain the option name declaration. The existing options are described in the backend-specific part of the documentation.
<div class="note">
<p><span class="note">Environment configuration:</span></p>
<p>The <code>SOCI_BACKENDS_PATH</code> environment variable defines the set of paths where the shared libraries will be searched for. There can be many paths, separated by colons, and they are used from left to right until the library with the appropriate name is found. If this variable is not set or is empty, the current directory is used as a default path for dynamically loaded backends.</p>
</div>
<p>The run-time selection of backends is also supported with libraries
linked statically. Each backend provides a separate function of the
form <code>register_factory_<i>name</i></code>, where
<code><i>name</i></code> is a backend name. Thus:</p>
<pre class="example">
extern "C" void register_factory_postgresql();
// ...
register_factory_postgresql();
session sql("postgresql://dbname=mydb");
</pre>
<p>The above example registers the backend for PostgreSQL and later
creates the session object for that backend. This form is provided for
those projects that prefer static linking but still wish to benefit
from run-time backend selection.</p>
<p>An alternative way to set up the session is to create it in the disconnected state and connect later:</p>
<pre class="example">
session sql;
// some time later:
sql.open(postgresql, "dbname=mydb");
// or:
sql.open("postgresql://dbname=mydb");
// or also:
connection_parameters parameters("postgresql", "dbname=mydb");
sql.open(parameters);
</pre>
<p>The rules for backend naming are the same as with the constructors described above.</p>
<p>The session can be also explicitly <code>close</code>d and <code>reconnect</code>ed, which can help with basic session error recovery. The <code>reconnect</code> function has no parameters and attempts to use the same values as those provided with earlier constructor or <code>open</code> calls.</p>
<p>See also the page devoted to <a href="multithreading.html">multithreading</a> for a detailed description of connection pools.</p>
<p>It is possible to have many active <code>session</code>s at the same
time, even using different backends.</p>
<div class="note">
<p><span class="note">Portability note:</span></p>
<p>The following backend factories are currently (as of 3.1.0 release) available:</p>
<ul>
<li><code><a href="backends/mysql.html">mysql</a></code> (requires <code>#include "soci-mysql.h"</code>)</li>
<li><code><a href="backends/oracle.html">oracle</a></code> (requires <code>#include "soci-oracle.h"</code>)</li>
<li><code><a href="backends/postgresql.html">postgresql</a></code> (requires <code>#include "soci-postgresql.h"</code>)</li>
</ul>
<p>The following backends are also available, with various levels of completeness:</p>
<ul>
<li><code><a href="backends/sqlite3.html">sqlite3</a></code> (requires <code>#include "soci-sqlite3.h"</code>)</li>
<li><code><a href="backends/odbc.html">odbc</a></code> (requires <code>#include "soci-odbc.h"</code>)</li>
<li><code><a href="backends/firebird.html">firebird</a></code> (requires <code>#include "soci-firebird.h"</code>)</li>
</ul>
</div>
<table class="foot-links" border="0" cellpadding="2" cellspacing="2">
<tr>
<td class="foot-link-left">
<a href="errors.html">Previous (Errors)</a>
</td>
<td class="foot-link-right">
<a href="queries.html">Next (Queries)</a>
</td>
</tr>
</table>
<p class="copyright">Copyright &copy; 2013 Mateusz Loskot</p>
<p class="copyright">Copyright &copy; 2004-2008 Maciej Sobczak, Stephen Hutton</p>
</body>
</html>

View File

@@ -1,128 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en'>
<head>
<meta content="text/html; charset=ISO-8859-1" http-equiv="content-type" />
<link rel="stylesheet" type="text/css" href="style.css" />
<title>SOCI - errors</title>
</head>
<body>
<p class="banner">SOCI - The C++ Database Access Library</p>
<h2>Errors</h2>
<p>All DB-related errors manifest themselves as exceptions of type <code>soci_error</code>,
which is derived from <code>std::runtime_error</code>.<br />
This allows to
handle database errors within the standard exception framework:</p>
<pre class="example">
int main()
{
try
{
// regular code
}
catch (std::exception const &amp; e)
{
cerr &lt;&lt; "Bang! " &lt;&lt; e.what() &lt;&lt; endl;
}
}
</pre>
<div class="note">
<p><span class="note">Portability note:</span></p>
<p>The Oracle backend can also throw the instances of the <code>oracle_soci_error</code>,
which is publicly derived from <code>soci_error</code> and has an
additional public <code>err_num_</code>
member containing the Oracle error code:</p>
<pre class="example">
int main()
{
try
{
// regular code
}
catch (soci::oracle_soci_error const &amp; e)
{
cerr &lt;&lt; "Oracle error: " &lt;&lt; e.err_num_
&lt;&lt; " " &lt;&lt; e.what() &lt;&lt; endl;
}
catch (soci::exception const &amp; e)
{
cerr &lt;&lt; "Some other error: " &lt;&lt; e.what() &lt;&lt; endl;
}
}
</pre>
</div>
<div class="note">
<p><span class="note">Portability note:</span></p>
<p>The MySQL backend can throw instances of the <code>mysql_soci_error</code>,
which is publicly derived from <code>soci_error</code> and has an
additional public <code>err_num_</code>
member containing the MySQL error code (as returned by
<code>mysql_errno()</code>):</p>
<pre class="example">
int main()
{
try
{
// regular code
}
catch (soci::mysql_soci_error const &amp; e)
{
cerr &lt;&lt; "MySQL error: " &lt;&lt; e.err_num_
&lt;&lt; " " &lt;&lt; e.what() &lt;&lt; endl;
}
catch (soci::exception const &amp; e)
{
cerr &lt;&lt; "Some other error: " &lt;&lt; e.what() &lt;&lt; endl;
}
}
</pre>
</div>
<div class="note">
<p><span class="note">Portability note:</span></p>
<p>The PostgreSQL backend can also throw the instances of the <code>postgresql_soci_error</code>,
which is publicly derived from <code>soci_error</code> and has an
additional public <code>sqlstate()</code>
member function returning the five-character "SQLSTATE" error code:</p>
<pre class="example">
int main()
{
try
{
// regular code
}
catch (soci::postgresql_soci_error const &amp; e)
{
cerr &lt;&lt; "PostgreSQL error: " &lt;&lt; e.sqlstate()
&lt;&lt; " " &lt;&lt; e.what() &lt;&lt; endl;
}
catch (soci::exception const &amp; e)
{
cerr &lt;&lt; "Some other error: " &lt;&lt; e.what() &lt;&lt; endl;
}
}
</pre>
</div>
<table class="foot-links" border="0" cellpadding="2" cellspacing="2">
<tr>
<td class="foot-link-left">
<a href="installation.html">Previous (Installation)</a>
</td>
<td class="foot-link-right">
<a href="connections.html">Next (Connections and simple queries)</a>
</td>
</tr>
</table>
<p class="copyright">Copyright &copy; 2004-2013 Maciej Sobczak, Stephen Hutton, Mateusz Loskot</p>
</body>
</html>

View File

@@ -1,758 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en'>
<head>
<meta content="text/html; charset=ISO-8859-1" http-equiv="content-type" />
<link rel="stylesheet" type="text/css" href="style.css" />
<title>SOCI - exchanging data</title>
</head>
<body>
<p class="banner">SOCI - The C++ Database Access Library</p>
<h2>Exchanging data</h2>
<div class="navigation">
<a href="#bind_local">Binding local data</a><br />
<div class="navigation-indented">
<a href="#bind_output">Binding output data</a><br />
<a href="#bind_input">Binding input data</a><br />
<a href="#bind_position">Binding by position</a><br />
<a href="#bind_name">Binding by name</a><br />
</div>
<a href="exchange.html#data_states">Handling of nulls and other conditions</a><br />
<div class="navigation-indented">
<a href="#indicators">Indicators</a><br />
</div>
<a href="#types">Types</a><br />
<div class="navigation-indented">
<a href="#static">Static binding</a><br />
<a href="#static_bulk">Static binding for bulk operations</a><br />
<a href="#dynamic">Dynamic resultset binding</a><br />
<a href="#custom_types">Extending with user-provided datatypes</a><br />
<a href="#object_relational">Object-relational mapping</a><br />
</div>
<a href="#blob">Large objects (BLOBs)</a><br />
</div>
<h3 id="bind_local">Binding local data</h3>
<div class="note">
<p><span class="note">Note:</span>
The Oracle documentation uses two terms: <i>defining</i> (for
instructing the library where the <i>output</i> data should go) and <i>binding</i>
(for the <i>input</i> data and <i>input/output</i> PL/SQL
parameters). For the sake of simplicity, SOCI uses the term <i>binding</i>
for both of these.</p>
</div>
<h4 id="bind_output">Binding output data</h4>
<p>The <code>into</code> expression is used to add binding information to
the statement:</p>
<pre class="example">
int count;
sql &lt;&lt; "select count(*) from person", into(count);
string name;
sql &lt;&lt; "select name from person where id = 7", into(name);
</pre>
<p>In the above examples, some data is retrieved from the database and
transmitted <i>into</i> the given local variable.</p>
<p>There should be as many <code>into</code> elements as there are
expected columns in the result (see <a href="#dynamic">dynamic
resultset binding</a> for the exception to this rule).</p>
<h4 id="bind_input">Binding input data</h4>
<p>The <code>use</code> expression associates the SQL placeholder (written with colon) with the local data:</p>
<pre class="example">
int val = 7;
sql &lt;&lt; "insert into numbers(val) values(:val)", use(val);
</pre>
<p>In the above statement, the first "val" is a column name (assuming
that
there is appropriate table <code>numbers</code> with this column), the
second "val" (with colon) is a
placeholder and its name is ignored here, and the third "val" is a name
of local variable.</p>
<p>To better understand the meaning of each "val" above, consider also:</p>
<pre class="example">
int number = 7;
sql &lt;&lt; "insert into numbers(val) values(:blabla)", use(number);
</pre>
<p>Both examples above will insert the value of some local variable into
the table <code>numbers</code> - we say that the local variable is <i>used</i> in the SQL statement.</p>
<p>There should be as many <code>use</code> elements as there are
parameters used in the SQL query.</p>
<div class="note">
<p><span class="note">Portability note:</span></p>
<p>Older versions of the PostgreSQL client API do not allow to use input
parameters at all. In order to compile SOCI with those old client
libraries, define the <code>SOCI_POSTGRESQL_NOPARAMS</code> preprocessor
name passing <code>-DSOCI_POSTGRESQL_NOPARAMS=ON</code> variable to CMake.</p>
</div>
<h4 id="bind_position">Binding by position</h4>
<p>If there is more output or input "holes" in the single statement, it
is possible to use many <code>into</code> and <code>use</code>
expressions, separated by commas, where each expression will be
responsible for the consecutive "hole" in the statement:</p>
<pre class="example">
string firstName = "John", lastName = "Smith";
int personId = 7;
sql &lt;&lt; "insert into person(id, firstname, lastname) values(:id, :fn, :ln)",
use(personId), use(firstName), use(lastName);
sql &lt;&lt; "select firstname, lastname from person where id = :id",
into(firstName), into(lastName), use(personId);
</pre>
<p>In the code above, the order of "holes" in the SQL statement and the
order of <code>into</code> and <code>use</code> expression should
match.</p>
<h4 id="bind_name">Binding by name</h4>
<p>The SQL placeholders that have their names (with colon) can be bound
by name to clearly associate the local variable with the given placeholder.</p>
<p>This explicit naming allows to use different order of elements:</p>
<pre class="example">
string firstName = "John", lastName = "Smith";
int personId = 7;
sql &lt;&lt; "insert into person(id, firstname, lastname) values(:id, :fn, :ln)",
use(firstName, "fn"), use(lastName, "ln"), use(personId, "id");
</pre>
<p>or bind the same local data to many "holes" at the same time:</p>
<pre class="example">
string addr = "...";
sql &lt;&lt; "update person"
" set mainaddress = :addr, contactaddress = :addr"
" where id = 7",
use(addr, "addr");
</pre>
<div class="note">
<p><span class="note">Object lifetime and immutability:</span></p>
<p>SOCI assumes that local variables provided as <code>use</code> elements
live at least as long at it takes to execute the whole statement.
In short statement forms like above, the statement is executed <i>sometime</i>
at the end of the full expression and the whole process is driven by the invisible
temporary object handled by the library. If the data provided by user comes
from another temporary variable, it might be possible for the compiler to arrange
them in a way that the user data will be destroyed <i>before</i> the statement will
have its chance to execute, referencing objects that no longer exist:</p>
<pre class="example">
// dangerous code:
string getNameFromSomewhere();
sql &lt;&lt; "insert into person(name) values(:n)",
use(getNameFromSomewhere());
</pre>
<p>In the above example, the data passed to the database comes from the temporary
variable that is a result of call to <code>getNameFromSomewhere</code> - this
should be avoided and named variables should be used to ensure safe lifetime relations:</p>
<pre class="example">
// safe code:
string getNameFromSomewhere();
string name = getNameFromSomewhere();
sql &lt;&lt; "insert into person(name) values(:n)",
use(name);
</pre>
<p>It is still possible to provide <code>const</code> data for use elements.
Note that some database servers, like Oracle, allow PL/SQL procedures to modify their
in/out parameters - this is detected by the SOCI library and an error is reported
if the database attempts to modify the <code>use</code> element that holds <code>const</code>
data.</p>
<p>The above example can be ultimately written in the following way:</p>
<pre class="example">
// safe and efficient code:
string getNameFromSomewhere();
const string &amp; name = getNameFromSomewhere();
sql &lt;&lt; "insert into person(name) values(:n)",
use(name);
</pre>
</div>
<div class="note">
<p><span class="note">Portability notes:</span></p>
<p>The PostgreSQL backend allows to use the "native" PostgreSQL way of
naming parameters in the query, which is by numbers like <code>$1</code>,
<code>$2</code>, <code>$3</code>, etc. In fact, the backend <i>rewrites</i>
the given query to the native form - and this is also one of the very few places
where SOCI intrudes into the SQL query. For portability reasons, it is
recommended to use named parameters, as shown in the examples above.<br />
The query rewriting can be switched off by compiling the backend with
the <code>SOCI_POSTGRESQL_NOBINDBYNAME</code> name defined (pass
<code>-DSOCI_POSTGRESQL_NOBINDBYNAME=ON</code> variable to CMake).
Note that in this case it is also necessary to define <code>SOCI_POSTGRESQL_NOPREPARE</code>
(controlled by CMake variable <code>-DSOCI_POSTGRESQL_NOPREPARE=ON</code>),
because statement preparation relies on successful query rewriting.
In practice, both macros will be needed for PostgreSQL server older than 8.0.</p>
</div>
<h3 id="data_states">Handling nulls and other conditions</h3>
<h4 id="indicators">Indicators</h4>
<p>In order to support null values and other conditions which are not
real errors, the concept of <i>indicator</i> is provided.</p>
<p>For example, when the following SQL query is executed:</p>
<pre class="example">
select name from person where id = 7
</pre>
<p>there are three possible outcomes:</p>
<ol>
<li>there is a person with id = 7 and his name is returned</li>
<li>there is a person with id = 7, but he has no name (his name is
null in the database table)</li>
<li>there is no such person</li>
</ol>
<p>Whereas the first alternative is easy to handle, the other two are more
complex. Moreover, they are not necessarily errors from the
application's point of view and what's more interesting, they are <i>different</i>
and the application may wish to detect which is the case.<br />
The following example does this:</p>
<pre class="example">
string name;
indicator ind;
sql &lt;&lt; "select name from person where id = 7", into(name, ind);
if (sql.got_data())
{
switch (ind)
{
case i_ok:
// the data was returned without problems
break;
case i_null:
// there is a person, but he has no name (his name is null)
break;
case i_truncated:
// the name was returned only in part,
// because the provided buffer was too short
// (not possible with std::string, but possible with char* and char[])
break;
}
}
else
{
// no such person in the database
}
</pre>
<p>The use of indicator variable is optional, but if it is not used and
the result would be <code>i_null</code>,
then the exception is thrown. This means that you should use indicator
variables everywhere where the application logic (and database schema)
allow the "attribute not set" condition.</p>
<p>Indicator variables can be also used when binding input data, to
control whether the data is to be used as provided, or explicitly
overrided to be null:</p>
<pre class="example">
int id = 7;
string name;
indicator ind = i_null;
sql &lt;&lt; "insert into person(id, name) values(:id, :name)",
use(id), use(name, ind);
</pre>
<p>In the above example, the row is inserted with <code>name</code>
attribute set to null.</p>
<p>Indicator variables can also be used in conjunction with vector
based insert, update, and select statements:</p>
<pre class="example">
vector&lt;string&gt; names(100);
vector&lt;indicator&gt; inds;
sql &lt;&lt; "select name from person where id = 7", into(names, inds);
</pre>
<p>The above example retrieves first 100 rows of data (or less). The
initial size of <code>names</code> vector provides the (maximum)
number of rows that should be read. Both vectors will be
automatically resized according to the number of rows that were
actually read.</p>
<p>The following example inserts null for each value of name:</p>
<pre class="example">
vector&lt;int&gt; ids;
vector&lt;string&gt; names;
vector&lt;indicator&gt; nameIndicators;
for (int i = 0; i != 10; ++i)
{
ids.push_back(i);
names.push_back("");
nameIndicators.push_back(i_null);
}
sql &lt;&lt; "insert into person(id, name) values(:id, :name)",
use(ids), use(name, nameIndicators);
</pre>
<p>See also <a href="boost.html">Integration with Boost</a> to learn
how the Boost.Optional library can be used to handle null data conditions
in a more natural way.</p>
<h3 id="types">Types</h3>
<h4 id="static">Static type binding</h4>
<p>The static binding for types is most useful when the types used in
the database are known at compile time - this was already presented
above with the help of <code>into</code> and <code>use</code>
functions.</p>
<p>The following types are currently supported for use with <code>into</code>
and <code>use</code> expressions:</p>
<ul>
<li><code>char</code> (for character values)</li>
<li><code>short</code>, <code>int</code>, <code>unsigned
long</code>, <code>long long</code>, <code>double</code> (for numeric values)</li>
<li><code>char*</code>, <code>char[]</code>, <code>std::string</code>
(for string values)</li>
<li><code>std::tm</code><code></code> (for datetime
values)</li>
<li><code>soci::statement</code> (for nested statements and PL/SQL
cursors)</li>
<li><code>soci::blob</code> (for Binary Large OBjects)</li>
<li><code>soci::row_id</code> (for row identifiers)</li>
</ul>
<p>See the test code that accompanies the library to see how each of
these types is used.</p>
<h4 id="static_bulk">Static type binding for bulk operations</h4>
<p>Bulk inserts, updates, and selects are supported through the
following <code>std::vector</code> based into and use types:
</p>
<ul>
<li><code>std::vector&lt;char&gt;</code></li>
<li><code>std::vector&lt;short&gt;</code></li>
<li><code>std::vector&lt;int&gt;</code></li>
<li><code>std::vector&lt;unsigned long&gt;</code></li>
<li><code>std::vector&lt;long long&gt;</code></li>
<li><code>std::vector&lt;double&gt;</code></li>
<li><code>std::vector&lt;std::string&gt;</code></li>
<li><code>std::vector&lt;std::tm&gt;</code></li>
</ul>
<p>Use of the vector based types mirrors that of the standard types, with
the size of the vector used to specify the number of records to process
at a time. See below for examples.</p>
<p>Note that bulk operations are supported only for <code>std::vector</code>s of the types listed above.</p>
<h4 id="dynamic">Dynamic resultset binding</h4>
<p>For certain applications it is desirable to be able to select data from
arbitrarily structured tables (e.g. via "<code>select * from ...</code>") and format the
resulting data based upon its type.
SOCI supports this through the <code>soci::row</code> and <code>soci::column_properties</code>
classes.</p>
<p>Data is selected into a <code>row</code> object, which holds <code>column_properties</code>
objects describing
the attributes of data contained in each column. Once the data type for each
column is known, the data can be formatted appropriately.</p>
<p>For example, the code below creates an XML document from a selected row
of data from an arbitrary table:</p>
<pre class="example">
row r;
sql &lt;&lt; "select * from some_table", into(r);
std::ostringstream doc;
doc &lt;&lt; "&lt;row&gt;" &lt;&lt; std::endl;
for(std::size_t i = 0; i != r.size(); ++i)
{
const column_properties &amp; props = r.get_properties(i);
doc &lt;&lt; '&lt;' &lt;&lt; props.get_name() &lt;&lt; '&gt;';
switch(props.get_data_type())
{
case dt_string:
doc &lt;&lt; r.get&lt;std::string&gt;(i);
break;
case dt_double:
doc &lt;&lt; r.get&lt;double&gt;(i);
break;
case dt_integer:
doc &lt;&lt; r.get&lt;int&gt;(i);
break;
case dt_long_long:
doc &lt;&lt; r.get&lt;long long&gt;(i);
break;
case dt_unsigned_long_long:
doc &lt;&lt; r.get&lt;unsigned long long&gt;(i);
break;
case dt_date:
std::tm when = r.get&lt;std::tm&gt;(i);
doc &lt;&lt; asctime(&amp;when);
break;
}
doc &lt;&lt; "&lt;/" &lt;&lt; props.get_name() &lt;&lt; '&gt;' &lt;&lt; std::endl;
}
doc &lt;&lt; "&lt;/row&gt;";
</pre>
<p>The type <code>T</code> parameter that should be passed to
<code>row::get&lt;T&gt;()</code> depends on the SOCI data type that
is returned from
<code>column_properties::get_data_type()</code>.</p>
<p><code>row::get&lt;T&gt;()</code>
throws an exception of type
<code>std::bad_cast</code> if an incorrect type <code>T</code> is
requested.</p>
<table border="1" cellpadding="5" cellspacing="0">
<tbody>
<tr>
<th>SOCI Data Type</th>
<th><code>row::get&lt;T&gt;</code> specialization</th>
</tr>
<tr>
<td><code>dt_double</code></td>
<td><code>double</code></td>
</tr>
<tr>
<td><code>dt_integer</code></td>
<td><code>int</code></td>
</tr>
<tr>
<td><code>dt_long_long</code></td>
<td><code>long long</code></td>
</tr>
<tr>
<td><code>dt_unsigned_long_long</code></td>
<td><code>unsigned long long</code></td>
</tr>
<tr>
<td><code>dt_string</code></td>
<td><code>std::string</code></td>
</tr>
<tr>
<td><code>dt_date</code></td>
<td><code>std::tm</code><code></code></td>
</tr>
</tbody>
</table>
<p>The mapping of underlying database column types to SOCI datatypes is database specific.
See the <a href="backends/index.html">backend documentation</a> for details.</p>
<p>The <code>row</code> also provides access to indicators for each column:</p>
<pre>
row r;
sql &lt;&lt; "select name from some_table where id = 1", into(r);
if (r.get_indicator(0) != soci::i_null)
{
std::cout &lt;&lt; r.get&lt;std::string&gt;(0);
}
</pre>
<p>It is also possible to extract data from the <code>row</code> object using its stream-like
interface, where each extracted variable should have matching type respective to its position in the chain:</p>
<pre class="example">
row r;
sql &lt;&lt; "select name, address, age from persons where id = 123", into(r);
string name, address;
int age;
r >> name >> address >> age;
</pre>
<p>Note, however, that this interface is <i>not</i> compatible with the standard
<code>std::istream</code> class and that it is only possible to extract a single row at a time
- for "safety" reasons the row boundary is preserved and it is necessary to perform the
<code>fetch</code> operation explicitly for each consecutive row
(see <a href="statements.html">next page</a>).</p>
<h4 id="custom_types">Extending SOCI to support custom (user-defined) C++ types</h4>
<p>SOCI can be easily extended with support for user-defined datatypes.</p>
<p>The extension mechanism relies on appropriate specialization of the <code>type_conversion</code>
struct that converts to and from one of the following SOCI base types:</p>
<ul>
<li><code>double</code></li>
<li><code>int</code></li>
<li><code>long long</code></li>
<li><code>unsigned long long</code></li>
<li><code>std::string</code></li>
<li><code>char</code></li>
<li><code>std::tm</code></li>
</ul>
<p>There are three required class members for a valid <code>type_conversion</code>
specialization:</p>
<ul>
<li>the <code>base_type</code> type definition, aliasing either one of the base types <i>or another ser-defined type</i></li>
<li>the <code>from_base()</code> static member function, converting from
the base type</li>
<li>the <code>to_base()</code> static member function, converting to the
base type</li>
</ul>
<p>Note that no database-specific code is required to define user conversion.</p>
<p>The following example shows how the user can extend SOCI to
support his own type <code>MyInt</code>, which here is some wrapper
for the fundamental <code>int</code> type:</p>
<pre class="example">
class MyInt
{
public:
MyInt() {}
MyInt(int i) : i_(i) {}
void set(int i) { i_ = i; }
int get() const { return i_; }
private:
int i_;
};
namespace soci
{
template &lt;&gt;
struct type_conversion&lt;MyInt&gt;
{
typedef int base_type;
static void from_base(int i, indicator ind, MyInt &amp; mi)
{
if (ind == i_null)
{
throw soci_error("Null value not allowed for this type");
}
mi.set(i);
}
static void to_base(const MyInt &amp; mi, int &amp; i, indicator &amp; ind)
{
i = mi.get();
ind = i_ok;
}
};
}
</pre>
<p>The above specialization for <code>soci::type_conversion&lt;MyInt&gt;</code> is enough
to enable the following:</p>
<pre class="example">
MyInt i;
sql &lt;&lt; "select count(*) from person", into(i);
cout &lt;&lt; "We have " &lt;&lt; i.get() &lt;&lt; " persons in the database.\n";
</pre>
<p>Note that there is a number of types from the Boost library integrated with SOCI out of the box, see <a href="boost.html">Integration with Boost</a> for complete description. Use these as examples of conversions for more complext data types.</p>
<p>Note also that user-defined datatypes are not supported with <a href="#static_bulk">bulk data transfer</a>.</p>
<p>Another possibility to extend SOCI with custom data types is to use
the <code>into_type&lt;T&gt;</code> and <code>use_type&lt;T&gt;</code>
class templates, which specializations can be user-provided. These
specializations need to implement the interface defined by,
respectively, the <code>into_type_base</code> and <code>use_type_base</code>
classes.</p>
<p>Note that when specializing these template classes the only convention
is that when the indicator
variable is used (see below), it should appear in the second position.
Please refer to the library source code to see how this is done for the
standard types.</p>
<h4 id="object_relational">Object-relational mapping</h4>
<p>SOCI provides a class called <code>values</code> specifically to
enable object-relational mapping via <code>type_conversion</code>
specializations.</p>
<p>For example, the following code maps a <code>Person</code> object to
and from a
database table containing columns <code>"ID"</code>, <code>"FIRST_NAME"</code>, <code>"LAST_NAME"</code>, and
<code>"GENDER"</code>.</p>
<p>Note that the mapping is non-invasive - the <code>Person</code> object
itself does not contain any SOCI-specific code:</p>
<pre class="example">
struct Person
{
int id;
std::string firstName;
std::string lastName;
std::string gender;
};
namespace soci
{
template&lt;&gt;
struct type_conversion&lt;Person&gt;
{
typedef values base_type;
static void from_base(values const &amp; v, indicator /* ind */, Person &amp; p)
{
p.id = v.get&lt;int&gt;("ID");
p.firstName = v.get&lt;std::string&gt;("FIRST_NAME");
p.lastName = v.get&lt;std::string&gt;("LAST_NAME");
// p.gender will be set to the default value "unknown"
// when the column is null:
p.gender = v.get&lt;std::string&gt;("GENDER", "unknown");
// alternatively, the indicator can be tested directly:
// if (v.indicator("GENDER") == i_null)
// {
// p.gender = "unknown";
// }
// else
// {
// p.gender = v.get&lt;std::string&gt;("GENDER");
// }
}
static void to_base(const Person &amp; p, values &amp; v, indicator &amp; ind)
{
v.set("ID", p.id);
v.set("FIRST_NAME", p.firstName);
v.set("LAST_NAME", p.lastName);
v.set("GENDER", p.gender, p.gender.empty() ? i_null : i_ok);
ind = i_ok;
}
};
}
</pre>
<p>With the above <code>type_conversion</code> specialization in place, it
is possible to use <code>Person</code> directly with SOCI:</p>
<pre class="example">
session sql(oracle, "service=db1 user=scott password=tiger");
Person p;
p.id = 1;
p.lastName = "Smith";
p.firstName = "Pat";
sql &lt;&lt; "insert into person(id, first_name, last_name) "
"values(:ID, :FIRST_NAME, :LAST_NAME)", use(p);
Person p1;
sql &lt;&lt; "select * from person", into(p1);
assert(p1.id == 1);
assert(p1.firstName + p.lastName == "PatSmith");
assert(p1.gender == "unknown");
p.firstName = "Patricia";
sql &lt;&lt; "update person set first_name = :FIRST_NAME "
"where id = :ID", use(p);
</pre>
<div class="note">
<p><span class="note">Note:</span> The <code>values</code>
class is currently not suited for use outside of <code>type_conversion</code>
specializations. It is specially designed to facilitate
object-relational mapping when used as shown above.</p>
</div>
<h3 id="blob">Large objects (BLOBs)</h3>
<p>The SOCI library provides also an interface for basic operations on
large objects (BLOBs - Binary Large OBjects).</p>
<pre class="example">
blob b(sql); // sql is a session object
sql &lt;&lt; "select mp3 from mymusic where id = 123", into(b);
</pre>
<p>The following functions are provided in the <code>blob</code>
interface, mimicking the file-like operations:</p>
<ul>
<li><code>std::size_t get_len();</code></li>
<li><code>std::size_t read(std::size_t offset, char *buf, std::size_t
toRead);</code></li>
<li><code>std::size_t write(std::size_t offset, char const *buf,
std::size_t toWrite);</code></li>
<li><code>std::size_t append(char const *buf, std::size_t toWrite);</code></li>
<li><code>void trim(std::size_t newLen);</code></li>
</ul>
<p>The <code>offset</code> parameter is always counted from the beginning
of the BLOB's data.</p>
<div class="note">
<p><span class="note">Portability notes:</span></p>
<ol>
<li>The way to define BLOB table columns and create or destroy BLOB
objects in the database varies between different database engines.
Please see the SQL documentation relevant for the given server to learn
how this is actually done. The test programs provided with the SOCI
library can be also a simple source of full working examples.</li>
<li>The <code>trim</code> function is not currently available for
the PostgreSQL backend.</li>
</ol>
</div>
<table class="foot-links" border="0" cellpadding="2" cellspacing="2">
<tr>
<td class="foot-link-left">
<a href="basics.html">Previous (Connections and simple queries)</a>
</td>
<td class="foot-link-right">
<a href="statements.html">Next (Statements, procedures and transactions)</a>
</td>
</tr>
</table>
<p class="copyright">Copyright &copy; 2010-2013 Mateusz Loskot</p>
<p class="copyright">Copyright &copy; 2012 Vadim Zeitlin</p>
<p class="copyright">Copyright &copy; 2004-2008 Maciej Sobczak, Stephen Hutton</p>
</body>
</html>

View File

@@ -1,102 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en'>
<head>
<meta content="text/html; charset=ISO-8859-1" http-equiv="content-type" />
<link rel="stylesheet" type="text/css" href="style.css" />
<title>SOCI</title>
</head>
<body>
<p class="banner">SOCI - The C++ Database Access Library</p>
<h1>Documentation and tutorial</h1>
<div class="navigation">
<a href="structure.html">Structure</a><br />
<a href="installation.html">Installation</a><br />
<a href="errors.html">Errors</a><br />
<a href="connections.html">Connections</a><br />
<a href="queries.html">Queries</a><br />
<a href="exchange.html">Exchanging data</a><br />
<a href="statements.html">Statements, procedures and transactions</a><br />
<a href="multithreading.html">Multithreading and SOCI</a><br />
<a href="boost.html">Integration with Boost</a><br />
<a href="interfaces.html">Interfaces</a><br />
<a href="beyond.html">Beyond standard SQL</a><br />
<a href="reference.html">Client interface reference</a><br />
<a href="backends.html">Backends reference</a><br />
<a href="rationale.html">Rationale FAQ</a><br /><br />
<a href="languages/ada/index.html">Ada language binding</a><br /><br />
<a href="backends/index.html">Existing backends and supported platforms</a>
</div>
<p>The following (complete!) example is purposedly provided without any explanation.</p>
<pre class="example">
#include "soci.h"
#include "soci-oracle.h"
#include &lt;iostream&gt;
#include &lt;istream&gt;
#include &lt;ostream&gt;
#include &lt;string&gt;
#include &lt;exception&gt;
using namespace soci;
using namespace std;
bool get_name(string &amp;name)
{
cout &lt;&lt; "Enter name: ";
return cin &gt;&gt; name;
}
int main()
{
try
{
session sql(oracle, "service=mydb user=john password=secret");
int count;
sql &lt;&lt; "select count(*) from phonebook", into(count);
cout &lt;&lt; "We have " &lt;&lt; count &lt;&lt; " entries in the phonebook.\n";
string name;
while (get_name(name))
{
string phone;
indicator ind;
sql &lt;&lt; "select phone from phonebook where name = :name",
into(phone, ind), use(name);
if (ind == i_ok)
{
cout &lt;&lt; "The phone number is " &lt;&lt; phone &lt;&lt; '\n';
}
else
{
cout &lt;&lt; "There is no phone for " &lt;&lt; name &lt;&lt; '\n';
}
}
}
catch (exception const &amp;e)
{
cerr &lt;&lt; "Error: " &lt;&lt; e.what() &lt;&lt; '\n';
}
}
</pre>
<table class="foot-links" border="0" cellpadding="2" cellspacing="2">
<tr>
<td class="foot-link-left"></td>
<td class="foot-link-right">
<a href="structure.html">Next (Library structure, files and compilation)</a>
</td>
</tr>
</table>
<p class="copyright">Copyright &copy; 2010-2013 Mateusz Loskot</p>
<p class="copyright">Copyright &copy; 2012 Vadim Zeitlin</p>
<p class="copyright">Copyright &copy; 2004-2008 Maciej Sobczak, Stephen Hutton</p>
</body>
</html>

View File

@@ -1,466 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en'>
<head>
<meta content="text/html; charset=ISO-8859-1" http-equiv="content-type" />
<link rel="stylesheet" type="text/css" href="style.css" />
<title>SOCI - structure</title>
</head>
<body>
<p class="banner">SOCI - The C++ Database Access Library</p>
<h2>Installation</h2>
<div class="navigation">
<a href="#requirements">Requirements</a><br />
<a href="#downloading">Downloading</a><br />
<a href="#cmake">Building using CMake</a><br />
<div class="navigation-indented">
<a href="#unix">On Unix</a><br />
<a href="#windows">On Windows</a><br />
</div>
<a href="#unix-makefiles">Building using classic Makefiles on Unix</a> (deprecated)<br />
<a href="#testing">Running Tests</a><br />
<a href="#usage">Usage</a><br />
</div>
<h3 id="requirements">Requirements</h3>
<p>Below is an overall list of SOCI core:</p>
<ul>
<li>C++ compiler: <a href="http://gcc.gnu.org/">GCC</a>, <a href="http://msdn.microsoft.com/en-us/visualc">Microsoft Visual C++</a>, <a href="http://clang.llvm.org/">LLVM/clang</a></li>
<li><a href="http://www.cmake.org">CMake</a> 2.8+ - in order to use build configuration for CMake</li>
<li><a href="http://www.boost.org">Boost C++ Libraries</a>: DateTime, Fusion, Optional, Preprocessor, Tuple</li>
</ul>
<p>and backend-specific dependencies:</p>
<ul>
<li><a href="http://pic.dhe.ibm.com/infocenter/db2luw/v10r1/topic/com.ibm.swg.im.dbclient.install.doc/doc/c0023452.html">DB2 Call Level Interface (CLI)</a>
<li><a href="http://www.firebirdsql.org/manual/ufb-cs-clientlib.html">Firebird client library</a>
<li><a href="http://dev.mysql.com/doc/refman/5.6/en/c.html">mysqlclient</a> - C API to MySQL</li>
<li><a href="">ODBC (Open Database Connectivity)</a> implementation: <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms710252.aspx">Microsoft ODBC</a>, <a href="http://www.iodbc.org/">iODBC</a>, <a href="http://www.unixodbc.org/">unixODBC</a></li>
<li><a href="http://www.oracle.com/technetwork/database/features/oci/index.html">Oracle Call Interface (OCI)</a></li>
<li><a href="http://www.postgresql.org/docs/8.4/static/libpq.html">libpq</a> - C API to PostgreSQL</li>
<li><a href="http://www.sqlite.org/">SQLite 3</a> library</li>
</li>
</ul>
<h3 id="downloading">Downloading</h3>
<p>Download package with latest release of the SOCI source code: <a href="https://sourceforge.net/projects/soci/files/soci/">soci-X.Y.Z</a>, where X.Y.Z is the version number. Unpack the archive.</p>
<p>You can always clone SOCI from the Git repository:</p>
<pre>git clone git://github.com/SOCI/soci.git</pre>
<h3 id="cmake">Building using CMake</h3>
<p>SOCI is configured to build using <a href="http://cmake.org/">CMake</a> system in version 2.8+.</p>
<p>The build configuration allows to control various aspects of compilation and installation by setting common CMake variables that change behaviour, describe system or control build (see <a href="http://cmake.org/cmake/help/documentation.html">CMake help</a>) as well as SOCI-specific variables described below. All these variables are available regardless of platform or compilation toolset used.</p>
<p>Running CMake from the command line allows to set variables in the CMake cache with the following syntax: <code>-DVARIABLE:TYPE=VALUE</code>. If you are new to CMake, you may find the tutorial <a href="http://cmake.org/cmake/help/runningcmake.html">Running CMake</a> helpful.</p>
<p>The following tables provide summary of variables accepted by CMake scripts configuring SOCI build. The lists consist of common variables for SOCI core and all backends as well as variables specific to SOCI backends and their direct dependencies.</p>
<table class="cmake-variables" cellpadding="2" cellspacing="2" summary="CMake essential variables (refer to CMake manual for complete list)">
<caption class="cmake-variables">List of a few essential CMake variables</caption>
<tr>
<td class="variable-name">CMAKE_BUILD_TYPE</td>
<td class="variable-type">string</td>
<td>Specifies the build type for make based generators (see CMake <a href="http://cmake.org/cmake/help/cmake-2-8-docs.html#variable:CMAKE_BUILD_TYPE">help</a>).</td>
</tr>
<tr>
<td class="variable-name">CMAKE_INSTALL_PREFIX</td>
<td class="variable-type">path</td>
<td>Install directory used by install command (see CMake <a href="http://cmake.org/cmake/help/cmake-2-8-docs.html#variable:CMAKE_INSTALL_PREFIX">help</a>).</td>
</tr>
<tr>
<td class="variable-name">CMAKE_VERBOSE_MAKEFILE</td>
<td class="variable-type">boolean</td>
<td>If ON, create verbose makefile (see CMake <a href="http://cmake.org/cmake/help/cmake-2-8-docs.html#variable:CMAKE_VERBOSE_MAKEFILE">help</a>).</td>
</tr>
</table>
<table class="cmake-variables" cellpadding="2" cellspacing="2" summary="SOCI Core configuration">
<caption class="cmake-variables">List of variables to control common SOCI features and dependencies</caption>
<tr>
<td class="variable-name">SOCI_STATIC</td>
<td class="variable-type">boolean</td>
<td>Request to build static libraries, along with shared, of SOCI core and all successfully configured backends.</td>
</tr>
<tr>
<td class="variable-name">SOCI_TESTS</td>
<td class="variable-type">boolean</td>
<td>Request to build regression tests for SOCI core and all successfully configured backends.</td>
</tr>
<tr>
<td class="variable-name">WITH_BOOST</td>
<td class="variable-type">boolean</td>
<td>Should CMake try to detect <a href="http://www.boost.org/">Boost C++ Libraries</a>. If ON, CMake will try to find Boost headers and binaries of <a href="http://www.boost.org/doc/libs/release/doc/html/date_time.html">Boost.Date_Time</a> library.</td>
</tr>
</table>
<h4 id="H2">IBM DB2</h4>
<table class="cmake-variables" cellpadding="2" cellspacing="2" summary="SOCI DB2 configuration">
<caption class="cmake-variables">SOCI DB2 backend configuration</caption>
<tr>
<td class="variable-name">WITH_DB2</td>
<td class="variable-type">boolean</td>
<td>Should CMake try to detect IBM DB2 Call Level Interface (CLI) library.</td>
</tr>
<tr>
<td class="variable-name">DB2_INCLUDE_DIR</td>
<td class="variable-type">string</td>
<td>Path to DB2 CLI include directories where CMake should look for <code>sqlcli1.h</code> header.</td>
</tr>
<tr>
<td class="variable-name">DB2_LIBRARIES</td>
<td class="variable-type">string</td>
<td>Full paths to <code>db2</code> or <code>db2api </code> libraries to link SOCI against to enable the backend support.</td>
</tr>
<tr>
<td class="variable-name">SOCI_DB2</td>
<td class="variable-type">boolean</td>
<td>Requests to build <a href="backends/db2.html">DB2</a> backend. Automatically switched on, if <code>WITH_DB2</code> is set to ON.</td>
</tr>
<tr>
<td class="variable-name">SOCI_DB2_TEST_CONNSTR</td>
<td class="variable-type">string</td>
<td>See <a href="backends/db2.html">DB2 backend refernece</a> for details. Example: <code>-DSOCI_DB2_TEST_CONNSTR:STRING="DSN=SAMPLE;Uid=db2inst1;Pwd=db2inst1;autocommit=off"</code></td>
</tr>
</table>
<h4 id="H1">Firebird</h4>
<table class="cmake-variables" cellpadding="2" cellspacing="2" summary="SOCI Firebird configuration">
<caption class="cmake-variables">SOCI Firebird backend configuration</caption>
<tr>
<td class="variable-name">WITH_FIREBIRD</td>
<td class="variable-type">boolean</td>
<td>Should CMake try to detect Firebird client library.</td>
</tr>
<tr>
<td class="variable-name">FIREBIRD_INCLUDE_DIR</td>
<td class="variable-type">string</td>
<td>Path to Firebird include directories where CMake should look for <code>ibase.h</code> header.</td>
</tr>
<tr>
<td class="variable-name">FIREBIRD_LIBRARIES</td>
<td class="variable-type">string</td>
<td>Full paths to Firebird <code>fbclient</code> or <code>fbclient_ms</code> libraries to link SOCI against to enable the backend support.</td>
</tr>
<tr>
<td class="variable-name">SOCI_FIREBIRD</td>
<td class="variable-type">boolean</td>
<td>Requests to build <a href="backends/firebird.html">Firebird</a> backend. Automatically switched on, if <code>WITH_FIREBIRD</code> is set to ON.</td>
</tr>
<tr>
<td class="variable-name">SOCI_FIREBIRD_TEST_CONNSTR</td>
<td class="variable-type">string</td>
<td>See <a href="backends/firebird.html">Firebird backend refernece</a> for details. Example: <code>-DSOCI_FIREBIRD_TEST_CONNSTR:STRING="service=LOCALHOST:/tmp/soci_test.fdb user=SYSDBA password=masterkey"</code></td>
</tr>
</table>
<h4 id="mysql">MySQL</h4>
<table class="cmake-variables" cellpadding="2" cellspacing="2" summary="SOCI MySQL configuration">
<caption class="cmake-variables">SOCI MySQL backend configuration</caption>
<tr>
<td class="variable-name">WITH_MYSQL</td>
<td class="variable-type">boolean</td>
<td>Should CMake try to detect <a href="http://dev.mysql.com/doc/refman/5.0/en/c.html">mysqlclient</a> libraries providing MySQL C API. Note, currently the <a href="http://dev.mysql.com/doc/refman/5.0/en/building-clients.html">mysql_config</a> program is not being used.</td>
</tr>
<tr>
<td class="variable-name">MYSQL_DIR</td>
<td class="variable-type">string</td>
<td>Path to MySQL installation root directory. CMake will scan subdirectories <code>MYSQL_DIR/include</code> and <code>MYSQL_DIR/lib</code> respectively for MySQL headers and libraries.</td>
</tr>
<tr>
<td class="variable-name">MYSQL_INCLUDE_DIR</td>
<td class="variable-type">string</td>
<td>Path to MySQL include directory where CMake should look for <code>mysql.h</code> header.</td>
</tr>
<tr>
<td class="variable-name">MYSQL_LIBRARIES</td>
<td class="variable-type">string</td>
<td>Full paths to libraries to link SOCI against to enable the backend support.</td>
</tr>
<tr>
<td class="variable-name">SOCI_MYSQL</td>
<td class="variable-type">boolean</td>
<td>Requests to build <a href="backends/mysql.html">MySQL</a> backend. Automatically switched on, if <code>WITH_MYSQL</code> is set to ON.</td>
</tr>
<tr>
<td class="variable-name">SOCI_MYSQL_TEST_CONNSTR</td>
<td class="variable-type">string</td>
<td>Connection string to MySQL test database. Format of the string is explained <a href="backends/mysql.html">MySQL backend refernece</a>. Example: <code>-DSOCI_MYSQL_TEST_CONNSTR:STRING="db=mydb user=mloskot password=secret"</code></td>
</tr>
</table>
<h4 id="odbc">ODBC</h4>
<table class="cmake-variables" cellpadding="2" cellspacing="2" summary="SOCI ODBC configuration">
<caption class="cmake-variables">SOCI ODBC backend configuration</caption>
<tr>
<td class="variable-name">WITH_ODBC</td>
<td class="variable-type">boolean</td>
<td>Should CMake try to detect ODBC libraries. On Unix systems, CMake tries to find <a href="http://www.unixodbc.org/">unixODBC</a> or <a href="http://www.iodbc.org/">iODBC</a> implementations.</td>
</tr>
<tr>
<td class="variable-name">ODBC_INCLUDE_DIR</td>
<td class="variable-type">string</td>
<td>Path to ODBC implementation include directories where CMake should look for <code>sql.h</code> header.</td>
</tr>
<tr>
<td class="variable-name">ODBC_LIBRARIES</td>
<td class="variable-type">string</td>
<td>Full paths to libraries to link SOCI against to enable the backend support.</td>
</tr>
<tr>
<td class="variable-name">SOCI_ODBC</td>
<td class="variable-type">boolean</td>
<td>Requests to build <a href="backends/odbc.html">ODBC</a> backend. Automatically switched on, if <code>WITH_ODBC</code> is set to ON.</td>
</tr>
<tr>
<td class="variable-name">SOCI_ODBC_TEST_{database}_CONNSTR</td>
<td class="variable-type">string</td>
<td>ODBC Data Source Name (DSN) or ODBC File Data Source Name (FILEDSN) to test database: Microsoft Access (.mdb), Microsoft SQL Server, MySQL, PostgreSQL or any other ODBC SQL data source. {database} is placeholder for name of database driver ACCESS, MYSQL, POSTGRESQL, etc. See <a href="backends/odbc.html">ODBC backend refernece</a> for details. Example: <code>-DSOCI_ODBC_TEST_POSTGRESQL_CONNSTR="FILEDSN=/home/mloskot/dev/soci/_git/build/test-postgresql.dsn"</code></td>
</tr>
</table>
<h4 id="oracle">Oracle</h4>
<table class="cmake-variables" cellpadding="2" cellspacing="2" summary="SOCI Oracle configuration">
<caption class="cmake-variables">SOCI Oracle backend configuration</caption>
<tr>
<td class="variable-name">WITH_ORACLE</td>
<td class="variable-type">boolean</td>
<td>Should CMake try to detect <a href="http://en.wikipedia.org/wiki/Oracle_Call_Interface">Oracle Call Interface (OCI)</a> libraries.</td>
</tr>
<tr>
<td class="variable-name">ORACLE_INCLUDE_DIR</td>
<td class="variable-type">string</td>
<td>Path to Oracle include directory where CMake should look for <code>oci.h</code> header.</td>
</tr>
<tr>
<td class="variable-name">ORACLE_LIBRARIES</td>
<td class="variable-type">string</td>
<td>Full paths to libraries to link SOCI against to enable the backend support.</td>
</tr>
<tr>
<td class="variable-name">SOCI_ORACLE</td>
<td class="variable-type">boolean</td>
<td>Requests to build <a href="backends/oracle.html">Oracle</a> backend. Automatically switched on, if <code>WITH_ORACLE</code> is set to ON.</td>
</tr>
<tr>
<td class="variable-name">SOCI_ORACLE_TEST_CONNSTR</td>
<td class="variable-type">string</td>
<td>Connection string to Oracle test database. Format of the string is explained <a href="backends/oracle.html">Oracle backend refernece</a>. Example: <code>-DSOCI_ORACLE_TEST_CONNSTR:STRING="service=orcl user=scott password=tiger"</code></td>
</tr>
</table>
<h4 id="postgresql">PostgreSQL</h4>
<table class="cmake-variables" cellpadding="2" cellspacing="2" summary="SOCI Oracle configuration">
<caption class="cmake-variables">SOCI PostgreSQL backend configuration</caption>
<tr>
<td class="variable-name">WITH_POSTGRESQL</td>
<td class="variable-type">boolean</td>
<td>Should CMake try to detect PostgreSQL client interface libraries. SOCI relies on <a href="http://www.postgresql.org/docs/9.0/interactive/libpq.html">libpq</a> C library.</td>
</tr>
<tr>
<td class="variable-name">POSTGRESQL_INCLUDE_DIR</td>
<td class="variable-type">string</td>
<td>Path to PostgreSQL include directory where CMake should look for <code>libpq-fe.h</code> header.</td>
</tr>
<tr>
<td class="variable-name">POSTGRESQL_LIBRARIES</td>
<td class="variable-type">string</td>
<td>Full paths to libraries to link SOCI against to enable the backend support.</td>
</tr>
<tr>
<td class="variable-name">SOCI_POSTGRESQL</td>
<td class="variable-type">boolean</td>
<td>Requests to build <a href="backends/postgresql.html">PostgreSQL</a> backend. Automatically switched on, if <code>WITH_POSTGRESQL</code> is set to ON.</td>
</tr>
<tr>
<td class="variable-name">SOCI_POSTGRESQL_TEST_CONNSTR</td>
<td class="variable-type">boolean</td>
<td>Connection string to PostgreSQL test database. Format of the string is explained <a href="backends/postgresql.html">PostgreSQL backend refernece</a>. Example: <code>-DSOCI_POSTGRESQL_TEST_CONNSTR:STRING="dbname=mydb user=mloskot"</code></td>
</tr>
</table>
<h4 id="sqlite">SQLite 3</h4>
<table class="cmake-variables" cellpadding="2" cellspacing="2" summary="SOCI Oracle configuration">
<caption class="cmake-variables">SOCI SQLite 3 backend configuration</caption>
<tr>
<td class="variable-name">WITH_SQLITE3</td>
<td class="variable-type">boolean</td>
<td>Should CMak try to detect <a href="http://www.sqlite.org/cintro.html">SQLite C/C++ library</a>. As bonus, the configuration tries <a href="http://trac.osgeo.org/osgeo4w/">OSGeo4W</a> distribution if <code>OSGEO4W_ROOT</code> environment variable is set.</td>
</tr>
<tr>
<td class="variable-name">SQLITE_INCLUDE_DIR</td>
<td class="variable-type">string</td>
<td>Path to SQLite 3 include directory where CMake should look for <code>sqlite3.h</code> header.</td>
</tr>
<tr>
<td class="variable-name">SQLITE_LIBRARIES</td>
<td class="variable-type">string</td>
<td>Full paths to libraries to link SOCI against to enable the backend support.</td>
</tr>
<tr>
<td class="variable-name">SOCI_SQLITE3</td>
<td class="variable-type">boolean</td>
<td>Requests to build <a href="backends/sqlite3.html">SQLite3</a> backend. Automatically switched on, if <code>WITH_SQLITE3</code> is set to ON.</td>
</tr>
<tr>
<td class="variable-name">SOCI_SQLITE3_TEST_CONNSTR</td>
<td class="variable-type">string</td>
<td>Connection string is simply a file path where SQLite3 test database will be created (e.g. /home/john/soci_test.db). Check <a href="backends/sqlite3.html">SQLite3 backend refernece</a> for details. Example: <code>-DSOCI_SQLITE3_TEST_CONNSTR="my.db"</code></td>
</tr>
</table>
<h4 id="empty">Empty (sample backend)</h4>
<table class="cmake-variables" cellpadding="2" cellspacing="2" summary="SOCI Oracle configuration">
<caption class="cmake-variables">SOCI empty sample backend configuration</caption>
<tr>
<td class="variable-name">SOCI_EMPTY</td>
<td class="variable-type">boolean</td>
<td>Builds the <a href="backends.html">sample backend</a> called Empty. Always ON by default.</td>
</tr>
<tr>
<td class="variable-name">SOCI_EMPTY_TEST_CONNSTR</td>
<td class="variable-type">string</td>
<td>Connection string used to run regression tests of the Empty backend. It is a dummy value. Example: <code>-DSOCI_EMPTY_TEST_CONNSTR="dummy connection"</code></td>
</tr>
</table>
<p>By default, CMake will try to determine availability of all depdendencies automatically. If you are lucky, you will not need to specify any of the CMake variables explained above. However, if CMake reports some of the core or backend-specific dependencies as missing, you will need specify relevant variables to tell CMake where to look for the required components.</p>
<p>CMake configures SOCI build performing sequence of steps. Each
subsequent step is dependant on result of previous steps corresponding
with particular feature. First, CMake checks system platform and
compilation toolset. Next, CMake tries to find all external
dependencies. Then, depending on the results of the dependency check,
CMake determines SOCI backends which are possible to build. The
SOCI-specific variables described above provide users with basic
control of this behaviour.</p>
<h4 id="unix">Building using CMake on Unix</h4>
<p>Short version using GNU Make makefiles:</p>
<pre class="example">
$ mkdir build
$ cd build
$ cmake -G "Unix Makefiles" -DWITH_BOOST=OFF -DWITH_ORACLE=OFF (...) ../soci-X.Y.Z
$ make
$ make install
</pre>
<h4 id="windows">Building using CMake on Windows</h4>
<p>Short version using Visual Studio 2010 and MSBuild:</p>
<pre class="example">
C:\>MKDIR build
C:\>cd build
C:\build>cmake -G "Visual Studio 10" -DWITH_BOOST=OFF -DWITH_ORACLE=OFF (...) ..\soci-X.Y.Z
C:\build>msbuild.exe SOCI.sln
</pre>
<h3 id="unix-makefiles">Building using classic Makefiles on Unix (deprecated)</h3>
<p><em>NOTE: These Makefiles have not been maintained for long time.
The officially maintained build configuration is CMake. If you still want to
use these Makefiles, you've been warned that you may need to patch them.</em></p>
<p>The classic set of Makefiles for Unix/Linux systems is provided for those users who need complete control over the whole process
and who can benefit from the basic scaffolding that they can extend on their own.
In this sense, the basic Makefiles are supposed to provide a minimal starting point for custom experimentation and are not intended to be a complete build/installation solution.<br />
At the same time, they are complete in the sense that they can compile the library with all test programs and for some users this level of support will be just fine.</p>
<p>The <code>core</code> directory of the library distribution contains
the <code>Makefile.basic</code> that can be used to compile the core part of
the library. Run <code>make -f Makefile.basic</code> or <code>make -f Makefile.basic shared</code> to get the static and shared versions, respectively.
Similarly, the <code>backends/<i>name</i></code> directory contains the
backend part for each supported backend with the appropriate <code>Makefile.basic</code>
and the <code>backends/<i>name</i>/test</code>
directory contains the test program for the given backend.</p>
<p>For example, the simplest way to compile the static version of the
library and the test program for PostgreSQL is:</p>
<pre class="example">
$ cd src/core
$ make -f Makefile.basic
$ cd ../backends/postgresql
$ make -f Makefile.basic
$ cd test
$ make -f Makefile.basic
</pre>
<div class="note">
<p><span class="note">Note:</span>
For each backend and its test program, the <code>Makefile.basic</code>s
contain the variables that can have values specific to the given
environment - they usually name the include and library paths.
These variables are placed at the beginning of the <code>Makefile.basic</code>s.
Please review their values in case of any compilation problems.</p>
</div>
<p>The Makefiles for test programs can be a good starting point to find out correct compiler and linker options.</p>
<h3 id="testing">Running regression tests</h3>
<p>The process of running regression tests highly depends on user's environment and build configuration, so it may be quite involving process. The CMake configuration provides variables to allow users willing to run the tests to configure build and specify database connection parameters (see the tables above for variable names).</p>
<p>In order to run regression tests, configure and build desired SOCI backends and prepare working database instances for them.</p>
<p>While configuring build with CMake, specify <code>SOCI_TESTS=ON</code> to enable building regression tests. Also, specify <code>SOCI_{backend name}_TEST_CONNSTR</code> variables to tell the tests runner how to connect with your test databases.</p>
<p>Dedicated <code>make test</code> target can be used to execute regression tests on build completion:</p>
<pre class="example">
$ mkdir build
$ cd build
$ cmake -G "Unix Makefiles" -DWITH_BOOST=OFF \
-DSOCI_TESTS=ON \
-DSOCI_EMPTY_TEST_CONNSTR="dummy connection" \
-DSOCI_SQLITE3_TEST_CONNSTR="test.db" \
(...)
../soci-X.Y.Z
$ make
$ make test
$ make install
</pre>
<p>In the example above, regression tests for the sample Empty backend and SQLite 3 backend are configured for execution by <code>make test</code> target.</p>
<h3 id="usage">Libraries usage</h3>
<p>CMake build produces set of shared and static libraries for SOCI core and backends separately. On Unix, for example, <code>build/lib</code> directory
will consist of the static libraries named like <code>libsoci_core.a</code>, <code>libsoci_sqlite3.a</code> and shared libraries with names like
<code>libsoci_core.so.3.2.2</code>, <code>libsoci_sqlite3.so.3.2.2</code>, and so on.</p>
<p>In order to use SOCI in your program, you need to specify your project build configuration with paths to SOCI headers and libraries,
and specify linker to link against the libraries you want to use in your program.</p>
</p>
<table class="foot-links" border="0" cellpadding="2" cellspacing="2">
<tr>
<td class="foot-link-left">
<a href="structure.html">Previous (Structure)</a>
</td>
<td class="foot-link-right">
<a href="errors.html">Next (Errors)</a>
</td>
</tr>
</table>
<p class="copyright">Copyright &copy; 2010-2013 Mateusz Loskot</p>
<p class="copyright">Copyright &copy; 2004-2011 Maciej Sobczak, Stephen Hutton</p>
</body>
</html>

View File

@@ -1,103 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en'>
<head>
<meta content="text/html; charset=ISO-8859-1" http-equiv="content-type" />
<link rel="stylesheet" type="text/css" href="style.css" />
<title>SOCI - integration with Boost</title>
</head>
<body>
<p class="banner">SOCI - The C++ Database Access Library</p>
<h2>Interfaces</h2>
<p>One of the major features of SOCI, although not immediately visible, is the variety of interfaces (APIs) that are available for the user. These can be divided into <i>sugar</i>, <i>core</i> and <i>simple</i>.</p>
<h4>Sugar</h4>
<p>The most exposed and promoted interface supports the syntax sugar that makes SOCI similar in look and feel to embedded SQL. The example of application code using this interface is:</p>
<pre class="example">
session sql("postgresql://dbname=mydb");
int id = 123;
string name;
sql &lt;&lt; "select name from persons where id = :id", into(name), use(id);
</pre>
<h4>Core</h4>
<p>The above example is equivalent to the following, more explicit sequence of calls:</p>
<pre class="example">
session sql("postgresql://dbname=mydb");
int id = 123;
string name;
statement st(sql);
st.exchange(into(name));
st.exchange(use(id));
st.alloc();
st.prepare("select name from persons where id = :id");
st.define_and_bind();
st.execute(true);
</pre>
<p>The value of the <i>core</i> interface is that it is the basis for all other interfaces, and can be also used by developers to easily prepare their own convenience interfaces. Users who cannot or for some reason do not want to use the natural <i>sugar</i> interface should try the <i>core</i> one as the foundation and access point to all SOCI functionality.</p>
<p>Note that the <i>sugar</i> interface wraps only those parts of the <i>core</i> that are related to data binding and query streaming.</p>
<h4>Simple</h4>
<p>The <i>simple</i> interface is provided specifically to allow easy integration of the SOCI library with other languages that have the ability to link with binaries using the "C" calling convention. To facilitate this integration, the <i>simple</i> interface does not use any pointers to data except C-style strings and opaque handles, but the consequence of this is that user data is managed by SOCI and not by user code. To avoid exceptions passing the module boundaries, all errors are reported as state variables of relevant objects.</p>
<p>The above examples can be rewritten as (without error-handling):</p>
<pre class="example">
#include &lt;soci-simple.h&gt;
// ...
session_handle sql = soci_create_session("postgresql://dbname=mydb");
statement_handle st = soci_create_statement(sql);
soci_use_int(st, "id");
soci_set_use_int(st, "id", 123);
int namePosition = soci_into_string(st);
soci_prepare(st, "select name from persons where id = :id");
soci_execute(st, true);
char const * name = soci_get_into_string(st, namePosition);
printf("name is %s\n", name);
soci_destroy_statement(st);
soci_destroy_session(sql);
</pre>
<p>The <i>simple</i> interface supports single and bulk data exchange for static binding. Dynamic row description is not supported in this release.</p>
<p>See <a href="reference.html#simpleclient">Simple client interface</a> reference documentation for more details.</p>
<h4>Low-level backend interface</h4>
<p>The low-level backend interface allows to interact with backends directly and in principle allows to access the database without involving any other component. There is no particular reason to use this interface in the user code.</p>
<table class="foot-links" border="0" cellpadding="2" cellspacing="2">
<tr>
<td class="foot-link-left">
<a href="boost.html">Previous (Boost)</a>
</td>
<td class="foot-link-right">
<a href="beyond.html">Next (Beyond standard SQL)</a>
</td>
</tr>
</table>
<p class="copyright">Copyright &copy; 2012 Vadim Zeitlin</p>
<p class="copyright">Copyright &copy; 2004-2008 Maciej Sobczak, Stephen Hutton</p>
</body>
</html>

View File

@@ -1,64 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en'>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<title>SOCI-Ada - documentation</title>
<link rel="stylesheet" type="text/css" href="style.css" />
</head>
<body>
<h1>SOCI-Ada - manual</h1>
<p class="section"><b>Concepts</b></p>
<p>
The SOCI-Ada library borrows its concepts and naming from the main SOCI project. They are shortly explained here in the bottom-up fashion.
</p>
<p>
One of the main properties of the library is that the data objects which are bound for transfer to and from the database server are managed by the library itself and are not directly visible from the user code. This ensures that no aliasing of objects occurs between Ada and underlying C++ code, which makes the inter-language interface easier and more resilient to the differences in how compilers handle the linkage. As a direct result of this design choice, users of SOCI-Ada need to instruct the library to internally create all objects that will be subject to data transfer.
</p>
<p>
There are two kinds of objects that can be managed by the SOCI-Ada library:
</p>
<ul>
<li><i>Into elements</i>, which are data objects that are transferred from the database to the user program as a result of executing a query. There are single into elements for binding single rows of results and vector into elements for binding whole bunches of data corresponding to whole result sets or their subranges. The into elements are identified by their <i>position</i>.</li>
<li><i>Use elements</i>, which are data objects that are transferred from the user program to the database as parameters of the query (and, if supported by the target database, that can be modified by the database server and transferred back to the user program). There are single use elements for binding parameters of single-row queries and vector use elements for binding whole bunches of data for transfer. The use elements are identified by their <i>name</i>.</li>
</ul>
<p>
The user program can read the current value of into and use elements and assign new values to use elements. Elements are strongly typed and the following types are currently supported:
</p>
<ul>
<li><code>String</code></li>
<li><code>SOCI.DB_Integer</code>, which is defined by the library in terms of <code>Interfaces.C.int</code></li>
<li><code>SOCI.DB_Long_Long_Integer</code>, which is defined in terms of <code>Interfaces.Integer_64</code></li>
<li><code>SOCI.DB_Long_Float</code>, which is defined in terms of <code>Interfaces.C.double</code></li>
<li><code>Ada.Calendar.Time</code></li>
</ul>
<p>
Both into and use elements are managed for a single <i>statement</i>, which can be prepared once and executed once or many times, with data transfer handled during execution or fetch phase.
</p>
<p>
Statements can be managed explicitly, which is required if they are to be used repeteadly or when data transfer is needed or implicitly, which is a shorthand notation that is particularly useful with simple queries or DDL commands.
</p>
<p>
All statements are handled within the context of some <i>session</i>, which also supports <i>transactions</i>.
</p>
<p>
Sessions can be managed in isolation or as a group called <i>connection pool</i>, which helps to decouple tasking design choices from the concurrency policies at the database connection level. Sessions are <i>leased</i> from the pool for some time during which no other task can access them and returned back when no longer needed, where they can be acquired again by other tasks.
</p>
<p>
All potential problems are signalled via exceptions that have some descriptive message attached to them.
</p>
<table class="foot-links" border="0" cellpadding="2" cellspacing="2">
<tr>
<td class="foot-link-left">
<a href="index.html">Back to index</a>
</td>
<td class="foot-link-right">
<a href="idioms.html">Common Idioms</a>
</td>
</tr>
</table>
<p class="copyright">Copyright &copy; 2008-2011 Maciej Sobczak</p>
</body>
</html>

View File

@@ -1,306 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en'>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<title>SOCI-Ada - documentation</title>
<link rel="stylesheet" type="text/css" href="style.css" />
</head>
<body>
<h1>SOCI-Ada - manual</h1>
<p class="section"><b>Common Idioms</b></p>
<p>
As any other library, SOCI-Ada has its set of idioms that ensure optimal work in terms of performance and resource usage. Still, the optimal use will depend on the concrete usage scenario - the places where programmer choices are needed will be described explicitly.
</p>
<p>
The idioms below are provided as <i>complete programs</i> with the intent to make them more understandable and to give complete context of use for each idiom. The programs assume that the target database is PostgreSQL, but this can be changed by a different connection string in each place where the sessions are established. The programs use the Ada 2005 interface and some minor changes will be required to adapt them for Ada 95 compilers.
</p>
<p class="section"><b>Single query without data transfer</b></p>
<p>
This type of query is useful for DDL commands and can be executed directly on the given session, without explicit statement management.
</p>
<pre class="example">
with SOCI;
procedure My_Program is
SQL : SOCI.Session := SOCI.Make_Session ("postgresql://dbname=my_database");
begin
SQL.Execute ("drop table some_table");
end My_Program;
</pre>
<div class="note">
<p><span class="note">Note:</span></p>
<p>
The session object is initialized by a constructor function call. An alternative would be to declare it without initialization and later use the <code>Open</code> operation to establish a physical connection with the database.
</p>
</div>
<p class="section"><b>Simple query without parameters resulting in one row of data</b></p>
<p>
This type of query requires only single into elements, which together with the statement have to be manipulated explicitly.
</p>
<pre class="example">
with SOCI;
with Ada.Text_IO;
procedure My_Program is
SQL : SOCI.Session := SOCI.Make_Session ("postgresql://dbname=my_database");
St : SOCI.Statement := SOCI.Make_Statement (SQL);
Pos : SOCI.Into_Position;
Num_Of_Persons : SOCI.DB_Integer;
begin
Pos := St.Into_Integer;
St.Prepare ("select count(*) from persons");
St.Execute (True);
Num_Of_Persons := St.Get_Into_Integer (Pos);
Ada.Text_IO.Put_Line ("Number of persons: " &amp; SOCI.DB_Integer'Image (Num_Of_Persons));
end My_Program;
</pre>
<div class="note">
<p><span class="note">Note:</span></p>
<p>
The into element is inspected by providing the position value that was obtained at the time if was created. No operations are defined for the position type. There can be many into elements with a single query.
</p>
</div>
<p class="section"><b>Simple query with parameters and without results</b></p>
<p>
This type of query requires only use elements.
</p>
<pre class="example">
with SOCI;
procedure My_Program is
SQL : SOCI.Session := SOCI.Make_Session ("postgresql://dbname=my_database");
St : SOCI.Statement := SOCI.Make_Statement (SQL);
begin
St.Use_Integer ("increase");
St.Set_Use_Integer ("increase", 1000);
St.Prepare ("update persons set salary = salary + :increase");
St.Execute (True);
end My_Program;
</pre>
<div class="note">
<p><span class="note">Note:</span></p>
<p>
The "<code>:increase</code>" in the query is a placeholder variable. There can be many such variables and each of them needs to be filled in by respective use element.
</p>
</div>
<p class="section"><b>Repeated query with parameters and without results</b></p>
<p>
This type of query requires only use elements, but they can be set differently for each statement execution.
</p>
<pre class="example">
with SOCI;
procedure My_Program is
SQL : SOCI.Session := SOCI.Make_Session ("postgresql://dbname=my_database");
St : SOCI.Statement := SOCI.Make_Statement (SQL);
begin
St.Use_String ("name");
St.Prepare ("insert into countries(country_name) values(:name)");
St.Set_Use_String ("name", "Poland");
St.Execute (True);
St.Set_Use_String ("name", "Switzerland");
St.Execute (True);
St.Set_Use_String ("name", "France");
St.Execute (True);
end My_Program;
</pre>
<div class="note">
<p><span class="note">Note:</span></p>
<p>
Each time the query is executed, the <i>current</i> values of use elements are transferred to the database.
</p>
</div>
<p class="section"><b>Batch query with parameters and without results</b></p>
<p>
This type of query requires vector use elements. Compare with the previous example.
</p>
<pre class="example">
with SOCI;
procedure My_Program is
SQL : SOCI.Session := SOCI.Make_Session ("postgresql://dbname=my_database");
St : SOCI.Statement := SOCI.Make_Statement (SQL);
First : SOCI.Vector_Index;
use type SOCI.Vector_Index;
begin
St.Use_Vector_String ("name");
St.Use_Vectors_Resize (3);
First := St.Use_Vectors_First_Index;
St.Set_Use_Vector_String ("name", First + 0, "Poland");
St.Set_Use_Vector_String ("name", First + 1, "Switzerland");
St.Set_Use_Vector_String ("name", First + 2, "France");
St.Prepare ("insert into countries(country_name) values(:name)");
St.Execute (True);
end My_Program;
</pre>
<div class="note">
<p><span class="note">Note:</span></p>
<p>
The whole bunch of data is transferred to the database if the target database server supports it and the statement is automatically repeated otherwise. This is the preferred way to transfer many rows of data to the server when the data for all rows are known before executing the query.
</p>
</div>
<div class="note">
<p><span class="note">Note:</span></p>
<p>
The query can be executed many times and each time a new batch of data can be transferred to the server. The size of the batch (set by calling <code>Use_Vectors_Resize</code>) can be different each time the query is executed, but cannot be larger than the size that was used the first time. The size of the batch defines a tradeoff between the amount of data being transmitted in a single step (this influences the memory used by the user program and the time of a single call) and the number of executions required to handle big data sets. The optimal size of the batch will therefore differ depending on the application, but in general tens of thousands is a reasonable limit for a batch size - the performance of the whole operation is usually not affected above this value so there is no need to imply higher memory usage at the client side.
</p>
</div>
<p class="section"><b>Simple query with many rows of results</b></p>
<p>
This type of query requires simple into elements.
</p>
<pre class="example">
with SOCI;
with Ada.Text_IO;
procedure My_Program is
SQL : SOCI.Session := SOCI.Make_Session ("postgresql://dbname=my_database");
St : SOCI.Statement := SOCI.Make_Statement (SQL);
Pos : SOCI.Into_Position;
begin
Pos := St.Into_String;
St.Prepare ("select country_name from countries");
St.Execute;
while St.Fetch loop
Ada.Text_IO.Put_Line (St.Get_Into_String (Pos));
end loop;
end My_Program;
</pre>
<div class="note">
<p><span class="note">Note:</span></p>
<p>
The loop above executes as many times as there are rows in the result. After each row is read, the into elements contain the respective values from that row. The <code>Execute</code> operation is called without parameter, which is <code>False</code> by default, meaning that no data transfer is intended. The data is being transferred only during the <code>Fetch</code> operation, which returns <code>False</code> when no data has been retrieved and the result is exhausted.
</p>
<p>
This type of query can have simple parameters which are fixed at the execution time.
</p>
</div>
<p class="section"><b>Batch query with many rows of results</b></p>
<p>
This type of query requires vector into elements. Compare with previous example.
</p>
<pre class="example">
with SOCI;
with Ada.Text_IO;
procedure My_Program is
SQL : SOCI.Session := SOCI.Make_Session ("postgresql://dbname=my_database");
St : SOCI.Statement := SOCI.Make_Statement (SQL);
Pos : SOCI.Into_Position;
Batch_Size : constant := 10;
begin
Pos := St.Into_Vector_String;
St.Into_Vectors_Resize (Batch_Size);
St.Prepare ("select country_name from countries");
St.Execute;
while St.Fetch loop
for I in St.Into_Vectors_First_Index .. St.Into_Vectors_Last_Index loop
Ada.Text_IO.Put_Line (St.Get_Into_Vector_String (Pos, I));
end loop;
St.Into_Vectors_Resize (Batch_Size);
end loop;
end My_Program;
</pre>
<div class="note">
<p><span class="note">Note:</span></p>
<p>
The loop above is nested. The outer <code>while</code> loop fetches consecutive batches of rows from the database with requested batch size; the returned batch can be smaller than requested (the into vector elements are downsized automatically if needed) and the intended batch size is requested again before repeating the <code>Fetch</code> operation. For each returned batch, the into vector elements are inspected in the inner <code>for</code> loop. This scheme ensures correct operation independently on the size of returned batch and is therefore a recommended idiom for efficiently returning many rows of data.
</p>
<p>
There is a tradeoff between efficiency and memory usage and this tradeoff is controlled by the requested batch size. Similarly to one of the examples above, there is no benefit from using batches bigger than tens of thousands of rows.
</p>
<p>
This type of query can have simple (not vectors) parameters that are fixed at execution time.
</p>
</div>
<div class="note">
<p><span class="note">Final note:</span></p>
<p>
Follow good database usage principles and avoid constructing queries by concatenating strings computed at run-time. Thanks to a good type system Ada is much better in preventing various SQL-injection attacks than weaker languages like PHP, but there is still a potential for vulnerability or at least performance loss. As a rule of thumb, rely on <i>use elements</i> to parameterize your queries and to provide clean separation between data and code. This will prevent many security vulnerabilities and will allow some servers to optimize their work by reusing already cached execution plans.
</p>
</div>
<table class="foot-links" border="0" cellpadding="2" cellspacing="2">
<tr>
<td class="foot-link-left">
<a href="concepts.html">Concepts</a>
</td>
<td class="foot-link-right">
<a href="reference.html">API Reference</a>
</td>
</tr>
</table>
<p class="copyright">Copyright &copy; 2008-2011 Maciej Sobczak</p>
</body>
</html>

View File

@@ -1,78 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en'>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<title>SOCI-Ada Language Binding - documentation</title>
<link rel="stylesheet" type="text/css" href="style.css" />
</head>
<body>
<h1>SOCI-Ada Language Binding - documentation</h1>
<p>
<a href="#introduction">Introduction</a><br />
<a href="#compilation">Compilation</a><br />
<a href="concepts.html">Concepts</a><br />
<a href="idioms.html">Common Idioms</a><br />
<a href="reference.html">API Reference</a><br />
</p>
<hr />
<p class="section"><a name="introduction" /><b>Introduction</b></p>
<p>
SOCI-Ada is a database access library for Ada.
</p>
<p>
The library itself is a wrapper for the selected functionality of the SOCI library, which is a C++ database access library recognized for its high quality and innovative interface.
</p>
<p>
The SOCI-Ada library offers the following features to the Ada community:
</p>
<ul>
<li>Modular design based on dynamic backend loading. Thanks to this feature, new backends implemented within the context of the main SOCI project are immediately available for Ada programmers without any additional work. A large community of C++ users can help ensure that the new backends are well tested in a variety of environments and usage scenarios.</li>
<li>Native backends for major database servers ensure optimal performance and minimize configuration overhead and complexity that is usually associated with other database access methods.</li>
<li>Direct support for bulk operations allow to achieve high performance with queries that operate on large data sets.</li>
<li>Very liberal open-source license (<a href="http://www.opensource.org/licenses/bsl1.0.html" target="_blank">Boost, accepted by Open Source Initiative</a>) that encourages both commercial and non-commercial use.</li>
<li>Easy to use and compact interface.</li>
</ul>
<p>
Currently the following database servers are directly supported via their native interfaces:
</p>
<ul>
<li>Oracle</li>
<li>PostgreSQL</li>
<li>MySQL</li>
</ul>
<p>
Other backends exist in the SOCI Git repository and can be provided with future version of the library.
</p>
<p class="section"><a name="compilation" /><b>Compilation</b></p>
<p>
In order to use SOCI-Ada, compile the C++ parts first (core and required backends).
</p>
<p>
<b>Note:</b> SOCI header files are not needed to use SOCI-Ada, only compiled SOCI libraries (core and relevant backend) need to exist to build and use SOCI-Ada programs.
</p>
<p>
The SOCI-Ada library itself is a single package named
<code>SOCI</code>. This package can be just imported in the target project as is or pre-built to the binary form if required.
</p>
<p>
In order to link the user programs the <code>-lsoci_core -lstdc++</code> linker options need to be provided on the Unix/Linux platforms.
</p>
<table class="foot-links" border="0" cellpadding="2" cellspacing="2">
<tr>
<td class="foot-link-left">
</td>
<td class="foot-link-right">
<a href="concepts.html">Concepts</a>
</td>
</tr>
</table>
<p class="copyright">Copyright &copy; 2008-2011 Maciej Sobczak</p>
</body>
</html>

View File

@@ -1,674 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en'>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<title>SOCI-Ada - documentation</title>
<link rel="stylesheet" type="text/css" href="style.css" />
</head>
<body>
<h1>SOCI-Ada - manual</h1>
<p class="section"><b>API Reference</b></p>
<p>
The SOCI-Ada library is entirely implemented as a single package named
<code>SOCI</code>. Additional child packages contain single procedures
for static registration of backends - these child packages are not
necessary for typical use, but can be useful to force static
linking of backend code.
</p>
<p>
The following describes all publicly visible elements of this package:
</p>
<hr />
<pre class="example">
--
-- General exception related to database and library usage.
--
Database_Error : exception;
</pre>
<p>
Each problem related to the interaction with the database or to the incorrect usage of the library itself is signalled by raising this exception. Each occurrence of this exception has some human-readable error message that can be obtained by a call to <code>Ada.Exceptions.Exception_Message</code>.
</p>
<hr />
<pre class="example">
--
-- Session.
--
type Session is tagged limited private;
not overriding
function Make_Session (Connection_String : in String) return Session;
not overriding
procedure Open (This : in out Session; Connection_String : in String);
not overriding
procedure Close (This : in out Session);
not overriding
function Is_Open (This : in Session) return Boolean;
</pre>
<p>
The <code>Session</code> object can exist in two states: "connected" (or "open") and "disconnected". It can be created as connected at initialization time with a call to the constructor function <code>Make_Session</code> or left default-initialized in the disconnected state and later changed to connected with <code>Open</code> (the latter option is the only that is available in the Ada 95 version of the library). <code>Session</code> objects can be also associated with the connection pool, see below.
</p>
<p>
The <code>Connection_String</code> should have the form <code>"backendname://parameters"</code>, where <code>backendname</code> is used to construct the name of the dynamically loadable library that will be used to provide specific database services. Backends included in the current distribution of the main SOCI library are:
</p>
<ul>
<li><code>oracle</code> (implemented as <code>libsoci_oracle.so</code> or <code>libsoci_oracle.dll</code>)</li>
<li><code>postgresql</code> (implemented as <code>libsoci_postgresql.so</code> or <code>libsoci_postgresql.dll</code>)</li>
<li><code>mysql</code> (implemented as <code>libsoci_mysql.so</code> or <code>libsoci_mysql.dll</code>)</li>
</ul>
<p>
Other backends can be added to the library in the future or by the user himself, please see the documentation of the main SOCI library for details.
</p>
<p>
The <code>parameters</code> component of the <code>Connection_String</code> depends on the given backend, please see the documentation of the main SOCI project for the meaning and recognized options. The web pages related to the backends above are:
</p>
<ul>
<li>Oracle: <a href="http://soci.sourceforge.net/doc/backends/oracle.html" target="_blank">http://soci.sourceforge.net/doc/backends/oracle.html</a></li>
<li>PostgreSQL: <a href="http://soci.sourceforge.net/doc/backends/postgresql.html" target="_blank">http://soci.sourceforge.net/doc/backends/postgresql.html</a></li>
<li>MySQL: <a href="http://soci.sourceforge.net/doc/backends/mysql.html" target="_blank">http://soci.sourceforge.net/doc/backends/mysql.html</a></li>
</ul>
<p>
The <code>Open</code> operation can be called only in the disconnected state (which changes the state of <code>Session</code> object to connected). The <code>Close</code> operation can be called in any state (provided that the session is not associated with the connection pool, see below) and after that the <code>Session</code> is in the disconnected state.
</p>
<p>
<code>Session</code> objects are closed automatically as part of their finalization. If the <code>Session</code> object is associated with the connection pool, the finalizer detaches from the pool without closing the connection.
</p>
<hr />
<pre class="example">
-- Transaction management.
not overriding
procedure Start (This : in Session);
not overriding
procedure Commit (This : in Session);
not overriding
procedure Rollback (This : in Session);
</pre>
<p>
These operations handle transactions. The exact meaning of transactions and whether transactions are automatic for some kinds of statements (and which ones) depend on the target database.
</p>
<hr />
<pre class="example">
-- Immediate query execution.
not overriding
procedure Execute (This : in Session; Query : in String);
</pre>
<p>
This operation allows to create implicit statement, prepare it for the given <code>Query</code> and execute it.
</p>
<hr />
<pre class="example">
--
-- Connection pool management.
--
type Connection_Pool (Size : Positive) is tagged limited private;
not overriding
procedure Open
(This : in out Connection_Pool;
Position : in Positive;
Connection_String : in String);
not overriding
procedure Close (This : in out Connection_Pool; Position : in Positive);
not overriding
procedure Lease (This : in out Connection_Pool; S : in out Session'Class);
</pre>
<p>
The <code>Connection_Pool</code> encapsulates a fixed-size collection of sessions. Individual sessions are indexed from <code>1</code> to <code>Size</code> (provided as discriminant) and can be <code>Open</code>ed and <code>Close</code>d explicitly. Each connection in the pool can be created with different <code>Connection_String</code>, if needed.
</p>
<p>
The <code>Lease</code> operation allows to associate a given <code>Session</code> object (that has to be in the disconnected state itself) with one connection from the pool. The pool guarantees that at most one task can lease a given connection from the pool. If there are no free connections in the pool, the <code>Lease</code> operation will block waiting until some connection is freed.
</p>
<p>
The <code>Session</code> object that is associated with a connection from the pool automatically gives it back to pool as part of the <code>Session</code>'s finalizer. There is no other way to "detach" from the pool.
</p>
<div class="note">
<p><span class="note">Note:</span></p>
<p>
It is assumed that the lifetime of <code>Connection_Pool</code> encloses the lifetimes of all <code>Session</code> objects that are leased from it. There is no particular protection against it and it is possible to construct a code example with allocators that create partially overlapping <code>Connection_Pool</code> and <code>Session</code>, but this is considered obscure and not representative to the actual use scenarios. To avoid any potential problems, create <code>Connection_Pool</code> in the scope that encloses the scopes of leased <code>Session</code>s.
</p>
</div>
<hr />
<pre class="example">
--
-- Statement.
--
type Statement (&lt;&gt;) is tagged limited private;
type Data_State is (Data_Null, Data_Not_Null);
type Into_Position is private;
type Vector_Index is new Natural;
</pre>
<p>
The <code>Statement</code> type and supporting types. <code>Data_State</code> is used to indicate null values in the database sense - each value of into or use elements has a state from this type.
</p>
<p>
<code>Into_Position</code> is used to identify into elements. <code>Vector_Index</code> is used to name individual entries in vector into and use elements.
</p>
<hr />
<pre class="example">
not overriding
function Make_Statement (Sess : in Session'Class) return Statement;
-- Ada 95 version:
-- procedure Make_Statement (This : in out Statement; Sess : in Session'Class);
</pre>
<p>
Construction function for creating <code>Statement</code> objects. The <code>Statement</code> is associated with one <code>Session</code> for its whole lifetime.
</p>
<hr />
<pre class="example">
-- Statement preparation and execution.
not overriding
procedure Prepare (This : in Statement; Query : in String);
not overriding
procedure Execute
(This : in Statement;
With_Data_Exchange : in Boolean := False);
not overriding
function Execute
(This : in Statement;
With_Data_Exchange : in Boolean := False) return Boolean;
not overriding
function Fetch (This : in Statement) return Boolean;
not overriding
function Got_Data (This : in Statement) return Boolean;
</pre>
<p>
The <code>Prepare</code> operation needs to be called before any other operation in the above group and it prepares the execution for the given <code>Query</code>. No into and use elements can be created after this operation is called.
</p>
<p>
The <code>Execute</code> operations cause the statement to execute, which might be combined with data exchange if requested. The function version of this operation returns <code>True</code> if some data has been returned back from the database server.
</p>
<p>
The <code>Fetch</code> function is used to transfer next portion of data (a single row or a whole bunch) from the database server and returns <code>True</code> if some data has been fetched. If this function returns <code>False</code> it means that no new data will be ever fetched for this statement and indicates the end-of-row condition.
</p>
<p>
The <code>Got_Data</code> function returns <code>True</code> if the last execution or fetch resulted in some data being transmitted from the database server.
</p>
<hr />
<pre class="example">
--
-- Data items handling.
--
-- Database-specific types.
-- These types are most likely identical to standard Integer,
-- Long_Long_Integer and Long_Float, but are defined distinctly
-- to avoid interfacing problems with other compilers.
type DB_Integer is new Interfaces.C.int;
type DB_Long_Long_Integer is new Interfaces.Integer_64;
type DB_Long_Float is new Interfaces.C.double;
</pre>
<p>
The data types used for interaction with the database are:
</p>
<ul>
<li><code>String</code></li>
<li><code>DB_Integer</code>, defined above</li>
<li><code>DB_Long_Long_Integer</code>, defined above</li>
<li><code>DB_Long_Float</code>, defined above</li>
<li><code>Ada.Calendar.Time</code></li>
</ul>
<hr />
<pre class="example">
-- Creation of single into elements.
not overriding
function Into_String (This : in Statement) return Into_Position;
not overriding
function Into_Integer (This : in Statement) return Into_Position;
not overriding
function Into_Long_Long_Integer (This : in Statement) return Into_Position;
not overriding
function Into_Long_Float (This : in Statement) return Into_Position;
not overriding
function Into_Time (This : in Statement) return Into_Position;
</pre>
<p>
These functions instruct the library to create internal simple into elements of the relevant type. They return the position of the into element, which can be later used to identify it.
</p>
<div class="note">
<p><span class="note">Note:</span></p>
<p>
Simple into elements cannot be created together with vector into elements for the same statement.
</p>
</div>
<hr />
<pre class="example">
-- Creation of vector into elements.
not overriding
function Into_Vector_String (This : in Statement) return Into_Position;
not overriding
function Into_Vector_Integer (This : in Statement) return Into_Position;
not overriding
function Into_Vector_Long_Long_Integer (This : in Statement) return Into_Position;
not overriding
function Into_Vector_Long_Float (This : in Statement) return Into_Position;
not overriding
function Into_Vector_Time (This : in Statement) return Into_Position;
</pre>
<p>
These functions instruct the library to create internal vector into elements of the relevant type. They return the position of the into element, which can be later used to identify it.
</p>
<div class="note">
<p><span class="note">Note:</span></p>
<p>
Vector into elements are empty (they have size 0) after they are created and have to be resized before any data is written to them.
</p>
</div>
<div class="note">
<p><span class="note">Note:</span></p>
<p>
Simple into elements cannot be created together with vector into elements for the same statement.
</p>
</div>
<hr />
<pre class="example">
-- Inspection of single into elements.
not overriding
function Get_Into_State
(This : in Statement;
Position : in Into_Position)
return Data_State;
not overriding
function Get_Into_String
(This : in Statement;
Position : in Into_Position)
return String;
not overriding
function Get_Into_Integer
(This : in Statement;
Position : in Into_Position)
return DB_Integer;
not overriding
function Get_Into_Long_Long_Integer
(This : in Statement;
Position : in Into_Position)
return DB_Long_Long_Integer;
not overriding
function Get_Into_Long_Float
(This : in Statement;
Position : in Into_Position)
return DB_Long_Float;
not overriding
function Get_Into_Time
(This : in Statement;
Position : in Into_Position)
return Ada.Calendar.Time;
</pre>
<p>
These functions allow to inspect the state and value of the simple into element identified by its position. If the state of the given element is <code>Data_Null</code>, the data-reading functions raise exceptions for that element.
</p>
<hr />
<pre class="example">
-- Inspection of vector into elements.
not overriding
function Get_Into_Vectors_Size (This : in Statement) return Natural;
not overriding
function Into_Vectors_First_Index (This : in Statement) return Vector_Index;
not overriding
function Into_Vectors_Last_Index (This : in Statement) return Vector_Index;
not overriding
procedure Into_Vectors_Resize (This : in Statement; New_Size : in Natural);
</pre>
<p>
The <code>Get_Into_Vectors_Size</code> returns the number of entries in any of the vector into elements for the given statement.
</p>
<p>
The <code>Into_Vectors_First_Index</code> returns the lowest index value for vector into elements (which is always <code>0</code>, even if the vectors are empty). The <code>Into_Vectors_Last_Index</code> returns the last index of into vectors, and raises the <code>CONSTRAINT_ERROR</code> exception if the vectors are empty.
</p>
<p>
The <code>Into_Vectors_Resize</code> procedure allows to change the size of all use vectors for the given statement.
</p>
<hr />
<pre class="example">
not overriding
function Get_Into_Vector_State
(This : in Statement;
Position : in Into_Position;
Index : in Vector_Index)
return Data_State;
not overriding
function Get_Into_Vector_String
(This : in Statement;
Position : in Into_Position;
Index : in Vector_Index)
return String;
not overriding
function Get_Into_Vector_Integer
(This : in Statement;
Position : in Into_Position;
Index : in Vector_Index)
return DB_Integer;
not overriding
function Get_Into_Vector_Long_Long_Integer
(This : in Statement;
Position : in Into_Position;
Index : in Vector_Index)
return DB_Long_Long_Integer;
not overriding
function Get_Into_Vector_Long_Float
(This : in Statement;
Position : in Into_Position;
Index : in Vector_Index)
return DB_Long_Float;
not overriding
function Get_Into_Vector_Time
(This : in Statement;
Position : in Into_Position;
Index : in Vector_Index)
return Ada.Calendar.Time;
</pre>
<p>
These functions allow to inspect the state and value of the vector use element identified by its position and index. If the state of the given element is <code>Data_Null</code>, the data-reading functions raise exceptions for that element.
</p>
<hr />
<pre class="example">
-- Creation of single use elements.
not overriding
procedure Use_String (This : in Statement; Name : in String);
not overriding
procedure Use_Integer (This : in Statement; Name : in String);
not overriding
procedure Use_Long_Long_Integer (This : in Statement; Name : in String);
not overriding
procedure Use_Long_Float (This : in Statement; Name : in String);
not overriding
procedure Use_Time (This : in Statement; Name : in String);
</pre>
<p>
These functions instruct the library to create internal simple use elements of the relevant type, identified by the given <code>Name</code>.
</p>
<div class="note">
<p><span class="note">Note:</span></p>
<p>
Simple use elements cannot be created together with vector use elements for the same statement.
</p>
<p>
Vector use elements cannot be created together with any into elements for the same statement.
</p>
</div>
<hr />
<pre class="example">
-- Creation of vector use elements.
not overriding
procedure Use_Vector_String (This : in Statement; Name : in String);
not overriding
procedure Use_Vector_Integer (This : in Statement; Name : in String);
not overriding
procedure Use_Vector_Long_Long_Integer (This : in Statement; Name : in String);
not overriding
procedure Use_Vector_Long_Float (This : in Statement; Name : in String);
not overriding
procedure Use_Vector_Time (This : in Statement; Name : in String);
</pre>
<p>
These functions instruct the library to create internal vector use elements of the relevant type, identified by the given <code>Name</code>.
</p>
<div class="note">
<p><span class="note">Note:</span></p>
<p>
Simple use elements cannot be created together with vector use elements for the same statement.
</p>
<p>
Vector use elements cannot be created together with any into elements for the same statement.
</p>
</div>
<hr />
<pre class="example">
-- Modifiers for single use elements.
not overriding
procedure Set_Use_State
(This : in Statement;
Name : in String;
State : in Data_State);
not overriding
procedure Set_Use_String
(This : in Statement;
Name : in String;
Value : in String);
not overriding
procedure Set_Use_Integer
(This : in Statement;
Name : in String;
Value : in DB_Integer);
not overriding
procedure Set_Use_Long_Long_Integer
(This : in Statement;
Name : in String;
Value : in DB_Long_Long_Integer);
not overriding
procedure Set_Use_Long_Float
(This : in Statement;
Name : in String;
Value : in DB_Long_Float);
not overriding
procedure Set_Use_Time
(This : in Statement;
Name : in String;
Value : in Ada.Calendar.Time);
</pre>
<p>
These operations allow to modify the state and value of simple use elements. Setting the value of use element automatically sets its state to <code>Data_Not_Null</code>.
</p>
<hr />
<pre class="example">
-- Modifiers for vector use elements.
not overriding
function Get_Use_Vectors_Size (This : in Statement) return Natural;
not overriding
function Use_Vectors_First_Index (This : in Statement) return Vector_Index;
not overriding
function Use_Vectors_Last_Index (This : in Statement) return Vector_Index;
not overriding
procedure Use_Vectors_Resize (This : in Statement; New_Size : in Natural);
</pre>
<p>
The <code>Get_Use_Vectors_Size</code> returns the number of entries in any of the vector use elements for the given statement.
</p>
<p>
The <code>Use_Vectors_First_Index</code> returns the lowest index value for vector use elements (which is always <code>0</code>, even if the vectors are empty). The <code>Use_Vectors_Last_Index</code> returns the last index of use vectors, and raises the <code>CONSTRAINT_ERROR</code> exception if the vectors are empty.
</p>
<p>
The <code>Use_Vectors_Resize</code> procedure allows to change the size of all use vectors for the given statement.
</p>
<hr />
<pre class="example">
not overriding
procedure Set_Use_Vector_State
(This : in Statement;
Name : in String;
Index : in Vector_Index;
State : in Data_State);
not overriding
procedure Set_Use_Vector_String
(This : in Statement;
Name : in String;
Index : in Vector_Index;
Value : in String);
not overriding
procedure Set_Use_Vector_Integer
(This : in Statement;
Name : in String;
Index : in Vector_Index;
Value : in DB_Integer);
not overriding
procedure Set_Use_Vector_Long_Long_Integer
(This : in Statement;
Name : in String;
Index : in Vector_Index;
Value : in DB_Long_Long_Integer);
not overriding
procedure Set_Use_Vector_Long_Float
(This : in Statement;
Name : in String;
Index : in Vector_Index;
Value : in DB_Long_Float);
not overriding
procedure Set_Use_Vector_Time
(This : in Statement;
Name : in String;
Index : in Vector_Index;
Value : in Ada.Calendar.Time);
</pre>
<p>
These operations allow to modify the state and value of vector use elements. Setting the value of use element automatically sets its state to <code>Data_Not_Null</code>.
</p>
<hr />
<pre class="example">
-- Inspection of single use elements.
--
-- Note: Use elements can be modified by the database if they
-- are bound to out and inout parameters of stored procedures
-- (although this is not supported by all database backends).
-- This feature is available only for single use elements.
not overriding
function Get_Use_State
(This : in Statement;
Name : in String)
return Data_State;
not overriding
function Get_Use_String
(This : in Statement;
Name : in String)
return String;
not overriding
function Get_Use_Integer
(This : in Statement;
Name : in String)
return DB_Integer;
not overriding
function Get_Use_Long_Long_Integer
(This : in Statement;
Name : in String)
return DB_Long_Long_Integer;
not overriding
function Get_Use_Long_Float
(This : in Statement;
Name : in String)
return DB_Long_Float;
not overriding
function Get_Use_Time
(This : in Statement;
Name : in String)
return Ada.Calendar.Time;
</pre>
<p>
These functions allow to inspect the state and value of the simple use element identified by its name. If the state of the given element is <code>Data_Null</code>, the data-reading functions raise exceptions for that element.
</p>
<table class="foot-links" border="0" cellpadding="2" cellspacing="2">
<tr>
<td class="foot-link-left">
<a href="idioms.html">Idioms</a>
</td>
<td class="foot-link-right">
</td>
</tr>
</table>
<p class="copyright">Copyright &copy; 2008-2011 Maciej Sobczak</p>
</body>
</html>

View File

@@ -1,67 +0,0 @@
body
{
background-color: white;
color: black;
margin-left: 100px;
margin-right: 100px;
font-family: arial, sans-serif;
font-size: small;
}
div.note
{
border-color: black;
border-style: dotted;
border-width: 1px;
margin-top: 20px;
padding-left: 20px;
padding-right: 20px;
}
span.note
{
font-size: large;
font-weight: bold;
}
code
{
/* font-weight: bold; */
background-color: white;
color: #8B0000;
/* font-size: large; */
}
pre.example
{
background-color: #F0F0F0;
color: black;
border-width: 1px;
border-style: dashed;
border-color: blue;
padding: 10px 10px 10px 10px;
}
table.foot-links
{
width: 100%;
padding-top: 20px;
}
td.foot-link-left
{
text-align: left;
}
td.foot-link-right
{
text-align: right;
}
p.copyright
{
border-top-color: black;
border-top-style: solid;
border-top-width: 1px;
padding-top: 5px;
}

View File

@@ -1,64 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en'>
<head>
<meta content="text/html; charset=ISO-8859-1" http-equiv="content-type" />
<link rel="stylesheet" type="text/css" href="style.css" />
<title>SOCI - multithreading</title>
</head>
<body>
<p class="banner">SOCI - The C++ Database Access Library</p>
<h2>Multithreading</h2>
<p>The general rule for multithreading is that SOCI classes are <i>not</i> thread-safe, meaning that their instances should not be used concurrently by multiple threads.</p>
<p>The simplest solution for multithreaded code is to set up a separate <code>session</code> object for each thread that needs to inteact with the database. Depending on the design of the client application this might be also the most straightforward approach.</p>
<p>For some applications, however, it might be preferable to decouple the set of threads from the set of sessions, so that they can be optimized separately with different resources in mind. The <code>connection_pool</code> class is provided for this purpose:</p>
<pre class="example">
// phase 1: preparation
const size_t poolSize = 10;
connection_pool pool(poolSize);
for (size_t i = 0; i != poolSize; ++i)
{
session &amp; sql = pool.at(i);
sql.open("postgresql://dbname=mydb");
}
// phase 2: usage from working threads
{
session sql(pool);
sql &lt;&lt; "select something from somewhere...";
} // session is returned to the pool automatically
</pre>
<p>The <code>connection_pool</code>'s constructor expects the size of the pool and internally creates an array of <code>session</code>s in the disconnected state. Later, the <code>at</code> function provides <i>non-synchronized</i> access to each element of the array. Note that this function is <i>not</i> thread-safe and exists only to make it easier to set up the pool in the initialization phase.</p>
<p>Note that it is not obligatory to use the same connection parameters for all sessions in the pool, although this will be most likely the usual case.</p>
<p>The working threads that need to <i>lease</i> a single session from the pool use the dedicated constructor of the <code>session</code> class - this constructor blocks until some session object becomes available in the pool and attaches to it, so that all further uses will be forwarded to the <code>session</code> object managed by the pool. As long as the local <code>session</code> object exists, the associated session in the pool is <i>locked</i> and no other thread will gain access to it. When the local <code>session</code> variable goes out of scope, the related entry in the pool's internal array is released, so that it can be used by other threads. This way, the connection pool guarantees that its session objects are never used by more than one thread at a time.</p>
<p>Note that the above scheme is the simplest way to use the connection pool, but it is also constraining in the fact that the <code>session</code>'s constructor can <i>block</i> waiting for the availability of some entry in the pool. For more demanding users there are also low-level functions that allow to lease sessions from the pool with timeout on wait. Please consult the <a href="reference.html">reference</a> for details.</p>
<table class="foot-links" border="0" cellpadding="2" cellspacing="2">
<tr>
<td class="foot-link-left">
<a href="statements.html">Previous (Statements, procedures and transactions)</a>
</td>
<td class="foot-link-right">
<a href="boost.html">Next (Boost)</a>
</td>
</tr>
</table>
<p class="copyright">Copyright &copy; 2004-2008 Maciej Sobczak, Stephen Hutton</p>
</body>
</html>

View File

@@ -1,146 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en'>
<head>
<meta content="text/html; charset=ISO-8859-1" http-equiv="content-type" />
<link rel="stylesheet" type="text/css" href="style.css" />
<title>SOCI - queries</title>
</head>
<body>
<p class="banner">SOCI - The C++ Database Access Library</p>
<h2>Queries</h2>
<h3>Simple SQL statements</h3>
<p>In many cases, the SQL query is intended to be executed only once,
which means that statement parsing and execution can go together.
The <code>session</code> class provides a special <code>once</code>
member, which triggers parsing and execution of such one-time
statements:</p>
<pre class="example">
sql.once &lt;&lt; "drop table persons";
</pre>
<p>For shorter syntax, the following form is also allowed:</p>
<pre class="example">
sql &lt;&lt; "drop table persons";
</pre>
<p>The IOStream-like interface is exactly what it looks like, so that
the
statement text can be composed of many parts, involving anything that
is <i>streamable</i> (including custom classes, if they have
appropriate <code>operator&lt;&lt;</code>):</p>
<pre class="example">
string tableName = "persons";
sql &lt;&lt; "drop table " &lt;&lt; tableName;
int id = 123;
sql &lt;&lt; "delete from companies where id = " &lt;&lt; id;
</pre>
<h3>Query transformation</h3>
<p>In SOCI 3.2.0, query transformation mechanism was introduced.</p>
<p>Query transformation is specified as user-defined unary function or callable
function object with input parameter of type <code>std::string</code> which
returns object of type <code>std::string</code> as well.</p>
<p>The query transformation function is registered for current database session
using dedicated <code>session::set_query_transformation</code> method.
Then, the transformation function is called with query string as argument
just before the query is sent to database backend for execution or for
preparation.</p>
<p>For one-time statements, query transformation is performed before
each execution of statement. For prepared statements, query is transformed
only once, before preparation, regardless how many times it is executed.</p>
<p>A few short examples how to use query transformation:</p>
<ul><li>defined as free function:</li></ul>
<pre class="example">
std::string less_than_ten(std::string query)
{
return query + " WHERE price < 10";
}
session sql(postgresql, "dbname=mydb");
sql.set_query_transformation(less_than_ten);
sql &lt;&lt; "DELETE FROM item";
</pre>
<ul><li>defined as function object:</li></ul>
<pre class="example">
struct order : std::unary_function&lt;std::string, std::string&gt;
{
order(std::string const& by) : by_(by) {}
result_type operator()(argument_type query) const
{
return query + " ORDER BY " + by_;
}
std::string by_;
};
char const* query = "SELECT * FROM product";
sql.set_query_transformation(order("price");
sql &lt;&lt; query;
sql.set_query_transformation(order("id");
sql &lt;&lt; query;
</pre>
<ul><li>defined as lambda function (since C++11):</li></ul>
<pre class="example">
std::string dep = "sales";
sql.set_query_transformation(
[&dep](std::string const& query) {
return query + " WHERE department = '" + dep + "'";
});
sql &lt;&lt; "SELECT * FROM employee";
</pre>
<p>Query transformations enable users with simple mechanism to apply extra
requirements to or interact with SQL statement being executed and that is
without changing the SQL statement itself which may be passed from different
parts of application.</p>
<p>For example, the query transformation may be used to:</p>
<ul>
<li>modify or add clauses of SQL statements (i.e. <code>WHERE</code>
clause with new condition)</li>
<li>prefix table names with new schema to allow namespaces switch</li>
<li>validate SQL statements</li>
<li>perform sanitization checking for any unverified input</li>
<li>apply database-specific features like add optimization hints to SQL
statements (i.e. <code>SELECT /*+RULE*/ A FROM C</code> in Oracle 9)</li>
</ul>
<p>Query transformation mechanism can also be considered for similar uses as
<code>prefix_with</code> function from
<a href="http://docs.sqlalchemy.org/en/latest/core/expression_api.html">SQLAlchemy Expressions API</a>.</p>
<table class="foot-links" border="0" cellpadding="2" cellspacing="2">
<tr>
<td class="foot-link-left">
<a href="connections.html">Previous (Connections)</a>
</td>
<td class="foot-link-right">
<a href="exchange.html">Next (Exchanging data)</a>
</td>
</tr>
</table>
<p class="copyright">Copyright &copy; 2013 Mateusz Loskot</p>
<p class="copyright">Copyright &copy; 2004-2008 Maciej Sobczak, Stephen Hutton</p>
</body>
</html>

View File

@@ -1,313 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en'>
<head>
<meta content="text/html; charset=ISO-8859-1" http-equiv="content-type" />
<link rel="stylesheet" type="text/css" href="style.css" />
<title>SOCI - rationale</title>
</head>
<body>
<p class="banner">SOCI - The C++ Database Access Library</p>
<h2>Rationale FAQ</h2>
<p>This part of the documentation is supposed to gather in a single place
the usual questions (and answers) about SOCI with regard to the design
decisions that have shaped it.</p>
<h3>Q: Why "SOCI"?</h3>
<p>SOCI was initially developed in the environment where Oracle was the
main database technology in use. As a wrapper for the native OCI API
(Oracle Call Interface), the name "Simple Oracle Call Interface" was
quite obvious - until the 2.0 release, when the internal architecture
was largely redesigned to allow the use of <i>backends</i> that support other
database servers. We have kept the same name to indicate that Oracle is
the main supported technology in the sense
that the library includes only those features that were naturally
implemented in
Oracle. With the 2.1 release of the library, two new backends were
added (MySQL and SQLite3) and we decided to drop the original full name
so that new users looking for a library supporting any of these simpler
libraries are not discouraged by seeing "Oracle" somewhere in the name.
The other possible interpretation was "Syntax Oriented Call Interface",
which stresses the fact that SOCI was built to support the most natural
and easy interface for the user that is similar to the Embedded SQL
concept (see below). But on the other hand, SOCI also provides other
features (like object-relational mapping) and as a whole it is not just
"emulator" of the Embedded SQL. With all these considerations in mind,
SOCI is just "SOCI - The C++ Database Access Library".</p>
<p>Still, Oracle is considered to be the main driving server technology in
terms of the set of features that are supported by the library. This
also means that backends for other servers might need to
work around some of the imposed idioms and protocols, but already
available and well-working PostgreSQL, MySQL and SQLite3 backends show
that it's actually not that
bad and the abstractions provided by the library are actually very
universal. Of
course, some of the features that were provided for Oracle might not be
supported for all other servers, but we think that it's better to have
one leading technology (where at least one group is fully happy)
instead of some "common denominator" for all databases (where <i>nobody</i> is happy).</p>
<h3>Q: Where the basic SOCI syntax comes from?</h3>
<p>The basic SOCI syntax was inspired by the Embedded SQL, which is part
of the SQL standard, supported by the major DB technologies and even
available as built-in part of the languages used in some DB-oriented
integrated
development environments. The term "Embedded SQL" is enough for Google
to spit millions of references - one of the typical examples is:</p>
<pre class="example">
{
int a;
/* ... */
EXEC SQL SELECT salary INTO :a
FROM Employee
WHERE SSN=876543210;
/* ... */
printf("The salary is %d\n", a);
/* ... */
}
</pre>
<p>The above is not a regular C (nor C++) code, of course. It's the mix of
C and SQL and there is a separate, specialized preprocessor needed to
convert it to something that the actual C (or C++) compiler will be
able to understand. This means that the compilation of the program
using embedded SQL is two-phase: preprocess the embedded SQL part and
compile the result. This two-phase development is quite troublesome,
especially when it comes to debugging. Yet, the advantage of it is that
the code expresses the programmer's intents in a very straightforward
way: read something from the database and put it into the local
variable. Just like that.</p>
<p>The SOCI library was born as an anwer to the following question: is it
possible to have the same expressive power without the disadvantages of
two-phase builds?</p>
<p>The following was chosen to be the basic SOCI syntax that can mirror
the above Embedded SQL example:</p>
<pre class="example">
int a;
sql &lt;&lt; "SELECT salary FROM Employee WHERE SSN=876543210", into(a);
</pre>
<p>(as you see, SOCI changes the order of elements a little bit, so that
the SQL query is separate and not mixed with other elements)</p>
<p>Apart from mimicking the Embedded SQL techniques in the regular, fully
standard C++ code, the above syntax has the following benefit: it is
<i>minimal</i> with respect to what has to
be said. Every single piece above is needed and expresses something
important, like:</p>
<ul>
<li>which session should be used (the client can be connected to many
databases at the same time) - here, the <code>sql</code> object
encapsulates the session,</li>
<li>what SQL query should be executed - here, it's the string
literal, but it could be also a <code>std::string</code> variable,</li>
<li>where to put the result - here, the local variable <code>a</code>
will receive the result.</li>
</ul>
<p>Everything else is just a couple of operators that allow to treat the
whole as a single expression. It's rather difficult to remove anything
from this example.</p>
<p>The fact that the basic SOCI syntax is minimal (but without being
obscure at the same time, see below) means that the programmer does not
need to bother with unnecessary noise that some other database
libraries impose. We hope that after having written one line of code
like above by themselves, most programmers will react with something
like "how obvious!" instead of "how advanced!".</p>
<h3>Q: Why should I use SQL queries as strings in my program? I prefer the query to be generated or composed piece-by-piece by separate functions.</h3>
<p>First, you don't need to use SQL queries as string literals. In bigger
projects it is a common practice to store SQL queries externally (in a
file, or in a... database) and load them before use. This means that
they are not necessarily expected to appear in the program code, as
they do in our simple code examples and the advantage of separating
them from the source code of the main program is, among others, the
possibility to optimize and tune the SQL queries without recompilation
and relinking of the whole program.</p>
<p>What is the most important, though, is that SOCI does not try to mess
with the
text of the query (apart from very few cases), which means that the
database server will get exactly the same text of the query as is used
in the program. The advantage of this is that there is no new SQL-like
(or even SQL-<i>un</i>like)
syntax that you would need to learn, and also that it's much easier to
convince a typical
DBA to help with SQL tuning or other specialized activities, if he is
given the material in the form that is not polluted with any foreign
abstractions.</p>
<h3>Q: Why not some stream-like interface, which is well-known to all C++ programmers?</h3>
<p>An example of the stream-like interface might be something like this
(this is imaginary syntax, not supported by SOCI):</p>
<pre class="example">
sql.exec("select a, b, c from some_table");
while (!sql.eof())
{
int a, b, c;
sql &gt;&gt; a &gt;&gt; b &gt;&gt; c;
// ...
}
</pre>
<p>We think that the data stored in the relational database should be
treated as a set of relations - which is exactly what it is. This means
that what is read from the database as a result of some SQL query is a
<i>set of rows</i>. This set might be
ordered, but it is still a set of rows, not a uniformly flat list of values.
This distinction might seem to be unnecessarily low-level and that the
uniform stream-like presentation of data is more preferable, but it's
actually the other way round - the set of rows is something more
structured - and that structure was <i>designed</i>
into the database - than the flat stream and
is therefore less prone to programming errors like miscounting the
number of values that is expected in each row.</p>
<p>Consider the following programming error:</p>
<pre class="example">
sql.exec("select a, b from some_table"); // only TWO columns
while (!sql.eof())
{
int a, b, c;
sql &gt;&gt; a &gt;&gt; b &gt;&gt; c; // this causes "row-tearing"
// ...
}
</pre>
<p><i>"How to detect the end of each line in a file"</i> is a common beginner's question that
relates to the use of IOStreams - and this
common question clearly shows that for the record-oriented data the
stream is not an optimal abstraction. Of course, we don't claim that
IOStreams is bad - but we do insist that the record-oriented data is
better manipulated in a way that is also record-aware.</p>
<p>Having said that, we <i>have</i> provided some form of the stream-like
interface, but with the important limitation that the stream is always bound to the
single row, so that the row-tearing effect is not possible. In other words,
data returned from the database is still structured into rows, but each row can be
separately traversed like a stream. We hope that it provides a good balance between
convenience and code safety.</p>
<h3>Q: Why use indicators instead of some special value to discover that something is null?</h3>
<p>Some programmers are used to indicating the null value by using some
special (which means: "unlikely" to be ever used) value - for example,
to use the smallest integer value to indicate null integer. Or to use
empty string to indicate null string. And so on.</p>
<p>We think that it's <i>completely wrong</i>. Null (in the database sense) is an
information <i>about</i> the data. It describes the <i>state</i> of the data and if it's null,
then there's <i>no data at all</i>.
Nothing. Null. It does not make any sense to talk about some special
value if in fact there is <i>no</i>
value at all - especially if we take into account that, for example, the
smallest integer value (or whatever else you choose as the "special"
value) might not be <i>that</i>
special in the given application or domain.</p>
<p>Thus, SOCI uses a separate indicators to describe the state of
exchanged data. It also has an additional benefit of allowing the
library to convey more than two states (null and not null). Indeed, the
SOCI library uses indicators also to report that the data was read, but
truncated (this applies to strings when reading to fixed-length
character arrays). Truncation is also an information about the data and
as such it's better to have it in addition to the data, not as part of
it.</p>
<p>Having said that, it is important to point at the <a href="boost.html">Integration with Boost</a>
that allows to use <code>boost::optional&lt;T&gt;</code> to conveniently pack together
the data and the information about its state.</p>
<h3>Q: Overloaded comma operator is just obfuscation, I don't like it.</h3>
<p>Well, consider the following:</p>
<p>"Send the query X to the server Y <i>and</i> put result into variable Z."</p>
<p>Above, the "and" plays a role of the comma. Even if overloading the
comma operator is not a very popular practice in C++, some libraries do
this, achieving terse and easy to learn syntax. We are pretty sure that
in SOCI the comma operator was overloaded with a good effect.</p>
<h3>Q: The <code>operator&lt;&lt;</code> provides a bad abstraction for the "input" statements.</h3>
<p>Indeed, the <code>operator&lt;&lt;</code> in the basic SOCI syntax
shows that something (the query) is <i>sent</i> somewhere (to the server).
Some people don't like this, especially when the "select" statements
are involved. If the high-level idea is to <i>read</i>
data from somewhere, then <code>operator&lt;&lt;</code>
seems unintuitive to the die-hard IOStreams users. The fact is,
however, that the code containing SQL statement already indicates
that there is a client-server relationship with some other software
component (very likely remote). In such code it does not make any sense
to pretend that the communication is one-way only, because it's clear
that even the "select" statements need to be <i>sent</i> somewhere. This approach is
also more uniform and allows to cover other statements like "drop
table" or alike, where no data is expected to be exchanged at all (and
therefore the IOStreams analogies for data exchange have no sense at
all). No matter what is the kind of the SQL statement, it is <i>sent</i>
to the server and this
"sending" justifies the choice of <code>operator&lt;&lt;</code>.</p>
<p>Using different operators (<code>operator&gt;&gt;</code> and <code>operator&lt;&lt;</code>)
as a way of distinguishing between different high-level ideas
(<i>reading</i> and <i>writing</i> from the data store,
respectively) does make sense on much higher level of abstraction,
where the SQL statement itself is already hidden - and we do encourage
programmers to use SOCI for implementing such high-level abstractions.
For this, the object-relational mapping facilities available in SOCI
might prove to be a valuable tool as well, as an effective bridge
between the low-level world of SQL statements and the high-level world
of user-defined abstract data types.</p>
<h3>Q: Why the Boost license?</h3>
<p>We decided to use the <a target="_blank"
href="http://www.boost.org/LICENSE_1_0.txt">Boost license</a>, because
it's well recognized in the C++ community, allows us to keep our
minimum copyrights, and at the same time allows SOCI to be safely used
in commercial projects, without imposing concerns (or just plain
uncertainty) typical to other open source licenses, like GPL. We also
hope that by choosing the Boost license we have made the life easier
for both us and our users. It saves us from answering law-related
questions that were already answered on the <a target="_blank"
href="http://www.boost.org/more/license_info.html">Boost license info
page</a> and it should also give more confidence to our users -
especially to those of them, who already accepted the conditions of the
Boost license - the just have one license less to analyze.</p>
<p>Still, if for any reason the conditions of this license are not
acceptable, we encourage the users to contact us directly (see <a
target="_blank" href="http://soci.sourceforge.net/people.html">links</a>
on the relevant SOCI page) to discuss any remaining concerns.</p>
<table class="foot-links" border="0" cellpadding="2" cellspacing="2">
<tr>
<td class="foot-link-left">
<a href="backends.html">Previous (Backends reference)</a>
</td>
<td class="foot-link-right">
<a href="backends/index.html">Next (Existing backends)</a>
</td>
</tr>
</table>
<p class="copyright">Copyright &copy; 2004-2006 Maciej Sobczak, Stephen Hutton</p>
</body>
</html>

View File

@@ -1,963 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en'>
<head>
<meta content="text/html; charset=ISO-8859-1" http-equiv="content-type" />
<link rel="stylesheet" type="text/css" href="style.css" />
<title>SOCI - reference</title>
</head>
<body>
<p class="banner">SOCI - The C++ Database Access Library</p>
<h2>Client interface reference</h2>
<div class="navigation">
<a href="#commontypes">commonly used types</a><br />
<a href="#session">class session</a><br />
<a href="#parameters">class connection_parameters</a><br />
<a href="#pool">class connection_pool</a><br />
<a href="#transaction">class transaction</a><br />
<a href="#into">function into</a><br />
<a href="#use">function use</a><br />
<a href="#statement">class statement</a><br />
<a href="#procedure">class procedure</a><br />
<a href="#typeconversion">class type_conversion</a><br />
<a href="#row">class row</a><br />
<a href="#columnproperties">class column_properties</a><br />
<a href="#values">class values</a><br />
<a href="#blob">class blob</a><br />
<a href="#rowid">class rowid</a><br />
<a href="#backendfactory">class backend_factory</a><br /><br />
<a href="#simpleclient">Simple client interface</a><br />
</div>
<p>The core client interface is a set of classes and free functions declared in
the <code>soci.h</code> header file. All names are dbeclared in the <code>soci</code>
namespace.</p>
<p>There are also additional names declared in the <code>soci::details</code>
namespace, but they are not supposed to be directly used by the users
of the library and are therefore not documented here. When such types
are used in the declarations that are part of the "public" interface,
they are replaced by "IT", which means "internal type". Types related
to the backend interface are named here, but documented on the <a
href="backends.html">next page</a>.</p>
<h3 id="commontypes">commonly used types</h3>
<p>The following types are commonly used in the rest of the interface:</p>
<pre class="example">
// data types, as seen by the user
enum data_type { dt_string, dt_date, dt_double, dt_integer, dt_long_long, dt_unsigned_long_long };
// the enum type for indicator variables
enum indicator { i_ok, i_null, i_truncated };
// the type used for reporting exceptions
class soci_error : public std::runtime_error { /* ... */ };
</pre>
<p>The <code>data_type</code> type defines the basic SOCI data types.
User provided data types need to be associated with one of these basic
types.</p>
<p>The <code>indicator</code> type defines the possible states of data.</p>
<p>The <code>soci_error</code> type is used for error reporting.</p>
<h3 id="session">class session</h3>
<p>The <code>session</code> class encapsulates the connection to the
database.</p>
<pre class="example">
class session
{
public:
session();
explicit session(connection_parameters const &amp; parameters);
session(backend_factory const &amp; factory, std::string const &amp; connectString);
session(std::string const &amp; backendName, std::string const &amp; connectString);
explicit session(std::string const &amp; connectString);
explicit session(connection_pool &amp; pool);
~session();
void open(backend_factory const &amp; factory, std::string const &amp; connectString);
void open(std::string const &amp; backendName, std::string const &amp; connectString);
void open(std::string const &amp; connectString);
void close();
void reconnect();
void begin();
void commit();
void rollback();
<i>IT</i> once;
<i>IT</i> prepare;
template &lt;typename T&gt; <i>IT</i> operator&lt;&lt;(T const &amp; t);
bool got_data() const;
bool get_next_sequence_value(std::string const &amp; sequence, long &amp; value);
bool get_last_insert_id(std::string const &amp; table, long &amp; value);
std::ostringstream &amp; get_query_stream();
void set_log_stream(std::ostream * s);
std::ostream * get_log_stream() const;
std::string get_last_query() const;
void uppercase_column_names(bool forceToUpper);
details::session_backend * get_backend();
std::string get_backend_name() const;
};
</pre>
<p>This class contains the following members:</p>
<ul>
<li>Various constructors. The default one creates the session in the disconnected state.
The others expect the backend factory object, or the backend name, or the URL-like
composed connection string or the special parameters object containing both the backend
and the connection string as well as possibly other connection options.
The last constructor creates a session proxy associated
with the session that is available in the given pool and releases it back to the pool
when its lifetime ends. Example:
<pre class="example">
session sql(postgresql, "dbname=mydb");
session sql("postgresql", "dbname=mydb");
session sql("postgresql://dbname=mydb");
</pre>
The constructors that take backend name as string load the shared library (if not yet loaded)
with name computed as <code>libsoci_ABC.so</code> (or <code>libsoci_ABC.dll</code> on Windows)
where <code>ABC</code> is the given backend name.
</li>
<li><code>open</code>, <code>close</code> and <code>reconnect</code> functions for
reusing the same session object many times; the <code>reconnect</code> function attempts
to establish the connection with the same parameters as most recently used with constructor
or <code>open</code>. The arguments for <code>open</code> are treated in the same way as
for constructors.
</li>
<li><code>begin</code>, <code>commit</code> and <code>rollback</code>
functions for transaction control.
</li>
<li><code>once</code> member, which is used for performing <i>instant</i>
queries that do not need to be separately prepared. Example:
<pre class="example">
sql.once &lt;&lt; "drop table persons";
</pre>
</li>
<li><code>prepare</code> member, which is used for statement
preparation - the result of the statement preparation must be provided
to the constructor of the <code>statement</code> class. Example:
<pre class="example">
int i;
statement st = (sql.prepare &lt;&lt;
"insert into numbers(value) values(:val)", use(i));
</pre>
</li>
<li><code>operator&lt;&lt;</code> that is a shortcut forwarder to the
equivalent operator of the <code>once</code> member. Example:
<pre class="example">
sql &lt;&lt; "drop table persons";
</pre>
</li>
<li><code>got_data</code> returns true if the last executed query had non-empty result.</li>
<li><code>get_next_sequence_value</code> returns true if the next value of
the sequence with the specified name was generated and returned in its
second argument. Unless you can be sure that your program will use only
databases that support sequences, consider using this method in conjunction
with <code>get_last_insert_id()</code> as explained in
<a href="beyond.html#sequences">"Working with sequences"</a> section.</li>
<li><code>get_last_insert_id</code> returns true if it could retrieve the
last value automatically generated by the database for an auto-incremented
field. Notice that although this method takes the table name, for some
databases, such as Microsoft SQL Server and SQLite, this value is actually
global, so you should attempt to retrieve it immediately after performing an
insertion.</li>
<li><code>get_query_stream</code> provides direct access to the stream object that is used
to accumulate the query text and exists in particular to allow the user to imbue specific locale
to this stream.</li>
<li><code>set_log_stream</code> and <code>get_log_stream</code> functions for setting and getting
the current stream object used for basic query logging. By default, it is <code>NULL</code>, which means no logging.
The string value that is actually logged into the stream is one-line verbatim copy of the query string provided by the user,
without including any data from the <code>use</code> elements. The query is logged exactly once, before the preparation step.</li>
<li><code>get_last_query</code> retrieves the text of the last used query.</li>
<li><code>uppercase_column_names</code> allows to force all column names to uppercase in dynamic row description;
this function is particularly useful for portability, since various database servers
report column names differently (some preserve case, some change it).</li>
<li><code>get_backend</code> returns the internal
pointer to the concrete backend implementation of the session. This is
provided for advanced users that need access to the functionality that
is not otherwise available.</li>
<li><code>get_backend_name</code> is a convenience forwarder to the same function
of the backend object.</li>
</ul>
<p>See <a href="basics.html">Connections and simple queries</a> for more
examples.</p>
<h3 id="parameters">class connection_parameters</h3>
<p>The <code>connection_parameters</code> class is a simple container for the backend pointer, connection string and any other connection options. It is used together with <code>session</code> constructor and <code>open()</code> method.</p>
<pre class="example">
class connection_parameters
{
public:
connection_parameters();
connection_parameters(backend_factory const &amp; factory, std::string const &amp; connectString);
connection_parameters(std::string const &amp; backendName, std::string const &amp; connectString);
explicit connection_parameters(std::string const &amp; fullConnectString);
void set_option(const char * name, std::string const &amp; value);
bool get_option(const char * name, std::string &amp; value) const
};
</pre>
<p>The methods of this class are:</p>
<ul>
<li>Default constructor is rarely used as it creates an uninitialized
object and the only way to initialize it later is to assign another, valid,
connection_parameters object to this one.</li>
<li>The other constructors correspond to the similar constructors of the
<code>session</code> class and specify both the backend, either as a
pointer to it or by name, and the connection string.</li>
<li><code>set_option</code> can be used to set the value of an option with
the given name. Currently all option values are strings, so if you need to
set a numeric option you need to convert it to a string first. If an option
with the given name had been already set before, its old value is
overwritten.</li>
</ul>
<h3 id="pool">class connection_pool</h3>
<p>The <code>connection_pool</code> class encapsulates the thread-safe pool of connections
and ensures that only one thread at a time has access to any connection that it manages.</p>
<pre class="example">
class connection_pool
{
public:
explicit connection_pool(std::size_t size);
~connection_pool();
session &amp; at(std::size_t pos);
std::size_t lease();
bool try_lease(std::size_t &amp; pos, int timeout);
void give_back(std::size_t pos);
};
</pre>
<p>The operations of the pool are:</p>
<ul>
<li>Constructor that takes the intended size of the pool. After construction,
the pool contains regular <code>session</code> objects in disconnected state.</li>
<li><code>at</code> function that provides direct access to any given entry
in the pool. This function is <i>non-synchronized</i>.</li>
<li><code>lease</code> function waits until some entry is available (which means
that it is not used) and returns the position of that entry in the pool, marking
it as <i>locked</i>.</li>
<li><code>try_lease</code> acts like <code>lease</code>, but allows to set up a
time-out (relative, in milliseconds) on waiting. Negative time-out value means no time-out.
Returns <code>true</code> if the entry was obtained, in which case its position
is written to the <code>pos</code> parametr, and <code>false</code> if no entry
was available before the time-out.</li>
<li><code>give_back</code> should be called when the entry on the given position
is no longer in use and can be passed to other requesting thread.</li>
</ul>
<p>Note: calls to <code>lease</code> and <code>give_back</code> are automated by the
dedicated constructor of the <code>session</code> class, see above.</p>
<h3 id="transaction">class transaction</h3>
<p>The class <code>transaction</code> can be used for associating the transaction
with some code scope. It is a RAII wrapper for regular transaction operations that
automatically rolls back in its destructor <i>if</i> the transaction was not explicitly
committed before.</p>
<pre class="example">
class transaction
{
public:
explicit transaction(session & sql);
~transaction();
void commit();
void rollback();
private:
// ...
};
</pre>
<p>Note that objects of this class are not notified of other transaction related operations
that might be executed by user code explicitly or hidden inside SQL queries.
It is not recommended to mix different ways of managing transactions.</p>
<h3 id="into">function into</h3>
<p>The function <code>into</code> is used for binding local output data
(in other words, it defines where the results of the query are stored).</p>
<pre class="example">
template &lt;typename T&gt;
<i>IT</i> into(T &amp; t);
template &lt;typename T, typename T1&gt;
<i>IT</i> into(T &amp; t, T1 p1);
template &lt;typename T&gt;
<i>IT</i> into(T &amp; t, indicator &amp; ind);
template &lt;typename T, typename T1&gt;
<i>IT</i> into(T &amp; t, indicator &amp; ind, T1 p1);
template &lt;typename T&gt;
<i>IT</i> into(T &amp; t, std::vector&lt;indicator&gt; &amp; ind);
</pre>
<p>Example:</p>
<pre class="example">
int count;
sql &lt;&lt; "select count(*) from person", into(count);
</pre>
<p>See <a href="exchange.html#bind_local">Binding local data</a>
for more examples.</p>
<h3 id="use">function use</h3>
<p>The function <code>use</code> is used for binding local input data (in
other words, it defines where the parameters of the query come from).</p>
<pre class="example">
template &lt;typename T&gt;
<i>IT</i> use(T &amp; t);
template &lt;typename T, typename T1&gt;
<i>IT</i> use(T &amp; t, T1 p1);
template &lt;typename T&gt;
<i>IT</i> use(T &amp; t, indicator &amp; ind);
template &lt;typename T, typename T1&gt;
<i>IT</i> use(T &amp; t, indicator &amp; ind, T1 p1);
template &lt;typename T&gt;
<i>IT</i> use(T &amp; t, std::vector&lt;indicator&gt; const &amp; ind);
template &lt;typename T, typename T1&gt;
<i>IT</i> use(T &amp; t, std::vector&lt;indicator&gt; const &amp; ind, T1 p1);
</pre>
<p>Example:</p>
<pre class="example">
int val = 7;
sql &lt;&lt; "insert into numbers(val) values(:val)", use(val);
</pre>
<p>See <a href="exchange.html#bind_local">Binding local data</a>
for more examples.</p>
<h3 id="statement">class statement</h3>
<p>The <code>statement</code> class encapsulates the prepared statement.</p>
<pre class="example">
class statement
{
public:
statement(session &amp; s);
statement(<i>IT</i> const &amp; prep);
~statement();
statement(statement const &amp; other);
void operator=(statement const &amp; other);
void alloc();
void bind(values &amp; v);
void exchange(<i>IT</i> const &amp; i);
void exchange(<i>IT</i> const &amp; u);
void clean_up();
void prepare(std::string const &amp; query);
void define_and_bind();
bool execute(bool withDataExchange = false);
long long get_affected_rows();
bool fetch();
bool got_data() const;
void describe();
void set_row(row * r);
void exchange_for_rowset(<i>IT</i> const &amp; i);
details::statement_backend * get_backend();
};
</pre>
<p>This class contains the following members:</p>
<ul>
<li>Constructor accepting the <code>session</code> object. This can
be used for later query preparation. Example:
<pre class="example">
statement stmt(sql);
</pre>
</li>
<li>Constructor accepting the result of using <code>prepare</code>
on the <code>session</code> object, see example provided above for the
<code>session</code> class.</li>
<li>Copy operations.</li>
<li><code>alloc</code> function, which allocates necessary internal resources.</li>
<li><code>bind</code> function, which is used to bind the <code>values</code>
object - this is used in the object-relational mapping and normally
called automatically.</li>
<li>exchange functions for registering the binding of local data -
they expect the result of calling the <code>into</code> or <code>use</code>
functions and are normally invoked automatically.</li>
<li><code>clean_up</code> function for cleaning up resources, normally
called automatically.</li>
<li><code>prepare</code> function for preparing the statement for
repeated execution.</li>
<li><code>define_and_bind</code> function for actually executing the
registered bindings, normally called automatically.</li>
<li><code>execute</code> function for executing the statement. If its
parameter is <code>false</code> then there is no data exchange with
locally bound variables (this form should be used if later <code>fetch</code>
of multiple rows is foreseen). Returns <code>true</code> if there was at least
one row of data returned.</li>
<li><code>get_affected_rows</code> function returns the number of rows
affected by the last statement. Returns <code>-1</code> if it's not
implemented by the backend being used.</li>
<li><code>fetch</code> function for retrieving the next portion of
the result. Returns <code>true</code> if there was new data.</li>
<li><code>got_data</code> return <code>true</code> if the most recent
execution returned any rows.</li>
<li><code>describe</code> function for extracting the type
information for the result (note: no data is exchanged). This is normally
called automatically and only when dynamic resultset binding is used.</li>
<li><code>set_row</code> function for associating the <code>statement</code>
and <code>row</code> objects, normally called automatically.</li>
<li><code>exchange_for_rowset</code> as a special case for binding <code>rowset</code>
objects.</li>
<li><code>get_backend</code> function that returns the internal
pointer to
the concrete backend implementation of the statement object. This is
provided
for advanced users that need access to the functionality that is not
otherwise available.</li>
</ul>
<p>See <a href="statements.html#preparation">Statement preparation and
repeated execution</a> for example uses.</p>
<p>Most of the functions from the <code>statement</code> class
interface are called automatically, but can be also used explicitly.
See <a href="interfaces">Interfaces</a> for the description of various way to use
this interface.</p>
<h3 id="procedure">class procedure</h3>
<p>The <code>procedure</code> class encapsulates the call to the stored
procedure and is aimed for higher portability of the client code.</p>
<pre class="example">
class procedure
{
public:
procedure(<i>IT</i> const &amp; prep);
bool execute(bool withDataExchange = false);
bool fetch();
bool got_data() const;
};
</pre>
<p>The constructor expects the result of using <code>prepare</code>
on the <code>session</code> object.</p>
<p>See <a href="statements.html#procedures">Stored procedures</a> for
examples.</p>
<h3 id="typeconversion">class type_conversion</h3>
<p>The <code>type_conversion</code> class is a traits class that is
supposed to be provided (specialized) by the user for defining
conversions to and from one of the basic SOCI types.</p>
<pre class="example">
template &lt;typename T&gt;
struct type_conversion
{
typedef T base_type;
static void from_base(base_type const &amp; in, indicator ind, T &amp; out);
static void to_base(T const &amp; in, base_type &amp; out, indicator &amp; ind);
};
</pre>
<p>Users are supposed to properly implement the <code>from_base</code> and <code>to_base</code>
functions in their specializations of this template class.</p>
<p>See <a href="exchange.html#custom_types">Extending
SOCI to support custom (user-defined) C++ types</a>.</p>
<h3 id="row">class row</h3>
<p>The <code>row</code> class encapsulates the data and type information
retrieved for the single row when the dynamic rowset binding is used.</p>
<pre class="example">
class row
{
public:
row();
~row();
void uppercase_column_names(bool forceToUpper);
std::size_t size() const;
indicator get_indicator(std::size_t pos) const;
indicator get_indicator(std::string const &amp; name) const;
column_properties const &amp; get_properties (std::size_t pos) const;
column_properties const &amp; get_properties (std::string const &amp; name) const;
template &lt;typename T&gt;
T get(std::size_t pos) const;
template &lt;typename T&gt;
T get(std::size_t pos, T const &amp; nullValue) const;
template &lt;typename T&gt;
T get(std::string const &amp; name) const;
template &lt;typename T&gt;
T get(std::string const &amp; name, T const &amp; nullValue) const;
template &lt;typename T&gt;
row const &amp; operator&gt;&gt;(T &amp; value) const;
void skip(std::size_t num = 1) const;
void reset_get_counter() const
};
</pre>
<p>This class contains the following members:</p>
<ul>
<li>Default constructor that allows to declare a <code>row</code>
variable.</li>
<li><code>uppercase_column_names</code> - see the same function in the <code>session</code> class.</li>
<li><code>size</code> function that returns the number of columns in
the row.</li>
<li><code>get_indicator</code> function that returns the indicator value
for the given column (column is specified by position - starting from 0
- or by name).</li>
<li><code>get_properties</code> function that returns the properties
of the column given by position (starting from 0) or by name.</li>
<li><code>get</code> functions that return the value of the column
given by position or name. If the column contains null, then these
functions either return the provided "default" <code>nullValue</code>
or throw an exception.</li>
<li><code>operator&gt;&gt;</code> for convenience stream-like
extraction interface. Subsequent calls to this function are equivalent
to calling <code>get</code> with increasing position parameter,
starting from the beginning.</li>
<li><code>skip</code> and <code>reset_get_counter</code> allow to change the
order of data extraction for the above operator.</li>
</ul>
<p>See <a href="exchange.html#dynamic">Dynamic resultset binding</a> for
examples.</p>
<h3 id="columnproperties">class column_properties</h3>
<p>The <code>column_properties</code> class provides the type and name
information about the particular column in a rowset.</p>
<pre class="example">
class column_properties
{
public:
std::string get_name() const;
data_type get_data_type() const;
};
</pre>
<p>This class contains the following members:</p>
<ul>
<li><code>get_name</code> function that returns the name of the column.</li>
<li><code>get_data_type</code> that returns the type of the column.</li>
</ul>
<p>See <a href="exchange.html#dynamic">Dynamic resultset binding</a> for
examples.</p>
<h3 id="values">class values</h3>
<p>The <code>values</code> class encapsulates the data and type
information and is used for object-relational mapping.</p>
<pre class="example">
class values
{
public:
values();
void uppercase_column_names(bool forceToUpper);
indicator get_indicator(std::size_t pos) const;
indicator get_indicator(std::string const &amp; name) const;
template &lt;typename T&gt;
T get(std::size_t pos) const;
template &lt;typename T&gt;
T get(std::size_t pos, T const &amp; nullValue) const;
template &lt;typename T&gt;
T get(std::string const &amp; name) const;
template &lt;typename T&gt;
T get(std::string const &amp; name, T const &amp; nullValue) const;
template &lt;typename T&gt;
values const &amp; operator&gt;&gt;(T &amp; value) const;
void skip(std::size_t num = 1) const;
void reset_get_counter() const;
template &lt;typename T&gt;
void set(std::string const &amp; name, T const &amp; value, indicator indic = i_ok);
template &lt;typename T&gt;
void set(const T &amp; value, indicator indic = i_ok);
template &lt;typename T&gt;
values &amp; operator&lt;&lt;(T const &amp; value);
};
</pre>
<p>This class contains the same members as the <code>row</code> class (with the same meaning)
plus:</p>
<ul>
<li><code>set</code> function for storing values in named columns or in subsequent positions.</li>
<li><code>operator&lt;&lt;</code> for convenience.</li>
</ul>
<p>See <a href="exchange.html#object_relational">Object-relational mapping</a>
for examples.</p>
<h3 id="blob">class blob</h3>
<p>The <code>blob</code> class encapsulates the "large object"
functionality.</p>
<pre class="example">
class blob
{
public:
explicit blob(session &amp; s);
~blob();
std::size_t getLen();
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);
details::blob_backend * get_backend();
};
</pre>
<p>This class contains the following members:</p>
<ul>
<li>Constructor associating the <code>blob</code> object with the <code>session</code> object.</li>
<li><code>get_len</code> function that returns the size of the BLOB
object.</li>
<li><code>read</code> function that reads the BLOB data into provided
buffer.</li>
<li><code>write</code> function that writes the BLOB data from
provided buffer.</li>
<li><code>append</code> function that appends to the existing BLOB
data.</li>
<li><code>trim</code> function that truncates the existing data to
the new length.</li>
<li><code>get_backend</code> function that returns the internal
pointer to
the concrete backend implementation of the BLOB object. This is
provided
for advanced users that need access to the functionality that is not
otherwise available.</li>
</ul>
<p>See <a href="exchange.html#blob">Large objects (BLOBs)</a> for more
discussion.</p>
<h3 id="rowid">class rowid</h3>
<p>The <code>rowid</code> class encapsulates the "row identifier" object.</p>
<pre class="example">
class rowid
{
public:
explicit rowid(Session &amp; s);
~rowid();
details::rowid_backend * get_backend();
};
</pre>
<p>This class contains the following members:</p>
<ul>
<li>Constructor associating the <code>rowid</code> object with the <code>session</code>
object.</li>
<li><code>get_backend</code> function that returns the internal
pointer to
the concrete backend implementation of the <code>rowid</code> object.</li>
</ul>
<h3 id="backendfactory">class backend_factory</h3>
<p>The <code>backend_factory</code> class provides the abstract interface
for concrete backend factories.</p>
<pre class="example">
struct backend_factory
{
virtual details::session_backend * make_session(
std::string const &amp; connectString) const = 0;
};
</pre>
<p>The only member of this class is the <code>make_session</code> function
that is supposed to create concrete backend implementation of the
session object.</p>
<p>Objects of this type are declared by each backend and should be
provided to the constructor of the <code>session</code> class.
In simple programs users do not need to use this class directly, but
the example use is:</p>
<pre class="example">
backend_factory &amp; factory = postgresql;
std::string connectionParameters = "dbname=mydb";
session sql(factory, parameters);
</pre>
<h3 id="simpleclient">Simple client interface</h3>
<p>The simple client interface is provided with other languages in mind,
to allow easy integration of the SOCI library with script interpreters and those
languages that have the ability to link directly with object files using
the "C" calling convention.</p>
<p>The functionality of this interface is limited and in particular the
dynamic rowset description and type conversions are not supported in this release.
On the other hand, the important feature of this interface is that it does not
require passing pointers to data managed by the user, because all data is handled
at the SOCI side. This should make it easier to integrate SOCI with languages that
have constrained ability to understand the C type system.</p>
<p>Users of this interface need to explicitly <code>#include &lt;soci-simple.h&gt;</code>.</p>
<pre class="example">
typedef void * session_handle;
session_handle soci_create_session(char const * connectionString);
void soci_destroy_session(session_handle s);
void soci_begin(session_handle s);
void soci_commit(session_handle s);
void soci_rollback(session_handle s);
int soci_session_state(session_handle s);
char const * soci_session_error_message(session_handle s);
</pre>
<p>The functions above provide the <i>session</i> abstraction with the help of opaque handle.
The <code>soci_session_state</code> function returns <code>1</code> if there was no error
during the most recently executed function and <code>0</code> otherwise, in which
case the <code>soci_session_error_message</code> can be used to obtain a human-readable
error description.</p>
<p>Note that the only function that cannot report all errors this way is <code>soci_create_session</code>,
which returns <code>NULL</code> if it was not possible to create an internal object
representing the session. However, if the proxy object was created, but the connection
could not be established for whatever reason, the error message can be obtained in
the regular way.</p>
<pre class="example">
typedef void * statement_handle;
statement_handle soci_create_statement(session_handle s);
void soci_destroy_statement(statement_handle st);
int soci_statement_state(statement_handle s);
char const * soci_statement_error_message(statement_handle s);
</pre>
<p>The functions above create and destroy the statement object. If the statement cannot
be created by the <code>soci_create_statement</code> function, the error condition is set up in the related session object;
for all other functions the error condition is set in the statement object itself.</p>
<pre class="example">
int soci_into_string (statement_handle st);
int soci_into_int (statement_handle st);
int soci_into_long_long(statement_handle st);
int soci_into_double (statement_handle st);
int soci_into_date (statement_handle st);
int soci_into_string_v (statement_handle st);
int soci_into_int_v (statement_handle st);
int soci_into_long_long_v(statement_handle st);
int soci_into_double_v (statement_handle st);
int soci_into_date_v (statement_handle st);
</pre>
<p>These functions create new data items for storing query results (<i>into elements</i>).
These elements can be later identified by their position, which is counted from 0. For convenience,
these function return the position of the currently added element. In case of error,
<code>-1</code> is returned and the error condition is set in the statement object.</p>
<p>The <code>_v</code> versions create a <code>vector</code> into elements, which can be used
to retrieve whole arrays of results.</p>
<pre class="example">
int soci_get_into_state(statement_handle st, int position);
int soci_get_into_state_v(statement_handle st, int position, int index);
</pre>
<p>This function returns <code>1</code> if the into element at the given position has non-null value and <code>0</code> otherwise.
The <code>_v</code> version works with <code>vector</code> elements and expects an array index.</p>
<pre class="example">
int soci_into_get_size_v(statement_handle st);
void soci_into_resize_v (statement_handle st, int new_size);
</pre>
<p>The functions above allow to get and set the size of vector into element.</p>
<p>Note: the <code>soci_into_resize_v</code> always sets <i>all</i> into vectors in the given statement
to the same size, which guarantees that all vector into elements have equal size.</p>
<pre class="example">
char const * soci_get_into_string (statement_handle st, int position);
int soci_get_into_int (statement_handle st, int position);
long long soci_get_into_long_long(statement_handle st, int position);
double soci_get_into_double (statement_handle st, int position);
char const * soci_get_into_date (statement_handle st, int position);
char const * soci_get_into_string_v (statement_handle st, int position, int index);
int soci_get_into_int_v (statement_handle st, int position, int index);
long long soci_get_into_long_long_v(statement_handle st, int position, int index);
double soci_get_into_double_v (statement_handle st, int position, int index);
char const * soci_get_into_date_v (statement_handle st, int position, int index);
</pre>
<p>The functions above allow to retrieve the current value of the given into element.</p>
<p>Note: the <code>date</code> function returns the date value in the "<code>YYYY MM DD HH mm ss</code>" string format.</p>
<pre class="example">
void soci_use_string (statement_handle st, char const * name);
void soci_use_int (statement_handle st, char const * name);
void soci_use_long_long(statement_handle st, char const * name);
void soci_use_double (statement_handle st, char const * name);
void soci_use_date (statement_handle st, char const * name);
void soci_use_string_v (statement_handle st, char const * name);
void soci_use_int_v (statement_handle st, char const * name);
void soci_use_long_long_v(statement_handle st, char const * name);
void soci_use_double_v (statement_handle st, char const * name);
void soci_use_date_v (statement_handle st, char const * name);
</pre>
<p>The functions above allow to create new data elements that will be used to provide
data to the query (<i>use elements</i>). The new elements can be later identified by given name, which
must be unique for the given statement.</p>
<pre class="example">
void soci_set_use_state(statement_handle st, char const * name, int state);
</pre>
<p>The <code>soci_set_use_state</code> function allows to set the state of the given use element.
If the <code>state</code> parameter is set to non-zero the use element is considered non-null
(which is also the default state after creating the use element).</p>
<pre class="example">
int soci_use_get_size_v(statement_handle st);
void soci_use_resize_v (statement_handle st, int new_size);
</pre>
<p>These functions get and set the size of vector use elements (see comments for vector into elements above).</p>
<pre class="example">
void soci_set_use_string (statement_handle st, char const * name, char const * val);
void soci_set_use_int (statement_handle st, char const * name, int val);
void soci_set_use_long_long(statement_handle st, char const * name, long long val);
void soci_set_use_double (statement_handle st, char const * name, double val);
void soci_set_use_date (statement_handle st, char const * name, char const * val);
void soci_set_use_state_v (statement_handle st, char const * name, int index, int state);
void soci_set_use_string_v (statement_handle st, char const * name, int index, char const * val);
void soci_set_use_int_v (statement_handle st, char const * name, int index, int val);
void soci_set_use_long_long_v(statement_handle st, char const * name, int index, long long val);
void soci_set_use_double_v (statement_handle st, char const * name, int index, double val);
void soci_set_use_date_v (statement_handle st, char const * name, int index, char const * val);
</pre>
<p>The functions above set the value of the given use element, for both single and vector elements.</p>
<p>Note: the expected format for the data values is "<code>YYYY MM DD HH mm ss</code>".</p>
<pre class="example">
int soci_get_use_state (statement_handle st, char const * name);
char const * soci_get_use_string (statement_handle st, char const * name);
int soci_get_use_int (statement_handle st, char const * name);
long long soci_get_use_long_long(statement_handle st, char const * name);
double soci_get_use_double (statement_handle st, char const * name);
char const * soci_get_use_date (statement_handle st, char const * name);
</pre>
<p>These functions allow to inspect the state and value of named use elements.</p>
<p>Note: these functions are provide only for single use elements, not for vectors;
the rationale for this is that modifiable use elements are not supported for bulk operations.</p>
<pre class="example">
void soci_prepare(statement_handle st, char const * query);
int soci_execute(statement_handle st, int withDataExchange);
int soci_fetch(statement_handle st);
int soci_got_data(statement_handle st);
</pre>
<p>The functions above provide the core execution functionality for the statement object
and their meaning is equivalent to the respective functions in the core C++ interface
described above.</p>
<table class="foot-links" border="0" cellpadding="2" cellspacing="2">
<tr>
<td class="foot-link-left">
<a href="beyond.html">Previous (Beyond standard SQL)</a>
</td>
<td class="foot-link-right">
<a href="backends.html">Next (Backends reference)</a>
</td>
</tr>
</table>
<p class="copyright">Copyright &copy; 2013 Mateusz Loskot</p>
<p class="copyright">Copyright &copy; 2012 Vadim Zeitlin</p>
<p class="copyright">Copyright &copy; 2004-2006 Maciej Sobczak, Stephen Hutton</p>
</body>
</html>

View File

@@ -1,389 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en'>
<head>
<meta content="text/html; charset=ISO-8859-1" http-equiv="content-type" />
<link rel="stylesheet" type="text/css" href="style.css" />
<title>SOCI - statements, procedures and transactions</title>
</head>
<body>
<p class="banner">SOCI - The C++ Database Access Library</p>
<h2>Statements, procedures and transactions</h2>
<div class="navigation">
<a href="#preparation">Statement preparation and repeated execution</a><br />
<a href="#rowset">Rowset and iterator-based access</a><br />
<a href="#bulk">Bulk operations</a><br />
<a href="#procedures">Stored procedures</a><br />
<a href="#transactions">Transactions</a><br />
<a href="#logging">Basic logging support</a><br />
</div>
<h3 id="preparation">Statement preparation and repeated execution</h3>
<p>Consider the following examples:</p>
<pre class="example">
// Example 1.
for (int i = 0; i != 100; ++i)
{
sql &lt;&lt; "insert into numbers(value) values(" &lt;&lt; i &lt;&lt; ")";
}
// Example 2.
for (int i = 0; i != 100; ++i)
{
sql &lt;&lt; "insert into numbers(value) values(:val)", use(i);
}
</pre>
<p>Both examples will populate the table <code>numbers</code> with the
values from <code>0</code> to <code>99</code>.</p>
<p>The problem is that in both examples, not only the statement execution is
repeated 100 times, but also the statement parsing and preparation.
This means unnecessary overhead, even if some of the database servers
are likely to optimize the second case. In fact, more complicated queries are
likely to suffer in terms of lower performance, because finding the optimal
execution plan is quite expensive and here it would be needlessly repeated.</p>
<p>The following example uses the class <code>statement</code>
explicitly, by preparing the statement only once and repeating its
execution with changing data (note the use of <code>prepare</code>
member of <code>session</code> class):</p>
<pre class="example">
int i;
statement st = (sql.prepare &lt;&lt;
"insert into numbers(value) values(:val)",
use(i));
for (i = 0; i != 100; ++i)
{
st.execute(true);
}
</pre>
<p>The <code>true</code> parameter given to the <code>execute</code>
method indicates that the actual data exchange is wanted, so that the
meaning of the whole example is "prepare the statement and exchange the
data for each value of variable <code>i</code>".</p>
<div class="note">
<p><span class="note">Portability note:</span></p>
<p>The above syntax is supported for all backends, even if some database server
does not actually provide this functionality - in which case the library will internally
execute the query in a single phase, without really separating
the statement preparation from execution.</p>
<p>For PostgreSQL servers older than 8.0 it is necessary to define the
<code>SOCI_POSTGRESQL_NOPREPARE</code> macro while compiling the library
to fall back to this one-phase behaviour. Simply, pass
<code>-DSOCI_POSTGRESQL_NOPREPARE=ON</code> variable to CMake.</p>
</div>
<h3 id="rowset">Rowset and iterator-based access</h3>
<p>The <code>rowset</code> class provides an alternative means of executing queries and accessing results using STL-like iterator interface.</p>
<p>The <code>rowset_iterator</code> type is compatible with requirements defined for input iterator category and is available via <code>iterator</code> and <code>const_iterator</code> definitions in the <code>rowset</code> class.</p>
<p>The <code>rowset</code> itself can be used only with select queries.</p>
<p>The following example creates an instance of the <code>rowset</code> class and binds query results into elements of <code>int</code> type - in this query only one result column is expected. After executing the query the code iterates through the query result using <code>rowset_iterator</code>:</p>
<pre class="example">
rowset&lt;int&gt; rs = (sql.prepare &lt;&lt; "select values from numbers");
for (rowset&lt;int&gt;::const_iterator it = rs.begin(); it != rs.end(); ++it)
{
cout &lt;&lt; *it &lt;&lt; '\n';
}
</pre>
<p>Another example shows how to retrieve more complex results, where <code>rowset</code> elements are of type <code>row</code> and therefore use <a href="exchange.html#dynamic">dynamic bindings</a>:</p>
<pre class="example">
// person table has 4 columns
rowset&lt;row&gt; rs = (sql.prepare &lt;&lt; "select id, firstname, lastname, gender from person");
// iteration through the resultset:
for (rowset&lt;row&gt;::const_iterator it = rs.begin(); it != rs.end(); ++it)
{
row const&amp; row = *it;
// dynamic data extraction from each row:
cout &lt;&lt; "Id: " &lt;&lt; row.get&lt;int&gt;(0) &lt;&lt; '\n'
&lt;&lt; "Name: " &lt;&lt; row.get&lt;string&gt;(1) &lt;&lt; " " &lt;&lt; row.get&lt;string&gt;(2) &lt;&lt; '\n'
&lt;&lt; "Gender: " &lt;&lt; row.get&lt;string&gt;(3) &lt;&lt; endl;
}
</pre>
<p><code>rowset_iterator</code> can be used with standard algorithms as well:</p>
<pre class="example">
rowset&lt;string&gt; rs = (sql.prepare &lt;&lt; "select firstname from person");
std::copy(rs.begin(), rs.end(), std::ostream_iterator&lt;std::string&gt;(std::cout, "\n"));
</pre>
<p>Above, the query result contains a single column which is bound to <code>rowset</code> element of type of <code>std::string</code>. All records are sent to standard output using the <code>std::copy</code> algorithm.</p>
<h3 id="bulk">Bulk operations</h3>
<p>When using some databases, further performance improvements may be possible by having the underlying database API group operations together to reduce network roundtrips. SOCI makes such bulk operations possible by supporting <code>std::vector</code>
based types:</p>
<pre class="example">
// Example 3.
const int BATCH_SIZE = 25;
std::vector&lt;int&gt; ids;
for (int i = 0; i != BATCH_SIZE; ++i)
{
ids.push_back(i);
}
statement st = (sql.prepare &lt;&lt;
"insert into numbers(value) values(:val)",
use(ids));
for (int i = 0; i != 4; ++i)
{
st.execute(true);
}
</pre>
<p>(Of course, the size of the vector that will achieve optimum
performance will vary, depending on many environmental factors, such as
network speed.)</p>
<p>It is also possible to read all the numbers written in the above
examples:</p>
<pre class="example">
int i;
statement st = (sql.prepare &lt;&lt;
"select value from numbers order by value",
into(i));
st.execute();
while (st.fetch())
{
cout &lt;&lt; i &lt;&lt; '\n';
}
</pre>
<p>In the above example, the <code>execute</code> method is called
with the default parameter <code>false</code>. This means that the
statement should be executed, but the actual data exchange will be
performed later.</p>
<p>Further <code>fetch</code>
calls perform the actual data retrieval and cursor traversal. The
<i>end-of-cursor</i> condition is indicated by the <code>fetch</code>
function returning <code>false</code>.</p>
<p>The above code example should be treated as an idiomatic way
of reading many rows of data, <i>one at a time</i>.</p>
<p>It is further possible to select records in batches into <code>std::vector</code>
based types, with the size of the vector specifying the number of
records to retrieve in each round trip:</p>
<pre class="example">
std::vector&lt;int&gt; valsOut(100);
sql &lt;&lt; "select val from numbers", into(valsOut);
</pre>
<p>Above, the value <code>100</code> indicates that no more values
should be retrieved, even if it would be otherwise possible. If there
are less rows than asked for, the vector will be appropriately
down-sized.</p>
<p>The <code>statement::execute()</code> and <code>statement::fetch()</code>
functions can also be used to repeatedly select all rows returned by a
query into a vector based type:</p>
<pre class="example">
const int BATCH_SIZE = 30;
std::vector&lt;int&gt; valsOut(BATCH_SIZE);
statement st = (sql.prepare &lt;&lt;
"select value from numbers",
into(valsOut));
st.execute();
while (st.fetch())
{
std::vector&lt;int&gt;::iterator pos;
for(pos = valsOut.begin(); pos != valsOut.end(); ++pos)
{
cout &lt;&lt; *pos &lt;&lt; '\n';
}
valsOut.resize(BATCH_SIZE);
}
</pre>
<p>Assuming there are 100 rows returned by the query, the above code
will retrieve and print all of them. Since the output vector was
created with size 30, it will take (at least) 4 calls to <code>fetch()</code>
to retrieve all 100 values. Each call to <code>fetch()</code>
can potentially resize the vector to a size less than its initial size
- how often this happens depends on the underlying database
implementation.
This explains why the <code>resize(BATCH_SIZE)</code> operation is
needed - it is there to ensure that each time the <code>fetch()</code>
is called, the vector is ready to accept the next bunch of values.
Without this operation, the vector <i>might</i>
be getting smaller with subsequent iterations of the loop, forcing more
iterations to be performed (because <i>all</i>
rows will be read anyway), than really needed.</p>
<p>Note the following details about the above examples:</p>
<ul>
<li>After performing <code>fetch()</code>, the vector's size might
be <i>less</i> than requested, but <code>fetch()</code>
returning true means that there was <i>at least one</i> row retrieved.</li>
<li>It is forbidden to manually resize the vector to the size <i>higher</i> than it was initially (this
can cause the vector to reallocate its internal buffer and the library
can lose track of it).</li>
</ul>
<p>Taking these points under consideration, the above code example should
be treated as an idiomatic way of reading many rows by bunches of
requested size.</p>
<div class="note">
<p><span class="note">Portability note:</span></p>
<p>Actually, all supported backends guarantee that the requested
number of rows will be read with each fetch and that the vector will
never be down-sized, unless for the last fetch, when the end of rowset condition is met.
This means that the manual vector
resizing is in practice not needed - the vector will keep its size until the end of
rowset. The above idiom, however, is provided with future backends in
mind, where the constant size of the vector might be too expensive to
guarantee and where allowing <code>fetch</code> to down-size the
vector even before reaching the end of rowset might buy some
performance gains.</p>
</div>
<h3 id="procedures">Stored procedures</h3>
<p>The <code>procedure</code> class provides a convenient mechanism for
calling stored procedures:</p>
<pre class="example">
sql &lt;&lt; "create or replace procedure echo(output out varchar2,"
"input in varchar2) as "
"begin output := input; end;";
std::string in("my message");
std::string out;
procedure proc = (sql.prepare &lt;&lt; "echo(:output, :input)",
use(out, "output"),
use(in, "input"));
proc.execute(true);
assert(out == "my message");
</pre>
<div class="note">
<p><span class="note">Portability note:</span></p>
<p>The above way of calling stored procedures is provided for portability
of the code that might need it. It is of course still possible to call
procedures or functions using the syntax supported by the given
database server.</p>
</div>
<h3 id="transactions">Transactions</h3>
<p>The SOCI library provides the following members of the <code>session</code>
class for transaction management:</p>
<ul>
<li><code>void begin();</code></li>
<li><code>void commit();</code></li>
<li><code>void rollback();</code></li>
</ul>
<p>In addition to the above there is a RAII wrapper that allows to associate the transaction with the
given scope of code:</p>
<pre class="example">
class transaction
{
public:
explicit transaction(session & sql);
~transaction();
void commit();
void rollback();
private:
// ...
};
</pre>
<p>The object of class <code>transaction</code> will roll back automatically when the object is destroyed
(usually as a result of leaving the scope) <i>and</i> when the transaction was not explicitly committed before that.</p>
<p>A typical usage pattern for this class might be:</p>
<pre class="example">
{
transaction tr(sql);
sql << "insert into ...";
sql << "more sql queries ...";
// ...
tr.commit();
}
</pre>
<p>With the above pattern the transaction is committed only when the code successfully
reaches the end of block. If some exception is thrown before that, the scope will be left
without reaching the final statement and the transaction object
will automatically roll back in its destructor.</p>
<div class="note">
<p><span class="note">Portability note:</span></p>
<p>Different database servers have different policies with regard to the
implicit transaction management. Some of them start the implicit
transaction with the first DML statement and keep it open until
explicitly commited or rolled back (or closing the whole session).
Others will treat each statement as if it was a separate, auto-commited
transaction. For better compatibility, it is recommended to use the
above functions for explicit transaction management.</p>
</div>
<h3 id="logging">Basic logging support</h3>
<p>The following members of the <code>session</code> class support the basic logging functionality:</p>
<ul>
<li><code>void set_log_stream(std::ostream * s);</code></li>
<li><code>std::ostream * get_log_stream() const;</code></li>
<li><code>std::string get_last_query() const;</code></li>
</ul>
<p>The first two functions allow to set the user-provided output stream object for logging. The <code>NULL</code> value, which is the default, means that there is no logging. An example use might be:</p>
<pre class="example">
session sql(oracle, "...");
ofstream file("my_log.txt");
sql.set_log_stream(&amp;file);
// ...
</pre>
<p>Each statement logs its query string before the preparation step (whether explicit or implicit) and therefore logging is effective whether the query succeeds or not. Note that each prepared query is logged only once, independent on how many times it is executed.</p>
<p>The <code>get_last_query</code> function allows to retrieve the last used query.</p>
<table class="foot-links" border="0" cellpadding="2" cellspacing="2">
<tr>
<td class="foot-link-left">
<a href="exchange.html">Previous (Exchanging data)</a>
</td>
<td class="foot-link-right">
<a href="multithreading.html">Next (Multithreading)</a>
</td>
</tr>
</table>
<p class="copyright">Copyright &copy; 2010 Mateusz Loskot</p>
<p class="copyright">Copyright &copy; 2004-2011 Maciej Sobczak, Stephen Hutton</p>
</body>
</html>

View File

@@ -1,81 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en'>
<head>
<meta content="text/html; charset=ISO-8859-1" http-equiv="content-type" />
<link rel="stylesheet" type="text/css" href="style.css" />
<title>SOCI - structure</title>
</head>
<body>
<p class="banner">SOCI - The C++ Database Access Library</p>
<h2>Structure</h2>
<div class="diagram">
<img alt="Library structure diagram" src="structure.png" />
</div>
<p>The picture above presents the structure of the library, together with its
clients and servers. The boxes filled with cyan represent components that
are part of the library distribution.</p>
<p>The SOCI library is extensible in the following ways:</p>
<ul>
<li>More backends can be added to target various database servers.</li>
<li>More interfaces can be defined on top of common backend interface.</li>
<li>Other languages can use the <i>simple interface</i>, which was designed specifically
for the "C" calling convention to ensure easy binding.</li>
</ul>
<p>The core part of the library and the backend interface definition are
placed in the <code>core</code> directory of the library distribution.
The <code>soci-backend.h</code> file is an internal abstract
interface to the actual backends, which are needed to perform
operations on the given database server. Normally, the C++ client
program needs to interface with the <code>soci.h</code> header and the
header(s) relevant to the given backend(s) (for example, <code>soci-oracle.h</code>),
although with dynamic backend loading this can be avoided.
It is possible for the same program to use many backends at the same
time.</p>
<p>Everything in SOCI is
declared in the namespace <code>soci</code>.
All code examples presented in this documentation assume that your code
begins with something
like:</p>
<pre class="example">
#include "soci.h"
// other includes if necessary
using namespace soci;
// ...
</pre>
<div class="note">
<p><span class="note">Note:</span>
In simple programs, <code>#include</code> for the relevant
backend is needed only in the file where the <code>session</code>
object is created with explicit name of the backend factory.
The example program on the <a href="index.html">previous
page</a> shows the appropriate <code>#include</code> directive for the
Oracle backend. It is also possible to name backends at run-time
as part of the connection string, in which case no backend-specific
<code>#include</code> directive is necessary.</p>
</div>
<table class="foot-links" border="0" cellpadding="2" cellspacing="2">
<tr>
<td class="foot-link-left">
<a href="index.html">Previous (Contents)</a>
</td>
<td class="foot-link-right">
<a href="installation.html">Next (Installation)</a>
</td>
</tr>
</table>
<p class="copyright">Copyright &copy; 2010 Mateusz Loskot</p>
<p class="copyright">Copyright &copy; 2004-2011 Maciej Sobczak, Stephen Hutton</p>
</body>
</html>

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

View File

@@ -1,118 +0,0 @@
body
{
background-color: white;
color: black;
margin-left: 100px;
margin-right: 100px;
font-family: arial, sans-serif;
font-size: small;
}
p.banner
{
font-size: x-large;
font-weight: bold;
font-stretch: expanded;
border-bottom-color: black;
border-bottom-style: solid;
border-bottom-width: 1px;
padding-bottom: 5px;
}
div.navigation { }
div.navigation-indented
{
margin-left: 40px;
}
div.diagram
{
text-align: center;
}
div.note
{
border-color: black;
border-style: dotted;
border-width: 1px;
margin-top: 20px;
padding-left: 20px;
padding-right: 20px;
}
span.note
{
font-size: large;
font-weight: bold;
}
code
{
/* font-weight: bold; */
background-color: white;
color: #8B0000;
/* font-size: large; */
}
pre.example
{
background-color: #F0F0F0;
color: black;
border-width: 1px;
border-style: dashed;
border-color: blue;
padding: 10px 10px 10px 10px;
}
table.foot-links
{
width: 100%;
padding-top: 20px;
}
td.foot-link-left
{
text-align: left;
}
td.foot-link-right
{
text-align: right;
}
table.cmake-variables
{
width: 100%;
/*border: solid;*/
}
caption.cmake-variables
{
background-color: #E0E0E0;
font-style: italic;
font-weight: bold;
}
td.variable-name
{
width: 25%;
}
td.variable-type
{
width: 7%;
}
tr.header
{
/* background-color: #F0F0F0; */
}
p.copyright
{
border-top-color: black;
border-top-style: solid;
border-top-width: 1px;
padding-top: 5px;
}

273
docs/backends.md Normal file
View File

@@ -0,0 +1,273 @@
## Backends reference
This part of the documentation is provided for those who want towrite (and contribute!) their own backends. It is anyway recommendedthat authors of new backend see the code of some existing backend forhints on how things are really done.
The backend interface is a set of base classes that the actual backendsare supposed to specialize. The main SOCI interface uses only theinterface and respecting the protocol (for example, the order offunction calls) described here. Note that both the interface and theprotocol were initially designed with the Oracle database in mind,
which means that whereas it is quite natural with respect to the way Oracle API
(OCI) works, it might impose some implementation burden on otherbackends, where things are done differently and therefore have to beadjusted, cached, converted, etc.
The interface to the common SOCI interface is defined in the `core/soci-backend.h` header file. This file is dissected below.
All names are defined in either `soci` or `soci::details` namespace.
// data types, as seen by the user
enum data_type
{
dt_string, dt_date, dt_double, dt_integer, dt_long_long, dt_unsigned_long_long
};
// the enum type for indicator variables
enum indicator { i_ok, i_null, i_truncated };
// data types, as used to describe exchange format
enum exchange_type
{
x_char,
x_stdstring,
x_short,
x_integer,
x_long_long,
x_unsigned_long_long,
x_double,
x_stdtm,
x_statement,
x_rowid,
x_blob
};
struct cstring_descriptor
{
cstring_descriptor(char * str, std::size_t bufSize)
: str_(str), bufSize_(bufSize) {}
char * str_;
std::size_t bufSize_;
};
// actually in error.h:
class soci_error : public std::runtime_error
{
public:
soci_error(std::string const & msg);
};
The `data_type` enumeration type defines all types that form the core type support for SOCI. The enum itself can be used by clients when dealing with dynamic rowset description.
The `indicator` enumeration type defines all recognized *states* of data. The `i_truncated` state is provided for the case where the string is retrieved from the database into the char buffer that is not long enough to hold the whole value.
The `exchange_type` enumeration type defines all possible types that can be used with the `into` and `use` elements.
The `cstring_descriptor` is a helper class that allows to store the address of `char` buffer together with its size. The objects of this class are passed to the backend when the `x_cstring` type is involved.
The `soci_error` class is an exception type used for database-related (and also usage-related) errors. The backends should throw exceptions of this or derived type only.
class standard_into_type_backend
{
public:
standard_into_type_backend() {}
virtual ~standard_into_type_backend() {}
virtual void define_by_pos(int& position, void* data, exchange_type type) = 0;
virtual void pre_fetch() = 0;
virtual void post_fetch(bool gotData, bool calledFromFetch, indicator* ind) = 0;
virtual void clean_up() = 0;
};
The `standard_into_type_back_end` class implements the dynamic interactions with the simple (non-bulk) `into` elements. The objects of this class (or, rather, of the derived class implemented by the actual backend) are created by the `statement` object when the `into` element is bound - in terms of lifetime management, `statement` is the master of this class.
* `define_by_pos` - Called when the `into` element is bound, once and before the statement is executed. The `data` pointer points to the variable used for `into` element (or to the `cstring_descriptor` object, which is artificially created when the plain `char` buffer is used for data exchange). The `position` parameter is a "column number", assigned by the library. The backend should increase this parameter, according to the number of fields actually taken (usually 1).
* `pre_fetch` - Called before each row is fetched.
* `post_fetch` - Called after each row is fetched. The `gotData` parameter is `true` if the fetch operation really retrievedsome data and `false` otherwise; `calledFromFetch` is `true` when the call is from the fetch operation and `false` if it is from the execute operation (this is also the case for simple, one-time queries). In particular, `(calledFromFetch && !gotData)` indicates that there is an end-of-rowset condition. `ind` points to the indicator provided by the user, or is `NULL`, if there is no indicator.
* `clean_up` - Called once when the statement is destroyed.
The intended use of `pre_fetch` and `post_fetch` functions is to manage any internal buffer and/or data conversion foreach value retrieved from the database. If the given server supportsbinary data transmission and the data format for the given type agreeswith what is used on the client machine, then these two functions neednot do anything; otherwise buffer management and data conversionsshould go there.
class vector_into_type_backend
{
public:
vector_into_type_backend() {}
virtual ~vector_into_type_backend() {}
virtual void define_by_pos(int& position, void* data, exchange_type type) = 0;
virtual void pre_fetch() = 0;
virtual void post_fetch(bool gotData, indicator* ind) = 0;
virtual void resize(std::size_t sz) = 0;
virtual std::size_t size() = 0;
virtual void clean_up() = 0;
};
The `vector_into_type_back_end` has similar structure and purpose as the previous one, but is used for vectors (bulk data retrieval).
The `data` pointer points to the variable of type `std::vector<T>;` (and *not* to its internal buffer), `resize` is supposed to really resize the user-provided vector and `size`
is supposed to return the current size of this vector. The important difference with regard to the previous class is that `ind` points (if not `NULL`) to the beginning of the *array* of indicators. The backend should fill this array according to the actual state of the retrieved data.
* `bind_by_pos` - Called for each `use` element, once and before the statement is executed - for those `use` elements that do not provide explicit names for parameter binding. The meaning of parameters is same as in previous classes.
* `bind_by_name` - Called for those `use` elements that provide the explicit name.
* `pre_use` - Called before the data is transmitted to the server (this means before the statement is executed, which can happen many times for the prepared statement). `ind` points to the indicator provided by the user (or is `NULL`).
* `post_use` - Called after statement execution. `gotData` and `ind` have the same meaning as in `standard_into_type_back_end::post_fetch`, and this can be used by those backends whose respective servers support two-way data exchange (like in/out parameters in stored procedures).
The intended use for `pre_use` and `post_use` methods is to manage any internal buffers and/or data conversion. They can be called many times with the same statement.
class vector_use_type_backend
{
public:
virtual ~vector_use_type_backend() {}
virtual void bind_by_pos(int& position,
void* data, exchange_type type) = 0;
virtual void bind_by_name(std::string const& name,
void* data, exchange_type type) = 0;
virtual void pre_use(indicator const* ind) = 0;
virtual std::size_t size() = 0;
virtual void clean_up() = 0;
};
Objects of this type (or rather of type derived from this one) are used to implement interactions with user-provided vector (bulk) `use` elements and are managed by the `statement` object. The `data` pointer points to the whole vector object provided by the user (and *not* to its internal buffer); `ind` points to the beginning of the array of indicators (or is `NULL`). The meaning of this
interface is analogous to those presented above.
class statement_backend
{
public:
statement_backend() {}
virtual ~statement_backend() {}
virtual void alloc() = 0;
virtual void clean_up() = 0;
virtual void prepare(std::string const& query, statement_type eType) = 0;
enum exec_fetch_result
{
ef_success,
ef_no_data
};
virtual exec_fetch_result execute(int number) = 0;
virtual exec_fetch_result fetch(int number) = 0;
virtual long long get_affected_rows() = 0;
virtual int get_number_of_rows() = 0;
virtual std::string rewrite_for_procedure_call(std::string const& query) = 0;
virtual int prepare_for_describe() = 0;
virtual void describe_column(int colNum, data_type& dtype,
std::string& column_name) = 0;
virtual standard_into_type_backend* make_into_type_backend() = 0;
virtual standard_use_type_backend* make_use_type_backend() = 0;
virtual vector_into_type_backend* make_vector_into_type_backend() = 0;
virtual vector_use_type_backend* make_vector_use_type_backend() = 0;
};
The `statement_backend` type implements the internals of the `statement` objects. The objects of this class are created by the `session` object.
* `alloc` - Called once to allocate everything that is needed for the statement to work correctly.
* `clean_up` - Supposed to clean up the resources, called once.
* `prepare` - Called once with the text of the SQL query. For servers that support explicit query preparation, this is the place to do it.
* `execute` - Called to execute the query; if number is zero, the intent is not to exchange data with the user-provided objects (`into` and `use` elements); positive values mean the number of rows to exchange (more than 1 is used only for bulk operations).
* `fetch` - Called to fetch next bunch of rows; number is positive and determines the requested number of rows (more than 1 is used only for bulk operations).
* `get_affected_rows` - Called to determine the actual number of rows affected by data modifying statement.
* `get_number_of_rows` - Called to determine the actual number of rows retrieved by the previous call to `execute` or `fetch`.
* `rewrite_for_procedure_call` - Used when the `procedure` is used instead of `statement`, to call the stored procedure. This function should rewrite the SQL query (if necessary) to the form that will allow to execute the given procedure.
* `prepare_for_describe` - Called once when the `into` element is used with the `row` type, which means that dynamic rowset description should be performed. It is supposed to do whatever is needed to later describe the column properties and should return the number of columns.
* `describe_column` - Called once for each column (column numbers - `colNum` - start from 1), should fill its parameters according to the column properties.
* `make_into_type_backend`, `make_use_type_backend`, `make_vector_into_type_backend`, `make_vector_use_type_backend` - Called once for each `into` or `use` element, to create the objects of appropriate classes (described above).
Notes
1. Whether the query is executed using the simple one-time syntax or is prepared, the `alloc`, `prepare` and `execute` functions are always called, in this order.
2. All `into` and `use` elements are bound (their `define_by_pos` or `bind_by_pos`/`bind_by_name` functions are called) *between* statement preparation and execution.
class rowid_backend
{
public:
virtual ~rowid_backend() {}
};
The `rowid_backend` class is a hook for the backends to provide their own state for the row identifier. It has no functions, since the only portable interaction with the row identifier object is to use it with `into` and `use` elements.
class blob_backend
{
public:
virtual ~blob_backend() {}
virtual std::size_t get_len() = 0;
virtual std::size_t read(std::size_t offset, char * buf,
std::size_t toRead) = 0;
virtual std::size_t write(std::size_t offset, char const * buf,
std::size_t toWrite) = 0;
virtual std::size_t append(char const * buf, std::size_t toWrite) = 0;
virtual void trim(std::size_t newLen) = 0;
};
The `blob_backend` interface provides the entry points for the `blob` methods.
class session_backend
{
public:
virtual ~session_backend() {}
virtual void begin() = 0;
virtual void commit() = 0;
virtual void rollback() = 0;
virtual bool get_next_sequence_value(session&, std::string const&, long&);
virtual bool get_last_insert_id(session&, std::string const&, long&);
virtual std::string get_backend_name() const = 0;
virtual statement_backend * make_statement_backend() = 0;
virtual rowid_backend * make_rowid_backend() = 0;
virtual blob_backend * make_blob_backend() = 0;
};
The object of the class derived from `session_backend` implements the internals of the `session` object.
* `begin`, `commit`, `rollback` - Forward-called when the same functions of `session` are called by user.
* `get_next_sequence_value`, `get_last_insert_id` - Called to retrieve sequences or auto-generated values and every backend should define at least one of them to allow the code using auto-generated values to work.
* `make_statement_backend`, `make_rowid_backend`, `make_blob_backend` - Called to create respective implementations for the `statement`, `rowid` and `blob` classes.
struct backend_factory
{
virtual ~backend_factory() {}
virtual details::session_backend * make_session(
std::string const& connectString) const = 0;
};
The `backend_factory` is a base class for backend-provided factory class that is able to create valid sessions. The `connectString` parameter passed to `make_session` is provided here by the `session` constructor and contains only the backend-related parameters, without the backend name (if the dynamic backend loading is used).
The actual backend factory object is supposed to be provided by the backend implementation and declared in its header file. In addition to this, the `factory_ABC` function with the "C" calling convention and returning the pointer to concrete factory object should be provided, where `ABC` is the backend name.
The following example is taken from `soci-postgresql.h`, which declares entities of the PostgreSQL backend:
struct postgresql_backend_factory : backend_factory
{
virtual postgresql_session_backend* make_session(
std::string const& connectString) const;
};
extern postgresql_backend_factory const postgresql;
extern "C"
{
// for dynamic backend loading
backend_factory const * factory_postgresql();
} // extern "C"
With the above declarations, it is enough to pass the `postgresql` factory name to the constructor of the `session` object, which will use this factory to create concrete implementations for any other objects that are needed, with the help of appropriate `make_XYZ` functions. Alternatively, the `factory_postgresql` function will be called automatically by the backend loader if the backend name is provided at run-time instead.
Note that the backend source code is placed in the `backends/*name*` directory (for example, `backends/oracle`) and the test driver is in `backends/*name*/test`. There is also `backends/empty` directory provided as a skeleton for development of new backends and their tests. It is recommended that all backends respect naming conventions by just appending their name to the base-class names. The backend name used for the global factory object should clearly identify the given database engine, like `oracle`, `postgresql`, `mysql`, and so on.

90
docs/backends/db2.md Normal file
View File

@@ -0,0 +1,90 @@
## DB2 Backend Reference
* [Prerequisites](#prerequisites)
* [Supported Versions](#versions)
* [Tested Platforms](#platforms)
* [Required Client Libraries](#required)
* [Connecting to the Database](#connecting)
* [SOCI Feature Support](#features)
* [Dynamic Binding](#dynamic)
* [Binding by Name](#name)
* [Bulk Operations](#bulk)
* [Transactions](#transactions)
* [BLOB Data Type](#blob)
* [RowID Data Type](#rowid)
* [Nested Statements](#nested)
* [Stored Procedures](#stored)
* [Accessing the Native Database API](#native)
* [Backend-specific Extensions](#extensions)
* [Configuration options](#config)
### <a name="prerequisites"></a> Prerequisites
#### <a name="versions"></a> Supported Versions
The SOCI DB2 backend.
#### <a name="platforms"></a> Tested Platforms
<table>
<tbody>
<tr><th>DB2 version</th><th>Operating System</th><th>Compiler</th></tr>
<tr><td>-</td><td>Linux PPC64</td><td>GCC</td></tr>
<tr><td>9.1</td><td>Linux</td><td>GCC</td></tr>
<tr><td>9.5</td><td>Linux</td><td>GCC</td></tr>
<tr><td>9.7</td><td>Linux</td><td>GCC</td></tr>
<tr><td>10.1</td><td>Linux</td><td>GCC</td></tr>
<tr><td>10.1</td><td>Windows 8</td><td>Visual Studio 2012</td></tr>
</tbody>
</table>
#### <a name="required"></a> Required Client Libraries
The SOCI DB2 backend requires IBM DB2 Call Level Interface (CLI) library.
#### <a name="connecting"></a> Connecting to the Database
On Unix, before using the DB2 backend please make sure, that you have sourced DB2 profile into your environment:
. ~/db2inst1/sqllib/db2profile
To establish a connection to the DB2 database, create a session object using the <code>DB2</code> backend factory together with the database file name:
soci::session sql(soci::db2, "your DB2 connection string here");
### <a name="features"></a> SOCI Feature Support
#### <a name="dynamic"></a> Dynamic Binding
TODO
#### <a name="bulk"></a> Bulk Operations
Supported, but with caution as it hasn't been extensively tested.
#### <a name="transactions"></a> Transactions
Currently, not supported.
#### <a name="blob"></a> BLOB Data Type
Currently, not supported.
#### <a name="nested"></a> Nested Statements
Nesting statements are not processed by SOCI in any special way and they work as implemented by the DB2 database.
#### <a name="stored"></a> Stored Procedures
Stored procedures are supported, with <code>CALL</code> statement.
### <a name="native"></a> Acessing the native database API
TODO
### <a name="backend"></a> Backend-specific extensions
None.
### <a name="config"></a> Configuration options
None.

200
docs/backends/firebird.md Normal file
View File

@@ -0,0 +1,200 @@
## Firebird Backend Reference
* [Prerequisites](#prerequisites)
* [Supported Versions](#versions)
* [Tested Platforms](#platforms)
* [Required Client Libraries](#required)
* [Connecting to the Database](#connecting)
* [SOCI Feature Support](#features)
* [Dynamic Binding](#dynamic)
* [Binding by Name](#name)
* [Bulk Operations](#bulk)
* [Transactions](#transactions)
* [BLOB Data Type](#blob)
* [RowID Data Type](#rowid)
* [Nested Statements](#nested)
* [Stored Procedures](#stored)
* [Accessing the Native Database API](#native)
* [Backend-specific Extensions](#extensions)
* [Configuration options](#configuration)
* [FirebirdSOCIError](#firebirdsocierror)
### <a name="prerequisites"></a> Prerequisites
#### <a name="versions"></a> Supported Versions
The SOCI Firebird backend supports versions of Firebird from 1.5 to 2.5 and can be used with either the client-server or embedded Firebird libraries. The former is the default, to select the latter set <tt>SOCI_FIREBIRD_EMBEDDED</tt> CMake option to <tt>ON</tt> value when building.
#### <a name="tested"></a> Tested Platforms
<table>
<tbody>
<tr><th>Firebird version</th><th>Operating System</th><th>Compiler</th></tr>
<tr><td>1.5.2.4731</td><td>SunOS 5.10</td><td>g++ 3.4.3</td></tr>
<tr><td>1.5.2.4731</td><td>Windows XP</td><td>Visual C++ 8.0</td></tr>
<tr><td>1.5.3.4870</td><td>Windows XP</td><td>Visual C++ 8.0 Professional</td></tr>
<tr><td>2.5.2.26540</td><td>Debian GNU/Linux 7</td><td>g++ 4.7.2</td></tr>
</tbody>
</table>
#### <a name="required"></a> Required Client Libraries
The Firebird backend requires Firebird's `libfbclient` client library.
### <a name="connecting"></a> Connecting to the Database
To establish a connection to a Firebird database, create a Session object using the firebird backend factory together with a connection string:
BackEndFactory const &backEnd = firebird;
Session sql(backEnd,
"service=/usr/local/firbird/db/test.fdb user=SYSDBA password=masterkey");
or simply:
Session sql(firebird,
"service=/usr/local/firbird/db/test.fdb user=SYSDBA password=masterkey");
The set of parameters used in the connection string for Firebird is:
* service
* user
* password
* role
* charset
The following parameters have to be provided as part of the connection string : *service*, *user*, *password*. Role and charset parameters are optional.
Once you have created a `Session` object as shown above, you can use it to access the database, for example:
int count;
sql << "select count(*) from user_tables", into(count);
(See the [SOCI basics](../basics.html) and [exchanging data](../exchange.html) documentation for general information on using the `Session` class.)
### <a name="features"></a> SOCI Feature Support
#### <a name="dynamic"></a> Dynamic Binding
The Firebird backend supports the use of the SOCI `Row` class, which facilitates retrieval of data whose type is not known at compile time.
When calling `Row::get<T>()`, the type you should pass as T depends upon the underlying database type. For the Firebird backend, this type mapping is:
<table>
<tbody>
<tr>
<th>Firebird Data Type</th>
<th>SOCI Data Type</th>
<th><code>Row::get&lt;T&gt;</code> specializations</th>
</tr>
<tr>
<td>numeric, decimal <br />*(where scale &gt; 0)*</td>
<td><code>eDouble</code></td>
<td><code>double</code></td>
</tr>
<tr>
<td>numeric, decimal <sup>[<a href="#note1">1</a>]</sup><br />*(where scale = 0)*</td>
<td><code>eInteger, eDouble</code></td>
<td><code>int, double</code></td>
</tr>
<tr>
<td>double precision, float</td>
<td><code>eDouble</code></td>
<td><code>double</code></td>
</tr>
<tr>
<td>smallint, integer</td>
<td><code>eInteger</code></td>
<td><code>int</code></td>
</tr>
<tr>
<td>char, varchar</td>
<td><code>eString</code></td>
<td><code>std::string</code></td>
</tr>
<tr>
<td>date, time, timestamp</td>
<td><code>eDate</code></td>
<td><code>std::tm</code></code></code></td>
</tr>
</tbody>
</table>
<a name="note1" />&nbsp;<sup>[1]</sup> &nbsp;There is also 64bit integer type for larger values which is
currently not supported.
(See the [dynamic resultset binding](../exchange.html#dynamic) documentation for general information on using the `Row` class.)
#### <a name="binding"></a> Binding by Name
In addition to [binding by position](../exchange.html#bind_position), the Firebird backend supports [binding by name](../exchange.html#bind_name), via an overload of the `use()` function:
int id = 7;
sql << "select name from person where id = :id", use(id, "id")
It should be noted that parameter binding by name is supported only by means of emulation, since the underlying API used by the backend doesn't provide this feature.
#### <a name="bulk"></a> Bulk Operations
The Firebird backend has full support for SOCI's [bulk operations](../statements.html#bulk) interface. This feature is also supported by emulation.
#### <a name="transactions"></a> Transactions
[Transactions](../statements.html#transactions) are also fully supported by the Firebird backend. In fact, an implicit transaction is always started when using this backend if one hadn't been started by explicitly calling <tt>begin()</tt> before. The current transaction is automatically committed in `Session's` destructor.
#### <a name="blob"></a> BLOB Data Type
The Firebird backend supports working with data stored in columns of type Blob, via SOCI's `[BLOB](../exchange.html#blob)` class.
It should by noted, that entire Blob data is fetched from database to allow random read and write access. This is because Firebird itself allows only writing to a new Blob or reading from existing one - modifications of existing Blob means creating a new one. Firebird backend hides those details from user.
#### <a name="rowid"></a> RowID Data Type
This feature is not supported by Firebird backend.
#### <a name="nested"></a> Nested Statements
This feature is not supported by Firebird backend.
#### <a name="stored"></a> Stored Procedures
Firebird stored procedures can be executed by using SOCI's [Procedure](../statements.html#procedures) class.
### <a name="native"></a> Acessing the native database API
SOCI provides access to underlying datbabase APIs via several getBackEnd() functions, as described in the [beyond SOCI](../beyond.html) documentation.
The Firebird backend provides the following concrete classes for navite API access:
<table>
<tbody>
<tr>
<th>Accessor Function</th>
<th>Concrete Class</th>
</tr>
<tr>
<td><code>SessionBackEnd* Session::getBackEnd()</code></td>
<td><code>FirebirdSessionBackEnd</code></td>
</tr>
<tr>
<td><code>StatementBackEnd* Statement::getBackEnd()</code></td>
<td><code>FirebirdStatementBackEnd</code></td>
</tr>
<tr>
<td><code>BLOBBackEnd* BLOB::getBackEnd()</code></td>
<td><code>FirebirdBLOBBackEnd</code></td>
</tr>
<tr>
<td><code>RowIDBackEnd* RowID::getBackEnd()</code></td>
<td<>code>FirebirdRowIDBackEnd</code></td>
</tr>
</tbody>
</table>
### <a name="extensions"></a> Backend-specific extensions
#### <a name="firebirdsocierror"></a> FirebirdSOCIError
The Firebird backend can throw instances of class `FirebirdSOCIError`, which is publicly derived from `SOCIError` and has an additional public `status_` member containing the Firebird status vector.

View File

@@ -1,21 +1,10 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en'>
<head>
<meta content="text/html; charset=ISO-8859-1" http-equiv="content-type" />
<link rel="stylesheet" type="text/css" href="../style.css" />
<title>SOCI - Existing Backends</title>
</head>
## Existing backends and supported platforms
<body>
<p class="banner">SOCI - The C++ Database Access Library</p>
### Supported Features
<h2>Existing backends and supported platforms</h2>
(Follow the links to learn more about each backend.)
<h4>Supported Features</h4>
<p>(Follow the links to learn more about each backend.)</p>
<table border="1" cellpadding="5" cellspacing="0">
<table>
<tbody>
<tr>
<th></th>
@@ -62,7 +51,7 @@
<td>YES</td>
<td>YES</td>
<td><a href="mysql.html#transactions">YES</a>
(with servers that support them, usually >=&nbsp;4.0)</td>
(with servers that support them, usually >=&nbsp;4.0)</td>
<td>YES</td>
<td><a href="firebird.html#transactions">YES</a></td>
<td>YES</td>
@@ -110,17 +99,3 @@
</tr>
</tbody>
</table>
<table class="foot-links" border="0" cellpadding="2" cellspacing="2">
<tr>
<td class="foot-link-left">
<a href="../rationale.html">Previous (Rationale FAQ)</a>
</td>
</tr>
</table>
<p class="copyright">Copyright &copy; 2013 Mateusz Loskot</p>
<p class="copyright">Copyright &copy; 2004-2008 Maciej Sobczak, Stephen Hutton</p>
</body>
</html>

Some files were not shown because too many files have changed in this diff Show More