mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-20 02:55:50 +00:00
Merge commit '9708a1260720d879d76a10f894925962f20611bc' as 'src/soci'
This commit is contained in:
22
src/soci/.gitattributes
vendored
Normal file
22
src/soci/.gitattributes
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
# Auto detect text files and perform LF normalization
|
||||
* text=auto
|
||||
|
||||
# Custom for Visual Studio
|
||||
*.cs diff=csharp
|
||||
*.sln merge=union
|
||||
*.csproj merge=union
|
||||
*.vbproj merge=union
|
||||
*.fsproj merge=union
|
||||
*.dbproj merge=union
|
||||
|
||||
# Standard to msysgit
|
||||
*.doc diff=astextplain
|
||||
*.DOC diff=astextplain
|
||||
*.docx diff=astextplain
|
||||
*.DOCX diff=astextplain
|
||||
*.dot diff=astextplain
|
||||
*.DOT diff=astextplain
|
||||
*.pdf diff=astextplain
|
||||
*.PDF diff=astextplain
|
||||
*.rtf diff=astextplain
|
||||
*.RTF diff=astextplain
|
||||
24
src/soci/.gitignore
vendored
Normal file
24
src/soci/.gitignore
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
# General
|
||||
*.swp
|
||||
tags
|
||||
tmp
|
||||
|
||||
# Build directories
|
||||
_build*
|
||||
src/_build*
|
||||
src/build
|
||||
|
||||
# Visual Studio
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.suo
|
||||
|
||||
# KDevelop
|
||||
*.kate-swp
|
||||
*.kdev4
|
||||
|
||||
# Qt Creator
|
||||
*.config
|
||||
*.creator*
|
||||
*.files
|
||||
*.includes
|
||||
40
src/soci/.travis.yml
Normal file
40
src/soci/.travis.yml
Normal file
@@ -0,0 +1,40 @@
|
||||
# .travis.yml
|
||||
# Configure Travis CI service to build SOCI library, http://github.com/SOCI
|
||||
#
|
||||
# Copyright (c) 2013 Mateusz Loskot <mateusz@loskot.net>
|
||||
#
|
||||
language: cpp
|
||||
|
||||
compiler:
|
||||
- g++
|
||||
#- clang
|
||||
|
||||
services:
|
||||
- mysql
|
||||
- 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
|
||||
|
||||
before_install: ./bin/ci/before_install.sh
|
||||
before_script: ./bin/ci/before_script.sh
|
||||
script: ./bin/ci/script.sh
|
||||
|
||||
notifications:
|
||||
email:
|
||||
recipients:
|
||||
- soci-devel@lists.sourceforge.net
|
||||
on_success: change # [always|never|change] # default: change
|
||||
on_failure: always # [always|never|change] # default: always
|
||||
|
||||
irc:
|
||||
channels:
|
||||
- "irc.freenode.org#soci"
|
||||
52
src/soci/README.md
Normal file
52
src/soci/README.md
Normal file
@@ -0,0 +1,52 @@
|
||||
SOCI - The C++ Database Access Library
|
||||
======================================
|
||||
|
||||
Website: http://soci.sourceforge.net
|
||||
|
||||
GitHub hosts SOCI source code repository, issues tracker and wiki:
|
||||
https://github.com/SOCI
|
||||
|
||||
Downloads and mailing lists at
|
||||
http://sourceforge.net/projects/soci/
|
||||
|
||||
Travis CI service at https://travis-ci.org/SOCI/soci
|
||||
|
||||
[](https://travis-ci.org/SOCI/soci)
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
The SOCI library is distributed under the terms of the [Boost Software License](http://www.boost.org/LICENSE_1_0.txt).
|
||||
|
||||
Requirements
|
||||
------------
|
||||
|
||||
Core:
|
||||
* C++ compiler
|
||||
* Boost C++ Libraries (optional, headers only)
|
||||
|
||||
Backend specific client libraries for:
|
||||
* DB2
|
||||
* Firebird
|
||||
* MySQL
|
||||
* ODBC andwith specific database driver
|
||||
* Oracle
|
||||
* PostgreSQL
|
||||
* SQLite 3
|
||||
|
||||
See documentation at http://soci.sourceforge.net for details
|
||||
|
||||
Brief History
|
||||
-------------
|
||||
Originally, SOCI was developed by [Maciej Sobczak](http://www.msobczak.com/)
|
||||
at [CERN](http://www.cern.ch/) as abstraction layer for Oracle,
|
||||
a **Simple Oracle Call Interface**.
|
||||
Later, several database backends have been developed for SOCI,
|
||||
thus the long name has lost its practicality.
|
||||
Currently, if you like, SOCI may stand for **Simple Open (Database) Call Interface**
|
||||
or something similar.
|
||||
|
||||
> "CERN is also a user of the SOCI library, which serves as a database access
|
||||
> layer in some of the control system components."
|
||||
|
||||
-- Maciej Sobczak at [Inspirel](http://www.inspirel.com/users.html)
|
||||
13
src/soci/bin/ci/before_install.sh
Executable file
13
src/soci/bin/ci/before_install.sh
Executable file
@@ -0,0 +1,13 @@
|
||||
#!/bin/bash -e
|
||||
# Run before_install actions for SOCI build at travis-ci.org
|
||||
#
|
||||
# Copyright (c) 2013 Mateusz Loskot <mateusz@loskot.net>
|
||||
#
|
||||
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
|
||||
|
||||
before_install="${TRAVIS_BUILD_DIR}/bin/ci/before_install_${SOCI_TRAVIS_BACKEND}.sh"
|
||||
[ -x ${before_install} ] && ${before_install} || echo "nothing to run"
|
||||
39
src/soci/bin/ci/before_install_db2.sh
Executable file
39
src/soci/bin/ci/before_install_db2.sh
Executable file
@@ -0,0 +1,39 @@
|
||||
#!/bin/bash -e
|
||||
# Installs DB2 for SOCI build at travis-ci.org
|
||||
#
|
||||
# Copyright (c) 2013 Brian R. Toonen <toonen@alcf.anl.gov>
|
||||
# Copyright (c) 2013 Mateusz Loskot <mateusz@loskot.net>
|
||||
#
|
||||
source ${TRAVIS_BUILD_DIR}/bin/ci/common.sh
|
||||
|
||||
sudo bash -c 'echo "deb http://archive.canonical.com/ubuntu precise partner" >> /etc/apt/sources.list'
|
||||
sudo apt-get update -qq
|
||||
sudo apt-get install -y db2exc
|
||||
|
||||
echo "Running db2profile and db2rmln"
|
||||
sudo /bin/sh -c '. ~db2inst1/sqllib/db2profile ; $DB2DIR/cfg/db2rmln'
|
||||
|
||||
echo "Setting up db2 users"
|
||||
echo -e "db2inst1\ndb2inst1" | sudo passwd db2inst1
|
||||
echo -e "db2fenc1\ndb2fenc1" | sudo passwd db2fenc1
|
||||
echo -e "dasusr1\ndasusr1" | sudo passwd dasusr1
|
||||
|
||||
echo "Configuring DB2 ODBC driver"
|
||||
if test `getconf LONG_BIT` = "64" ; then
|
||||
if test -f /home/db2inst1/sqllib/lib64/libdb2o.so ; then
|
||||
DB2_ODBC_DRIVER=/home/db2inst1/sqllib/lib64/libdb2o.so
|
||||
else
|
||||
echo "ERROR: can't find the 64-bit DB2 ODBC library"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
if test -f /home/db2inst1/sqllib/lib32/libdb2.so ; then
|
||||
DB2_ODBC_DRIVER=/home/db2inst1/sqllib/lib32/libdb2.so
|
||||
elif test -f /home/db2inst1/sqllib/lib/libdb2.so ; then
|
||||
DB2_ODBC_DRIVER=/home/db2inst1/sqllib/lib/libdb2.so
|
||||
else
|
||||
echo "ERROR: can't find the 32-bit DB2 ODBC library"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
echo "DB2 ODBC driver set to $DB2_ODBC_DRIVER"
|
||||
16
src/soci/bin/ci/before_install_firebird.sh
Executable file
16
src/soci/bin/ci/before_install_firebird.sh
Executable file
@@ -0,0 +1,16 @@
|
||||
#!/bin/bash -e
|
||||
# Install Firebird server for SOCI at travis-ci.org
|
||||
#
|
||||
# Copyright (c) 2013 Mateusz Loskot <mateusz@loskot.net>
|
||||
#
|
||||
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
|
||||
# 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
|
||||
cat /etc/default/firebird2.5 | grep ENABLE_FIREBIRD_SERVER
|
||||
sudo service firebird2.5-super start
|
||||
13
src/soci/bin/ci/before_install_odbc.sh
Executable file
13
src/soci/bin/ci/before_install_odbc.sh
Executable file
@@ -0,0 +1,13 @@
|
||||
#!/bin/bash -e
|
||||
# Install ODBC libraries for SOCI at travis-ci.org
|
||||
#
|
||||
# Copyright (c) 2013 Mateusz Loskot <mateusz@loskot.net>
|
||||
#
|
||||
source ${TRAVIS_BUILD_DIR}/bin/ci/common.sh
|
||||
|
||||
sudo apt-get install -qq \
|
||||
tar bzip2 \
|
||||
unixodbc-dev \
|
||||
libmyodbc odbc-postgresql
|
||||
|
||||
sudo odbcinst -i -d -f /usr/share/libmyodbc/odbcinst.ini
|
||||
15
src/soci/bin/ci/before_install_oracle.sh
Executable file
15
src/soci/bin/ci/before_install_oracle.sh
Executable file
@@ -0,0 +1,15 @@
|
||||
#!/bin/bash -e
|
||||
# Install Oracle client libraries for SOCI at travis-ci.org
|
||||
#
|
||||
# Copyright (c) 2013 Mateusz Loskot <mateusz@loskot.net>
|
||||
#
|
||||
source ${TRAVIS_BUILD_DIR}/bin/ci/common.sh
|
||||
|
||||
sudo apt-get install -qq tar bzip2 libaio1
|
||||
|
||||
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
|
||||
9
src/soci/bin/ci/before_script.sh
Executable file
9
src/soci/bin/ci/before_script.sh
Executable file
@@ -0,0 +1,9 @@
|
||||
#!/bin/bash -e
|
||||
# Run before_script actions for SOCI build at travis-ci.org
|
||||
#
|
||||
# Copyright (c) 2013 Mateusz Loskot <mateusz@loskot.net>
|
||||
#
|
||||
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"
|
||||
10
src/soci/bin/ci/before_script_db2.sh
Executable file
10
src/soci/bin/ci/before_script_db2.sh
Executable file
@@ -0,0 +1,10 @@
|
||||
#!/bin/bash -e
|
||||
# Sets up environment for SOCI backend DB2 at travis-ci.org
|
||||
#
|
||||
# Copyright (c) 2013 Brian R. Toonen <toonen@alcf.anl.gov>
|
||||
# Copyright (c) 2013 Mateusz Loskot <mateusz@loskot.net>
|
||||
#
|
||||
source ${TRAVIS_BUILD_DIR}/bin/ci/common.sh
|
||||
|
||||
sudo -u db2inst1 -i db2 "CREATE DATABASE SOCITEST"
|
||||
sudo -u db2inst1 -i db2 "ACTIVATE DATABASE SOCITEST"
|
||||
11
src/soci/bin/ci/before_script_firebird.sh
Executable file
11
src/soci/bin/ci/before_script_firebird.sh
Executable file
@@ -0,0 +1,11 @@
|
||||
#!/bin/bash -e
|
||||
# Configure Firebird database for SOCI build at travis-ci.org
|
||||
#
|
||||
# Mateusz Loskot <mateusz@loskot.net>, http://github.com/SOCI
|
||||
#
|
||||
source ${TRAVIS_BUILD_DIR}/bin/ci/common.sh
|
||||
|
||||
isql-fb -z -q -i /dev/null # --version
|
||||
echo 'CREATE DATABASE "LOCALHOST:/tmp/soci_test.fdb" PAGE_SIZE = 16384;' > /tmp/create_soci_test.sql
|
||||
isql-fb -u SYSDBA -p masterkey -i /tmp/create_soci_test.sql -q
|
||||
cat /tmp/create_soci_test.sql
|
||||
9
src/soci/bin/ci/before_script_mysql.sh
Executable file
9
src/soci/bin/ci/before_script_mysql.sh
Executable file
@@ -0,0 +1,9 @@
|
||||
#!/bin/bash -e
|
||||
# Sets up environment for SOCI backend MySQL at travis-ci.org
|
||||
#
|
||||
# Mateusz Loskot <mateusz@loskot.net>, http://github.com/SOCI
|
||||
#
|
||||
source ${TRAVIS_BUILD_DIR}/bin/ci/common.sh
|
||||
|
||||
mysql --version
|
||||
mysql -e 'create database soci_test;'
|
||||
11
src/soci/bin/ci/before_script_odbc.sh
Executable file
11
src/soci/bin/ci/before_script_odbc.sh
Executable file
@@ -0,0 +1,11 @@
|
||||
#!/bin/bash -e
|
||||
# Sets up environment for SOCI backend ODBC at travis-ci.org
|
||||
#
|
||||
# Mateusz Loskot <mateusz@loskot.net>, http://github.com/SOCI
|
||||
#
|
||||
source ${TRAVIS_BUILD_DIR}/bin/ci/common.sh
|
||||
|
||||
mysql --version
|
||||
mysql -e 'create database soci_test;'
|
||||
psql --version
|
||||
psql -c 'create database soci_test;' -U postgres
|
||||
9
src/soci/bin/ci/before_script_postgresql.sh
Executable file
9
src/soci/bin/ci/before_script_postgresql.sh
Executable file
@@ -0,0 +1,9 @@
|
||||
#!/bin/bash -e
|
||||
# Sets up environment for SOCI backend PostgreSQL at travis-ci.org
|
||||
#
|
||||
# Mateusz Loskot <mateusz@loskot.net>, http://github.com/SOCI
|
||||
#
|
||||
source ${TRAVIS_BUILD_DIR}/bin/ci/common.sh
|
||||
|
||||
psql --version
|
||||
psql -c 'create database soci_test;' -U postgres
|
||||
36
src/soci/bin/ci/common.sh
Normal file
36
src/soci/bin/ci/common.sh
Normal file
@@ -0,0 +1,36 @@
|
||||
#!/bin/bash -e
|
||||
# Common definitions used by SOCI build scripts at travis-ci.org
|
||||
#
|
||||
# Copyright (c) 2013 Mateusz Loskot <mateusz@loskot.net>
|
||||
#
|
||||
if [[ "$TRAVIS" != "true" ]] ; then
|
||||
echo "Running this script makes no sense outside of travis-ci.org"
|
||||
exit 1
|
||||
fi
|
||||
#
|
||||
# Environment
|
||||
#
|
||||
TCI_NUMTHREADS=2
|
||||
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
|
||||
#
|
||||
tmstamp()
|
||||
{
|
||||
echo -n "[$(date '+%H:%M:%S')]" ;
|
||||
}
|
||||
|
||||
run_make()
|
||||
{
|
||||
[ $TCI_NUMTHREADS -gt 0 ] && make -j $TCI_NUMTHREADS ] || make
|
||||
}
|
||||
|
||||
run_test()
|
||||
{
|
||||
ctest -V --output-on-failure .
|
||||
}
|
||||
14
src/soci/bin/ci/script.sh
Executable file
14
src/soci/bin/ci/script.sh
Executable file
@@ -0,0 +1,14 @@
|
||||
#!/bin/bash -e
|
||||
# Run test script actions for SOCI build at travis-ci.org
|
||||
#
|
||||
# Copyright (c) 2013 Mateusz Loskot <mateusz@loskot.net>
|
||||
#
|
||||
source ${TRAVIS_BUILD_DIR}/bin/ci/common.sh
|
||||
|
||||
# prepare build directory
|
||||
builddir="${TRAVIS_BUILD_DIR}/src/_build"
|
||||
mkdir -p ${builddir}
|
||||
cd ${builddir}
|
||||
|
||||
# build and run tests
|
||||
${TRAVIS_BUILD_DIR}/bin/ci/script_${SOCI_TRAVIS_BACKEND}.sh
|
||||
24
src/soci/bin/ci/script_db2.sh
Executable file
24
src/soci/bin/ci/script_db2.sh
Executable file
@@ -0,0 +1,24 @@
|
||||
#!/bin/bash -e
|
||||
# Builds and tests SOCI backend DB2 at travis-ci.org
|
||||
#
|
||||
# Copyright (c) 2013 Brian R. Toonen <toonen@alcf.anl.gov>
|
||||
# Copyright (c) 2013 Mateusz Loskot <mateusz@loskot.net>
|
||||
#
|
||||
source ${TRAVIS_BUILD_DIR}/bin/ci/common.sh
|
||||
|
||||
cmake \
|
||||
-DSOCI_TESTS=ON \
|
||||
-DSOCI_STATIC=OFF \
|
||||
-DSOCI_DB2=ON \
|
||||
-DSOCI_EMPTY=OFF \
|
||||
-DSOCI_FIREBIRD=OFF \
|
||||
-DSOCI_MYSQL=OFF \
|
||||
-DSOCI_ODBC=OFF \
|
||||
-DSOCI_ORACLE=OFF \
|
||||
-DSOCI_POSTGRESQL=OFF \
|
||||
-DSOCI_SQLITE3=OFF \
|
||||
-DSOCI_DB2_TEST_CONNSTR:STRING="DSN=SOCITEST\;Uid=db2inst1\;Pwd=db2inst1" \
|
||||
..
|
||||
|
||||
run_make
|
||||
run_test
|
||||
22
src/soci/bin/ci/script_empty.sh
Executable file
22
src/soci/bin/ci/script_empty.sh
Executable file
@@ -0,0 +1,22 @@
|
||||
#!/bin/bash -e
|
||||
# Builds and tests SOCI backend empty at travis-ci.org
|
||||
#
|
||||
# Copyright (c) 2013 Mateusz Loskot <mateusz@loskot.net>
|
||||
#
|
||||
source ${TRAVIS_BUILD_DIR}/bin/ci/common.sh
|
||||
|
||||
cmake \
|
||||
-DSOCI_TESTS=ON \
|
||||
-DSOCI_STATIC=OFF \
|
||||
-DSOCI_DB2=OFF \
|
||||
-DSOCI_EMPTY=ON \
|
||||
-DSOCI_FIREBIRD=OFF \
|
||||
-DSOCI_MYSQL=OFF \
|
||||
-DSOCI_ODBC=OFF \
|
||||
-DSOCI_ORACLE=OFF \
|
||||
-DSOCI_POSTGRESQL=OFF \
|
||||
-DSOCI_SQLITE3=OFF \
|
||||
..
|
||||
|
||||
run_make
|
||||
run_test
|
||||
23
src/soci/bin/ci/script_firebird.sh
Executable file
23
src/soci/bin/ci/script_firebird.sh
Executable file
@@ -0,0 +1,23 @@
|
||||
#!/bin/bash -e
|
||||
# Builds and tests SOCI backend Firebird at travis-ci.org
|
||||
#
|
||||
# Copyright (c) 2013 Mateusz Loskot <mateusz@loskot.net>
|
||||
#
|
||||
source ${TRAVIS_BUILD_DIR}/bin/ci/common.sh
|
||||
|
||||
cmake \
|
||||
-DSOCI_TESTS=ON \
|
||||
-DSOCI_STATIC=OFF \
|
||||
-DSOCI_DB2=OFF \
|
||||
-DSOCI_EMPTY=OFF \
|
||||
-DSOCI_FIREBIRD=ON \
|
||||
-DSOCI_MYSQL=OFF \
|
||||
-DSOCI_ODBC=OFF \
|
||||
-DSOCI_ORACLE=OFF \
|
||||
-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
|
||||
23
src/soci/bin/ci/script_mysql.sh
Executable file
23
src/soci/bin/ci/script_mysql.sh
Executable file
@@ -0,0 +1,23 @@
|
||||
#!/bin/bash -e
|
||||
# Builds and tests SOCI backend SQLite3 at travis-ci.org
|
||||
#
|
||||
# Copyright (c) 2013 Mateusz Loskot <mateusz@loskot.net>
|
||||
#
|
||||
source ${TRAVIS_BUILD_DIR}/bin/ci/common.sh
|
||||
|
||||
cmake \
|
||||
-DSOCI_TESTS=ON \
|
||||
-DSOCI_STATIC=OFF \
|
||||
-DSOCI_DB2=OFF \
|
||||
-DSOCI_EMPTY=OFF \
|
||||
-DSOCI_FIREBIRD=OFF \
|
||||
-DSOCI_MYSQL=ON \
|
||||
-DSOCI_ODBC=OFF \
|
||||
-DSOCI_ORACLE=OFF \
|
||||
-DSOCI_POSTGRESQL=OFF \
|
||||
-DSOCI_SQLITE3=OFF \
|
||||
-DSOCI_MYSQL_TEST_CONNSTR:STRING="db=soci_test" \
|
||||
..
|
||||
|
||||
run_make
|
||||
run_test
|
||||
24
src/soci/bin/ci/script_odbc.sh
Executable file
24
src/soci/bin/ci/script_odbc.sh
Executable file
@@ -0,0 +1,24 @@
|
||||
#!/bin/bash -e
|
||||
# Builds and tests SOCI backend ODBC at travis-ci.org
|
||||
#
|
||||
# Copyright (c) 2013 Mateusz Loskot <mateusz@loskot.net>
|
||||
#
|
||||
source ${TRAVIS_BUILD_DIR}/bin/ci/common.sh
|
||||
|
||||
cmake \
|
||||
-DSOCI_TESTS=ON \
|
||||
-DSOCI_STATIC=OFF \
|
||||
-DSOCI_DB2=OFF \
|
||||
-DSOCI_EMPTY=OFF \
|
||||
-DSOCI_FIREBIRD=OFF \
|
||||
-DSOCI_MYSQL=OFF \
|
||||
-DSOCI_ODBC=ON \
|
||||
-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;" \
|
||||
..
|
||||
|
||||
run_make
|
||||
run_test
|
||||
30
src/soci/bin/ci/script_oracle.sh
Executable file
30
src/soci/bin/ci/script_oracle.sh
Executable file
@@ -0,0 +1,30 @@
|
||||
#!/bin/bash -e
|
||||
# Builds and tests SOCI backend Oracle at travis-ci.org
|
||||
#
|
||||
# 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
|
||||
|
||||
cmake \
|
||||
-DSOCI_TESTS=ON \
|
||||
-DSOCI_STATIC=OFF \
|
||||
-DSOCI_DB2=OFF \
|
||||
-DSOCI_EMPTY=OFF \
|
||||
-DSOCI_FIREBIRD=OFF \
|
||||
-DSOCI_MYSQL=OFF \
|
||||
-DSOCI_ODBC=OFF \
|
||||
-DSOCI_ORACLE=ON \
|
||||
-DSOCI_POSTGRESQL=OFF \
|
||||
-DSOCI_SQLITE3=OFF \
|
||||
-DSOCI_ORACLE_TEST_CONNSTR:STRING="service=brzuchol.loskot.net user=${ORACLE_USER} password=soci_secret" \
|
||||
..
|
||||
|
||||
run_make
|
||||
run_test
|
||||
23
src/soci/bin/ci/script_postgresql.sh
Executable file
23
src/soci/bin/ci/script_postgresql.sh
Executable file
@@ -0,0 +1,23 @@
|
||||
#!/bin/bash -e
|
||||
# Builds and tests SOCI backend SQLite3 at travis-ci.org
|
||||
#
|
||||
# Copyright (c) 2013 Mateusz Loskot <mateusz@loskot.net>
|
||||
#
|
||||
source ${TRAVIS_BUILD_DIR}/bin/ci/common.sh
|
||||
|
||||
cmake \
|
||||
-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="dbname=soci_test user=postgres" \
|
||||
..
|
||||
|
||||
run_make
|
||||
run_test
|
||||
23
src/soci/bin/ci/script_sqlite3.sh
Executable file
23
src/soci/bin/ci/script_sqlite3.sh
Executable file
@@ -0,0 +1,23 @@
|
||||
#!/bin/bash -e
|
||||
# Builds and tests SOCI backend SQLite3 at travis-ci.org
|
||||
#
|
||||
# Copyright (c) 2013 Mateusz Loskot <mateusz@loskot.net>
|
||||
#
|
||||
source ${TRAVIS_BUILD_DIR}/bin/ci/common.sh
|
||||
|
||||
cmake \
|
||||
-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=OFF \
|
||||
-DSOCI_SQLITE3=ON \
|
||||
-DSOCI_SQLITE3_TEST_CONNSTR:STRING="soci_test.db" \
|
||||
..
|
||||
|
||||
run_make
|
||||
run_test
|
||||
89
src/soci/bin/vm/debian-oracle10g-install.sh
Normal file
89
src/soci/bin/vm/debian-oracle10g-install.sh
Normal file
@@ -0,0 +1,89 @@
|
||||
#/bin/sh
|
||||
# Script performs non-interactive instllation of Oracle XE 10g on Debian
|
||||
#
|
||||
# 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!)
|
||||
#
|
||||
set -ex
|
||||
|
||||
#
|
||||
# Utilities
|
||||
#
|
||||
function free_backup()
|
||||
{
|
||||
# Multiple copies to be on safe side
|
||||
cp /usr/bin/free /root
|
||||
mv /usr/bin/free /usr/bin/free.original
|
||||
}
|
||||
|
||||
function free_restore()
|
||||
{
|
||||
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
|
||||
cat <<EOF >> /usr/bin/free
|
||||
#!/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
|
||||
chmod 755 /usr/bin/free
|
||||
|
||||
# Enable HTTPS for APT repositories.
|
||||
apt-get -q update
|
||||
apt-get -qy install apt-transport-https
|
||||
|
||||
# Register the Oracle repository.
|
||||
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- | apt-key add -
|
||||
apt-get -q update
|
||||
|
||||
# Install the Oracle 10g Express Edition.
|
||||
apt-get -qy install oracle-xe
|
||||
|
||||
# Clean APT cache.
|
||||
apt-get clean
|
||||
|
||||
# Fix the problem when the configuration script eats the last
|
||||
# character of the password if it is 'n': replace IFS="\n" with IFS=$'\n'.
|
||||
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
|
||||
/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=40 SCOPE=SPFILE;" | \
|
||||
sqlplus -S -L sys/admin AS SYSDBA
|
||||
|
||||
# Set Oracle environment variables on login.
|
||||
cat <<END >>/root/.bashrc
|
||||
|
||||
. /usr/lib/oracle/xe/app/oracle/product/10.2.0/server/bin/oracle_env.sh
|
||||
END
|
||||
|
||||
free_restore
|
||||
|
||||
2
src/soci/build/README
Normal file
2
src/soci/build/README
Normal file
@@ -0,0 +1,2 @@
|
||||
This directory is dedicated for:
|
||||
- other building systems contributed by SOCI team and users
|
||||
37
src/soci/build/unix/build-core.tcl
Normal file
37
src/soci/build/unix/build-core.tcl
Normal file
@@ -0,0 +1,37 @@
|
||||
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"
|
||||
}
|
||||
142
src/soci/build/unix/build-mysql.tcl
Normal file
142
src/soci/build/unix/build-mysql.tcl
Normal file
@@ -0,0 +1,142 @@
|
||||
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"
|
||||
}
|
||||
120
src/soci/build/unix/build-oracle.tcl
Normal file
120
src/soci/build/unix/build-oracle.tcl
Normal file
@@ -0,0 +1,120 @@
|
||||
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"
|
||||
}
|
||||
148
src/soci/build/unix/build-postgresql.tcl
Normal file
148
src/soci/build/unix/build-postgresql.tcl
Normal file
@@ -0,0 +1,148 @@
|
||||
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"
|
||||
}
|
||||
142
src/soci/build/unix/build-sqlite3.tcl
Normal file
142
src/soci/build/unix/build-sqlite3.tcl
Normal file
@@ -0,0 +1,142 @@
|
||||
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"
|
||||
}
|
||||
87
src/soci/build/unix/build.tcl
Executable file
87
src/soci/build/unix/build.tcl
Executable file
@@ -0,0 +1,87 @@
|
||||
#!/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"
|
||||
}
|
||||
}
|
||||
}
|
||||
14
src/soci/build/unix/execute.tcl
Normal file
14
src/soci/build/unix/execute.tcl
Normal file
@@ -0,0 +1,14 @@
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
47
src/soci/build/unix/find-boost.tcl
Normal file
47
src/soci/build/unix/find-boost.tcl
Normal file
@@ -0,0 +1,47 @@
|
||||
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]
|
||||
}
|
||||
74
src/soci/build/unix/install.tcl
Normal file
74
src/soci/build/unix/install.tcl
Normal file
@@ -0,0 +1,74 @@
|
||||
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 ""
|
||||
60
src/soci/build/unix/parse-parameters.tcl
Normal file
60
src/soci/build/unix/parse-parameters.tcl
Normal file
@@ -0,0 +1,60 @@
|
||||
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
|
||||
499
src/soci/doc/backends.html
Normal file
499
src/soci/doc/backends.html
Normal file
@@ -0,0 +1,499 @@
|
||||
<!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 & 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& 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 &&
|
||||
!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& 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<T></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& position,
|
||||
void* data, exchange_type type, bool readOnly) = 0;
|
||||
virtual void bind_by_name(std::string const& 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& 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;
|
||||
};
|
||||
</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& 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;
|
||||
};
|
||||
</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&, 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;
|
||||
};
|
||||
</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& 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& 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 © 2013 Mateusz Loskot</p>
|
||||
<p class="copyright">Copyright © 2012 Vadim Zeitlin</p>
|
||||
<p class="copyright">Copyright © 2004-2006 Maciej Sobczak, Stephen Hutton</p>
|
||||
</body>
|
||||
</html>
|
||||
120
src/soci/doc/backends/db2.html
Normal file
120
src/soci/doc/backends/db2.html
Normal file
@@ -0,0 +1,120 @@
|
||||
<!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 © 2013 Mateusz Loskot</p>
|
||||
</body>
|
||||
</html>
|
||||
240
src/soci/doc/backends/firebird.html
Normal file
240
src/soci/doc/backends/firebird.html
Normal file
@@ -0,0 +1,240 @@
|
||||
<!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 &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 << "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<T>()</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<T></code> specializations</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>numeric, decimal <br /><i>(where scale > 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" /> <sup>[1]</sup> 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 << "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 © 2004-2006 Maciej Sobczak, Stephen Hutton, Rafal Bobrowski</p>
|
||||
</body>
|
||||
</html>
|
||||
126
src/soci/doc/backends/index.html
Normal file
126
src/soci/doc/backends/index.html
Normal file
@@ -0,0 +1,126 @@
|
||||
<!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>
|
||||
|
||||
<body>
|
||||
<p class="banner">SOCI - The C++ Database Access Library</p>
|
||||
|
||||
<h2>Existing backends and supported platforms</h2>
|
||||
|
||||
<h4>Supported Features</h4>
|
||||
|
||||
<p>(Follow the links to learn more about each backend.)</p>
|
||||
|
||||
<table border="1" cellpadding="5" cellspacing="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th><a href="oracle.html">Oracle</a></th>
|
||||
<th><a href="postgresql.html">PostgreSQL</a></th>
|
||||
<th><a href="mysql.html">MySQL</a></th>
|
||||
<th><a href="sqlite3.html">SQLite3</a></th>
|
||||
<th><a href="firebird.html">Firebird</a></th>
|
||||
<th><a href="odbc.html">ODBC</a></th>
|
||||
<th><a href="db2.html">DB2</a></th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Binding by Name</td>
|
||||
<td>YES</td>
|
||||
<td><a href="postgresql.html#bindingbyname">YES (>=8.0)</a></td>
|
||||
<td><a href="mysql.html#bindingbyname">YES</a></td>
|
||||
<td>YES</td>
|
||||
<td><a href="firebird.html#bindingbyname">YES</a></td>
|
||||
<td>YES</td>
|
||||
<td>YES</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Dynamic Binding</td>
|
||||
<td><a href="oracle.html#dynamic">YES</a></td>
|
||||
<td><a href="postgresql.html#dynamic">YES</a></td>
|
||||
<td><a href="mysql.html#dynamic">YES</a></td>
|
||||
<td>YES</td>
|
||||
<td>YES</td>
|
||||
<td>YES</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Bulk Operations</td>
|
||||
<td>YES</td>
|
||||
<td>YES</td>
|
||||
<td>YES</td>
|
||||
<td>YES</td>
|
||||
<td><a href="firebird.html#bulk">YES</a></td>
|
||||
<td>YES</td>
|
||||
<td>YES</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Transactions</td>
|
||||
<td>YES</td>
|
||||
<td>YES</td>
|
||||
<td><a href="mysql.html#transactions">YES</a>
|
||||
(with servers that support them, usually >= 4.0)</td>
|
||||
<td>YES</td>
|
||||
<td><a href="firebird.html#transactions">YES</a></td>
|
||||
<td>YES</td>
|
||||
<td>YES</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>BLOB Data Type</td>
|
||||
<td>YES</td>
|
||||
<td><a href="postgresql.html#blob">YES</a></td>
|
||||
<td>MySQL's BLOB type is mapped to <code>std::string</code></td>
|
||||
<td>YES</td>
|
||||
<td><a href="firebird.html#blob">YES</a></td>
|
||||
<td>NO</td>
|
||||
<td>NO</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>RowID Data Type</td>
|
||||
<td>YES</td>
|
||||
<td>YES</td>
|
||||
<td>NO</td>
|
||||
<td>NO</td>
|
||||
<td>NO</td>
|
||||
<td>NO</td>
|
||||
<td>NO</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Nested Statements</td>
|
||||
<td>YES</td>
|
||||
<td>NO</td>
|
||||
<td>NO</td>
|
||||
<td>NO</td>
|
||||
<td>NO</td>
|
||||
<td>NO</td>
|
||||
<td>YES</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Stored Procedures</td>
|
||||
<td>YES</td>
|
||||
<td>YES</td>
|
||||
<td><a href="mysql.html#procedures">NO (but stored functions, YES)</a></td>
|
||||
<td>NO</td>
|
||||
<td>YES</td>
|
||||
<td>NO</td>
|
||||
<td>YES</td>
|
||||
</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 © 2013 Mateusz Loskot</p>
|
||||
<p class="copyright">Copyright © 2004-2008 Maciej Sobczak, Stephen Hutton</p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
261
src/soci/doc/backends/mysql.html
Normal file
261
src/soci/doc/backends/mysql.html
Normal file
@@ -0,0 +1,261 @@
|
||||
<!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 << "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<T>()</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<T></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 >= 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 << "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 © 2004-2008 Maciej Sobczak, Stephen Hutton, Pawel Aleksander Fedorynski</p>
|
||||
</body>
|
||||
</html>
|
||||
288
src/soci/doc/backends/odbc.html
Normal file
288
src/soci/doc/backends/odbc.html
Normal file
@@ -0,0 +1,288 @@
|
||||
<!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& 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 << "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<T>()</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<T></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 << "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 << "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& e)
|
||||
{
|
||||
cerr << "ODBC Error Code: " << e.odbc_error_code() << endl
|
||||
<< "Native Error Code: " << e.native_error_code() << endl
|
||||
<< "SOCI Message: " << e.what() << std::endl
|
||||
<< "ODBC Message: " << e.odbc_error_message() << endl;
|
||||
}
|
||||
catch (exception const &e)
|
||||
{
|
||||
cerr << "Some other error: " << e.what() << 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 © 2013 Mateusz Loskot</p>
|
||||
<p class="copyright">Copyright © 2004-2006 Maciej Sobczak, Stephen Hutton, David Courtney</p>
|
||||
</body>
|
||||
</html>
|
||||
260
src/soci/doc/backends/oracle.html
Normal file
260
src/soci/doc/backends/oracle.html
Normal file
@@ -0,0 +1,260 @@
|
||||
<!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 << "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<T>()</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<T></code> specializations</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>number <i>(where scale > 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 ≤ std::numeric_limits<int>::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 << "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 <<
|
||||
"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 << name << '\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 & e)
|
||||
{
|
||||
cerr << "Oracle error: " << e.err_num_
|
||||
<< " " << e.what() << endl;
|
||||
}
|
||||
catch (exception const &e)
|
||||
{
|
||||
cerr << "Some other error: " << e.what() << endl;
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p class="copyright">Copyright © 2004-2008 Maciej Sobczak, Stephen Hutton</p>
|
||||
</body>
|
||||
</html>
|
||||
230
src/soci/doc/backends/postgresql.html
Normal file
230
src/soci/doc/backends/postgresql.html
Normal file
@@ -0,0 +1,230 @@
|
||||
<!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 << "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<T>()</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<T></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 << "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 << "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 © 2004-2008 Maciej Sobczak, Stephen Hutton</p>
|
||||
</body>
|
||||
</html>
|
||||
207
src/soci/doc/backends/sqlite3.html
Normal file
207
src/soci/doc/backends/sqlite3.html
Normal file
@@ -0,0 +1,207 @@
|
||||
<!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 << "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<T>()</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<T></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 << "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 << "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 © 2004-2006 Maciej Sobczak, Stephen Hutton, David Courtney</p>
|
||||
</body>
|
||||
</html>
|
||||
174
src/soci/doc/beyond.html
Normal file
174
src/soci/doc/beyond.html
Normal file
@@ -0,0 +1,174 @@
|
||||
<!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 << "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 << "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 << "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<oracle_session_back_end *>(sql.get_back_end());
|
||||
oracle_blob_back_end * blobBackEnd = static_cast<oracle_blob_back_end *>(b.get_back_end());
|
||||
|
||||
OCILobDisableBuffering(sessionBackEnd->svchp_, sessionBackEnd->errhp_, blobBackEnd->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 << "select oid from mytable where id = 7", into(rid);
|
||||
|
||||
postgresql_rowid_back_end * rbe = static_cast<postgresql_rowid_back_end *>(rid.get_back_end());
|
||||
|
||||
unsigned long oid = rbe->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 © 2012 Vadim Zeitlin</p>
|
||||
<p class="copyright">Copyright © 2004-2006 Maciej Sobczak, Stephen Hutton</p>
|
||||
</body>
|
||||
</html>
|
||||
106
src/soci/doc/boost.html
Normal file
106
src/soci/doc/boost.html
Normal file
@@ -0,0 +1,106 @@
|
||||
<!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<T></h4>
|
||||
|
||||
<p><code>boost::optional<T></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<T></code> objects can be used everywhere where the regular user provided
|
||||
values are expected.</p>
|
||||
<p>Example:</p>
|
||||
|
||||
<pre class="example">
|
||||
boost::optional<string> name;
|
||||
sql << "select name from person where id = 7", into(name);
|
||||
|
||||
if (name.is_initialized())
|
||||
{
|
||||
// OK, the name was retrieved and is not-null
|
||||
cout << "The name is " << name.get();
|
||||
}
|
||||
else
|
||||
{
|
||||
// the name is null
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>The <code>boost::optional<T></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<T1, ...></h4>
|
||||
|
||||
<p><code>boost::tuple<T1, ...></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<string, string, int> person;
|
||||
|
||||
sql << "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<T></code>:</p>
|
||||
|
||||
<pre class="example">
|
||||
boost::tuple<string, boost::optional<string>, int> person;
|
||||
|
||||
sql << "select name, phone, salary from persons where ...",
|
||||
into(person);
|
||||
|
||||
if (person.get<1>().is_initialized())
|
||||
{
|
||||
// the given person has a phone number
|
||||
}
|
||||
else
|
||||
{
|
||||
// this person does not have a phone number
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h4>boost::fusion::vector<T1, ...></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 <boost-optional.h>
|
||||
#include <boost-tuple.h>
|
||||
#include <boost-fusion.h>
|
||||
#include <boost-gregorian-date.h>
|
||||
</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 © 2004-2008 Maciej Sobczak, Stephen Hutton</p>
|
||||
</body>
|
||||
</html>
|
||||
142
src/soci/doc/connections.html
Normal file
142
src/soci/doc/connections.html
Normal file
@@ -0,0 +1,142 @@
|
||||
<!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 <soci-odbc.h></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 © 2013 Mateusz Loskot</p>
|
||||
<p class="copyright">Copyright © 2004-2008 Maciej Sobczak, Stephen Hutton</p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
128
src/soci/doc/errors.html
Normal file
128
src/soci/doc/errors.html
Normal file
@@ -0,0 +1,128 @@
|
||||
<!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 & e)
|
||||
{
|
||||
cerr << "Bang! " << e.what() << 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 & e)
|
||||
{
|
||||
cerr << "Oracle error: " << e.err_num_
|
||||
<< " " << e.what() << endl;
|
||||
}
|
||||
catch (soci::exception const & e)
|
||||
{
|
||||
cerr << "Some other error: " << e.what() << 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 & e)
|
||||
{
|
||||
cerr << "MySQL error: " << e.err_num_
|
||||
<< " " << e.what() << endl;
|
||||
}
|
||||
catch (soci::exception const & e)
|
||||
{
|
||||
cerr << "Some other error: " << e.what() << 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 & e)
|
||||
{
|
||||
cerr << "PostgreSQL error: " << e.sqlstate()
|
||||
<< " " << e.what() << endl;
|
||||
}
|
||||
catch (soci::exception const & e)
|
||||
{
|
||||
cerr << "Some other error: " << e.what() << 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 © 2004-2013 Maciej Sobczak, Stephen Hutton, Mateusz Loskot</p>
|
||||
</body>
|
||||
</html>
|
||||
758
src/soci/doc/exchange.html
Normal file
758
src/soci/doc/exchange.html
Normal file
@@ -0,0 +1,758 @@
|
||||
<!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 << "select count(*) from person", into(count);
|
||||
|
||||
string name;
|
||||
sql << "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 << "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 << "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 << "insert into person(id, firstname, lastname) values(:id, :fn, :ln)",
|
||||
use(personId), use(firstName), use(lastName);
|
||||
|
||||
sql << "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 << "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 << "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 << "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 << "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 & name = getNameFromSomewhere();
|
||||
sql << "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 << "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 << "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<string> names(100);
|
||||
vector<indicator> inds;
|
||||
sql << "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<int> ids;
|
||||
vector<string> names;
|
||||
vector<indicator> nameIndicators;
|
||||
|
||||
for (int i = 0; i != 10; ++i)
|
||||
{
|
||||
ids.push_back(i);
|
||||
names.push_back("");
|
||||
nameIndicators.push_back(i_null);
|
||||
}
|
||||
|
||||
sql << "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<char></code></li>
|
||||
<li><code>std::vector<short></code></li>
|
||||
<li><code>std::vector<int></code></li>
|
||||
<li><code>std::vector<unsigned long></code></li>
|
||||
<li><code>std::vector<long long></code></li>
|
||||
<li><code>std::vector<double></code></li>
|
||||
<li><code>std::vector<std::string></code></li>
|
||||
<li><code>std::vector<std::tm></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 << "select * from some_table", into(r);
|
||||
|
||||
std::ostringstream doc;
|
||||
doc << "<row>" << std::endl;
|
||||
for(std::size_t i = 0; i != r.size(); ++i)
|
||||
{
|
||||
const column_properties & props = r.get_properties(i);
|
||||
|
||||
doc << '<' << props.get_name() << '>';
|
||||
|
||||
switch(props.get_data_type())
|
||||
{
|
||||
case dt_string:
|
||||
doc << r.get<std::string>(i);
|
||||
break;
|
||||
case dt_double:
|
||||
doc << r.get<double>(i);
|
||||
break;
|
||||
case dt_integer:
|
||||
doc << r.get<int>(i);
|
||||
break;
|
||||
case dt_long_long:
|
||||
doc << r.get<long long>(i);
|
||||
break;
|
||||
case dt_unsigned_long_long:
|
||||
doc << r.get<unsigned long long>(i);
|
||||
break;
|
||||
case dt_date:
|
||||
std::tm when = r.get<std::tm>(i);
|
||||
doc << asctime(&when);
|
||||
break;
|
||||
}
|
||||
|
||||
doc << "</" << props.get_name() << '>' << std::endl;
|
||||
}
|
||||
doc << "</row>";
|
||||
</pre>
|
||||
|
||||
<p>The type <code>T</code> parameter that should be passed to
|
||||
<code>row::get<T>()</code> depends on the SOCI data type that
|
||||
is returned from
|
||||
<code>column_properties::get_data_type()</code>.</p>
|
||||
<p><code>row::get<T>()</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<T></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 << "select name from some_table where id = 1", into(r);
|
||||
if (r.get_indicator(0) != soci::i_null)
|
||||
{
|
||||
std::cout << r.get<std::string>(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 << "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 <>
|
||||
struct type_conversion<MyInt>
|
||||
{
|
||||
typedef int base_type;
|
||||
|
||||
static void from_base(int i, indicator ind, MyInt & mi)
|
||||
{
|
||||
if (ind == i_null)
|
||||
{
|
||||
throw soci_error("Null value not allowed for this type");
|
||||
}
|
||||
|
||||
mi.set(i);
|
||||
}
|
||||
|
||||
static void to_base(const MyInt & mi, int & i, indicator & ind)
|
||||
{
|
||||
i = mi.get();
|
||||
ind = i_ok;
|
||||
}
|
||||
};
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>The above specialization for <code>soci::type_conversion<MyInt></code> is enough
|
||||
to enable the following:</p>
|
||||
|
||||
<pre class="example">
|
||||
MyInt i;
|
||||
|
||||
sql << "select count(*) from person", into(i);
|
||||
|
||||
cout << "We have " << i.get() << " 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<T></code> and <code>use_type<T></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<>
|
||||
struct type_conversion<Person>
|
||||
{
|
||||
typedef values base_type;
|
||||
|
||||
static void from_base(values const & v, indicator /* ind */, Person & p)
|
||||
{
|
||||
p.id = v.get<int>("ID");
|
||||
p.firstName = v.get<std::string>("FIRST_NAME");
|
||||
p.lastName = v.get<std::string>("LAST_NAME");
|
||||
|
||||
// p.gender will be set to the default value "unknown"
|
||||
// when the column is null:
|
||||
p.gender = v.get<std::string>("GENDER", "unknown");
|
||||
|
||||
// alternatively, the indicator can be tested directly:
|
||||
// if (v.indicator("GENDER") == i_null)
|
||||
// {
|
||||
// p.gender = "unknown";
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// p.gender = v.get<std::string>("GENDER");
|
||||
// }
|
||||
}
|
||||
|
||||
static void to_base(const Person & p, values & v, indicator & ind)
|
||||
{
|
||||
v.set("ID", p.id);
|
||||
v.set("FIRST_NAME", p.firstName);
|
||||
v.set("LAST_NAME", p.lastName);
|
||||
v.set("GENDER", p.gender, p.gender.empty() ? i_null : i_ok);
|
||||
ind = i_ok;
|
||||
}
|
||||
};
|
||||
}
|
||||
</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 << "insert into person(id, first_name, last_name) "
|
||||
"values(:ID, :FIRST_NAME, :LAST_NAME)", use(p);
|
||||
|
||||
Person p1;
|
||||
sql << "select * from person", into(p1);
|
||||
assert(p1.id == 1);
|
||||
assert(p1.firstName + p.lastName == "PatSmith");
|
||||
assert(p1.gender == "unknown");
|
||||
|
||||
p.firstName = "Patricia";
|
||||
sql << "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 << "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 © 2010-2013 Mateusz Loskot</p>
|
||||
<p class="copyright">Copyright © 2012 Vadim Zeitlin</p>
|
||||
<p class="copyright">Copyright © 2004-2008 Maciej Sobczak, Stephen Hutton</p>
|
||||
</body>
|
||||
</html>
|
||||
102
src/soci/doc/index.html
Normal file
102
src/soci/doc/index.html
Normal file
@@ -0,0 +1,102 @@
|
||||
<!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 <iostream>
|
||||
#include <istream>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
#include <exception>
|
||||
|
||||
using namespace soci;
|
||||
using namespace std;
|
||||
|
||||
bool get_name(string &name)
|
||||
{
|
||||
cout << "Enter name: ";
|
||||
return cin >> name;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
try
|
||||
{
|
||||
session sql(oracle, "service=mydb user=john password=secret");
|
||||
|
||||
int count;
|
||||
sql << "select count(*) from phonebook", into(count);
|
||||
|
||||
cout << "We have " << count << " entries in the phonebook.\n";
|
||||
|
||||
string name;
|
||||
while (get_name(name))
|
||||
{
|
||||
string phone;
|
||||
indicator ind;
|
||||
sql << "select phone from phonebook where name = :name",
|
||||
into(phone, ind), use(name);
|
||||
|
||||
if (ind == i_ok)
|
||||
{
|
||||
cout << "The phone number is " << phone << '\n';
|
||||
}
|
||||
else
|
||||
{
|
||||
cout << "There is no phone for " << name << '\n';
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (exception const &e)
|
||||
{
|
||||
cerr << "Error: " << e.what() << '\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 © 2010-2013 Mateusz Loskot</p>
|
||||
<p class="copyright">Copyright © 2012 Vadim Zeitlin</p>
|
||||
<p class="copyright">Copyright © 2004-2008 Maciej Sobczak, Stephen Hutton</p>
|
||||
</body>
|
||||
</html>
|
||||
466
src/soci/doc/installation.html
Normal file
466
src/soci/doc/installation.html
Normal file
@@ -0,0 +1,466 @@
|
||||
<!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 © 2010-2013 Mateusz Loskot</p>
|
||||
<p class="copyright">Copyright © 2004-2011 Maciej Sobczak, Stephen Hutton</p>
|
||||
</body>
|
||||
</html>
|
||||
103
src/soci/doc/interfaces.html
Normal file
103
src/soci/doc/interfaces.html
Normal file
@@ -0,0 +1,103 @@
|
||||
<!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 << "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 <soci-simple.h>
|
||||
|
||||
// ...
|
||||
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 © 2012 Vadim Zeitlin</p>
|
||||
<p class="copyright">Copyright © 2004-2008 Maciej Sobczak, Stephen Hutton</p>
|
||||
</body>
|
||||
</html>
|
||||
64
src/soci/doc/languages/ada/concepts.html
Normal file
64
src/soci/doc/languages/ada/concepts.html
Normal file
@@ -0,0 +1,64 @@
|
||||
<!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 © 2008-2011 Maciej Sobczak</p>
|
||||
</body>
|
||||
</html>
|
||||
306
src/soci/doc/languages/ada/idioms.html
Normal file
306
src/soci/doc/languages/ada/idioms.html
Normal file
@@ -0,0 +1,306 @@
|
||||
<!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: " & 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 © 2008-2011 Maciej Sobczak</p>
|
||||
</body>
|
||||
</html>
|
||||
78
src/soci/doc/languages/ada/index.html
Normal file
78
src/soci/doc/languages/ada/index.html
Normal file
@@ -0,0 +1,78 @@
|
||||
<!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 © 2008-2011 Maciej Sobczak</p>
|
||||
</body>
|
||||
</html>
|
||||
674
src/soci/doc/languages/ada/reference.html
Normal file
674
src/soci/doc/languages/ada/reference.html
Normal file
@@ -0,0 +1,674 @@
|
||||
<!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 (<>) 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 © 2008-2011 Maciej Sobczak</p>
|
||||
</body>
|
||||
</html>
|
||||
67
src/soci/doc/languages/ada/style.css
Normal file
67
src/soci/doc/languages/ada/style.css
Normal file
@@ -0,0 +1,67 @@
|
||||
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;
|
||||
}
|
||||
64
src/soci/doc/multithreading.html
Normal file
64
src/soci/doc/multithreading.html
Normal file
@@ -0,0 +1,64 @@
|
||||
<!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 & sql = pool.at(i);
|
||||
|
||||
sql.open("postgresql://dbname=mydb");
|
||||
}
|
||||
|
||||
// phase 2: usage from working threads
|
||||
|
||||
{
|
||||
session sql(pool);
|
||||
|
||||
sql << "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 © 2004-2008 Maciej Sobczak, Stephen Hutton</p>
|
||||
</body>
|
||||
</html>
|
||||
146
src/soci/doc/queries.html
Normal file
146
src/soci/doc/queries.html
Normal file
@@ -0,0 +1,146 @@
|
||||
<!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 << "drop table persons";
|
||||
</pre>
|
||||
|
||||
<p>For shorter syntax, the following form is also allowed:</p>
|
||||
|
||||
<pre class="example">
|
||||
sql << "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<<</code>):</p>
|
||||
|
||||
<pre class="example">
|
||||
string tableName = "persons";
|
||||
sql << "drop table " << tableName;
|
||||
|
||||
int id = 123;
|
||||
sql << "delete from companies where id = " << 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 << "DELETE FROM item";
|
||||
</pre>
|
||||
|
||||
<ul><li>defined as function object:</li></ul>
|
||||
|
||||
<pre class="example">
|
||||
struct order : std::unary_function<std::string, std::string>
|
||||
{
|
||||
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 << query;
|
||||
sql.set_query_transformation(order("id");
|
||||
sql << 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 << "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 © 2013 Mateusz Loskot</p>
|
||||
<p class="copyright">Copyright © 2004-2008 Maciej Sobczak, Stephen Hutton</p>
|
||||
</body>
|
||||
</html>
|
||||
313
src/soci/doc/rationale.html
Normal file
313
src/soci/doc/rationale.html
Normal file
@@ -0,0 +1,313 @@
|
||||
<!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 << "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 >> a >> b >> 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 >> a >> b >> 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<T></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<<</code> provides a bad abstraction for the "input" statements.</h3>
|
||||
|
||||
<p>Indeed, the <code>operator<<</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<<</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<<</code>.</p>
|
||||
|
||||
<p>Using different operators (<code>operator>></code> and <code>operator<<</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 © 2004-2006 Maciej Sobczak, Stephen Hutton</p>
|
||||
</body>
|
||||
</html>
|
||||
963
src/soci/doc/reference.html
Normal file
963
src/soci/doc/reference.html
Normal file
@@ -0,0 +1,963 @@
|
||||
<!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 & parameters);
|
||||
session(backend_factory const & factory, std::string const & connectString);
|
||||
session(std::string const & backendName, std::string const & connectString);
|
||||
explicit session(std::string const & connectString);
|
||||
explicit session(connection_pool & pool);
|
||||
|
||||
~session();
|
||||
|
||||
void open(backend_factory const & factory, std::string const & connectString);
|
||||
void open(std::string const & backendName, std::string const & connectString);
|
||||
void open(std::string const & connectString);
|
||||
void close();
|
||||
void reconnect();
|
||||
|
||||
void begin();
|
||||
void commit();
|
||||
void rollback();
|
||||
|
||||
<i>IT</i> once;
|
||||
<i>IT</i> prepare;
|
||||
|
||||
template <typename T> <i>IT</i> operator<<(T const & t);
|
||||
|
||||
bool got_data() const;
|
||||
|
||||
bool get_next_sequence_value(std::string const & sequence, long & value);
|
||||
bool get_last_insert_id(std::string const & table, long & value);
|
||||
|
||||
std::ostringstream & 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 << "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 <<
|
||||
"insert into numbers(value) values(:val)", use(i));
|
||||
</pre>
|
||||
</li>
|
||||
<li><code>operator<<</code> that is a shortcut forwarder to the
|
||||
equivalent operator of the <code>once</code> member. Example:
|
||||
<pre class="example">
|
||||
sql << "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 & factory, std::string const & connectString);
|
||||
connection_parameters(std::string const & backendName, std::string const & connectString);
|
||||
explicit connection_parameters(std::string const & fullConnectString);
|
||||
|
||||
void set_option(const char * name, std::string const & value);
|
||||
bool get_option(const char * name, std::string & 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 & at(std::size_t pos);
|
||||
|
||||
std::size_t lease();
|
||||
bool try_lease(std::size_t & 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 <typename T>
|
||||
<i>IT</i> into(T & t);
|
||||
|
||||
template <typename T, typename T1>
|
||||
<i>IT</i> into(T & t, T1 p1);
|
||||
|
||||
template <typename T>
|
||||
<i>IT</i> into(T & t, indicator & ind);
|
||||
|
||||
template <typename T, typename T1>
|
||||
<i>IT</i> into(T & t, indicator & ind, T1 p1);
|
||||
|
||||
template <typename T>
|
||||
<i>IT</i> into(T & t, std::vector<indicator> & ind);
|
||||
</pre>
|
||||
|
||||
<p>Example:</p>
|
||||
|
||||
<pre class="example">
|
||||
int count;
|
||||
sql << "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 <typename T>
|
||||
<i>IT</i> use(T & t);
|
||||
|
||||
template <typename T, typename T1>
|
||||
<i>IT</i> use(T & t, T1 p1);
|
||||
|
||||
template <typename T>
|
||||
<i>IT</i> use(T & t, indicator & ind);
|
||||
|
||||
template <typename T, typename T1>
|
||||
<i>IT</i> use(T & t, indicator & ind, T1 p1);
|
||||
|
||||
template <typename T>
|
||||
<i>IT</i> use(T & t, std::vector<indicator> const & ind);
|
||||
|
||||
template <typename T, typename T1>
|
||||
<i>IT</i> use(T & t, std::vector<indicator> const & ind, T1 p1);
|
||||
</pre>
|
||||
|
||||
<p>Example:</p>
|
||||
|
||||
<pre class="example">
|
||||
int val = 7;
|
||||
sql << "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 & s);
|
||||
statement(<i>IT</i> const & prep);
|
||||
~statement();
|
||||
|
||||
statement(statement const & other);
|
||||
void operator=(statement const & other);
|
||||
|
||||
void alloc();
|
||||
void bind(values & v);
|
||||
void exchange(<i>IT</i> const & i);
|
||||
void exchange(<i>IT</i> const & u);
|
||||
void clean_up();
|
||||
|
||||
void prepare(std::string const & 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 & 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 & 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 <typename T>
|
||||
struct type_conversion
|
||||
{
|
||||
typedef T base_type;
|
||||
|
||||
static void from_base(base_type const & in, indicator ind, T & out);
|
||||
|
||||
static void to_base(T const & in, base_type & out, indicator & 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 & name) const;
|
||||
|
||||
column_properties const & get_properties (std::size_t pos) const;
|
||||
column_properties const & get_properties (std::string const & name) const;
|
||||
|
||||
template <typename T>
|
||||
T get(std::size_t pos) const;
|
||||
|
||||
template <typename T>
|
||||
T get(std::size_t pos, T const & nullValue) const;
|
||||
|
||||
template <typename T>
|
||||
T get(std::string const & name) const;
|
||||
|
||||
template <typename T>
|
||||
T get(std::string const & name, T const & nullValue) const;
|
||||
|
||||
template <typename T>
|
||||
row const & operator>>(T & 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>></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 & name) const;
|
||||
|
||||
template <typename T>
|
||||
T get(std::size_t pos) const;
|
||||
|
||||
template <typename T>
|
||||
T get(std::size_t pos, T const & nullValue) const;
|
||||
|
||||
template <typename T>
|
||||
T get(std::string const & name) const;
|
||||
|
||||
template <typename T>
|
||||
T get(std::string const & name, T const & nullValue) const;
|
||||
|
||||
template <typename T>
|
||||
values const & operator>>(T & value) const;
|
||||
|
||||
void skip(std::size_t num = 1) const;
|
||||
void reset_get_counter() const;
|
||||
|
||||
template <typename T>
|
||||
void set(std::string const & name, T const & value, indicator indic = i_ok);
|
||||
|
||||
template <typename T>
|
||||
void set(const T & value, indicator indic = i_ok);
|
||||
|
||||
template <typename T>
|
||||
values & operator<<(T const & 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<<</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 & 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 & 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 & 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 & 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 <soci-simple.h></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 © 2013 Mateusz Loskot</p>
|
||||
<p class="copyright">Copyright © 2012 Vadim Zeitlin</p>
|
||||
<p class="copyright">Copyright © 2004-2006 Maciej Sobczak, Stephen Hutton</p>
|
||||
</body>
|
||||
</html>
|
||||
389
src/soci/doc/statements.html
Normal file
389
src/soci/doc/statements.html
Normal file
@@ -0,0 +1,389 @@
|
||||
<!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 << "insert into numbers(value) values(" << i << ")";
|
||||
}
|
||||
|
||||
// Example 2.
|
||||
for (int i = 0; i != 100; ++i)
|
||||
{
|
||||
sql << "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 <<
|
||||
"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<int> rs = (sql.prepare << "select values from numbers");
|
||||
|
||||
for (rowset<int>::const_iterator it = rs.begin(); it != rs.end(); ++it)
|
||||
{
|
||||
cout << *it << '\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<row> rs = (sql.prepare << "select id, firstname, lastname, gender from person");
|
||||
|
||||
// iteration through the resultset:
|
||||
for (rowset<row>::const_iterator it = rs.begin(); it != rs.end(); ++it)
|
||||
{
|
||||
row const& row = *it;
|
||||
|
||||
// dynamic data extraction from each row:
|
||||
cout << "Id: " << row.get<int>(0) << '\n'
|
||||
<< "Name: " << row.get<string>(1) << " " << row.get<string>(2) << '\n'
|
||||
<< "Gender: " << row.get<string>(3) << endl;
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p><code>rowset_iterator</code> can be used with standard algorithms as well:</p>
|
||||
|
||||
<pre class="example">
|
||||
rowset<string> rs = (sql.prepare << "select firstname from person");
|
||||
|
||||
std::copy(rs.begin(), rs.end(), std::ostream_iterator<std::string>(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<int> ids;
|
||||
for (int i = 0; i != BATCH_SIZE; ++i)
|
||||
{
|
||||
ids.push_back(i);
|
||||
}
|
||||
|
||||
statement st = (sql.prepare <<
|
||||
"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 <<
|
||||
"select value from numbers order by value",
|
||||
into(i));
|
||||
st.execute();
|
||||
while (st.fetch())
|
||||
{
|
||||
cout << i << '\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<int> valsOut(100);
|
||||
sql << "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<int> valsOut(BATCH_SIZE);
|
||||
statement st = (sql.prepare <<
|
||||
"select value from numbers",
|
||||
into(valsOut));
|
||||
st.execute();
|
||||
while (st.fetch())
|
||||
{
|
||||
std::vector<int>::iterator pos;
|
||||
for(pos = valsOut.begin(); pos != valsOut.end(); ++pos)
|
||||
{
|
||||
cout << *pos << '\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 << "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 << "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(&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 © 2010 Mateusz Loskot</p>
|
||||
<p class="copyright">Copyright © 2004-2011 Maciej Sobczak, Stephen Hutton</p>
|
||||
</body>
|
||||
</html>
|
||||
81
src/soci/doc/structure.html
Normal file
81
src/soci/doc/structure.html
Normal file
@@ -0,0 +1,81 @@
|
||||
<!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 © 2010 Mateusz Loskot</p>
|
||||
<p class="copyright">Copyright © 2004-2011 Maciej Sobczak, Stephen Hutton</p>
|
||||
</body>
|
||||
</html>
|
||||
BIN
src/soci/doc/structure.odg
Normal file
BIN
src/soci/doc/structure.odg
Normal file
Binary file not shown.
BIN
src/soci/doc/structure.png
Normal file
BIN
src/soci/doc/structure.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 26 KiB |
118
src/soci/doc/style.css
Normal file
118
src/soci/doc/style.css
Normal file
@@ -0,0 +1,118 @@
|
||||
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;
|
||||
}
|
||||
20
src/soci/src/.gitignore
vendored
Normal file
20
src/soci/src/.gitignore
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
*~
|
||||
*.kdev[0-9]
|
||||
*.swp
|
||||
aclocal.m4
|
||||
autom4te.cache
|
||||
confdefs.h
|
||||
config.guess
|
||||
config.log
|
||||
config.status
|
||||
config.sub
|
||||
configure
|
||||
depcomp
|
||||
install-sh
|
||||
libtool
|
||||
ltmain.sh
|
||||
m4
|
||||
missing
|
||||
Makefile
|
||||
Makefile.in
|
||||
tmp
|
||||
73
src/soci/src/AUTHORS
Normal file
73
src/soci/src/AUTHORS
Normal file
@@ -0,0 +1,73 @@
|
||||
=== SOCI Team ===
|
||||
|
||||
Alex Ott
|
||||
David Courtney
|
||||
Denis Arnaud
|
||||
Denis Chapligin
|
||||
Julian Taylor
|
||||
Maciej Sobczak
|
||||
Mateusz Łoskot
|
||||
Paweł Aleksander Fedoryński
|
||||
Rafał Bobrowski
|
||||
Sergei Nikulov
|
||||
Steve Hutton
|
||||
Vadim Zeitlin
|
||||
Viacheslav Naydenov
|
||||
|
||||
=== SOCI Contributors ===
|
||||
|
||||
We would like to thank you for your contributions
|
||||
- they allowed us to improve the quality of the SOCI library:
|
||||
|
||||
Andrey Belobrov
|
||||
Andrey Utkin
|
||||
Andriy Gapon
|
||||
Artyom Beilis
|
||||
Artyom Tonkikh
|
||||
avg-I
|
||||
b-s-a
|
||||
Brian R. Toonen
|
||||
Cengizhan Paşaoğlu
|
||||
Chris Weed
|
||||
Cory Bennett
|
||||
creste
|
||||
Daniel Lidström
|
||||
Eli Green
|
||||
Faik Uygur
|
||||
Fedor Trushkin
|
||||
Frank Bielig
|
||||
Frederic Chateau
|
||||
Gevorg Voskanyan
|
||||
Henning Basold
|
||||
Howard Butler
|
||||
Ilia Barahovski
|
||||
Jakub Stachowski
|
||||
jamercee
|
||||
Joerg Sonnenberger
|
||||
Krzysztof Bieleń
|
||||
Mario Valesco
|
||||
Martin Muenstermann
|
||||
Mathias Hasselmann
|
||||
Matt Arsenault
|
||||
Matthieu Kermagoret
|
||||
Michael Davidsaver
|
||||
Mika Fischer
|
||||
Paul Bondo
|
||||
Petr Vanek
|
||||
Philip Pemberton
|
||||
Rainer Bauer
|
||||
Ricardo Andrade
|
||||
ryandesign
|
||||
Robert Massaioli
|
||||
Roger Orr
|
||||
Sergey Belyashov
|
||||
Shridhar Daithankar
|
||||
Sören Meyer-Eppler
|
||||
soyersoyer
|
||||
Stefan Chrobot
|
||||
Tomasz Olszewski
|
||||
Vaclav Slavik
|
||||
xol
|
||||
|
||||
There are a lot of people that help to drive SOCI project forward,
|
||||
if we have forgot to mention someone in here, send us an email!
|
||||
338
src/soci/src/CHANGES
Normal file
338
src/soci/src/CHANGES
Normal file
@@ -0,0 +1,338 @@
|
||||
This file contains the history of changes in the SOCI library.
|
||||
|
||||
---
|
||||
Version 3.2.2 differs from 3.2.1 in the following ways:
|
||||
|
||||
- Fixed once_temp_type destructor with noexcept(false) specifier for C++11
|
||||
- Fix uninitialized indicators in conversion_into_type and conversion_use_type specialisations
|
||||
- Fixed placeholder matching for PostgreSQL-style casts with ORM
|
||||
- Fixed memory leaking in use binding in case of bind/unbind sequence
|
||||
- Fixed sscanf formatter for MinGW/MSVC in backends
|
||||
- Fixed partial placeholder name matching for ORM cases
|
||||
- Added test for use of indicators with rowset<row>
|
||||
- Added test for get_affected_rows after bulk operations
|
||||
|
||||
- DB2
|
||||
-- Enable build and testing on Travis CI
|
||||
-- Fixed use type size calculation during bind/pre_use
|
||||
|
||||
- Firebird
|
||||
-- Enable memory cleanup to avoid leaks after binding
|
||||
-- Added missing C++ library headers
|
||||
-- Added get_affected_rows() support for bulk operations
|
||||
-- Fixed compilation with VS2008
|
||||
-- Fixed building tests with the backend built as DLL.
|
||||
|
||||
- MySQL
|
||||
-- Added get_affected_rows() support for bulk operations
|
||||
|
||||
- ODBC
|
||||
-- Always call ASCII version of ODBC function SQLGetDiagRec
|
||||
-- Fixed invalid condition test in assertions
|
||||
-- Added get_affected_rows() support for bulk operations
|
||||
-- Added support for (unsigned) long long vectors
|
||||
-- Changed mapping of SQL_BIGINT to dt_long_long in ODBC backend
|
||||
-- Added some trivial optimizations in statement preparation code
|
||||
|
||||
- Oracle
|
||||
-- Fixed missing noData_ reported in particular case when OCIStmtExecute returns success
|
||||
-- Improved Oracle testing setup on Travis CI
|
||||
|
||||
- PostgreSQL
|
||||
-- Added session::get_next_sequence_value() for PostgreSQL backend
|
||||
-- Added get_affected_rows() support for bulk operations
|
||||
-- Applied RAII and simplified error handling logic
|
||||
-- Fixed issue with exceptions escaping postgresql_statement_backend destructor
|
||||
|
||||
- SQLite3
|
||||
-- Replaced sqlite3_prepare with sqlite3_prepare_v2
|
||||
-- Added missing <cstdarg> header
|
||||
-- Fixed wrong size used in memcpy() during bulk processing
|
||||
-- Added get_affected_rows() support for bulk operations
|
||||
-- Added shared_cache=true propery to control SQLITE_OPEN_SHAREDCACHE flag
|
||||
|
||||
- Documentation
|
||||
-- Corrected usage examples
|
||||
|
||||
- Building
|
||||
-- Updated CMake for Oracle 12g
|
||||
-- Restructured and improved Travis CI setup to do single build per backend
|
||||
-- Fixed wrong GCC_VERSION used in CMake config for commandline-overriden GCC
|
||||
-- Allows CMake to find 32-bit DB2 on Windows x64
|
||||
-- Removed redundant Oracle libclntsh library lookup
|
||||
-- Fixed SQLITE3_LIBRARIES handling by find_package_handle_standard_args
|
||||
|
||||
---
|
||||
Version 3.2.1 differs from 3.2.0 in the following ways:
|
||||
|
||||
- Fixed binding of Oracle type NUMBER(9,0) to C++ int, by Tomasz Olszewski
|
||||
- Fixed Oracle client library detection on Windows, by Tomasz Olszewski
|
||||
- Fixed PostgreSQL issue with deallocate_prepared_statement called for non-existing statement
|
||||
- Fixed prepared insert statements with custom data types support, by Tomasz Olszewski
|
||||
- Fixed recent improvements in x:=y name binding, by Poul Bondo
|
||||
- Fixed query transformation assignment in pooled sessions, by Stefan Chrobot
|
||||
- Cleaned up SOCI_POSTGRESQL_NOPARAMS and related options in code and documentation
|
||||
- Dropped patch (micro) version number from documentation URLs on the website
|
||||
|
||||
---
|
||||
Version 3.2.0 differs from 3.1.0 in the following ways:
|
||||
|
||||
- SOCI is now organization at GitHub
|
||||
-- Git repository moved to https://github.com/SOCI/soci
|
||||
-- Opened new bug tracker (SF.net tracker is read-only)
|
||||
-- Opened Wiki for FAQ and development articles
|
||||
-- Website, mailing lists and downloads remain on SourceForge.net
|
||||
-- Applied GitFlow branching model
|
||||
-- Added package maintenance repository https://github.com/SOCI/soci-pkg
|
||||
|
||||
- Core
|
||||
-- Added connection_parameters to enable support for session options used by core, backends or low-level API.
|
||||
-- Added user-defined query transformation support based on function, functor and lambda
|
||||
-- Fixed missing connection check and backend setup ensured for session
|
||||
-- Fixed backend initialization when used with connection pool (Core)
|
||||
-- Fixed memory leaks on exception thrown during statement preparation stage
|
||||
|
||||
- DB2
|
||||
-- Added new backend for IBM DB2
|
||||
|
||||
- Firebird
|
||||
-- Fixed bug in repeated statement execution
|
||||
-- Fixed issues with input parameter binding
|
||||
-- Fixed connection string parsing to handle possible white-spaces
|
||||
-- Fixed issues with C++ type unsigned long
|
||||
-- Fixed reading negative values into C++ type double
|
||||
-- Added option to fetch numeric/decimal data into string of characters
|
||||
-- Added CMake configuration
|
||||
-- Updated tests
|
||||
-- Continued regular testing on Windows and Unix platforms
|
||||
|
||||
- MySQL
|
||||
-- Replaced use of type=InnoDB with engine=InnoDB
|
||||
-- Improved CMake configuration
|
||||
|
||||
- ODBC
|
||||
-- Added connection_parameters option ODBC_OPTION_DRIVER_COMPLETE
|
||||
-- Fixed issues in handling C++ types int and long on 64-bit architectures
|
||||
-- Added missing CMake configuration for tests
|
||||
-- Continued regular testing on Windows and Unix platforms
|
||||
|
||||
- Oracle
|
||||
-- Implemented statement::get_affected_rows() operation
|
||||
-- Use OCI_THREADED and OCI_ENV_NO_MUTEX with OCIEnvCreate
|
||||
-- Added numerous fixes and improvements in tests
|
||||
-- Added option to fetch numeric/decimal data into string of characters
|
||||
-- Fixed issues in binding procedure IN/OUT parameters
|
||||
|
||||
- PostgreSQL
|
||||
-- Add reading of BYTEA data into std::string (not fully-featured binary data support yet)
|
||||
-- Add JSON data type support available in PostgreSQL 9.2+
|
||||
-- Fixed incorrect assertion in postgresql::get_error_details
|
||||
-- Fixed premature deallocation of prepared statements
|
||||
-- Fixed servers-side memory leak in prepared statements
|
||||
-- Fixed memory leak of PGresult on exception thrown
|
||||
-- Fixed isues in parsing complex PL/PSQL functions
|
||||
|
||||
- SQLite3
|
||||
-- Implemented statement::get_affected_rows() operation
|
||||
-- Fixed handling of database file path with spaces
|
||||
|
||||
- Building, testing and installation
|
||||
-- Marked Makefile.basic as deprecated (maintainer wanted)
|
||||
-- Cleaned numerous compilation warnings reported by various compilers
|
||||
-- Improved compilation using latest version of clang
|
||||
-- Added numerous improvements in CMake configuration
|
||||
-- Added SOCI_STATIC option to enable/disable static libraries build
|
||||
-- Fixed issues with ignored -DWITH_<dependency> options
|
||||
-- Fixed FindMySQL.cmake to allow use of mysqlclient from custom location
|
||||
-- Added support of SQLITE_ROOT_DIR variable to FindSQLite3.cmake module
|
||||
-- Fixed and tested CMake configuration on OSX
|
||||
-- Fixed and tested CMake configuration on FreeBSD
|
||||
-- Fixed and tested CMake configuration to use with Ninja
|
||||
-- Fixed building using Visual Studio 2010
|
||||
-- Added support for building using Visual Studio 2012
|
||||
-- Set up SOCI continuous integration at travis-ci.org
|
||||
-- Added Debian packaging support to soci-pkg repository
|
||||
-- Added Fedora/CentOS/RedHat packaging support to soci-pkg repository
|
||||
|
||||
- Documentation
|
||||
-- Review and update to catch up with current status quo
|
||||
-- Updated code examples
|
||||
-- Start maintenance and hosting of SOCI documentation per released version
|
||||
|
||||
---
|
||||
Version 3.1.0 differs from 3.0.0 in the following ways:
|
||||
|
||||
- Added Ada language binding
|
||||
|
||||
- Migraded build system from GNU Autotools and Visual Studio projects to CMake
|
||||
|
||||
- CMake build tested with Visual Studio, GCC and clang
|
||||
|
||||
- Incorporated a compromise for naming versioned shared libraries
|
||||
|
||||
- Enhanced and improved integration with Boost libraries:
|
||||
-- Boost.DateTime
|
||||
-- Boost.Fusion
|
||||
-- Boost.Optional
|
||||
-- Boost.Tuple
|
||||
|
||||
- Bug fixes and improvements in core and backends:
|
||||
-- Added soci::values::get_properties accessor useful for composing soci::type_conversion
|
||||
-- Export advanced API of backend loader from DLL.
|
||||
-- Added static factory registration functions for backends
|
||||
-- Added get_affected_rows operation
|
||||
-- Fixed thread-safety of connection pool under Windows
|
||||
-- Fixed bug with droping const qualifiers when binding to std::vector<soci::indicator>
|
||||
-- Fixed bug in default initialization of an object of const backend_factory wihch requires user-provided default constructor (see C++03/C++0x)
|
||||
-- Fixes for 64-bit builds
|
||||
-- Removed redundant exchange_traits breaking ODR on LP64
|
||||
-- Better ODBC support
|
||||
-- Type conversion support for unsigned integer types
|
||||
-- Bug ID:1971436 - incorrect rowset copy operations
|
||||
-- Bug ID:2010367 - memory leak (ODBC)
|
||||
-- Bug ID:2010409 - invalid memory allocaton in define by position (ODBC)
|
||||
-- Bug ID:2021243 - long long type support in Visual C++
|
||||
-- Patch ID:2483066 - 64bit Linux and 64bit integer submitted
|
||||
-- Patch ID:2809809 - Fix build with GCC 4.4
|
||||
-- Patch ID:2809810 - Fix SQLite3 build with GCC 4.3
|
||||
-- Patch ID:2581206 - Windows unicode application
|
||||
-- Patch ID:3058275 - install target for cmake build submitted
|
||||
-- Patch ID:3069375 - use $(prefix)/lib64 on AMD64 platforms.
|
||||
-- Improved performance while accessing query results (MySQL)
|
||||
-- Bug fixes for PROCEDURE support (MySQL)
|
||||
-- Removed throw statements from mysql_rowid_backend and mysql_blob_backend destructors (MySQL)
|
||||
-- Verify that prepared statements survive session::reconnect() operatoin (MySQL)
|
||||
-- Improved support for time and date (MySQL, PostgreSQL)
|
||||
-- Fixed bug with strings of length exceeding 255 characters (ODBC)
|
||||
-- Improved interpretation of the connect string (Oracle)
|
||||
-- Added handling of unsigned long long (Oracle, SQLite3, PostgreSQL)
|
||||
-- Fixes in integral types support (PostgreSQL)
|
||||
-- Support for colon-casts (PostgreSQL)
|
||||
-- Added possibility for use BLOB (PostgreSQL)
|
||||
-- Added support for connection property "synchronous=on|off" (SQLite3)
|
||||
-- Improved BLOB data handling (SQLite3)
|
||||
-- Improved boolean type suppport (SQLite3)
|
||||
-- Session timeout support (SQLite3)
|
||||
-- Improved tests clean-up (SQLite3)
|
||||
-- Added missing typedef of sqlite3_destructor_type which has been defined in sqlite3.h but since 3.3.10 (see comment for reference to SQLite ticket)
|
||||
|
||||
- Updated tests for various backends and SQL data types
|
||||
|
||||
- Migrated from CVS to Git repository
|
||||
|
||||
- Changed naming convensions and style across all the source code
|
||||
|
||||
- Firebird backend removed from official release as not actively maintained. Available in the Git repository.
|
||||
|
||||
---
|
||||
Version 3.0.0 differs from 2.2.0 in the following ways:
|
||||
|
||||
- Exposed the session's locale object.
|
||||
|
||||
- Moved the "no data" flag from indicators to statement.
|
||||
|
||||
- Allowed const objects as "use" elements.
|
||||
|
||||
- Added connection mode for Oracle.
|
||||
|
||||
- Added RAII support for transactions.
|
||||
|
||||
- Added the open/close/reconnect functionality.
|
||||
|
||||
- Added support for long long as a fundamental data type.
|
||||
|
||||
- Unified column names for dynamic rowset description, to overcome
|
||||
differences between database servers.
|
||||
|
||||
- Added the "simple" interface for interfacing from other languages.
|
||||
|
||||
- Added thread-safe connection pool.
|
||||
|
||||
- Added integrated support for Boost data types: gregorian_date,
|
||||
fusion and tuple.
|
||||
|
||||
- Added dynamic backend loading.
|
||||
|
||||
- Changed the naming convention to comply with Boost recommendations.
|
||||
|
||||
---
|
||||
Version 2.2.0 differs from 2.1.0 in the following ways:
|
||||
|
||||
- Added true support for statement preparation with PostgreSQL.
|
||||
|
||||
- Added support for the stream-like extraction from Row.
|
||||
|
||||
- Added STL-compatible iterator interface for select statements.
|
||||
|
||||
- Refactored the set of common tests to validate core library functionality
|
||||
independently on the target database server.
|
||||
|
||||
- Introduced new backends for MS SQL Server (via ODBC) and Firebird.
|
||||
|
||||
- Provided complete build system for both Unix (autotools) and
|
||||
Windows (solution and project files for MSVC++).
|
||||
|
||||
---
|
||||
Version 2.1.0 differs from 2.0.1 in the following ways:
|
||||
|
||||
- Added two additional backends: MySQL and SQLite3
|
||||
|
||||
- Restructured the source code layout so that the whole library was broken
|
||||
into the "core" part and independent "backends", each in its own
|
||||
directory together with appropriate tests.
|
||||
|
||||
- Provided basic Makefiles for static and shared libraries on
|
||||
Linux-compatible systems.
|
||||
|
||||
- Added the general class and function reference to the documentation.
|
||||
|
||||
---
|
||||
Version 2.0.1 differs from 2.0.0 in the following ways:
|
||||
|
||||
- Corrected some typos in documentation.
|
||||
|
||||
- Corrected handling of dynamic rowset description for those backends
|
||||
which do not have dedicated description functionality.
|
||||
|
||||
- A bug fix to correctly handle std::tm in the Oracle backend.
|
||||
|
||||
- A bug fix to correctly handle object relational mapping when
|
||||
Values::set<T>() and Values::get<T>() are called where T is a
|
||||
TypeConversion-based type.
|
||||
|
||||
---
|
||||
Version 2.0.0 differs from 1.2.1 in the following ways:
|
||||
|
||||
- The whole library was internally re-architectured to allow operation
|
||||
with many different backends. The top-level part of the library
|
||||
(the syntax layer) provides essentially the same interface as in previous
|
||||
versions of the library, but it can work with independent (and dynamically
|
||||
selected) backends, possibly targeting different database engines.
|
||||
As a prove of concept (and to encourage developments of new backends),
|
||||
the PostgreSQL backend was provided in addition to the Oracle one.
|
||||
During this re-architecturing, some minor bugs were fixed as well.
|
||||
|
||||
- The old Boost-style license was changed to the new (v. 1.0) Boost license.
|
||||
|
||||
---
|
||||
The version 1.2.1 differs from 1.2.0 in the following ways:
|
||||
|
||||
- A bug was fixed that caused compile errors on MS VC++ compiler.
|
||||
|
||||
---
|
||||
The version 1.2.0 differs from 1.1.0 in the following ways:
|
||||
|
||||
- A memory leak when reading into Row objects was fixed.
|
||||
|
||||
- Bulk (array) operations were introduced for high-performance
|
||||
applications, where the number of network round-trips can be
|
||||
significantly reduced by operating on whole arrays (vectors).
|
||||
|
||||
---
|
||||
The version 1.1.0 differs from 1.0.1 in the following ways:
|
||||
|
||||
- Explicit support for calling stored procedures was added.
|
||||
|
||||
- Dynamic row recognition (type discovery) was added.
|
||||
|
||||
- Support for user-defined data types was added.
|
||||
105
src/soci/src/CMakeLists.txt
Normal file
105
src/soci/src/CMakeLists.txt
Normal file
@@ -0,0 +1,105 @@
|
||||
###############################################################################
|
||||
#
|
||||
# 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)
|
||||
|
||||
colormsg(_HIBLUE_ "Configuring SOCI:")
|
||||
|
||||
###############################################################################
|
||||
# SOCI version information
|
||||
###############################################################################
|
||||
include(SociVersion)
|
||||
|
||||
soci_version(MAJOR 3 MINOR 2 PATCH 2)
|
||||
|
||||
###############################################################################
|
||||
# Build features and variants
|
||||
###############################################################################
|
||||
include(SociSystemInfo)
|
||||
include(SociConfig)
|
||||
|
||||
boost_report_value(SOCI_PLATFORM_NAME)
|
||||
boost_report_value(SOCI_COMPILER_NAME)
|
||||
|
||||
option(SOCI_SHARED "Enable build of shared libraries" ON)
|
||||
boost_report_value(SOCI_SHARED)
|
||||
|
||||
option(SOCI_STATIC "Enable build of static libraries" ON)
|
||||
boost_report_value(SOCI_STATIC)
|
||||
|
||||
option(SOCI_TESTS "Enable build of collection of SOCI tests" ON)
|
||||
boost_report_value(SOCI_TESTS)
|
||||
|
||||
# Put the libaries and binaries that get built into directories at the
|
||||
# top of the build tree rather than in hard-to-find leaf
|
||||
# directories. This simplifies manual testing and the use of the build
|
||||
# tree rather than installed Boost libraries.
|
||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
|
||||
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
|
||||
|
||||
###############################################################################
|
||||
# Find SOCI dependencies
|
||||
###############################################################################
|
||||
|
||||
set(SOCI_CORE_DEPENDENCIES)
|
||||
|
||||
include(SociDependencies)
|
||||
|
||||
#message("${SOCI_CORE_DEPENDENCIES}")
|
||||
|
||||
###############################################################################
|
||||
# Installation
|
||||
###############################################################################
|
||||
|
||||
if(APPLE OR CMAKE_SIZEOF_VOID_P EQUAL 4)
|
||||
set(SOCI_LIBDIR "lib")
|
||||
else()
|
||||
set(SOCI_LIBDIR "lib64")
|
||||
endif()
|
||||
|
||||
set(BINDIR "bin" CACHE PATH "The directory to install binaries into.")
|
||||
set(LIBDIR ${SOCI_LIBDIR} CACHE PATH "The directory to install libraries into.")
|
||||
set(DATADIR "share" CACHE PATH "The directory to install data files into.")
|
||||
set(INCLUDEDIR "include" CACHE PATH "The directory to install includes into.")
|
||||
|
||||
###############################################################################
|
||||
# Enable tests
|
||||
###############################################################################
|
||||
enable_testing()
|
||||
# Configure for testing with dashboard submissions to CDash
|
||||
#include(CTest) # disabled as unused
|
||||
|
||||
# Define "make check" as alias for "make test"
|
||||
add_custom_target(check COMMAND ctest)
|
||||
|
||||
###############################################################################
|
||||
# Build configured components
|
||||
###############################################################################
|
||||
include(SociBackend)
|
||||
|
||||
include_directories(${SOCI_SOURCE_DIR}/core)
|
||||
|
||||
add_subdirectory(core)
|
||||
add_subdirectory(backends)
|
||||
13
src/soci/src/CTestConfig.cmake
Normal file
13
src/soci/src/CTestConfig.cmake
Normal file
@@ -0,0 +1,13 @@
|
||||
## This file should be placed in the root directory of your project.
|
||||
## Then modify the CMakeLists.txt file in the root directory of your
|
||||
## project to incorporate the testing dashboard.
|
||||
## # The following are required to uses Dart and the Cdash dashboard
|
||||
## ENABLE_TESTING()
|
||||
## INCLUDE(CTest)
|
||||
set(CTEST_PROJECT_NAME "SOCI")
|
||||
set(CTEST_NIGHTLY_START_TIME "00:00:00 EST")
|
||||
|
||||
set(CTEST_DROP_METHOD "http")
|
||||
set(CTEST_DROP_SITE "my.cdash.org")
|
||||
set(CTEST_DROP_LOCATION "/submit.php?project=SOCI")
|
||||
set(CTEST_DROP_SITE_CDASH TRUE)
|
||||
23
src/soci/src/LICENSE_1_0.txt
Normal file
23
src/soci/src/LICENSE_1_0.txt
Normal file
@@ -0,0 +1,23 @@
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
35
src/soci/src/README
Normal file
35
src/soci/src/README
Normal file
@@ -0,0 +1,35 @@
|
||||
SOCI - The C++ Database Access Library.
|
||||
|
||||
Copyright (C) 2004-2008 Maciej Sobczak, Stephen Hutton,
|
||||
David Courtney, Pawel Aleksander Fedorynski,
|
||||
Rafal Bobrowski, Mateusz Loskot
|
||||
|
||||
The homepage of the SOCI library is:
|
||||
http://soci.sourceforge.net/
|
||||
|
||||
---
|
||||
|
||||
You should see the following files and directories here:
|
||||
|
||||
- README - This file.
|
||||
- LICENSE_1_0.txt - Full text of the Boost license.
|
||||
- CHANGES - The description of changes.
|
||||
|
||||
- contrib - Acknowledgements for contributions.
|
||||
|
||||
- doc/ - Documentation.
|
||||
|
||||
- build/ - Additional build scripts and configuration files
|
||||
for various compilation systems.
|
||||
|
||||
- src/ - The source code of the library.
|
||||
|
||||
- src/core/ - The main part of the SOCI library.
|
||||
|
||||
- src/backends/ - Directory containing implementations and tests for
|
||||
all available backends.
|
||||
|
||||
|
||||
Please see the doc/structure.html file for compilation instructions.
|
||||
|
||||
---
|
||||
0
src/soci/src/TODO
Normal file
0
src/soci/src/TODO
Normal file
5
src/soci/src/backends/.gitignore
vendored
Normal file
5
src/soci/src/backends/.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
*.o
|
||||
*.la
|
||||
*.lo
|
||||
.deps
|
||||
.libs
|
||||
48
src/soci/src/backends/CMakeLists.txt
Normal file
48
src/soci/src/backends/CMakeLists.txt
Normal file
@@ -0,0 +1,48 @@
|
||||
###############################################################################
|
||||
#
|
||||
# This file is part of CMake configuration for SOCI library
|
||||
#
|
||||
# Copyright (C) 2010 Mateusz Loskot
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE_1_0.txt or copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
#
|
||||
###############################################################################
|
||||
colormsg(_HIBLUE_ "Configuring SOCI database backends:")
|
||||
|
||||
# First, we'll investigate what can be found from database engines
|
||||
foreach(dep ${SOCI_BACKENDS_DB_DEPENDENCIES})
|
||||
string(TOUPPER ${dep} depUP)
|
||||
if (WITH_${depUP})
|
||||
find_package(${dep})
|
||||
endif()
|
||||
if(${dep}_FOUND OR ${depUP}_FOUND)
|
||||
set(${depUP}_FOUND ON)
|
||||
else()
|
||||
set(${depUP}_FOUND OFF)
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# get all files in backends
|
||||
file(GLOB backend_dirs RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *)
|
||||
|
||||
# empty backend always on by default
|
||||
option(SOCI_EMPTY "Build empty backend" ON)
|
||||
if(SOCI_EMPTY)
|
||||
set(WITH_EMPTY ON)
|
||||
set(EMPTY_FOUND ON)
|
||||
endif()
|
||||
|
||||
# enable only found backends
|
||||
foreach(dir ${backend_dirs})
|
||||
if(IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${dir})
|
||||
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${dir}/CMakeLists.txt)
|
||||
string(TOUPPER ${dir} dirUP)
|
||||
if(${dirUP}_FOUND AND WITH_${dirUP})
|
||||
add_subdirectory(${dir})
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
message(STATUS "")
|
||||
18
src/soci/src/backends/db2/CMakeLists.txt
Normal file
18
src/soci/src/backends/db2/CMakeLists.txt
Normal file
@@ -0,0 +1,18 @@
|
||||
###############################################################################
|
||||
#
|
||||
# This file is part of CMake configuration for SOCI library
|
||||
#
|
||||
# Copyright (C) 2011 Denis Chapligin
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE_1_0.txt or copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
#
|
||||
###############################################################################
|
||||
soci_backend(DB2
|
||||
DEPENDS DB2
|
||||
HEADERS soci-db2.h
|
||||
DESCRIPTION "SOCI backend for DB2 Universal Database"
|
||||
AUTHORS "Denis Chapligin"
|
||||
MAINTAINERS "Denis Chapligin")
|
||||
|
||||
add_subdirectory(test)
|
||||
62
src/soci/src/backends/db2/blob.cpp
Normal file
62
src/soci/src/backends/db2/blob.cpp
Normal file
@@ -0,0 +1,62 @@
|
||||
//
|
||||
// Copyright (C) 2011-2013 Denis Chapligin
|
||||
// Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#define SOCI_DB2_SOURCE
|
||||
#include "soci-db2.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4355)
|
||||
#endif
|
||||
|
||||
using namespace soci;
|
||||
using namespace soci::details;
|
||||
|
||||
|
||||
db2_blob_backend::db2_blob_backend(db2_session_backend &session)
|
||||
: session_(session)
|
||||
{
|
||||
// ...
|
||||
}
|
||||
|
||||
db2_blob_backend::~db2_blob_backend()
|
||||
{
|
||||
// ...
|
||||
}
|
||||
|
||||
std::size_t db2_blob_backend::get_len()
|
||||
{
|
||||
// ...
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::size_t db2_blob_backend::read(
|
||||
std::size_t /* offset */, char * /* buf */, std::size_t /* toRead */)
|
||||
{
|
||||
// ...
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::size_t db2_blob_backend::write(
|
||||
std::size_t /* offset */, char const * /* buf */,
|
||||
std::size_t /* toWrite */)
|
||||
{
|
||||
// ...
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::size_t db2_blob_backend::append(
|
||||
char const * /* buf */, std::size_t /* toWrite */)
|
||||
{
|
||||
// ...
|
||||
return 0;
|
||||
}
|
||||
|
||||
void db2_blob_backend::trim(std::size_t /* newLen */)
|
||||
{
|
||||
// ...
|
||||
}
|
||||
21
src/soci/src/backends/db2/common.h
Normal file
21
src/soci/src/backends/db2/common.h
Normal file
@@ -0,0 +1,21 @@
|
||||
//
|
||||
// Copyright (C) 2013 Mateusz Loskot <mateusz@loskot.net>
|
||||
// Copyright (C) 2011-2013 Denis Chapligin
|
||||
// Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef SOCI_DB2_COMMON_H_INCLUDED
|
||||
#define SOCI_DB2_COMMON_H_INCLUDED
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace soci { namespace details { namespace db2 {
|
||||
|
||||
const std::size_t cli_max_buffer = 1024 * 1024 * 1024; //CLI limit is about 3 GB, but 1GB should be enough
|
||||
|
||||
}}} // namespace soci::details::db2
|
||||
|
||||
#endif // SOCI_DB2_COMMON_H_INCLUDED
|
||||
40
src/soci/src/backends/db2/factory.cpp
Normal file
40
src/soci/src/backends/db2/factory.cpp
Normal file
@@ -0,0 +1,40 @@
|
||||
//
|
||||
// Copyright (C) 2011-2013 Denis Chapligin
|
||||
// Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton, David Courtney
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#define SOCI_DB2_SOURCE
|
||||
#include "soci-db2.h"
|
||||
#include <backend-loader.h>
|
||||
|
||||
using namespace soci;
|
||||
using namespace soci::details;
|
||||
|
||||
|
||||
// concrete factory for ODBC concrete strategies
|
||||
db2_session_backend * db2_backend_factory::make_session(
|
||||
connection_parameters const & parameters) const
|
||||
{
|
||||
return new db2_session_backend(parameters);
|
||||
}
|
||||
|
||||
db2_backend_factory const soci::db2;
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
// for dynamic backend loading
|
||||
SOCI_DB2_DECL backend_factory const * factory_db2()
|
||||
{
|
||||
return &soci::db2;
|
||||
}
|
||||
|
||||
SOCI_DB2_DECL void register_factory_db2()
|
||||
{
|
||||
soci::dynamic_backends::register_backend("db2", soci::db2);
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
28
src/soci/src/backends/db2/row-id.cpp
Normal file
28
src/soci/src/backends/db2/row-id.cpp
Normal file
@@ -0,0 +1,28 @@
|
||||
//
|
||||
// Copyright (C) 2011-2013 Denis Chapligin
|
||||
// Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#define SOCI_DB2_SOURCE
|
||||
#include "soci-db2.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4355)
|
||||
#endif
|
||||
|
||||
using namespace soci;
|
||||
using namespace soci::details;
|
||||
|
||||
|
||||
db2_rowid_backend::db2_rowid_backend(db2_session_backend & /* session */)
|
||||
{
|
||||
// ...
|
||||
}
|
||||
|
||||
db2_rowid_backend::~db2_rowid_backend()
|
||||
{
|
||||
// ...
|
||||
}
|
||||
217
src/soci/src/backends/db2/session.cpp
Normal file
217
src/soci/src/backends/db2/session.cpp
Normal file
@@ -0,0 +1,217 @@
|
||||
//
|
||||
// Copyright (C) 2011-2013 Denis Chapligin
|
||||
// Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#define SOCI_DB2_SOURCE
|
||||
#include "soci-db2.h"
|
||||
#include <connection-parameters.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4355)
|
||||
#endif
|
||||
|
||||
using namespace soci;
|
||||
using namespace soci::details;
|
||||
|
||||
const std::string db2_soci_error::sqlState(std::string const & msg,const SQLSMALLINT htype,const SQLHANDLE hndl) {
|
||||
std::ostringstream ss(msg, std::ostringstream::app);
|
||||
|
||||
|
||||
SQLCHAR message[SQL_MAX_MESSAGE_LENGTH + 1];
|
||||
SQLCHAR sqlstate[SQL_SQLSTATE_SIZE + 1];
|
||||
SQLINTEGER sqlcode;
|
||||
SQLSMALLINT length;
|
||||
|
||||
if ( SQLGetDiagRec(htype,
|
||||
hndl,
|
||||
1,
|
||||
sqlstate,
|
||||
&sqlcode,
|
||||
message,
|
||||
SQL_MAX_MESSAGE_LENGTH + 1,
|
||||
&length) == SQL_SUCCESS ) {
|
||||
ss<<" SQLMESSAGE: ";
|
||||
ss<<message;
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
void db2_session_backend::parseKeyVal(std::string const & keyVal) {
|
||||
size_t delimiter=keyVal.find_first_of("=");
|
||||
std::string key=keyVal.substr(0,delimiter);
|
||||
std::string value=keyVal.substr(delimiter+1,keyVal.length());
|
||||
|
||||
if (!key.compare("DSN")) {
|
||||
this->dsn=value;
|
||||
}
|
||||
if (!key.compare("Uid")) {
|
||||
this->username=value;
|
||||
}
|
||||
if (!key.compare("Pwd")) {
|
||||
this->password=value;
|
||||
}
|
||||
this->autocommit=true; //Default value
|
||||
if (!key.compare("autocommit")) {
|
||||
if (!value.compare("off")) {
|
||||
this->autocommit=false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* DSN=SAMPLE;Uid=db2inst1;Pwd=db2inst1;AutoCommit=off */
|
||||
void db2_session_backend::parseConnectString(std::string const & connectString) {
|
||||
std::string processingString(connectString);
|
||||
size_t delimiter=processingString.find_first_of(";");
|
||||
while(delimiter!=std::string::npos) {
|
||||
std::string keyVal=processingString.substr(0,delimiter);
|
||||
parseKeyVal(keyVal);
|
||||
processingString=processingString.erase(0,delimiter+1);
|
||||
delimiter=processingString.find_first_of(";");
|
||||
}
|
||||
if (!processingString.empty()) {
|
||||
parseKeyVal(processingString);
|
||||
}
|
||||
}
|
||||
|
||||
db2_session_backend::db2_session_backend(
|
||||
connection_parameters const & parameters) :
|
||||
in_transaction(false)
|
||||
{
|
||||
parseConnectString(parameters.get_connect_string());
|
||||
SQLRETURN cliRC = SQL_SUCCESS;
|
||||
|
||||
/* Prepare handles */
|
||||
cliRC = SQLAllocHandle(SQL_HANDLE_ENV,SQL_NULL_HANDLE,&hEnv);
|
||||
if (cliRC != SQL_SUCCESS) {
|
||||
throw db2_soci_error("Error while allocating the enironment handle",cliRC);
|
||||
}
|
||||
|
||||
cliRC = SQLAllocHandle(SQL_HANDLE_DBC, hEnv, &hDbc);
|
||||
if (cliRC != SQL_SUCCESS) {
|
||||
std::string msg=db2_soci_error::sqlState("Error while allocating the connection handle",SQL_HANDLE_ENV,hEnv);
|
||||
SQLFreeHandle(SQL_HANDLE_ENV,hEnv);
|
||||
throw db2_soci_error(msg,cliRC);
|
||||
}
|
||||
|
||||
/* Set autocommit */
|
||||
if(this->autocommit) {
|
||||
cliRC = SQLSetConnectAttr(hDbc,SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_ON, SQL_NTS);
|
||||
} else {
|
||||
cliRC = SQLSetConnectAttr(hDbc,SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_OFF, SQL_NTS);
|
||||
}
|
||||
if (cliRC != SQL_SUCCESS) {
|
||||
std::string msg=db2_soci_error::sqlState("Error while setting autocommit attribute",SQL_HANDLE_DBC,hDbc);
|
||||
SQLFreeHandle(SQL_HANDLE_DBC,hDbc);
|
||||
SQLFreeHandle(SQL_HANDLE_ENV,hEnv);
|
||||
throw db2_soci_error(msg,cliRC);
|
||||
}
|
||||
|
||||
/* Connect to database */
|
||||
cliRC = SQLConnect(hDbc, const_cast<SQLCHAR *>((const SQLCHAR *) dsn.c_str()), SQL_NTS,
|
||||
const_cast<SQLCHAR *>((const SQLCHAR *) username.c_str()), SQL_NTS,
|
||||
const_cast<SQLCHAR *>((const SQLCHAR *) password.c_str()), SQL_NTS);
|
||||
if (cliRC != SQL_SUCCESS) {
|
||||
std::string msg=db2_soci_error::sqlState("Error connecting to database",SQL_HANDLE_DBC,hDbc);
|
||||
SQLFreeHandle(SQL_HANDLE_DBC,hDbc);
|
||||
SQLFreeHandle(SQL_HANDLE_ENV,hEnv);
|
||||
throw db2_soci_error(msg,cliRC);
|
||||
}
|
||||
}
|
||||
|
||||
db2_session_backend::~db2_session_backend()
|
||||
{
|
||||
clean_up();
|
||||
}
|
||||
|
||||
void db2_session_backend::begin()
|
||||
{
|
||||
// In DB2, transations begin implicitly; however, autocommit must be disabled for the duration of the transaction
|
||||
if(autocommit)
|
||||
{
|
||||
SQLRETURN cliRC = SQLSetConnectAttr(hDbc, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER) SQL_AUTOCOMMIT_OFF, SQL_NTS);
|
||||
if (cliRC != SQL_SUCCESS && cliRC != SQL_SUCCESS_WITH_INFO)
|
||||
{
|
||||
std::string msg=db2_soci_error::sqlState("Clearing the autocommit attribute failed", SQL_HANDLE_DBC, hDbc);
|
||||
SQLFreeHandle(SQL_HANDLE_DBC,hDbc);
|
||||
SQLFreeHandle(SQL_HANDLE_ENV,hEnv);
|
||||
throw db2_soci_error(msg,cliRC);
|
||||
}
|
||||
}
|
||||
|
||||
in_transaction = true;
|
||||
}
|
||||
|
||||
void db2_session_backend::commit()
|
||||
{
|
||||
if (!autocommit || in_transaction) {
|
||||
in_transaction = false;
|
||||
SQLRETURN cliRC = SQLEndTran(SQL_HANDLE_DBC,hDbc,SQL_COMMIT);
|
||||
if(autocommit)
|
||||
{
|
||||
SQLRETURN cliRC2 = SQLSetConnectAttr(hDbc, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER) SQL_AUTOCOMMIT_ON, SQL_NTS);
|
||||
if ((cliRC == SQL_SUCCESS || cliRC == SQL_SUCCESS_WITH_INFO) &&
|
||||
cliRC2 != SQL_SUCCESS && cliRC2 != SQL_SUCCESS_WITH_INFO)
|
||||
{
|
||||
std::string msg=db2_soci_error::sqlState("Setting the autocommit attribute failed", SQL_HANDLE_DBC, hDbc);
|
||||
SQLFreeHandle(SQL_HANDLE_DBC,hDbc);
|
||||
SQLFreeHandle(SQL_HANDLE_ENV,hEnv);
|
||||
throw db2_soci_error(msg,cliRC);
|
||||
}
|
||||
}
|
||||
if (cliRC != SQL_SUCCESS && cliRC != SQL_SUCCESS_WITH_INFO) {
|
||||
throw db2_soci_error("Commit failed",cliRC);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void db2_session_backend::rollback()
|
||||
{
|
||||
if (!autocommit || in_transaction) {
|
||||
in_transaction = false;
|
||||
SQLRETURN cliRC = SQLEndTran(SQL_HANDLE_DBC,hDbc,SQL_ROLLBACK);
|
||||
if(autocommit)
|
||||
{
|
||||
SQLRETURN cliRC2 = SQLSetConnectAttr(hDbc, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER) SQL_AUTOCOMMIT_ON, SQL_NTS);
|
||||
if ((cliRC == SQL_SUCCESS || cliRC == SQL_SUCCESS_WITH_INFO) &&
|
||||
cliRC2 != SQL_SUCCESS && cliRC2 != SQL_SUCCESS_WITH_INFO)
|
||||
{
|
||||
std::string msg=db2_soci_error::sqlState("Setting the autocommit attribute failed", SQL_HANDLE_DBC, hDbc);
|
||||
SQLFreeHandle(SQL_HANDLE_DBC,hDbc);
|
||||
SQLFreeHandle(SQL_HANDLE_ENV,hEnv);
|
||||
throw db2_soci_error(msg,cliRC);
|
||||
}
|
||||
}
|
||||
if (cliRC != SQL_SUCCESS && cliRC != SQL_SUCCESS_WITH_INFO) {
|
||||
throw db2_soci_error("Rollback failed",cliRC);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void db2_session_backend::clean_up()
|
||||
{
|
||||
// if a transaction is in progress, it will automatically be rolled back upon when the connection is disconnected/freed
|
||||
in_transaction = false;
|
||||
|
||||
SQLDisconnect(hDbc);
|
||||
SQLFreeHandle(SQL_HANDLE_DBC,hDbc);
|
||||
SQLFreeHandle(SQL_HANDLE_ENV,hEnv);
|
||||
}
|
||||
|
||||
db2_statement_backend * db2_session_backend::make_statement_backend()
|
||||
{
|
||||
return new db2_statement_backend(*this);
|
||||
}
|
||||
|
||||
db2_rowid_backend * db2_session_backend::make_rowid_backend()
|
||||
{
|
||||
return new db2_rowid_backend(*this);
|
||||
}
|
||||
|
||||
db2_blob_backend * db2_session_backend::make_blob_backend()
|
||||
{
|
||||
return new db2_blob_backend(*this);
|
||||
}
|
||||
282
src/soci/src/backends/db2/soci-db2.h
Normal file
282
src/soci/src/backends/db2/soci-db2.h
Normal file
@@ -0,0 +1,282 @@
|
||||
//
|
||||
// Copyright (C) 2011-2013 Denis Chapligin
|
||||
// Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef SOCI_DB2_H_INCLUDED
|
||||
#define SOCI_DB2_H_INCLUDED
|
||||
|
||||
#ifdef _WIN32
|
||||
# ifdef SOCI_DLL
|
||||
# ifdef SOCI_DB2_SOURCE
|
||||
# define SOCI_DB2_DECL __declspec(dllexport)
|
||||
# else
|
||||
# define SOCI_DB2_DECL __declspec(dllimport)
|
||||
# endif // SOCI_DB2_SOURCE
|
||||
# endif // SOCI_DLL
|
||||
#endif // _WIN32
|
||||
//
|
||||
// If SOCI_DB2_DECL isn't defined yet define it now
|
||||
#ifndef SOCI_DB2_DECL
|
||||
# define SOCI_DB2_DECL
|
||||
#endif
|
||||
|
||||
#include "soci-backend.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
|
||||
#include <sqlcli1.h>
|
||||
|
||||
namespace soci
|
||||
{
|
||||
namespace details { namespace db2
|
||||
{
|
||||
enum binding_method
|
||||
{
|
||||
BOUND_BY_NONE,
|
||||
BOUND_BY_NAME,
|
||||
BOUND_BY_POSITION
|
||||
};
|
||||
}}
|
||||
|
||||
static const std::size_t maxBuffer = 1024 * 1024 * 1024; //CLI limit is about 3 GB, but 1GB should be enough
|
||||
|
||||
class db2_soci_error : public soci_error {
|
||||
public:
|
||||
db2_soci_error(std::string const & msg, SQLRETURN rc) : soci_error(msg),errorCode(rc) {};
|
||||
~db2_soci_error() throw() { };
|
||||
|
||||
//We have to extract error information before exception throwing, cause CLI handles could be broken at the construction time
|
||||
static const std::string sqlState(std::string const & msg,const SQLSMALLINT htype,const SQLHANDLE hndl);
|
||||
|
||||
SQLRETURN errorCode;
|
||||
};
|
||||
|
||||
struct db2_statement_backend;
|
||||
|
||||
struct SOCI_DB2_DECL db2_standard_into_type_backend : details::standard_into_type_backend
|
||||
{
|
||||
db2_standard_into_type_backend(db2_statement_backend &st)
|
||||
: statement_(st),buf(NULL)
|
||||
{}
|
||||
|
||||
void define_by_pos(int& position, void* data, details::exchange_type type);
|
||||
|
||||
void pre_fetch();
|
||||
void post_fetch(bool gotData, bool calledFromFetch, indicator* ind);
|
||||
|
||||
void clean_up();
|
||||
|
||||
db2_statement_backend& statement_;
|
||||
|
||||
char* buf;
|
||||
void *data;
|
||||
details::exchange_type type;
|
||||
int position;
|
||||
SQLSMALLINT cType;
|
||||
SQLLEN valueLen;
|
||||
};
|
||||
|
||||
struct SOCI_DB2_DECL db2_vector_into_type_backend : details::vector_into_type_backend
|
||||
{
|
||||
db2_vector_into_type_backend(db2_statement_backend &st)
|
||||
: statement_(st),buf(NULL)
|
||||
{}
|
||||
|
||||
void define_by_pos(int& position, void* data, details::exchange_type type);
|
||||
|
||||
void pre_fetch();
|
||||
void post_fetch(bool gotData, indicator* ind);
|
||||
|
||||
void resize(std::size_t sz);
|
||||
std::size_t size();
|
||||
|
||||
void clean_up();
|
||||
|
||||
db2_statement_backend& statement_;
|
||||
|
||||
void prepare_indicators(std::size_t size);
|
||||
|
||||
SQLLEN *indptr;
|
||||
std::vector<SQLLEN> indVec;
|
||||
void *data;
|
||||
char *buf;
|
||||
int position_;
|
||||
details::exchange_type type;
|
||||
SQLSMALLINT cType;
|
||||
std::size_t colSize;
|
||||
};
|
||||
|
||||
struct SOCI_DB2_DECL db2_standard_use_type_backend : details::standard_use_type_backend
|
||||
{
|
||||
db2_standard_use_type_backend(db2_statement_backend &st)
|
||||
: statement_(st),buf(NULL),ind(0)
|
||||
{}
|
||||
|
||||
void bind_by_pos(int& position, void* data, details::exchange_type type, bool readOnly);
|
||||
void bind_by_name(std::string const& name, void* data, details::exchange_type type, bool readOnly);
|
||||
|
||||
void pre_use(indicator const* ind);
|
||||
void post_use(bool gotData, indicator* ind);
|
||||
|
||||
void clean_up();
|
||||
|
||||
db2_statement_backend& statement_;
|
||||
|
||||
void *prepare_for_bind(void *data, SQLLEN &size, SQLSMALLINT &sqlType, SQLSMALLINT &cType);
|
||||
|
||||
void *data;
|
||||
details::exchange_type type;
|
||||
int position;
|
||||
std::string name;
|
||||
char* buf;
|
||||
SQLLEN ind;
|
||||
};
|
||||
|
||||
struct SOCI_DB2_DECL db2_vector_use_type_backend : details::vector_use_type_backend
|
||||
{
|
||||
db2_vector_use_type_backend(db2_statement_backend &st)
|
||||
: statement_(st),buf(NULL) {}
|
||||
|
||||
void bind_by_pos(int& position, void* data, details::exchange_type type);
|
||||
void bind_by_name(std::string const& name, void* data, details::exchange_type type);
|
||||
|
||||
void pre_use(indicator const* ind);
|
||||
|
||||
std::size_t size();
|
||||
|
||||
void clean_up();
|
||||
|
||||
db2_statement_backend& statement_;
|
||||
|
||||
void prepare_indicators(std::size_t size);
|
||||
void prepare_for_bind(void *&data, SQLUINTEGER &size,SQLSMALLINT &sqlType, SQLSMALLINT &cType);
|
||||
void bind_helper(int &position, void *data, details::exchange_type type);
|
||||
|
||||
SQLLEN *indptr;
|
||||
std::vector<SQLLEN> indVec;
|
||||
void *data;
|
||||
char *buf;
|
||||
details::exchange_type type;
|
||||
std::size_t colSize;
|
||||
};
|
||||
|
||||
struct db2_session_backend;
|
||||
struct SOCI_DB2_DECL db2_statement_backend : details::statement_backend
|
||||
{
|
||||
db2_statement_backend(db2_session_backend &session);
|
||||
|
||||
void alloc();
|
||||
void clean_up();
|
||||
void prepare(std::string const& query, details::statement_type eType);
|
||||
|
||||
exec_fetch_result execute(int number);
|
||||
exec_fetch_result fetch(int number);
|
||||
|
||||
long long get_affected_rows();
|
||||
int get_number_of_rows();
|
||||
|
||||
std::string rewrite_for_procedure_call(std::string const& query);
|
||||
|
||||
int prepare_for_describe();
|
||||
void describe_column(int colNum, data_type& dtype, std::string& columnName);
|
||||
std::size_t column_size(int col);
|
||||
|
||||
db2_standard_into_type_backend* make_into_type_backend();
|
||||
db2_standard_use_type_backend* make_use_type_backend();
|
||||
db2_vector_into_type_backend* make_vector_into_type_backend();
|
||||
db2_vector_use_type_backend* make_vector_use_type_backend();
|
||||
|
||||
db2_session_backend& session_;
|
||||
|
||||
SQLHANDLE hStmt;
|
||||
std::string query_;
|
||||
std::vector<std::string> names;
|
||||
bool hasVectorUseElements;
|
||||
SQLUINTEGER numRowsFetched;
|
||||
details::db2::binding_method use_binding_method_;
|
||||
};
|
||||
|
||||
struct db2_rowid_backend : details::rowid_backend
|
||||
{
|
||||
db2_rowid_backend(db2_session_backend &session);
|
||||
|
||||
~db2_rowid_backend();
|
||||
};
|
||||
|
||||
struct db2_blob_backend : details::blob_backend
|
||||
{
|
||||
db2_blob_backend(db2_session_backend& session);
|
||||
|
||||
~db2_blob_backend();
|
||||
|
||||
std::size_t get_len();
|
||||
std::size_t read(std::size_t offset, char* buf, std::size_t toRead);
|
||||
std::size_t write(std::size_t offset, char const* buf, std::size_t toWrite);
|
||||
std::size_t append(char const* buf, std::size_t toWrite);
|
||||
void trim(std::size_t newLen);
|
||||
|
||||
db2_session_backend& session_;
|
||||
};
|
||||
|
||||
struct db2_session_backend : details::session_backend
|
||||
{
|
||||
db2_session_backend(connection_parameters const& parameters);
|
||||
|
||||
~db2_session_backend();
|
||||
|
||||
void begin();
|
||||
void commit();
|
||||
void rollback();
|
||||
|
||||
std::string get_backend_name() const { return "DB2"; }
|
||||
|
||||
void clean_up();
|
||||
|
||||
db2_statement_backend* make_statement_backend();
|
||||
db2_rowid_backend* make_rowid_backend();
|
||||
db2_blob_backend* make_blob_backend();
|
||||
|
||||
void parseConnectString(std::string const &);
|
||||
void parseKeyVal(std::string const &);
|
||||
|
||||
std::string dsn;
|
||||
std::string username;
|
||||
std::string password;
|
||||
bool autocommit;
|
||||
bool in_transaction;
|
||||
|
||||
SQLHANDLE hEnv; /* Environment handle */
|
||||
SQLHANDLE hDbc; /* Connection handle */
|
||||
};
|
||||
|
||||
struct SOCI_DB2_DECL db2_backend_factory : backend_factory
|
||||
{
|
||||
db2_backend_factory() {}
|
||||
db2_session_backend* make_session(
|
||||
connection_parameters const & parameters) const;
|
||||
};
|
||||
|
||||
extern SOCI_DB2_DECL db2_backend_factory const db2;
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
// for dynamic backend loading
|
||||
SOCI_DB2_DECL backend_factory const* factory_db2();
|
||||
SOCI_DB2_DECL void register_factory_db2();
|
||||
|
||||
} // extern "C"
|
||||
|
||||
} // namespace soci
|
||||
|
||||
#endif // SOCI_DB2_H_INCLUDED
|
||||
168
src/soci/src/backends/db2/standard-into-type.cpp
Normal file
168
src/soci/src/backends/db2/standard-into-type.cpp
Normal file
@@ -0,0 +1,168 @@
|
||||
//
|
||||
// Copyright (C) 2011-2013 Denis Chapligin
|
||||
// Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton, David Courtney
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#define SOCI_DB2_SOURCE
|
||||
#include "soci-db2.h"
|
||||
#include "common.h"
|
||||
#include <ctime>
|
||||
|
||||
using namespace soci;
|
||||
using namespace soci::details;
|
||||
|
||||
|
||||
void db2_standard_into_type_backend::define_by_pos(
|
||||
int & position, void * data, exchange_type type)
|
||||
{
|
||||
this->data = data;
|
||||
this->type = type;
|
||||
this->position = position;
|
||||
position++;
|
||||
|
||||
SQLUINTEGER size = 0;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case x_char:
|
||||
cType = SQL_C_CHAR;
|
||||
size = sizeof(char) + 1;
|
||||
buf = new char[size];
|
||||
data = buf;
|
||||
break;
|
||||
case x_stdstring:
|
||||
cType = SQL_C_CHAR;
|
||||
// Patch: set to min between column size and 100MB (used ot be 32769)
|
||||
// Column size for text data type can be too large for buffer allocation
|
||||
size = statement_.column_size(this->position);
|
||||
size = size > details::db2::cli_max_buffer ? details::db2::cli_max_buffer : size;
|
||||
size++;
|
||||
buf = new char[size];
|
||||
data = buf;
|
||||
break;
|
||||
case x_short:
|
||||
cType = SQL_C_SSHORT;
|
||||
size = sizeof(short);
|
||||
break;
|
||||
case x_integer:
|
||||
cType = SQL_C_SLONG;
|
||||
size = sizeof(SQLINTEGER);
|
||||
break;
|
||||
case x_long_long:
|
||||
cType = SQL_C_SBIGINT;
|
||||
size = sizeof(long long);
|
||||
break;
|
||||
case x_unsigned_long_long:
|
||||
cType = SQL_C_UBIGINT;
|
||||
size = sizeof(unsigned long long);
|
||||
break;
|
||||
case x_double:
|
||||
cType = SQL_C_DOUBLE;
|
||||
size = sizeof(double);
|
||||
break;
|
||||
case x_stdtm:
|
||||
cType = SQL_C_TYPE_TIMESTAMP;
|
||||
size = sizeof(TIMESTAMP_STRUCT);
|
||||
buf = new char[size];
|
||||
data = buf;
|
||||
break;
|
||||
case x_rowid:
|
||||
cType = SQL_C_UBIGINT;
|
||||
size = sizeof(unsigned long long);
|
||||
break;
|
||||
default:
|
||||
throw soci_error("Into element used with non-supported type.");
|
||||
}
|
||||
|
||||
valueLen = 0;
|
||||
|
||||
SQLRETURN cliRC = SQLBindCol(statement_.hStmt, static_cast<SQLUSMALLINT>(this->position),
|
||||
static_cast<SQLUSMALLINT>(cType), data, size, &valueLen);
|
||||
if (cliRC != SQL_SUCCESS)
|
||||
{
|
||||
throw db2_soci_error("Error while pre-fething into type",cliRC);
|
||||
}
|
||||
}
|
||||
|
||||
void db2_standard_into_type_backend::pre_fetch()
|
||||
{
|
||||
//...
|
||||
}
|
||||
|
||||
void db2_standard_into_type_backend::post_fetch(
|
||||
bool gotData, bool calledFromFetch, indicator * ind)
|
||||
{
|
||||
if (calledFromFetch == true && gotData == false)
|
||||
{
|
||||
// this is a normal end-of-rowset condition,
|
||||
// no need to do anything (fetch() will return false)
|
||||
return;
|
||||
}
|
||||
|
||||
if (gotData)
|
||||
{
|
||||
// first, deal with indicators
|
||||
if (SQL_NULL_DATA == valueLen)
|
||||
{
|
||||
if (ind == NULL)
|
||||
{
|
||||
throw soci_error(
|
||||
"Null value fetched and no indicator defined.");
|
||||
}
|
||||
|
||||
*ind = i_null;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ind != NULL)
|
||||
{
|
||||
*ind = i_ok;
|
||||
}
|
||||
}
|
||||
|
||||
// only std::string and std::tm need special handling
|
||||
if (type == x_char)
|
||||
{
|
||||
char *c = static_cast<char*>(data);
|
||||
*c = buf[0];
|
||||
}
|
||||
if (type == x_stdstring)
|
||||
{
|
||||
std::string *s = static_cast<std::string *>(data);
|
||||
*s = buf;
|
||||
if (s->size() >= (details::db2::cli_max_buffer - 1))
|
||||
{
|
||||
throw soci_error("Buffer size overflow; maybe got too large string");
|
||||
}
|
||||
}
|
||||
else if (type == x_stdtm)
|
||||
{
|
||||
std::tm *t = static_cast<std::tm *>(data);
|
||||
|
||||
TIMESTAMP_STRUCT * ts = reinterpret_cast<TIMESTAMP_STRUCT*>(buf);
|
||||
t->tm_isdst = -1;
|
||||
t->tm_year = ts->year - 1900;
|
||||
t->tm_mon = ts->month - 1;
|
||||
t->tm_mday = ts->day;
|
||||
t->tm_hour = ts->hour;
|
||||
t->tm_min = ts->minute;
|
||||
t->tm_sec = ts->second;
|
||||
|
||||
// normalize and compute the remaining fields
|
||||
std::mktime(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void db2_standard_into_type_backend::clean_up()
|
||||
{
|
||||
if (buf)
|
||||
{
|
||||
delete [] buf;
|
||||
buf = 0;
|
||||
}
|
||||
}
|
||||
201
src/soci/src/backends/db2/standard-use-type.cpp
Normal file
201
src/soci/src/backends/db2/standard-use-type.cpp
Normal file
@@ -0,0 +1,201 @@
|
||||
//
|
||||
// Copyright (C) 2011-2013 Denis Chapligin
|
||||
// Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton, David Courtney
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#define SOCI_DB2_SOURCE
|
||||
#include "soci-db2.h"
|
||||
#include <cctype>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <ctime>
|
||||
#include <sstream>
|
||||
|
||||
using namespace soci;
|
||||
using namespace soci::details;
|
||||
|
||||
void *db2_standard_use_type_backend::prepare_for_bind(
|
||||
void *data, SQLLEN &size, SQLSMALLINT &sqlType, SQLSMALLINT &cType)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
// simple cases
|
||||
case x_short:
|
||||
sqlType = SQL_SMALLINT;
|
||||
cType = SQL_C_SSHORT;
|
||||
size = sizeof(short);
|
||||
break;
|
||||
case x_integer:
|
||||
sqlType = SQL_INTEGER;
|
||||
cType = SQL_C_SLONG;
|
||||
size = sizeof(int);
|
||||
break;
|
||||
case x_long_long:
|
||||
sqlType = SQL_BIGINT;
|
||||
cType = SQL_C_SBIGINT;
|
||||
size = sizeof(long long);
|
||||
break;
|
||||
case x_unsigned_long_long:
|
||||
sqlType = SQL_BIGINT;
|
||||
cType = SQL_C_UBIGINT;
|
||||
size = sizeof(unsigned long long);
|
||||
break;
|
||||
case x_double:
|
||||
sqlType = SQL_DOUBLE;
|
||||
cType = SQL_C_DOUBLE;
|
||||
size = sizeof(double);
|
||||
break;
|
||||
|
||||
// cases that require adjustments and buffer management
|
||||
case x_char:
|
||||
{
|
||||
sqlType = SQL_CHAR;
|
||||
cType = SQL_C_CHAR;
|
||||
size = sizeof(char) + 1;
|
||||
buf = new char[size];
|
||||
char *c = static_cast<char*>(data);
|
||||
buf[0] = *c;
|
||||
buf[1] = '\0';
|
||||
ind = SQL_NTS;
|
||||
}
|
||||
break;
|
||||
case x_stdstring:
|
||||
{
|
||||
// TODO: No textual value is assigned here!
|
||||
|
||||
std::string* s = static_cast<std::string*>(data);
|
||||
sqlType = SQL_LONGVARCHAR;
|
||||
cType = SQL_C_CHAR;
|
||||
size = s->size() + 1;
|
||||
buf = new char[size];
|
||||
strncpy(buf, s->c_str(), size);
|
||||
ind = SQL_NTS;
|
||||
}
|
||||
break;
|
||||
case x_stdtm:
|
||||
{
|
||||
sqlType = SQL_TIMESTAMP;
|
||||
cType = SQL_C_TIMESTAMP;
|
||||
buf = new char[sizeof(TIMESTAMP_STRUCT)];
|
||||
std::tm *t = static_cast<std::tm *>(data);
|
||||
data = buf;
|
||||
size = 19; // This number is not the size in bytes, but the number
|
||||
// of characters in the date if it was written out
|
||||
// yyyy-mm-dd hh:mm:ss
|
||||
|
||||
TIMESTAMP_STRUCT * ts = reinterpret_cast<TIMESTAMP_STRUCT*>(buf);
|
||||
|
||||
ts->year = static_cast<SQLSMALLINT>(t->tm_year + 1900);
|
||||
ts->month = static_cast<SQLUSMALLINT>(t->tm_mon + 1);
|
||||
ts->day = static_cast<SQLUSMALLINT>(t->tm_mday);
|
||||
ts->hour = static_cast<SQLUSMALLINT>(t->tm_hour);
|
||||
ts->minute = static_cast<SQLUSMALLINT>(t->tm_min);
|
||||
ts->second = static_cast<SQLUSMALLINT>(t->tm_sec);
|
||||
ts->fraction = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case x_blob:
|
||||
break;
|
||||
case x_statement:
|
||||
case x_rowid:
|
||||
break;
|
||||
}
|
||||
|
||||
// Return either the pointer to C++ data itself or the buffer that we
|
||||
// allocated, if any.
|
||||
return buf ? buf : data;
|
||||
}
|
||||
|
||||
void db2_standard_use_type_backend::bind_by_pos(
|
||||
int &position, void *data, exchange_type type, bool /* readOnly */)
|
||||
{
|
||||
if (statement_.use_binding_method_ == details::db2::BOUND_BY_NAME)
|
||||
{
|
||||
throw soci_error("Binding for use elements must be either by position or by name.");
|
||||
}
|
||||
statement_.use_binding_method_ = details::db2::BOUND_BY_POSITION;
|
||||
|
||||
this->data = data; // for future reference
|
||||
this->type = type; // for future reference
|
||||
this->position = position++;
|
||||
}
|
||||
|
||||
void db2_standard_use_type_backend::bind_by_name(
|
||||
std::string const &name, void *data, exchange_type type, bool /* readOnly */)
|
||||
{
|
||||
if (statement_.use_binding_method_ == details::db2::BOUND_BY_POSITION)
|
||||
{
|
||||
throw soci_error("Binding for use elements must be either by position or by name.");
|
||||
}
|
||||
statement_.use_binding_method_ = details::db2::BOUND_BY_NAME;
|
||||
|
||||
int position = -1;
|
||||
int count = 1;
|
||||
|
||||
for (std::vector<std::string>::iterator it = statement_.names.begin();
|
||||
it != statement_.names.end(); ++it)
|
||||
{
|
||||
if (*it == name)
|
||||
{
|
||||
position = count;
|
||||
break;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
|
||||
if (position != -1)
|
||||
{
|
||||
this->data = data; // for future reference
|
||||
this->type = type; // for future reference
|
||||
this->position = position;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::ostringstream ss;
|
||||
ss << "Unable to find name '" << name << "' to bind to";
|
||||
throw soci_error(ss.str().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void db2_standard_use_type_backend::pre_use(indicator const *ind_ptr)
|
||||
{
|
||||
// first deal with data
|
||||
SQLSMALLINT sqlType;
|
||||
SQLSMALLINT cType;
|
||||
SQLLEN size;
|
||||
|
||||
void *sqlData = prepare_for_bind(data, size, sqlType, cType);
|
||||
|
||||
SQLRETURN cliRC = SQLBindParameter(statement_.hStmt,
|
||||
static_cast<SQLUSMALLINT>(position),
|
||||
SQL_PARAM_INPUT,
|
||||
cType, sqlType, size, 0, sqlData, size, &ind);
|
||||
|
||||
if (cliRC != SQL_SUCCESS)
|
||||
{
|
||||
throw db2_soci_error("Error while binding value",cliRC);
|
||||
}
|
||||
|
||||
// then handle indicators
|
||||
if (ind_ptr != NULL && *ind_ptr == i_null)
|
||||
{
|
||||
ind = SQL_NULL_DATA; // null
|
||||
}
|
||||
}
|
||||
|
||||
void db2_standard_use_type_backend::post_use(bool /*gotData*/, indicator* /*ind*/)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void db2_standard_use_type_backend::clean_up()
|
||||
{
|
||||
if (buf != NULL)
|
||||
{
|
||||
delete [] buf;
|
||||
buf = NULL;
|
||||
}
|
||||
}
|
||||
322
src/soci/src/backends/db2/statement.cpp
Normal file
322
src/soci/src/backends/db2/statement.cpp
Normal file
@@ -0,0 +1,322 @@
|
||||
//
|
||||
// Copyright (C) 2011-2013 Denis Chapligin
|
||||
// Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#define SOCI_DB2_SOURCE
|
||||
#include "soci-db2.h"
|
||||
#include <cctype>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4355)
|
||||
#endif
|
||||
|
||||
using namespace soci;
|
||||
using namespace soci::details;
|
||||
|
||||
|
||||
db2_statement_backend::db2_statement_backend(db2_session_backend &session)
|
||||
: session_(session),hasVectorUseElements(false),use_binding_method_(details::db2::BOUND_BY_NONE)
|
||||
{
|
||||
}
|
||||
|
||||
void db2_statement_backend::alloc()
|
||||
{
|
||||
SQLRETURN cliRC = SQL_SUCCESS;
|
||||
|
||||
cliRC = SQLAllocHandle(SQL_HANDLE_STMT,session_.hDbc,&hStmt);
|
||||
if (cliRC != SQL_SUCCESS) {
|
||||
throw db2_soci_error("Error while allocation statement handle",cliRC);
|
||||
}
|
||||
}
|
||||
|
||||
void db2_statement_backend::clean_up()
|
||||
{
|
||||
SQLRETURN cliRC = SQL_SUCCESS;
|
||||
|
||||
cliRC=SQLFreeHandle(SQL_HANDLE_STMT,hStmt);
|
||||
if (cliRC != SQL_SUCCESS) {
|
||||
throw db2_soci_error(db2_soci_error::sqlState("Statement handle clean-up error",SQL_HANDLE_STMT,hStmt),cliRC);
|
||||
}
|
||||
}
|
||||
|
||||
void db2_statement_backend::prepare(std::string const & query ,
|
||||
statement_type /* eType */)
|
||||
{
|
||||
// rewrite the query by transforming all named parameters into
|
||||
// the markers (:abc -> ?, etc.)
|
||||
|
||||
enum { normal, in_quotes, in_name } state = normal;
|
||||
|
||||
std::string name;
|
||||
|
||||
for (std::string::const_iterator it = query.begin(), end = query.end();
|
||||
it != end; ++it)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case normal:
|
||||
if (*it == '\'')
|
||||
{
|
||||
query_ += *it;
|
||||
state = in_quotes;
|
||||
}
|
||||
else if (*it == ':')
|
||||
{
|
||||
// Check whether this is a cast operator (e.g. 23::float)
|
||||
// and treat it as a special case, not as a named binding
|
||||
const std::string::const_iterator next_it = it + 1;
|
||||
if ((next_it != end) && (*next_it == ':'))
|
||||
{
|
||||
query_ += "::";
|
||||
++it;
|
||||
}
|
||||
else
|
||||
{
|
||||
state = in_name;
|
||||
}
|
||||
}
|
||||
else // regular character, stay in the same state
|
||||
{
|
||||
query_ += *it;
|
||||
}
|
||||
break;
|
||||
case in_quotes:
|
||||
if (*it == '\'')
|
||||
{
|
||||
query_ += *it;
|
||||
state = normal;
|
||||
}
|
||||
else // regular quoted character
|
||||
{
|
||||
query_ += *it;
|
||||
}
|
||||
break;
|
||||
case in_name:
|
||||
if (std::isalnum(*it) || *it == '_')
|
||||
{
|
||||
name += *it;
|
||||
}
|
||||
else // end of name
|
||||
{
|
||||
names.push_back(name);
|
||||
name.clear();
|
||||
std::ostringstream ss;
|
||||
ss << '?';
|
||||
query_ += ss.str();
|
||||
query_ += *it;
|
||||
state = normal;
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (state == in_name)
|
||||
{
|
||||
names.push_back(name);
|
||||
std::ostringstream ss;
|
||||
ss << '?';
|
||||
query_ += ss.str();
|
||||
}
|
||||
|
||||
SQLRETURN cliRC = SQLPrepare(hStmt, const_cast<SQLCHAR *>((const SQLCHAR *) query_.c_str()), SQL_NTS);
|
||||
if (cliRC!=SQL_SUCCESS) {
|
||||
throw db2_soci_error("Error while preparing query",cliRC);
|
||||
}
|
||||
}
|
||||
|
||||
statement_backend::exec_fetch_result
|
||||
db2_statement_backend::execute(int number )
|
||||
{
|
||||
SQLUINTEGER rows_processed = 0;
|
||||
SQLRETURN cliRC;
|
||||
|
||||
if (hasVectorUseElements)
|
||||
{
|
||||
SQLSetStmtAttr(hStmt, SQL_ATTR_PARAMS_PROCESSED_PTR, &rows_processed, 0);
|
||||
}
|
||||
|
||||
// if we are called twice for the same statement we need to close the open
|
||||
// cursor or an "invalid cursor state" error will occur on execute
|
||||
cliRC = SQLFreeStmt(hStmt,SQL_CLOSE);
|
||||
if (cliRC != SQL_SUCCESS)
|
||||
{
|
||||
throw db2_soci_error(db2_soci_error::sqlState("Statement execution error",SQL_HANDLE_STMT,hStmt),cliRC);
|
||||
}
|
||||
|
||||
cliRC = SQLExecute(hStmt);
|
||||
if (cliRC != SQL_SUCCESS && cliRC != SQL_SUCCESS_WITH_INFO)
|
||||
{
|
||||
throw db2_soci_error(db2_soci_error::sqlState("Statement execution error",SQL_HANDLE_STMT,hStmt),cliRC);
|
||||
}
|
||||
|
||||
SQLSMALLINT colCount;
|
||||
SQLNumResultCols(hStmt, &colCount);
|
||||
|
||||
if (number > 0 && colCount > 0)
|
||||
{
|
||||
return fetch(number);
|
||||
}
|
||||
|
||||
return ef_success;
|
||||
}
|
||||
|
||||
statement_backend::exec_fetch_result
|
||||
db2_statement_backend::fetch(int number )
|
||||
{
|
||||
numRowsFetched = 0;
|
||||
|
||||
SQLSetStmtAttr(hStmt, SQL_ATTR_ROW_BIND_TYPE, SQL_BIND_BY_COLUMN, 0);
|
||||
SQLSetStmtAttr(hStmt, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER)number, 0);
|
||||
SQLSetStmtAttr(hStmt, SQL_ATTR_ROWS_FETCHED_PTR, &numRowsFetched, 0);
|
||||
|
||||
SQLRETURN cliRC = SQLFetch(hStmt);
|
||||
|
||||
if (SQL_NO_DATA == cliRC)
|
||||
{
|
||||
return ef_no_data;
|
||||
}
|
||||
|
||||
if (cliRC != SQL_SUCCESS && cliRC != SQL_SUCCESS_WITH_INFO)
|
||||
{
|
||||
throw db2_soci_error(db2_soci_error::sqlState("Error while fetching data", SQL_HANDLE_STMT, hStmt), cliRC);
|
||||
}
|
||||
|
||||
return ef_success;
|
||||
}
|
||||
|
||||
long long db2_statement_backend::get_affected_rows()
|
||||
{
|
||||
SQLLEN rows;
|
||||
|
||||
SQLRETURN cliRC = SQLRowCount(hStmt, &rows);
|
||||
if (cliRC != SQL_SUCCESS && cliRC != SQL_SUCCESS_WITH_INFO)
|
||||
{
|
||||
throw db2_soci_error(db2_soci_error::sqlState("Error while getting affected row count", SQL_HANDLE_STMT, hStmt), cliRC);
|
||||
}
|
||||
else if (rows == -1)
|
||||
{
|
||||
throw soci_error("Error getting affected row count: statement did not perform an update, insert, delete, or merge");
|
||||
}
|
||||
|
||||
return rows;
|
||||
}
|
||||
|
||||
int db2_statement_backend::get_number_of_rows()
|
||||
{
|
||||
return numRowsFetched;
|
||||
}
|
||||
|
||||
std::string db2_statement_backend::rewrite_for_procedure_call(
|
||||
std::string const &query)
|
||||
{
|
||||
return query;
|
||||
}
|
||||
|
||||
int db2_statement_backend::prepare_for_describe()
|
||||
{
|
||||
SQLSMALLINT numCols;
|
||||
SQLNumResultCols(hStmt, &numCols);
|
||||
return numCols;
|
||||
}
|
||||
|
||||
void db2_statement_backend::describe_column(int colNum,
|
||||
data_type & type, std::string & columnName )
|
||||
{
|
||||
SQLCHAR colNameBuffer[2048];
|
||||
SQLSMALLINT colNameBufferOverflow;
|
||||
SQLSMALLINT dataType;
|
||||
SQLULEN colSize;
|
||||
SQLSMALLINT decDigits;
|
||||
SQLSMALLINT isNullable;
|
||||
|
||||
SQLRETURN cliRC = SQLDescribeCol(hStmt, static_cast<SQLUSMALLINT>(colNum),
|
||||
colNameBuffer, 2048,
|
||||
&colNameBufferOverflow, &dataType,
|
||||
&colSize, &decDigits, &isNullable);
|
||||
|
||||
if (cliRC != SQL_SUCCESS)
|
||||
{
|
||||
throw db2_soci_error(db2_soci_error::sqlState("Error while describing column",SQL_HANDLE_STMT,hStmt),cliRC);
|
||||
}
|
||||
|
||||
char const *name = reinterpret_cast<char const *>(colNameBuffer);
|
||||
columnName.assign(name, std::strlen(name));
|
||||
|
||||
switch (dataType)
|
||||
{
|
||||
case SQL_TYPE_DATE:
|
||||
case SQL_TYPE_TIME:
|
||||
case SQL_TYPE_TIMESTAMP:
|
||||
type = dt_date;
|
||||
break;
|
||||
case SQL_DOUBLE:
|
||||
case SQL_DECIMAL:
|
||||
case SQL_REAL:
|
||||
case SQL_FLOAT:
|
||||
case SQL_NUMERIC:
|
||||
type = dt_double;
|
||||
break;
|
||||
case SQL_TINYINT:
|
||||
case SQL_SMALLINT:
|
||||
case SQL_INTEGER:
|
||||
type = dt_integer;
|
||||
break;
|
||||
case SQL_BIGINT:
|
||||
type = dt_long_long;
|
||||
break;
|
||||
case SQL_CHAR:
|
||||
case SQL_VARCHAR:
|
||||
case SQL_LONGVARCHAR:
|
||||
default:
|
||||
type = dt_string;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t db2_statement_backend::column_size(int col) {
|
||||
SQLCHAR colNameBuffer[2048];
|
||||
SQLSMALLINT colNameBufferOverflow;
|
||||
SQLSMALLINT dataType;
|
||||
SQLULEN colSize;
|
||||
SQLSMALLINT decDigits;
|
||||
SQLSMALLINT isNullable;
|
||||
|
||||
SQLRETURN cliRC = SQLDescribeCol(hStmt, static_cast<SQLUSMALLINT>(col),
|
||||
colNameBuffer, 2048,
|
||||
&colNameBufferOverflow, &dataType,
|
||||
&colSize, &decDigits, &isNullable);
|
||||
|
||||
if (cliRC != SQL_SUCCESS)
|
||||
{
|
||||
throw db2_soci_error(db2_soci_error::sqlState("Error while detecting column size",SQL_HANDLE_STMT,hStmt),cliRC);
|
||||
}
|
||||
|
||||
return colSize;
|
||||
}
|
||||
|
||||
db2_standard_into_type_backend * db2_statement_backend::make_into_type_backend()
|
||||
{
|
||||
return new db2_standard_into_type_backend(*this);
|
||||
}
|
||||
|
||||
db2_standard_use_type_backend * db2_statement_backend::make_use_type_backend()
|
||||
{
|
||||
return new db2_standard_use_type_backend(*this);
|
||||
}
|
||||
|
||||
db2_vector_into_type_backend *
|
||||
db2_statement_backend::make_vector_into_type_backend()
|
||||
{
|
||||
return new db2_vector_into_type_backend(*this);
|
||||
}
|
||||
|
||||
db2_vector_use_type_backend * db2_statement_backend::make_vector_use_type_backend()
|
||||
{
|
||||
hasVectorUseElements = true;
|
||||
return new db2_vector_use_type_backend(*this);
|
||||
}
|
||||
14
src/soci/src/backends/db2/test/CMakeLists.txt
Normal file
14
src/soci/src/backends/db2/test/CMakeLists.txt
Normal file
@@ -0,0 +1,14 @@
|
||||
###############################################################################
|
||||
#
|
||||
# This file is part of CMake configuration for SOCI library
|
||||
#
|
||||
# Copyright (C) 2011 Denis Chapligin
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE_1_0.txt or copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
#
|
||||
###############################################################################
|
||||
soci_backend_test(
|
||||
BACKEND DB2
|
||||
SOURCE test-db2.cpp
|
||||
CONNSTR "DSN=SAMPLE;Uid=db2inst1;Pwd=db2inst1;autocommit=off")
|
||||
454
src/soci/src/backends/db2/test/test-db2.cpp
Normal file
454
src/soci/src/backends/db2/test/test-db2.cpp
Normal file
@@ -0,0 +1,454 @@
|
||||
//
|
||||
// Copyright (C) 2011-2013 Denis Chapligin
|
||||
// Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#include "soci.h"
|
||||
#include "soci-db2.h"
|
||||
#include "common-tests.h"
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
|
||||
using namespace soci;
|
||||
using namespace soci::tests;
|
||||
|
||||
std::string connectString;
|
||||
backend_factory const &backEnd = *soci::factory_db2();
|
||||
|
||||
|
||||
//
|
||||
// Support for soci Common Tests
|
||||
//
|
||||
|
||||
struct table_creator_one : public table_creator_base
|
||||
{
|
||||
table_creator_one(session & sql)
|
||||
: table_creator_base(sql)
|
||||
{
|
||||
sql << "CREATE TABLE SOCI_TEST(ID INTEGER, VAL SMALLINT, C CHAR, STR VARCHAR(20), SH SMALLINT, UL NUMERIC(20), D DOUBLE, "
|
||||
"TM TIMESTAMP, I1 INTEGER, I2 INTEGER, I3 INTEGER, NAME VARCHAR(20))";
|
||||
}
|
||||
};
|
||||
|
||||
struct table_creator_two : public table_creator_base
|
||||
{
|
||||
table_creator_two(session & sql)
|
||||
: table_creator_base(sql)
|
||||
{
|
||||
sql << "CREATE TABLE SOCI_TEST(NUM_FLOAT DOUBLE, NUM_INT INTEGER, NAME VARCHAR(20), SOMETIME TIMESTAMP, CHR CHAR)";
|
||||
}
|
||||
};
|
||||
|
||||
struct table_creator_three : public table_creator_base
|
||||
{
|
||||
table_creator_three(session & sql)
|
||||
: table_creator_base(sql)
|
||||
{
|
||||
sql << "CREATE TABLE SOCI_TEST(NAME VARCHAR(100) NOT NULL, PHONE VARCHAR(15))";
|
||||
}
|
||||
};
|
||||
|
||||
struct table_creator_for_get_affected_rows : table_creator_base
|
||||
{
|
||||
table_creator_for_get_affected_rows(session & sql)
|
||||
: table_creator_base(sql)
|
||||
{
|
||||
sql << "CREATE TABLE SOCI_TEST(VAL INTEGER)";
|
||||
}
|
||||
};
|
||||
|
||||
class test_context :public test_context_base
|
||||
{
|
||||
public:
|
||||
test_context(backend_factory const & pi_back_end, std::string const & pi_connect_string)
|
||||
: test_context_base(pi_back_end, pi_connect_string) {}
|
||||
|
||||
table_creator_base* table_creator_1(session & pr_s) const
|
||||
{
|
||||
pr_s << "SET CURRENT SCHEMA = 'DB2INST1'";
|
||||
return new table_creator_one(pr_s);
|
||||
}
|
||||
|
||||
table_creator_base* table_creator_2(session & pr_s) const
|
||||
{
|
||||
pr_s << "SET CURRENT SCHEMA = 'DB2INST1'";
|
||||
return new table_creator_two(pr_s);
|
||||
}
|
||||
|
||||
table_creator_base* table_creator_3(session & pr_s) const
|
||||
{
|
||||
pr_s << "SET CURRENT SCHEMA = 'DB2INST1'";
|
||||
return new table_creator_three(pr_s);
|
||||
}
|
||||
|
||||
table_creator_base* table_creator_4(session& s) const
|
||||
{
|
||||
return new table_creator_for_get_affected_rows(s);
|
||||
}
|
||||
|
||||
std::string to_date_time(std::string const & pi_datdt_string) const
|
||||
{
|
||||
return "to_date('" + pi_datdt_string + "', 'YYYY-MM-DD HH24:MI:SS')";
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// Additional tests to exercise the DB2 backend
|
||||
//
|
||||
|
||||
void test1()
|
||||
{
|
||||
{
|
||||
session sql(backEnd, connectString);
|
||||
|
||||
sql << "SELECT CURRENT TIMESTAMP FROM SYSIBM.SYSDUMMY1";
|
||||
sql << "SELECT " << 123 << " FROM SYSIBM.SYSDUMMY1";
|
||||
|
||||
std::string query = "CREATE TABLE DB2INST1.SOCI_TEST (ID BIGINT,DATA VARCHAR(8))";
|
||||
sql << query;
|
||||
|
||||
{
|
||||
const int i = 7;
|
||||
sql << "insert into db2inst1.SOCI_TEST (id) values (:id)", use(i,"id");
|
||||
int j = 0;
|
||||
sql << "select id from db2inst1.SOCI_TEST where id=7", into(j);
|
||||
assert(j == i);
|
||||
}
|
||||
|
||||
{
|
||||
const long int li = 9;
|
||||
sql << "insert into db2inst1.SOCI_TEST (id) values (:id)", use(li,"id");
|
||||
long int lj = 0;;
|
||||
sql << "select id from db2inst1.SOCI_TEST where id=9", into(lj);
|
||||
assert(lj == li);
|
||||
}
|
||||
|
||||
{
|
||||
const long long ll = 11;
|
||||
sql << "insert into db2inst1.SOCI_TEST (id) values (:id)", use(ll,"id");
|
||||
long long lj = 0;
|
||||
sql << "select id from db2inst1.SOCI_TEST where id=11", into(lj);
|
||||
assert(lj == ll);
|
||||
}
|
||||
|
||||
{
|
||||
const int i = 13;
|
||||
indicator i_ind = i_ok;
|
||||
sql << "insert into db2inst1.SOCI_TEST (id) values (:id)", use(i,i_ind,"id");
|
||||
int j = 0;
|
||||
indicator j_ind = i_null;
|
||||
sql << "select id from db2inst1.SOCI_TEST where id=13", into(j,j_ind);
|
||||
assert(j == i);
|
||||
assert(j_ind == i_ok);
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<int> numbers(100);
|
||||
for (int i = 0 ; i < 100 ; i++)
|
||||
{
|
||||
numbers[i] = i + 1000;
|
||||
}
|
||||
sql << "insert into db2inst1.SOCI_TEST (id) values (:id)", use(numbers,"id");
|
||||
sql << "select id from db2inst1.SOCI_TEST where id >= 1000 and id < 2000 order by id", into(numbers);
|
||||
for (int i = 0 ; i < 100 ; i++)
|
||||
{
|
||||
assert(numbers[i] == i + 1000);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<int> numbers(100);
|
||||
std::vector<indicator> inds(100);
|
||||
for (int i = 0 ; i < 100 ; i++)
|
||||
{
|
||||
numbers[i] = i + 2000;
|
||||
inds[i] = i_ok;
|
||||
}
|
||||
sql << "insert into db2inst1.SOCI_TEST (id) values (:id)", use(numbers,inds,"id");
|
||||
for (int i = 0 ; i < 100 ; i++)
|
||||
{
|
||||
numbers[i] = 0;
|
||||
inds[i] = i_null;
|
||||
}
|
||||
sql << "select id from db2inst1.SOCI_TEST where id >= 2000 and id < 3000 order by id", into(numbers,inds);
|
||||
for (int i = 0 ; i < 100 ; i++)
|
||||
{
|
||||
assert(numbers[i] == i + 2000);
|
||||
assert(inds[i] == i_ok);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
int i = 0;
|
||||
statement st = (sql.prepare << "select id from db2inst1.SOCI_TEST where id < 1000", into(i));
|
||||
st.execute();
|
||||
st.fetch();
|
||||
assert (i == 7);
|
||||
st.fetch();
|
||||
assert (i == 9);
|
||||
st.fetch();
|
||||
assert (i == 11);
|
||||
st.fetch();
|
||||
assert (i == 13);
|
||||
}
|
||||
|
||||
{
|
||||
int i = 0;
|
||||
indicator i_ind = i_null;
|
||||
std::string d;
|
||||
indicator d_ind = i_ok;
|
||||
statement st = (sql.prepare << "select id, data from db2inst1.SOCI_TEST where id = 13", into(i, i_ind), into(d, d_ind));
|
||||
st.execute();
|
||||
st.fetch();
|
||||
assert (i == 13);
|
||||
assert (i_ind == i_ok);
|
||||
assert (d_ind == i_null);
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<int> numbers(100);
|
||||
for (int i = 0 ; i < 100 ; i++)
|
||||
{
|
||||
numbers[i] = 0;
|
||||
}
|
||||
statement st = (sql.prepare << "select id from db2inst1.SOCI_TEST where id >= 1000 order by id", into(numbers));
|
||||
st.execute();
|
||||
st.fetch();
|
||||
for (int i = 0 ; i < 100 ; i++)
|
||||
{
|
||||
assert(numbers[i] == i + 1000);
|
||||
}
|
||||
st.fetch();
|
||||
for (int i = 0 ; i < 100 ; i++)
|
||||
{
|
||||
assert(numbers[i] == i + 2000);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<int> numbers(100);
|
||||
std::vector<indicator> inds(100);
|
||||
for (int i = 0 ; i < 100 ; i++)
|
||||
{
|
||||
numbers[i] = 0;
|
||||
inds[i] = i_null;
|
||||
}
|
||||
statement st = (sql.prepare << "select id from db2inst1.SOCI_TEST where id >= 1000 order by id", into(numbers, inds));
|
||||
st.execute();
|
||||
st.fetch();
|
||||
for (int i = 0 ; i < 100 ; i++)
|
||||
{
|
||||
assert(numbers[i] == i + 1000);
|
||||
assert(inds[i] == i_ok);
|
||||
}
|
||||
st.fetch();
|
||||
for (int i = 0 ; i < 100 ; i++)
|
||||
{
|
||||
assert(numbers[i] == i + 2000);
|
||||
assert(inds[i] == i_ok);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// XXX: what is the purpose of this test?? what is the expected value?
|
||||
int i = 0;
|
||||
statement st = (sql.prepare << "select id from db2inst1.SOCI_TEST", use(i));
|
||||
}
|
||||
|
||||
{
|
||||
// XXX: what is the purpose of this test?? what is the expected value?
|
||||
int i = 0;
|
||||
indicator ind = i_ok;
|
||||
statement st = (sql.prepare << "select id from db2inst1.SOCI_TEST", use(i, ind));
|
||||
}
|
||||
|
||||
{
|
||||
// XXX: what is the purpose of this test?? what is the expected value?
|
||||
std::vector<int> numbers(100);
|
||||
statement st = (sql.prepare << "select id from db2inst1.SOCI_TEST", use(numbers));
|
||||
}
|
||||
|
||||
{
|
||||
// XXX: what is the purpose of this test?? what is the expected value?
|
||||
std::vector<int> numbers(100);
|
||||
std::vector<indicator> inds(100);
|
||||
statement st = (sql.prepare << "select id from db2inst1.SOCI_TEST", use(numbers, inds));
|
||||
}
|
||||
|
||||
sql<<"DROP TABLE DB2INST1.SOCI_TEST";
|
||||
|
||||
sql.commit();
|
||||
}
|
||||
|
||||
std::cout << "test 1 passed" << std::endl;
|
||||
}
|
||||
|
||||
void test2() {
|
||||
{
|
||||
session sql(backEnd, connectString);
|
||||
|
||||
std::string query = "CREATE TABLE DB2INST1.SOCI_TEST (ID BIGINT,DATA VARCHAR(8),DT TIMESTAMP)";
|
||||
sql << query;
|
||||
|
||||
{
|
||||
int i = 7;
|
||||
std::string n("test");
|
||||
sql << "insert into db2inst1.SOCI_TEST (id,data) values (:id,:name)", use(i,"id"),use(n,"name");
|
||||
int j;
|
||||
std::string m;
|
||||
sql << "select id,data from db2inst1.SOCI_TEST where id=7", into(j),into(m);
|
||||
assert (j == i);
|
||||
assert (m == n);
|
||||
}
|
||||
|
||||
{
|
||||
int i = 8;
|
||||
sql << "insert into db2inst1.SOCI_TEST (id) values (:id)", use(i,"id");
|
||||
int j;
|
||||
std::string m;
|
||||
indicator ind = i_ok;
|
||||
sql << "select id,data from db2inst1.SOCI_TEST where id=8", into(j),into(m,ind);
|
||||
assert(j == i);
|
||||
assert(ind==i_null);
|
||||
}
|
||||
|
||||
{
|
||||
std::tm dt;
|
||||
sql << "select current timestamp from sysibm.sysdummy1",into(dt);
|
||||
sql << "insert into db2inst1.SOCI_TEST (dt) values (:dt)",use(dt,"dt");
|
||||
std::tm dt2;
|
||||
sql << "select dt from db2inst1.SOCI_TEST where dt is not null", into(dt2);
|
||||
assert(dt2.tm_year == dt.tm_year && dt2.tm_mon == dt.tm_mon && dt2.tm_mday == dt.tm_mday &&
|
||||
dt2.tm_hour == dt.tm_hour && dt2.tm_min == dt.tm_min && dt2.tm_sec == dt.tm_sec);
|
||||
}
|
||||
|
||||
sql<<"DROP TABLE DB2INST1.SOCI_TEST";
|
||||
sql.commit();
|
||||
}
|
||||
|
||||
std::cout << "test 2 passed" << std::endl;
|
||||
}
|
||||
|
||||
void test3() {
|
||||
{
|
||||
session sql(backEnd, connectString);
|
||||
int i;
|
||||
|
||||
std::string query = "CREATE TABLE DB2INST1.SOCI_TEST (ID BIGINT,DATA VARCHAR(8),DT TIMESTAMP)";
|
||||
sql << query;
|
||||
|
||||
std::vector<long long> ids(100);
|
||||
std::vector<std::string> data(100);
|
||||
std::vector<std::tm> dts(100);
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
ids[i] = 1000000000LL + i;
|
||||
data[i] = "test";
|
||||
dts[i].tm_year = 112;
|
||||
dts[i].tm_mon = 7;
|
||||
dts[i].tm_mday = 17;
|
||||
dts[i].tm_hour = 0;
|
||||
dts[i].tm_min = 0;
|
||||
dts[i].tm_sec = i % 60;
|
||||
}
|
||||
|
||||
sql << "insert into db2inst1.SOCI_TEST (id, data, dt) values (:id, :data, :dt)",
|
||||
use(ids, "id"), use(data,"data"), use(dts, "dt");
|
||||
|
||||
i = 0;
|
||||
rowset<row> rs = (sql.prepare<<"SELECT ID, DATA, DT FROM DB2INST1.SOCI_TEST");
|
||||
for (rowset<row>::const_iterator it = rs.begin(); it != rs.end(); it++)
|
||||
{
|
||||
const row & r = *it;
|
||||
const long long id = r.get<long long>(0);
|
||||
const std::string data = r.get<std::string>(1);
|
||||
const std::tm dt = r.get<std::tm>(2);
|
||||
|
||||
assert(id == 1000000000LL + i);
|
||||
assert(data == "test");
|
||||
assert(dt.tm_year == 112);
|
||||
assert(dt.tm_mon == 7);
|
||||
assert(dt.tm_mday == 17);
|
||||
assert(dt.tm_hour == 0);
|
||||
assert(dt.tm_min == 0);
|
||||
assert(dt.tm_sec == i % 60);
|
||||
|
||||
i += 1;
|
||||
}
|
||||
|
||||
sql<<"DROP TABLE DB2INST1.SOCI_TEST";
|
||||
sql.commit();
|
||||
}
|
||||
|
||||
std::cout << "test 3 passed" << std::endl;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// Redirect errors, unrecoverable problems, and assert() failures to STDERR,
|
||||
// instead of debug message window.
|
||||
// This hack is required to run asser()-driven tests by Buildbot.
|
||||
// NOTE: Comment this 2 lines for debugging with Visual C++ debugger to catch assertions inside.
|
||||
_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
|
||||
_CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
|
||||
#endif //_MSC_VER
|
||||
|
||||
if (argc == 2)
|
||||
{
|
||||
connectString = argv[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "usage: " << argv[0]
|
||||
<< " connectstring\n"
|
||||
<< "example: " << argv[0]
|
||||
<< " \'DSN=SAMPLE;Uid=db2inst1;Pwd=db2inst1;autocommit=off\'\n";
|
||||
std::exit(1);
|
||||
}
|
||||
|
||||
test_context tc(backEnd, connectString);
|
||||
common_tests tests(tc);
|
||||
tests.run();
|
||||
|
||||
try
|
||||
{
|
||||
std::cout<<"\nSOCI DB2 Tests:\n\n";
|
||||
|
||||
session sql(backEnd, connectString);
|
||||
|
||||
try
|
||||
{
|
||||
// attempt to delete the test table from previous runs
|
||||
sql << "DROP TABLE DB2INST1.SOCI_TEST";
|
||||
}
|
||||
catch (soci_error const & e)
|
||||
{
|
||||
// if the table didn't exist, then proceed
|
||||
}
|
||||
|
||||
test1();
|
||||
test2();
|
||||
test3();
|
||||
// ...
|
||||
|
||||
std::cout << "\nOK, all tests passed.\n\n";
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
catch (std::exception const & e)
|
||||
{
|
||||
std::cout << e.what() << '\n';
|
||||
}
|
||||
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
411
src/soci/src/backends/db2/vector-into-type.cpp
Normal file
411
src/soci/src/backends/db2/vector-into-type.cpp
Normal file
@@ -0,0 +1,411 @@
|
||||
//
|
||||
// Copyright (C) 2011-2013 Denis Chapligin
|
||||
// Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton, David Courtney
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#define SOCI_DB2_SOURCE
|
||||
#include "soci-db2.h"
|
||||
#include <cctype>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <ctime>
|
||||
#include <sstream>
|
||||
|
||||
using namespace soci;
|
||||
using namespace soci::details;
|
||||
|
||||
void db2_vector_into_type_backend::prepare_indicators(std::size_t size)
|
||||
{
|
||||
if (size == 0)
|
||||
{
|
||||
throw soci_error("Vectors of size 0 are not allowed.");
|
||||
}
|
||||
|
||||
indVec.resize(size);
|
||||
indptr = &indVec[0];
|
||||
}
|
||||
|
||||
void db2_vector_into_type_backend::define_by_pos(
|
||||
int &position, void *data, exchange_type type)
|
||||
{
|
||||
this->data = data; // for future reference
|
||||
this->type = type; // for future reference
|
||||
|
||||
SQLINTEGER size = 0; // also dummy
|
||||
|
||||
switch (type)
|
||||
{
|
||||
// simple cases
|
||||
case x_short:
|
||||
{
|
||||
cType = SQL_C_SSHORT;
|
||||
size = sizeof(short);
|
||||
std::vector<short> *vp = static_cast<std::vector<short> *>(data);
|
||||
std::vector<short> &v(*vp);
|
||||
prepare_indicators(v.size());
|
||||
data = &v[0];
|
||||
}
|
||||
break;
|
||||
case x_integer:
|
||||
{
|
||||
cType = SQL_C_SLONG;
|
||||
size = sizeof(SQLINTEGER);
|
||||
std::vector<SQLINTEGER> *vp = static_cast<std::vector<SQLINTEGER> *>(data);
|
||||
std::vector<SQLINTEGER> &v(*vp);
|
||||
prepare_indicators(v.size());
|
||||
data = &v[0];
|
||||
}
|
||||
break;
|
||||
case x_long_long:
|
||||
{
|
||||
cType = SQL_C_SBIGINT;
|
||||
size = sizeof(long long);
|
||||
std::vector<long long> *vp
|
||||
= static_cast<std::vector<long long> *>(data);
|
||||
std::vector<long long> &v(*vp);
|
||||
prepare_indicators(v.size());
|
||||
data = &v[0];
|
||||
}
|
||||
break;
|
||||
case x_unsigned_long_long:
|
||||
{
|
||||
cType = SQL_C_UBIGINT;
|
||||
size = sizeof(unsigned long long);
|
||||
std::vector<unsigned long long> *vp
|
||||
= static_cast<std::vector<unsigned long long> *>(data);
|
||||
std::vector<unsigned long long> &v(*vp);
|
||||
prepare_indicators(v.size());
|
||||
data = &v[0];
|
||||
}
|
||||
break;
|
||||
case x_double:
|
||||
{
|
||||
cType = SQL_C_DOUBLE;
|
||||
size = sizeof(double);
|
||||
std::vector<double> *vp = static_cast<std::vector<double> *>(data);
|
||||
std::vector<double> &v(*vp);
|
||||
prepare_indicators(v.size());
|
||||
data = &v[0];
|
||||
}
|
||||
break;
|
||||
|
||||
// cases that require adjustments and buffer management
|
||||
|
||||
case x_char:
|
||||
{
|
||||
cType = SQL_C_CHAR;
|
||||
|
||||
std::vector<char> *v
|
||||
= static_cast<std::vector<char> *>(data);
|
||||
|
||||
prepare_indicators(v->size());
|
||||
|
||||
size = sizeof(char) * 2;
|
||||
std::size_t bufSize = size * v->size();
|
||||
|
||||
colSize = size;
|
||||
|
||||
buf = new char[bufSize];
|
||||
data = buf;
|
||||
}
|
||||
break;
|
||||
case x_stdstring:
|
||||
{
|
||||
cType = SQL_C_CHAR;
|
||||
std::vector<std::string> *v
|
||||
= static_cast<std::vector<std::string> *>(data);
|
||||
colSize = statement_.column_size(position) + 1;
|
||||
std::size_t bufSize = colSize * v->size();
|
||||
buf = new char[bufSize];
|
||||
|
||||
prepare_indicators(v->size());
|
||||
|
||||
size = static_cast<SQLINTEGER>(colSize);
|
||||
data = buf;
|
||||
}
|
||||
break;
|
||||
case x_stdtm:
|
||||
{
|
||||
cType = SQL_C_TYPE_TIMESTAMP;
|
||||
std::vector<std::tm> *v
|
||||
= static_cast<std::vector<std::tm> *>(data);
|
||||
|
||||
prepare_indicators(v->size());
|
||||
|
||||
size = sizeof(TIMESTAMP_STRUCT);
|
||||
colSize = size;
|
||||
|
||||
std::size_t bufSize = size * v->size();
|
||||
|
||||
buf = new char[bufSize];
|
||||
data = buf;
|
||||
}
|
||||
break;
|
||||
|
||||
case x_statement: break; // not supported
|
||||
case x_rowid: break; // not supported
|
||||
case x_blob: break; // not supported
|
||||
}
|
||||
|
||||
SQLRETURN cliRC = SQLBindCol(statement_.hStmt, static_cast<SQLUSMALLINT>(position++),
|
||||
cType, data, size, indptr);
|
||||
if (cliRC != SQL_SUCCESS)
|
||||
{
|
||||
throw db2_soci_error("Error while pre-fetching into vector",cliRC);
|
||||
}
|
||||
}
|
||||
|
||||
void db2_vector_into_type_backend::pre_fetch()
|
||||
{
|
||||
// nothing to do for the supported types
|
||||
}
|
||||
|
||||
void db2_vector_into_type_backend::post_fetch(bool gotData, indicator *ind)
|
||||
{
|
||||
if (gotData)
|
||||
{
|
||||
// first, deal with data
|
||||
|
||||
// only std::string, std::tm and Statement need special handling
|
||||
if (type == x_char)
|
||||
{
|
||||
std::vector<char> *vp
|
||||
= static_cast<std::vector<char> *>(data);
|
||||
|
||||
std::vector<char> &v(*vp);
|
||||
char *pos = buf;
|
||||
std::size_t const vsize = v.size();
|
||||
for (std::size_t i = 0; i != vsize; ++i)
|
||||
{
|
||||
v[i] = *pos;
|
||||
pos += colSize;
|
||||
}
|
||||
}
|
||||
if (type == x_stdstring)
|
||||
{
|
||||
std::vector<std::string> *vp
|
||||
= static_cast<std::vector<std::string> *>(data);
|
||||
|
||||
std::vector<std::string> &v(*vp);
|
||||
|
||||
char *pos = buf;
|
||||
std::size_t const vsize = v.size();
|
||||
for (std::size_t i = 0; i != vsize; ++i)
|
||||
{
|
||||
v[i].assign(pos, strlen(pos));
|
||||
pos += colSize;
|
||||
}
|
||||
}
|
||||
else if (type == x_stdtm)
|
||||
{
|
||||
std::vector<std::tm> *vp
|
||||
= static_cast<std::vector<std::tm> *>(data);
|
||||
|
||||
std::vector<std::tm> &v(*vp);
|
||||
char *pos = buf;
|
||||
std::size_t const vsize = v.size();
|
||||
for (std::size_t i = 0; i != vsize; ++i)
|
||||
{
|
||||
std::tm t;
|
||||
|
||||
TIMESTAMP_STRUCT * ts = reinterpret_cast<TIMESTAMP_STRUCT*>(pos);
|
||||
t.tm_isdst = -1;
|
||||
t.tm_year = ts->year - 1900;
|
||||
t.tm_mon = ts->month - 1;
|
||||
t.tm_mday = ts->day;
|
||||
t.tm_hour = ts->hour;
|
||||
t.tm_min = ts->minute;
|
||||
t.tm_sec = ts->second;
|
||||
|
||||
// normalize and compute the remaining fields
|
||||
std::mktime(&t);
|
||||
v[i] = t;
|
||||
pos += colSize;
|
||||
}
|
||||
}
|
||||
|
||||
// then - deal with indicators
|
||||
if (ind != NULL)
|
||||
{
|
||||
std::size_t const indSize = statement_.get_number_of_rows();
|
||||
for (std::size_t i = 0; i != indSize; ++i)
|
||||
{
|
||||
if (indVec[i] > 0)
|
||||
{
|
||||
ind[i] = i_ok;
|
||||
}
|
||||
else if (indVec[i] == SQL_NULL_DATA)
|
||||
{
|
||||
ind[i] = i_null;
|
||||
}
|
||||
else
|
||||
{
|
||||
ind[i] = i_truncated;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::size_t const indSize = statement_.get_number_of_rows();
|
||||
for (std::size_t i = 0; i != indSize; ++i)
|
||||
{
|
||||
if (indVec[i] == SQL_NULL_DATA)
|
||||
{
|
||||
// fetched null and no indicator - programming error!
|
||||
throw soci_error(
|
||||
"Null value fetched and no indicator defined.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else // gotData == false
|
||||
{
|
||||
// nothing to do here, vectors are truncated anyway
|
||||
}
|
||||
}
|
||||
|
||||
void db2_vector_into_type_backend::resize(std::size_t sz)
|
||||
{
|
||||
indVec.resize(sz);
|
||||
switch (type)
|
||||
{
|
||||
// simple cases
|
||||
case x_char:
|
||||
{
|
||||
std::vector<char> *v = static_cast<std::vector<char> *>(data);
|
||||
v->resize(sz);
|
||||
}
|
||||
break;
|
||||
case x_short:
|
||||
{
|
||||
std::vector<short> *v = static_cast<std::vector<short> *>(data);
|
||||
v->resize(sz);
|
||||
}
|
||||
break;
|
||||
case x_integer:
|
||||
{
|
||||
std::vector<SQLINTEGER> *v = static_cast<std::vector<SQLINTEGER> *>(data);
|
||||
v->resize(sz);
|
||||
}
|
||||
break;
|
||||
case x_long_long:
|
||||
{
|
||||
std::vector<long long> *v
|
||||
= static_cast<std::vector<long long> *>(data);
|
||||
v->resize(sz);
|
||||
}
|
||||
break;
|
||||
case x_unsigned_long_long:
|
||||
{
|
||||
std::vector<unsigned long long> *v
|
||||
= static_cast<std::vector<unsigned long long> *>(data);
|
||||
v->resize(sz);
|
||||
}
|
||||
break;
|
||||
case x_double:
|
||||
{
|
||||
std::vector<double> *v
|
||||
= static_cast<std::vector<double> *>(data);
|
||||
v->resize(sz);
|
||||
}
|
||||
break;
|
||||
case x_stdstring:
|
||||
{
|
||||
std::vector<std::string> *v
|
||||
= static_cast<std::vector<std::string> *>(data);
|
||||
v->resize(sz);
|
||||
}
|
||||
break;
|
||||
case x_stdtm:
|
||||
{
|
||||
std::vector<std::tm> *v
|
||||
= static_cast<std::vector<std::tm> *>(data);
|
||||
v->resize(sz);
|
||||
}
|
||||
break;
|
||||
|
||||
case x_statement: break; // not supported
|
||||
case x_rowid: break; // not supported
|
||||
case x_blob: break; // not supported
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t db2_vector_into_type_backend::size()
|
||||
{
|
||||
std::size_t sz = 0; // dummy initialization to please the compiler
|
||||
switch (type)
|
||||
{
|
||||
// simple cases
|
||||
case x_char:
|
||||
{
|
||||
std::vector<char> *v = static_cast<std::vector<char> *>(data);
|
||||
sz = v->size();
|
||||
}
|
||||
break;
|
||||
case x_short:
|
||||
{
|
||||
std::vector<short> *v = static_cast<std::vector<short> *>(data);
|
||||
sz = v->size();
|
||||
}
|
||||
break;
|
||||
case x_integer:
|
||||
{
|
||||
std::vector<SQLINTEGER> *v = static_cast<std::vector<SQLINTEGER> *>(data);
|
||||
sz = v->size();
|
||||
}
|
||||
break;
|
||||
case x_long_long:
|
||||
{
|
||||
std::vector<long long> *v
|
||||
= static_cast<std::vector<long long> *>(data);
|
||||
sz = v->size();
|
||||
}
|
||||
break;
|
||||
case x_unsigned_long_long:
|
||||
{
|
||||
std::vector<unsigned long long> *v
|
||||
= static_cast<std::vector<unsigned long long> *>(data);
|
||||
sz = v->size();
|
||||
}
|
||||
break;
|
||||
case x_double:
|
||||
{
|
||||
std::vector<double> *v
|
||||
= static_cast<std::vector<double> *>(data);
|
||||
sz = v->size();
|
||||
}
|
||||
break;
|
||||
case x_stdstring:
|
||||
{
|
||||
std::vector<std::string> *v
|
||||
= static_cast<std::vector<std::string> *>(data);
|
||||
sz = v->size();
|
||||
}
|
||||
break;
|
||||
case x_stdtm:
|
||||
{
|
||||
std::vector<std::tm> *v
|
||||
= static_cast<std::vector<std::tm> *>(data);
|
||||
sz = v->size();
|
||||
}
|
||||
break;
|
||||
|
||||
case x_statement: break; // not supported
|
||||
case x_rowid: break; // not supported
|
||||
case x_blob: break; // not supported
|
||||
}
|
||||
|
||||
return sz;
|
||||
}
|
||||
|
||||
void db2_vector_into_type_backend::clean_up()
|
||||
{
|
||||
if (buf != NULL)
|
||||
{
|
||||
delete [] buf;
|
||||
buf = NULL;
|
||||
}
|
||||
}
|
||||
395
src/soci/src/backends/db2/vector-use-type.cpp
Normal file
395
src/soci/src/backends/db2/vector-use-type.cpp
Normal file
@@ -0,0 +1,395 @@
|
||||
//
|
||||
// Copyright (C) 2011-2013 Denis Chapligin
|
||||
// Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton, David Courtney
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#define SOCI_DB2_SOURCE
|
||||
#include "soci-db2.h"
|
||||
#include <cctype>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <ctime>
|
||||
#include <sstream>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// disables the warning about converting int to void*. This is a 64 bit compatibility
|
||||
// warning, but odbc requires the value to be converted on this line
|
||||
// SQLSetStmtAttr(statement_.hstmt_, SQL_ATTR_PARAMSET_SIZE, (SQLPOINTER)arraySize, 0);
|
||||
#pragma warning(disable:4312)
|
||||
#endif
|
||||
|
||||
|
||||
using namespace soci;
|
||||
using namespace soci::details;
|
||||
|
||||
void db2_vector_use_type_backend::prepare_indicators(std::size_t size)
|
||||
{
|
||||
if (size == 0)
|
||||
{
|
||||
throw soci_error("Vectors of size 0 are not allowed.");
|
||||
}
|
||||
|
||||
indVec.resize(size);
|
||||
indptr = &indVec[0];
|
||||
}
|
||||
|
||||
void db2_vector_use_type_backend::prepare_for_bind(void *&data, SQLUINTEGER &size,
|
||||
SQLSMALLINT &sqlType, SQLSMALLINT &cType)
|
||||
{
|
||||
switch (type)
|
||||
{ // simple cases
|
||||
case x_short:
|
||||
{
|
||||
sqlType = SQL_SMALLINT;
|
||||
cType = SQL_C_SSHORT;
|
||||
size = sizeof(short);
|
||||
std::vector<short> *vp = static_cast<std::vector<short> *>(data);
|
||||
std::vector<short> &v(*vp);
|
||||
prepare_indicators(v.size());
|
||||
data = &v[0];
|
||||
}
|
||||
break;
|
||||
case x_integer:
|
||||
{
|
||||
sqlType = SQL_INTEGER;
|
||||
cType = SQL_C_SLONG;
|
||||
size = sizeof(int);
|
||||
std::vector<int> *vp = static_cast<std::vector<int> *>(data);
|
||||
std::vector<int> &v(*vp);
|
||||
prepare_indicators(v.size());
|
||||
data = &v[0];
|
||||
}
|
||||
break;
|
||||
case x_long_long:
|
||||
{
|
||||
sqlType = SQL_BIGINT;
|
||||
cType = SQL_C_SBIGINT;
|
||||
size = sizeof(long long);
|
||||
std::vector<long long> *vp
|
||||
= static_cast<std::vector<long long> *>(data);
|
||||
std::vector<long long> &v(*vp);
|
||||
prepare_indicators(v.size());
|
||||
data = &v[0];
|
||||
}
|
||||
break;
|
||||
case x_unsigned_long_long:
|
||||
{
|
||||
sqlType = SQL_BIGINT;
|
||||
cType = SQL_C_UBIGINT;
|
||||
size = sizeof(unsigned long long);
|
||||
std::vector<unsigned long long> *vp
|
||||
= static_cast<std::vector<unsigned long long> *>(data);
|
||||
std::vector<unsigned long long> &v(*vp);
|
||||
prepare_indicators(v.size());
|
||||
data = &v[0];
|
||||
}
|
||||
break;
|
||||
case x_double:
|
||||
{
|
||||
sqlType = SQL_DOUBLE;
|
||||
cType = SQL_C_DOUBLE;
|
||||
size = sizeof(double);
|
||||
std::vector<double> *vp = static_cast<std::vector<double> *>(data);
|
||||
std::vector<double> &v(*vp);
|
||||
prepare_indicators(v.size());
|
||||
data = &v[0];
|
||||
}
|
||||
break;
|
||||
|
||||
// cases that require adjustments and buffer management
|
||||
case x_char:
|
||||
{
|
||||
std::vector<char> *vp
|
||||
= static_cast<std::vector<char> *>(data);
|
||||
std::size_t const vsize = vp->size();
|
||||
|
||||
prepare_indicators(vsize);
|
||||
|
||||
size = sizeof(char) * 2;
|
||||
buf = new char[size * vsize];
|
||||
|
||||
char *pos = buf;
|
||||
|
||||
for (std::size_t i = 0; i != vsize; ++i)
|
||||
{
|
||||
*pos++ = (*vp)[i];
|
||||
*pos++ = 0;
|
||||
}
|
||||
|
||||
sqlType = SQL_CHAR;
|
||||
cType = SQL_C_CHAR;
|
||||
data = buf;
|
||||
}
|
||||
break;
|
||||
case x_stdstring:
|
||||
{
|
||||
sqlType = SQL_CHAR;
|
||||
cType = SQL_C_CHAR;
|
||||
|
||||
std::vector<std::string> *vp
|
||||
= static_cast<std::vector<std::string> *>(data);
|
||||
std::vector<std::string> &v(*vp);
|
||||
|
||||
std::size_t maxSize = 0;
|
||||
std::size_t const vecSize = v.size();
|
||||
prepare_indicators(vecSize);
|
||||
for (std::size_t i = 0; i != vecSize; ++i)
|
||||
{
|
||||
std::size_t sz = v[i].length() + 1; // add one for null
|
||||
indVec[i] = static_cast<long>(sz);
|
||||
maxSize = sz > maxSize ? sz : maxSize;
|
||||
}
|
||||
|
||||
buf = new char[maxSize * vecSize];
|
||||
memset(buf, 0, maxSize * vecSize);
|
||||
|
||||
char *pos = buf;
|
||||
for (std::size_t i = 0; i != vecSize; ++i)
|
||||
{
|
||||
strncpy(pos, v[i].c_str(), v[i].length());
|
||||
pos += maxSize;
|
||||
}
|
||||
|
||||
data = buf;
|
||||
size = static_cast<SQLINTEGER>(maxSize);
|
||||
}
|
||||
break;
|
||||
case x_stdtm:
|
||||
{
|
||||
std::vector<std::tm> *vp
|
||||
= static_cast<std::vector<std::tm> *>(data);
|
||||
|
||||
prepare_indicators(vp->size());
|
||||
|
||||
buf = new char[sizeof(TIMESTAMP_STRUCT) * vp->size()];
|
||||
|
||||
sqlType = SQL_TYPE_TIMESTAMP;
|
||||
cType = SQL_C_TYPE_TIMESTAMP;
|
||||
data = buf;
|
||||
size = 19; // This number is not the size in bytes, but the number
|
||||
// of characters in the date if it was written out
|
||||
// yyyy-mm-dd hh:mm:ss
|
||||
}
|
||||
break;
|
||||
|
||||
case x_statement: break; // not supported
|
||||
case x_rowid: break; // not supported
|
||||
case x_blob: break; // not supported
|
||||
}
|
||||
|
||||
colSize = size;
|
||||
}
|
||||
|
||||
void db2_vector_use_type_backend::bind_helper(int &position, void *data, details::exchange_type type)
|
||||
{
|
||||
this->data = data; // for future reference
|
||||
this->type = type; // for future reference
|
||||
|
||||
SQLSMALLINT sqlType;
|
||||
SQLSMALLINT cType;
|
||||
SQLUINTEGER size;
|
||||
|
||||
prepare_for_bind(data, size, sqlType, cType);
|
||||
|
||||
SQLINTEGER arraySize = (SQLINTEGER)indVec.size();
|
||||
SQLSetStmtAttr(statement_.hStmt, SQL_ATTR_PARAMSET_SIZE, (SQLPOINTER)arraySize, 0);
|
||||
|
||||
SQLRETURN cliRC = SQLBindParameter(statement_.hStmt, static_cast<SQLUSMALLINT>(position++),
|
||||
SQL_PARAM_INPUT, cType, sqlType, size, 0,
|
||||
static_cast<SQLPOINTER>(data), size, indptr);
|
||||
|
||||
if ( cliRC != SQL_SUCCESS )
|
||||
{
|
||||
throw db2_soci_error("Error while binding value to column", cliRC);
|
||||
}
|
||||
}
|
||||
|
||||
void db2_vector_use_type_backend::bind_by_pos(int &position,
|
||||
void *data, exchange_type type)
|
||||
{
|
||||
if (statement_.use_binding_method_ == details::db2::BOUND_BY_NAME)
|
||||
{
|
||||
throw soci_error("Binding for use elements must be either by position or by name.");
|
||||
}
|
||||
statement_.use_binding_method_ = details::db2::BOUND_BY_POSITION;
|
||||
|
||||
bind_helper(position, data, type);
|
||||
}
|
||||
|
||||
void db2_vector_use_type_backend::bind_by_name(
|
||||
std::string const &name, void *data, exchange_type type)
|
||||
{
|
||||
int position = -1;
|
||||
int count = 1;
|
||||
|
||||
if (statement_.use_binding_method_ == details::db2::BOUND_BY_POSITION)
|
||||
{
|
||||
throw soci_error("Binding for use elements must be either by position or by name.");
|
||||
}
|
||||
statement_.use_binding_method_ = details::db2::BOUND_BY_NAME;
|
||||
|
||||
for (std::vector<std::string>::iterator it = statement_.names.begin();
|
||||
it != statement_.names.end(); ++it)
|
||||
{
|
||||
if (*it == name)
|
||||
{
|
||||
position = count;
|
||||
break;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
|
||||
if (position != -1)
|
||||
{
|
||||
bind_helper(position, data, type);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::ostringstream ss;
|
||||
ss << "Unable to find name '" << name << "' to bind to";
|
||||
throw soci_error(ss.str().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void db2_vector_use_type_backend::pre_use(indicator const *ind)
|
||||
{
|
||||
// first deal with data
|
||||
if (type == x_stdtm)
|
||||
{
|
||||
std::vector<std::tm> *vp
|
||||
= static_cast<std::vector<std::tm> *>(data);
|
||||
|
||||
std::vector<std::tm> &v(*vp);
|
||||
|
||||
char *pos = buf;
|
||||
std::size_t const vsize = v.size();
|
||||
for (std::size_t i = 0; i != vsize; ++i)
|
||||
{
|
||||
std::tm t = v[i];
|
||||
TIMESTAMP_STRUCT * ts = reinterpret_cast<TIMESTAMP_STRUCT*>(pos);
|
||||
|
||||
ts->year = static_cast<SQLSMALLINT>(t.tm_year + 1900);
|
||||
ts->month = static_cast<SQLUSMALLINT>(t.tm_mon + 1);
|
||||
ts->day = static_cast<SQLUSMALLINT>(t.tm_mday);
|
||||
ts->hour = static_cast<SQLUSMALLINT>(t.tm_hour);
|
||||
ts->minute = static_cast<SQLUSMALLINT>(t.tm_min);
|
||||
ts->second = static_cast<SQLUSMALLINT>(t.tm_sec);
|
||||
ts->fraction = 0;
|
||||
pos += sizeof(TIMESTAMP_STRUCT);
|
||||
}
|
||||
}
|
||||
|
||||
// then handle indicators
|
||||
if (ind != NULL)
|
||||
{
|
||||
std::size_t const vsize = size();
|
||||
for (std::size_t i = 0; i != vsize; ++i, ++ind)
|
||||
{
|
||||
if (*ind == i_null)
|
||||
{
|
||||
indVec[i] = SQL_NULL_DATA; // null
|
||||
}
|
||||
else
|
||||
{
|
||||
// for strings we have already set the values
|
||||
if (type != x_stdstring)
|
||||
{
|
||||
indVec[i] = SQL_NTS; // value is OK
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// no indicators - treat all fields as OK
|
||||
std::size_t const vsize = size();
|
||||
for (std::size_t i = 0; i != vsize; ++i, ++ind)
|
||||
{
|
||||
// for strings we have already set the values
|
||||
if (type != x_stdstring)
|
||||
{
|
||||
indVec[i] = SQL_NTS; // value is OK
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t db2_vector_use_type_backend::size()
|
||||
{
|
||||
std::size_t sz = 0; // dummy initialization to please the compiler
|
||||
switch (type)
|
||||
{
|
||||
// simple cases
|
||||
case x_char:
|
||||
{
|
||||
std::vector<char> *vp = static_cast<std::vector<char> *>(data);
|
||||
sz = vp->size();
|
||||
}
|
||||
break;
|
||||
case x_short:
|
||||
{
|
||||
std::vector<short> *vp = static_cast<std::vector<short> *>(data);
|
||||
sz = vp->size();
|
||||
}
|
||||
break;
|
||||
case x_integer:
|
||||
{
|
||||
std::vector<int> *vp = static_cast<std::vector<int> *>(data);
|
||||
sz = vp->size();
|
||||
}
|
||||
break;
|
||||
case x_long_long:
|
||||
{
|
||||
std::vector<long long> *vp
|
||||
= static_cast<std::vector<long long> *>(data);
|
||||
sz = vp->size();
|
||||
}
|
||||
break;
|
||||
case x_unsigned_long_long:
|
||||
{
|
||||
std::vector<unsigned long long> *vp
|
||||
= static_cast<std::vector<unsigned long long> *>(data);
|
||||
sz = vp->size();
|
||||
}
|
||||
break;
|
||||
case x_double:
|
||||
{
|
||||
std::vector<double> *vp
|
||||
= static_cast<std::vector<double> *>(data);
|
||||
sz = vp->size();
|
||||
}
|
||||
break;
|
||||
case x_stdstring:
|
||||
{
|
||||
std::vector<std::string> *vp
|
||||
= static_cast<std::vector<std::string> *>(data);
|
||||
sz = vp->size();
|
||||
}
|
||||
break;
|
||||
case x_stdtm:
|
||||
{
|
||||
std::vector<std::tm> *vp
|
||||
= static_cast<std::vector<std::tm> *>(data);
|
||||
sz = vp->size();
|
||||
}
|
||||
break;
|
||||
|
||||
case x_statement: break; // not supported
|
||||
case x_rowid: break; // not supported
|
||||
case x_blob: break; // not supported
|
||||
}
|
||||
|
||||
return sz;
|
||||
}
|
||||
|
||||
void db2_vector_use_type_backend::clean_up()
|
||||
{
|
||||
if (buf != NULL)
|
||||
{
|
||||
delete [] buf;
|
||||
buf = NULL;
|
||||
}
|
||||
}
|
||||
17
src/soci/src/backends/empty/CMakeLists.txt
Normal file
17
src/soci/src/backends/empty/CMakeLists.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
###############################################################################
|
||||
#
|
||||
# This file is part of CMake configuration for SOCI library
|
||||
#
|
||||
# Copyright (C) 2010 Mateusz Loskot
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE_1_0.txt or copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
#
|
||||
###############################################################################
|
||||
soci_backend(Empty
|
||||
HEADERS soci-empty.h
|
||||
DESCRIPTION "SOCI backend skeleton for development of new backends"
|
||||
AUTHORS "Maciej Sobczak, Stephen Hutton"
|
||||
MAINTAINERS "Maciej Sobczak")
|
||||
|
||||
add_subdirectory(test)
|
||||
88
src/soci/src/backends/empty/Makefile.basic
Normal file
88
src/soci/src/backends/empty/Makefile.basic
Normal file
@@ -0,0 +1,88 @@
|
||||
# The following variable is specific to this backend and its correct
|
||||
# values might depend on your environment - feel free to set it accordingly.
|
||||
|
||||
EMPTYINCLUDEDIR =
|
||||
|
||||
# The rest of the Makefile is indepentent of the target environment.
|
||||
|
||||
COMPILER = g++
|
||||
CXXFLAGS = -Wall -pedantic -Wno-long-long
|
||||
CXXFLAGSSO = ${CXXFLAGS} -fPIC
|
||||
INCLUDEDIRS = -I../../core ${EMPTYINCLUDEDIR}
|
||||
|
||||
|
||||
OBJECTS = blob.o factory.o row-id.o session.o standard-into-type.o \
|
||||
standard-use-type.o statement.o vector-into-type.o vector-use-type.o
|
||||
|
||||
OBJECTSSO = blob-s.o factory-s.o row-id-s.o session-s.o \
|
||||
standard-into-type-s.o standard-use-type-s.o statement-s.o \
|
||||
vector-into-type-s.o vector-use-type-s.o
|
||||
|
||||
|
||||
libsoci_empty.a : ${OBJECTS}
|
||||
ar rv $@ $?
|
||||
rm *.o
|
||||
|
||||
|
||||
blob.o : blob.cpp
|
||||
${COMPILER} -c $? ${CXXFLAGS} ${INCLUDEDIRS}
|
||||
|
||||
factory.o : factory.cpp
|
||||
${COMPILER} -c $? ${CXXFLAGS} ${INCLUDEDIRS}
|
||||
|
||||
row-id.o : row-id.cpp
|
||||
${COMPILER} -c $? ${CXXFLAGS} ${INCLUDEDIRS}
|
||||
|
||||
session.o : session.cpp
|
||||
${COMPILER} -c $? ${CXXFLAGS} ${INCLUDEDIRS}
|
||||
|
||||
standard-into-type.o : standard-into-type.cpp
|
||||
${COMPILER} -c $? ${CXXFLAGS} ${INCLUDEDIRS}
|
||||
|
||||
standard-use-type.o : standard-use-type.cpp
|
||||
${COMPILER} -c $? ${CXXFLAGS} ${INCLUDEDIRS}
|
||||
|
||||
statement.o : statement.cpp
|
||||
${COMPILER} -c $? ${CXXFLAGS} ${INCLUDEDIRS}
|
||||
|
||||
vector-into-type.o : vector-into-type.cpp
|
||||
${COMPILER} -c $? ${CXXFLAGS} ${INCLUDEDIRS}
|
||||
|
||||
vector-use-type.o : vector-use-type.cpp
|
||||
${COMPILER} -c $? ${CXXFLAGS} ${INCLUDEDIRS}
|
||||
|
||||
|
||||
shared : ${OBJECTSSO}
|
||||
${COMPILER} -shared -o libsoci_empty.so ${OBJECTSSO}
|
||||
rm *.o
|
||||
|
||||
blob-s.o : blob.cpp
|
||||
${COMPILER} -c -o $@ $? ${CXXFLAGSSO} ${INCLUDEDIRS}
|
||||
|
||||
factory-s.o : factory.cpp
|
||||
${COMPILER} -c -o $@ $? ${CXXFLAGSSO} ${INCLUDEDIRS}
|
||||
|
||||
row-id-s.o : row-id.cpp
|
||||
${COMPILER} -c -o $@ $? ${CXXFLAGSSO} ${INCLUDEDIRS}
|
||||
|
||||
session-s.o : session.cpp
|
||||
${COMPILER} -c -o $@ $? ${CXXFLAGSSO} ${INCLUDEDIRS}
|
||||
|
||||
standard-into-type-s.o : standard-into-type.cpp
|
||||
${COMPILER} -c -o $@ $? ${CXXFLAGSSO} ${INCLUDEDIRS}
|
||||
|
||||
standard-use-type-s.o : standard-use-type.cpp
|
||||
${COMPILER} -c -o $@ $? ${CXXFLAGSSO} ${INCLUDEDIRS}
|
||||
|
||||
statement-s.o : statement.cpp
|
||||
${COMPILER} -c -o $@ $? ${CXXFLAGSSO} ${INCLUDEDIRS}
|
||||
|
||||
vector-into-type-s.o : vector-into-type.cpp
|
||||
${COMPILER} -c -o $@ $? ${CXXFLAGSSO} ${INCLUDEDIRS}
|
||||
|
||||
vector-use-type-s.o : vector-use-type.cpp
|
||||
${COMPILER} -c -o $@ $? ${CXXFLAGSSO} ${INCLUDEDIRS}
|
||||
|
||||
|
||||
clean :
|
||||
rm -f libsoci_empty.a libsoci_empty.so
|
||||
61
src/soci/src/backends/empty/blob.cpp
Normal file
61
src/soci/src/backends/empty/blob.cpp
Normal file
@@ -0,0 +1,61 @@
|
||||
//
|
||||
// Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#define SOCI_EMPTY_SOURCE
|
||||
#include "soci-empty.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4355)
|
||||
#endif
|
||||
|
||||
using namespace soci;
|
||||
using namespace soci::details;
|
||||
|
||||
|
||||
empty_blob_backend::empty_blob_backend(empty_session_backend &session)
|
||||
: session_(session)
|
||||
{
|
||||
// ...
|
||||
}
|
||||
|
||||
empty_blob_backend::~empty_blob_backend()
|
||||
{
|
||||
// ...
|
||||
}
|
||||
|
||||
std::size_t empty_blob_backend::get_len()
|
||||
{
|
||||
// ...
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::size_t empty_blob_backend::read(
|
||||
std::size_t /* offset */, char * /* buf */, std::size_t /* toRead */)
|
||||
{
|
||||
// ...
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::size_t empty_blob_backend::write(
|
||||
std::size_t /* offset */, char const * /* buf */,
|
||||
std::size_t /* toWrite */)
|
||||
{
|
||||
// ...
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::size_t empty_blob_backend::append(
|
||||
char const * /* buf */, std::size_t /* toWrite */)
|
||||
{
|
||||
// ...
|
||||
return 0;
|
||||
}
|
||||
|
||||
void empty_blob_backend::trim(std::size_t /* newLen */)
|
||||
{
|
||||
// ...
|
||||
}
|
||||
42
src/soci/src/backends/empty/factory.cpp
Normal file
42
src/soci/src/backends/empty/factory.cpp
Normal file
@@ -0,0 +1,42 @@
|
||||
//
|
||||
// Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#define SOCI_EMPTY_SOURCE
|
||||
#include "soci-empty.h"
|
||||
#include <backend-loader.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4355)
|
||||
#endif
|
||||
|
||||
using namespace soci;
|
||||
using namespace soci::details;
|
||||
|
||||
// concrete factory for Empty concrete strategies
|
||||
empty_session_backend* empty_backend_factory::make_session(
|
||||
connection_parameters const& parameters) const
|
||||
{
|
||||
return new empty_session_backend(parameters);
|
||||
}
|
||||
|
||||
empty_backend_factory const soci::empty;
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
// for dynamic backend loading
|
||||
SOCI_EMPTY_DECL backend_factory const* factory_empty()
|
||||
{
|
||||
return &soci::empty;
|
||||
}
|
||||
|
||||
SOCI_EMPTY_DECL void register_factory_empty()
|
||||
{
|
||||
soci::dynamic_backends::register_backend("empty", soci::empty);
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
27
src/soci/src/backends/empty/row-id.cpp
Normal file
27
src/soci/src/backends/empty/row-id.cpp
Normal file
@@ -0,0 +1,27 @@
|
||||
//
|
||||
// Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#define SOCI_EMPTY_SOURCE
|
||||
#include "soci-empty.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4355)
|
||||
#endif
|
||||
|
||||
using namespace soci;
|
||||
using namespace soci::details;
|
||||
|
||||
|
||||
empty_rowid_backend::empty_rowid_backend(empty_session_backend & /* session */)
|
||||
{
|
||||
// ...
|
||||
}
|
||||
|
||||
empty_rowid_backend::~empty_rowid_backend()
|
||||
{
|
||||
// ...
|
||||
}
|
||||
63
src/soci/src/backends/empty/session.cpp
Normal file
63
src/soci/src/backends/empty/session.cpp
Normal file
@@ -0,0 +1,63 @@
|
||||
//
|
||||
// Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#define SOCI_EMPTY_SOURCE
|
||||
#include "soci-empty.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4355)
|
||||
#endif
|
||||
|
||||
using namespace soci;
|
||||
using namespace soci::details;
|
||||
|
||||
|
||||
empty_session_backend::empty_session_backend(
|
||||
connection_parameters const & /* parameters */)
|
||||
{
|
||||
// ...
|
||||
}
|
||||
|
||||
empty_session_backend::~empty_session_backend()
|
||||
{
|
||||
clean_up();
|
||||
}
|
||||
|
||||
void empty_session_backend::begin()
|
||||
{
|
||||
// ...
|
||||
}
|
||||
|
||||
void empty_session_backend::commit()
|
||||
{
|
||||
// ...
|
||||
}
|
||||
|
||||
void empty_session_backend::rollback()
|
||||
{
|
||||
// ...
|
||||
}
|
||||
|
||||
void empty_session_backend::clean_up()
|
||||
{
|
||||
// ...
|
||||
}
|
||||
|
||||
empty_statement_backend * empty_session_backend::make_statement_backend()
|
||||
{
|
||||
return new empty_statement_backend(*this);
|
||||
}
|
||||
|
||||
empty_rowid_backend * empty_session_backend::make_rowid_backend()
|
||||
{
|
||||
return new empty_rowid_backend(*this);
|
||||
}
|
||||
|
||||
empty_blob_backend * empty_session_backend::make_blob_backend()
|
||||
{
|
||||
return new empty_blob_backend(*this);
|
||||
}
|
||||
193
src/soci/src/backends/empty/soci-empty.h
Normal file
193
src/soci/src/backends/empty/soci-empty.h
Normal file
@@ -0,0 +1,193 @@
|
||||
//
|
||||
// Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef SOCI_EMPTY_H_INCLUDED
|
||||
#define SOCI_EMPTY_H_INCLUDED
|
||||
|
||||
#ifdef _WIN32
|
||||
# ifdef SOCI_DLL
|
||||
# ifdef SOCI_EMPTY_SOURCE
|
||||
# define SOCI_EMPTY_DECL __declspec(dllexport)
|
||||
# else
|
||||
# define SOCI_EMPTY_DECL __declspec(dllimport)
|
||||
# endif // SOCI_EMPTY_SOURCE
|
||||
# endif // SOCI_DLL
|
||||
#endif // _WIN32
|
||||
//
|
||||
// If SOCI_EMPTY_DECL isn't defined yet define it now
|
||||
#ifndef SOCI_EMPTY_DECL
|
||||
# define SOCI_EMPTY_DECL
|
||||
#endif
|
||||
|
||||
#include "soci-backend.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
|
||||
namespace soci
|
||||
{
|
||||
|
||||
struct empty_statement_backend;
|
||||
|
||||
struct SOCI_EMPTY_DECL empty_standard_into_type_backend : details::standard_into_type_backend
|
||||
{
|
||||
empty_standard_into_type_backend(empty_statement_backend &st)
|
||||
: statement_(st)
|
||||
{}
|
||||
|
||||
void define_by_pos(int& position, void* data, details::exchange_type type);
|
||||
|
||||
void pre_fetch();
|
||||
void post_fetch(bool gotData, bool calledFromFetch, indicator* ind);
|
||||
|
||||
void clean_up();
|
||||
|
||||
empty_statement_backend& statement_;
|
||||
};
|
||||
|
||||
struct SOCI_EMPTY_DECL empty_vector_into_type_backend : details::vector_into_type_backend
|
||||
{
|
||||
empty_vector_into_type_backend(empty_statement_backend &st)
|
||||
: statement_(st)
|
||||
{}
|
||||
|
||||
void define_by_pos(int& position, void* data, details::exchange_type type);
|
||||
|
||||
void pre_fetch();
|
||||
void post_fetch(bool gotData, indicator* ind);
|
||||
|
||||
void resize(std::size_t sz);
|
||||
std::size_t size();
|
||||
|
||||
void clean_up();
|
||||
|
||||
empty_statement_backend& statement_;
|
||||
};
|
||||
|
||||
struct SOCI_EMPTY_DECL empty_standard_use_type_backend : details::standard_use_type_backend
|
||||
{
|
||||
empty_standard_use_type_backend(empty_statement_backend &st)
|
||||
: statement_(st)
|
||||
{}
|
||||
|
||||
void bind_by_pos(int& position, void* data, details::exchange_type type, bool readOnly);
|
||||
void bind_by_name(std::string const& name, void* data, details::exchange_type type, bool readOnly);
|
||||
|
||||
void pre_use(indicator const* ind);
|
||||
void post_use(bool gotData, indicator* ind);
|
||||
|
||||
void clean_up();
|
||||
|
||||
empty_statement_backend& statement_;
|
||||
};
|
||||
|
||||
struct SOCI_EMPTY_DECL empty_vector_use_type_backend : details::vector_use_type_backend
|
||||
{
|
||||
empty_vector_use_type_backend(empty_statement_backend &st)
|
||||
: statement_(st) {}
|
||||
|
||||
void bind_by_pos(int& position, void* data, details::exchange_type type);
|
||||
void bind_by_name(std::string const& name, void* data, details::exchange_type type);
|
||||
|
||||
void pre_use(indicator const* ind);
|
||||
|
||||
std::size_t size();
|
||||
|
||||
void clean_up();
|
||||
|
||||
empty_statement_backend& statement_;
|
||||
};
|
||||
|
||||
struct empty_session_backend;
|
||||
struct SOCI_EMPTY_DECL empty_statement_backend : details::statement_backend
|
||||
{
|
||||
empty_statement_backend(empty_session_backend &session);
|
||||
|
||||
void alloc();
|
||||
void clean_up();
|
||||
void prepare(std::string const& query, details::statement_type eType);
|
||||
|
||||
exec_fetch_result execute(int number);
|
||||
exec_fetch_result fetch(int number);
|
||||
|
||||
long long get_affected_rows();
|
||||
int get_number_of_rows();
|
||||
|
||||
std::string rewrite_for_procedure_call(std::string const& query);
|
||||
|
||||
int prepare_for_describe();
|
||||
void describe_column(int colNum, data_type& dtype, std::string& columnName);
|
||||
|
||||
empty_standard_into_type_backend* make_into_type_backend();
|
||||
empty_standard_use_type_backend* make_use_type_backend();
|
||||
empty_vector_into_type_backend* make_vector_into_type_backend();
|
||||
empty_vector_use_type_backend* make_vector_use_type_backend();
|
||||
|
||||
empty_session_backend& session_;
|
||||
};
|
||||
|
||||
struct empty_rowid_backend : details::rowid_backend
|
||||
{
|
||||
empty_rowid_backend(empty_session_backend &session);
|
||||
|
||||
~empty_rowid_backend();
|
||||
};
|
||||
|
||||
struct empty_blob_backend : details::blob_backend
|
||||
{
|
||||
empty_blob_backend(empty_session_backend& session);
|
||||
|
||||
~empty_blob_backend();
|
||||
|
||||
std::size_t get_len();
|
||||
std::size_t read(std::size_t offset, char* buf, std::size_t toRead);
|
||||
std::size_t write(std::size_t offset, char const* buf, std::size_t toWrite);
|
||||
std::size_t append(char const* buf, std::size_t toWrite);
|
||||
void trim(std::size_t newLen);
|
||||
|
||||
empty_session_backend& session_;
|
||||
};
|
||||
|
||||
struct empty_session_backend : details::session_backend
|
||||
{
|
||||
empty_session_backend(connection_parameters const& parameters);
|
||||
|
||||
~empty_session_backend();
|
||||
|
||||
void begin();
|
||||
void commit();
|
||||
void rollback();
|
||||
|
||||
std::string get_backend_name() const { return "empty"; }
|
||||
|
||||
void clean_up();
|
||||
|
||||
empty_statement_backend* make_statement_backend();
|
||||
empty_rowid_backend* make_rowid_backend();
|
||||
empty_blob_backend* make_blob_backend();
|
||||
};
|
||||
|
||||
struct SOCI_EMPTY_DECL empty_backend_factory : backend_factory
|
||||
{
|
||||
empty_backend_factory() {}
|
||||
empty_session_backend* make_session(connection_parameters const& parameters) const;
|
||||
};
|
||||
|
||||
extern SOCI_EMPTY_DECL empty_backend_factory const empty;
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
// for dynamic backend loading
|
||||
SOCI_EMPTY_DECL backend_factory const* factory_empty();
|
||||
SOCI_EMPTY_DECL void register_factory_empty();
|
||||
|
||||
} // extern "C"
|
||||
|
||||
} // namespace soci
|
||||
|
||||
#endif // SOCI_EMPTY_H_INCLUDED
|
||||
39
src/soci/src/backends/empty/standard-into-type.cpp
Normal file
39
src/soci/src/backends/empty/standard-into-type.cpp
Normal file
@@ -0,0 +1,39 @@
|
||||
//
|
||||
// Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#define SOCI_EMPTY_SOURCE
|
||||
#include "soci-empty.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4355)
|
||||
#endif
|
||||
|
||||
using namespace soci;
|
||||
using namespace soci::details;
|
||||
|
||||
|
||||
void empty_standard_into_type_backend::define_by_pos(
|
||||
int & /* position */, void * /* data */, exchange_type /* type */)
|
||||
{
|
||||
// ...
|
||||
}
|
||||
|
||||
void empty_standard_into_type_backend::pre_fetch()
|
||||
{
|
||||
// ...
|
||||
}
|
||||
|
||||
void empty_standard_into_type_backend::post_fetch(
|
||||
bool /* gotData */, bool /* calledFromFetch */, indicator * /* ind */)
|
||||
{
|
||||
// ...
|
||||
}
|
||||
|
||||
void empty_standard_into_type_backend::clean_up()
|
||||
{
|
||||
// ...
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user