Merge branch 'master' into 45185_Inner_join_with_where

This commit is contained in:
SmitaRKulkarni 2023-02-16 16:20:20 +01:00 committed by GitHub
commit f3f459fe34
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1333 changed files with 109177 additions and 105189 deletions

View File

@ -2,7 +2,7 @@
name: Debug
'on':
[push, pull_request, release, workflow_dispatch, workflow_call]
[push, pull_request, pull_request_review, release, workflow_dispatch, workflow_call]
jobs:
DebugInfo:

View File

@ -0,0 +1,23 @@
name: PullRequestApprovedCI
env:
# Force the stdout and stderr streams to be unbuffered
PYTHONUNBUFFERED: 1
on: # yamllint disable-line rule:truthy
pull_request_review:
types:
- submitted
jobs:
MergeOnApproval:
runs-on: [self-hosted, style-checker]
steps:
- name: Check out repository code
uses: ClickHouse/checkout@v1
with:
clear-repository: true
- name: Merge approved PR
run: |
cd "$GITHUB_WORKSPACE/tests/ci"
python3 merge_pr.py --check-approved

3
.gitmodules vendored
View File

@ -296,6 +296,9 @@
[submodule "contrib/libdivide"]
path = contrib/libdivide
url = https://github.com/ridiculousfish/libdivide
[submodule "contrib/ulid-c"]
path = contrib/ulid-c
url = https://github.com/ClickHouse/ulid-c.git
[submodule "contrib/aws-crt-cpp"]
path = contrib/aws-crt-cpp
url = https://github.com/ClickHouse/aws-crt-cpp

View File

@ -476,7 +476,12 @@ enable_testing() # Enable for tests without binary
option(ENABLE_OPENSSL "This option performs a build with OpenSSL. NOTE! This option is insecure and should never be used. By default, ClickHouse uses and only supports BoringSSL" OFF)
option(ENABLE_OPENSSL_DYNAMIC "This option removes SSL from ClickHouse and will link to the OpenSSL version supplied by OS." OFF)
if (ARCH_S390X)
set(ENABLE_OPENSSL_DYNAMIC_DEFAULT ON)
else ()
set(ENABLE_OPENSSL_DYNAMIC_DEFAULT OFF)
endif ()
option(ENABLE_OPENSSL_DYNAMIC "This option removes SSL from ClickHouse and will link to the OpenSSL version supplied by OS." ${ENABLE_OPENSSL_DYNAMIC_DEFAULT})
# when installing to /usr - place configs to /etc but for /usr/local place to /usr/local/etc
if (CMAKE_INSTALL_PREFIX STREQUAL "/usr")

View File

@ -84,7 +84,10 @@ if (OS MATCHES "Linux"
set (CMAKE_TOOLCHAIN_FILE "cmake/linux/toolchain-aarch64.cmake" CACHE INTERNAL "")
elseif (ARCH MATCHES "^(ppc64le.*|PPC64LE.*)")
set (CMAKE_TOOLCHAIN_FILE "cmake/linux/toolchain-ppc64le.cmake" CACHE INTERNAL "")
elseif (ARCH MATCHES "^(s390x.*|S390X.*)")
set (CMAKE_TOOLCHAIN_FILE "cmake/linux/toolchain-s390x.cmake" CACHE INTERNAL "")
else ()
message (FATAL_ERROR "Unsupported architecture: ${ARCH}")
endif ()
endif()

View File

@ -15,7 +15,13 @@ ClickHouse® is an open-source column-oriented database management system that a
* [Code Browser (github.dev)](https://github.dev/ClickHouse/ClickHouse) with syntax highlight, powered by github.dev.
* [Contacts](https://clickhouse.com/company/contact) can help to get your questions answered if there are any.
## Events
## Upcoming Events
* [**ClickHouse Workshop**](https://clickhouse.com/company/events/2023-02-15-clickhouse-workshop?utm_source=github&utm_medium=social&utm_campaign=workshop) - Feb 15 & 16 - In this 2-day (3 hrs per day) free training, topics range from introductory content to a deep dive on interacting with and understanding your data. There will be both live training and hands-on labs.
* [**v23.2 Release Webinar**](https://clickhouse.com/company/events/v23-2-release-webinar?utm_source=github&utm_medium=social&utm_campaign=release-webinar-2023-02) - Feb 23 - 23.2 is rapidly approaching. Original creator, co-founder, and CTO of ClickHouse Alexey Milovidov will walk us through the highlights of the release.
* [**ClickHouse Meetup in Amsterdam**](https://www.meetup.com/clickhouse-netherlands-user-group/events/291485868/) - Mar 9 - The first ClickHouse Amsterdam Meetup of 2023 is here! 🎉 Join us for short lightning talks and long discussions. Food, drinks & good times on us.
* [**ClickHouse Meetup in SF Bay Area**](https://www.meetup.com/clickhouse-silicon-valley-meetup-group/events/291490121/) - Mar 14 - A night to meet with ClickHouse team in the San Francisco area! Food and drink are a given...but networking is the primary focus.
* [**ClickHouse Meetup in Austin**](https://www.meetup.com/clickhouse-austin-user-group/events/291486654/) - Mar 16 - The first ClickHouse Meetup in Austin is happening soon! Interested in speaking, let us know!
## Recent Recordings
* **FOSDEM 2023**: In the "Fast and Streaming Data" room Alexey gave a talk entitled "Building Analytical Apps With ClickHouse" that looks at the landscape of data tools, an interesting data set, and how you can interact with data quickly. Check out the recording on **[YouTube](https://www.youtube.com/watch?v=JlcI2Vfz_uk)**.
* **Recording available**: [**v23.1 Release Webinar**](https://www.youtube.com/watch?v=zYSZXBnTMSE) 23.1 is the ClickHouse New Year release. Original creator, co-founder, and CTO of ClickHouse Alexey Milovidov will walk us through the highlights of the release. Inverted indices, query cache, and so -- very -- much more.
* **Recording available**: [**ClickHouse Meetup at the CHEQ office in Tel Aviv**](https://www.meetup.com/clickhouse-tel-aviv-user-group/events/289599423/) - We are very excited to be holding our next in-person ClickHouse meetup at the CHEQ office in Tel Aviv! Hear from CHEQ, ServiceNow and Contentsquare, as well as a deep dive presentation from ClickHouse CTO Alexey Milovidov. Join us for a fun evening of talks, food and discussion!

View File

@ -28,8 +28,8 @@
#define NO_INLINE __attribute__((__noinline__))
#define MAY_ALIAS __attribute__((__may_alias__))
#if !defined(__x86_64__) && !defined(__aarch64__) && !defined(__PPC__) && !(defined(__riscv) && (__riscv_xlen == 64))
# error "The only supported platforms are x86_64 and AArch64, PowerPC (work in progress) and RISC-V 64 (experimental)"
#if !defined(__x86_64__) && !defined(__aarch64__) && !defined(__PPC__) && !defined(__s390x__) && !(defined(__riscv) && (__riscv_xlen == 64))
# error "The only supported platforms are x86_64 and AArch64, PowerPC (work in progress), s390x (work in progress) and RISC-V 64 (experimental)"
#endif
/// Check for presence of address sanitizer

View File

@ -1,8 +1,8 @@
/** Origin: musl-libc /src/math/exp10.c
* https://www.musl-libc.org/
* http://git.musl-libc.org/cgit/musl/tree/src/math/exp10.c
*/
/*
https://www.musl-libc.org/
http://git.musl-libc.org/cgit/musl/tree/src/math/exp10.c
musl as a whole is licensed under the following standard MIT license:
----------------------------------------------------------------------
@ -27,146 +27,6 @@ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------
Authors/contributors include:
Alex Dowad
Alexander Monakov
Anthony G. Basile
Arvid Picciani
Bobby Bingham
Boris Brezillon
Brent Cook
Chris Spiegel
Clément Vasseur
Daniel Micay
Denys Vlasenko
Emil Renner Berthing
Felix Fietkau
Felix Janda
Gianluca Anzolin
Hauke Mehrtens
Hiltjo Posthuma
Isaac Dunham
Jaydeep Patil
Jens Gustedt
Jeremy Huntwork
Jo-Philipp Wich
Joakim Sindholt
John Spencer
Josiah Worcester
Justin Cormack
Khem Raj
Kylie McClain
Luca Barbato
Luka Perkov
M Farkas-Dyck (Strake)
Mahesh Bodapati
Michael Forney
Natanael Copa
Nicholas J. Kain
orc
Pascal Cuoq
Petr Hosek
Pierre Carrier
Rich Felker
Richard Pennington
Shiz
sin
Solar Designer
Stefan Kristiansson
Szabolcs Nagy
Timo Teräs
Trutz Behn
Valentin Ochs
William Haddon
Portions of this software are derived from third-party works licensed
under terms compatible with the above MIT license:
The TRE regular expression implementation (src/regex/reg* and
src/regex/tre*) is Copyright © 2001-2008 Ville Laurikari and licensed
under a 2-clause BSD license (license text in the source files). The
included version has been heavily modified by Rich Felker in 2012, in
the interests of size, simplicity, and namespace cleanliness.
Much of the math library code (src/math/ * and src/complex/ *) is
Copyright © 1993,2004 Sun Microsystems or
Copyright © 2003-2011 David Schultz or
Copyright © 2003-2009 Steven G. Kargl or
Copyright © 2003-2009 Bruce D. Evans or
Copyright © 2008 Stephen L. Moshier
and labelled as such in comments in the individual source files. All
have been licensed under extremely permissive terms.
The ARM memcpy code (src/string/arm/memcpy_el.S) is Copyright © 2008
The Android Open Source Project and is licensed under a two-clause BSD
license. It was taken from Bionic libc, used on Android.
The implementation of DES for crypt (src/crypt/crypt_des.c) is
Copyright © 1994 David Burren. It is licensed under a BSD license.
The implementation of blowfish crypt (src/crypt/crypt_blowfish.c) was
originally written by Solar Designer and placed into the public
domain. The code also comes with a fallback permissive license for use
in jurisdictions that may not recognize the public domain.
The smoothsort implementation (src/stdlib/qsort.c) is Copyright © 2011
Valentin Ochs and is licensed under an MIT-style license.
The BSD PRNG implementation (src/prng/random.c) and XSI search API
(src/search/ *.c) functions are Copyright © 2011 Szabolcs Nagy and
licensed under following terms: "Permission to use, copy, modify,
and/or distribute this code for any purpose with or without fee is
hereby granted. There is no warranty."
The x86_64 port was written by Nicholas J. Kain and is licensed under
the standard MIT terms.
The mips and microblaze ports were originally written by Richard
Pennington for use in the ellcc project. The original code was adapted
by Rich Felker for build system and code conventions during upstream
integration. It is licensed under the standard MIT terms.
The mips64 port was contributed by Imagination Technologies and is
licensed under the standard MIT terms.
The powerpc port was also originally written by Richard Pennington,
and later supplemented and integrated by John Spencer. It is licensed
under the standard MIT terms.
All other files which have no copyright comments are original works
produced specifically for use as part of this library, written either
by Rich Felker, the main author of the library, or by one or more
contibutors listed above. Details on authorship of individual files
can be found in the git version control history of the project. The
omission of copyright and license comments in each file is in the
interest of source tree size.
In addition, permission is hereby granted for all public header files
(include/ * and arch/ * /bits/ *) and crt files intended to be linked into
applications (crt/ *, ldso/dlstart.c, and arch/ * /crt_arch.h) to omit
the copyright notice and permission notice otherwise required by the
license, and to use these files without any requirement of
attribution. These files include substantial contributions from:
Bobby Bingham
John Spencer
Nicholas J. Kain
Rich Felker
Richard Pennington
Stefan Kristiansson
Szabolcs Nagy
all of whom have explicitly granted such permission.
This file previously contained text expressing a belief that most of
the files covered by the above exception were sufficiently trivial not
to be subject to copyright, resulting in confusion over whether it
negated the permissions granted in the license. In the spirit of
permissive licensing, and of not having licensing issues being an
obstacle to adoption, that text has been removed.
*/
#include <cmath>

View File

@ -3,9 +3,9 @@
/** exp10 from GNU libm fails to give precise result for integer arguments.
* For example, exp10(3) gives 1000.0000000000001
* despite the fact that 1000 is exactly representable in double and float.
* Better to always use implementation from MUSL.
* Better to always use our own implementation based on a MUSL's one.
*
* Note: the function names are different to avoid confusion with symbols from the system libm.
* Note: the function name is different to avoid confusion with symbols from the system libm.
*/
double preciseExp10(double x);

View File

@ -360,7 +360,7 @@ struct integer<Bits, Signed>::_impl
constexpr const unsigned to_copy = min_bits / base_bits;
for (unsigned i = 0; i < to_copy; ++i)
self.items[little(i)] = rhs.items[little(i)];
self.items[little(i)] = rhs.items[integer<Bits2, Signed2>::_impl::little(i)];
if constexpr (Bits > Bits2)
{

File diff suppressed because it is too large Load Diff

View File

@ -1,52 +0,0 @@
Guenter Obiltschnig
Alex Fabijanic
Peter Schojer
Ferdinand Beyer
Krzysztof Burghardt
Claus Dabringer
Caleb Epstein
Eran Hammer-Lahav
Chris Johnson
Sergey Kholodilov
Ryan Kraay
Larry Lewis
Andrew J. P. Maclean
Andrew Marlow
Paschal Mushubi
Jiang Shan
David Shawley
Sergey Skorokhodov
Tom Tan
Sergey N. Yatskevich
Marc Chevrier
Philippe Cuvillier
Marian Krivos
Franky Braem
Philip Prindeville
Anton Yabchinskiy
Rangel Reale
Fabrizio Duhem
Patrick White
Mike Naquin
Roger Meier
Mathaus Mendel
Arturo Castro
Adrian Imboden
Matej Knopp
Patrice Tarabbia
Lucas Clemente
Karl Reid
Pascal Bach
Cristian Thiago Moecke
Sergei Nikulov
Aaron Kaluszka
Iyed Bennour
Scott Davis
Kristin Cowalcijk
Yuval Kashtan
Christopher Baker
Scott Davis
Jeff Adams
Martin Osborne
Björn Schramke
Francis Andre

View File

@ -18,121 +18,124 @@
#define Crypto_Cipher_INCLUDED
#include "Poco/Crypto/Crypto.h"
#include "Poco/RefCountedObject.h"
#include "Poco/AutoPtr.h"
#include <istream>
#include <ostream>
#include <vector>
#include "Poco/AutoPtr.h"
#include "Poco/Crypto/Crypto.h"
#include "Poco/RefCountedObject.h"
namespace Poco {
namespace Crypto {
class CryptoTransform;
class Crypto_API Cipher: public Poco::RefCountedObject
/// Represents the abstract base class from which all implementations of
/// symmetric/asymmetric encryption algorithms must inherit. Use the CipherFactory
/// class to obtain an instance of this class:
///
/// CipherFactory& factory = CipherFactory::defaultFactory();
/// // Creates a 256-bit AES cipher
/// Cipher* pCipher = factory.createCipher(CipherKey("aes-256"));
/// Cipher* pRSACipher = factory.createCipher(RSAKey(RSAKey::KL_1024, RSAKey::EXP_SMALL));
///
/// Check the different Key constructors on how to initialize/create
/// a key. The above example auto-generates random keys.
///
/// Note that you won't be able to decrypt data encrypted with a random key
/// once the Cipher is destroyed unless you persist the generated key and IV.
/// An example usage for random keys is to encrypt data saved in a temporary
/// file.
///
/// Once your key is set up, you can use the Cipher object to encrypt or
/// decrypt strings or, in conjunction with a CryptoInputStream or a
/// CryptoOutputStream, to encrypt streams of data.
///
/// Since encrypted strings will contain arbitrary binary data that will cause
/// problems in applications that are not binary-safe (eg., when sending
/// encrypted data in e-mails), the encryptString() and decryptString() can
/// encode (or decode, respectively) encrypted data using a "transport encoding".
/// Supported encodings are Base64 and BinHex.
///
/// The following example encrypts and decrypts a string utilizing Base64
/// encoding:
///
/// std::string plainText = "This is my secret information";
/// std::string encrypted = pCipher->encryptString(plainText, Cipher::ENC_BASE64);
/// std::string decrypted = pCipher->decryptString(encrypted, Cipher::ENC_BASE64);
///
/// In order to encrypt a stream of data (eg. to encrypt files), you can use
/// a CryptoStream:
///
/// // Create an output stream that will encrypt all data going through it
/// // and write pass it to the underlying file stream.
/// Poco::FileOutputStream sink("encrypted.dat");
/// CryptoOutputStream encryptor(sink, pCipher->createEncryptor());
///
/// Poco::FileInputStream source("source.txt");
/// Poco::StreamCopier::copyStream(source, encryptor);
///
/// // Always close output streams to flush all internal buffers
/// encryptor.close();
/// sink.close();
namespace Poco
{
namespace Crypto
{
public:
typedef Poco::AutoPtr<Cipher> Ptr;
typedef std::vector<unsigned char> ByteVec;
enum Encoding
/// Transport encoding to use for encryptString() and decryptString().
{
ENC_NONE = 0x00, /// Plain binary output
ENC_BASE64 = 0x01, /// Base64-encoded output
ENC_BINHEX = 0x02, /// BinHex-encoded output
ENC_BASE64_NO_LF = 0x81, /// Base64-encoded output, no linefeeds
ENC_BINHEX_NO_LF = 0x82 /// BinHex-encoded output, no linefeeds
};
virtual ~Cipher();
/// Destroys the Cipher.
virtual const std::string& name() const = 0;
/// Returns the name of the Cipher.
virtual CryptoTransform* createEncryptor() = 0;
/// Creates an encryptor object to be used with a CryptoStream.
virtual CryptoTransform* createDecryptor() = 0;
/// Creates a decryptor object to be used with a CryptoStream.
virtual std::string encryptString(const std::string& str, Encoding encoding = ENC_NONE);
/// Directly encrypt a string and encode it using the given encoding.
virtual std::string decryptString(const std::string& str, Encoding encoding = ENC_NONE);
/// Directly decrypt a string that is encoded with the given encoding.
virtual void encrypt(std::istream& source, std::ostream& sink, Encoding encoding = ENC_NONE);
/// Directly encrypts an input stream and encodes it using the given encoding.
virtual void decrypt(std::istream& source, std::ostream& sink, Encoding encoding = ENC_NONE);
/// Directly decrypt an input stream that is encoded with the given encoding.
protected:
Cipher();
/// Creates a new Cipher object.
private:
Cipher(const Cipher&);
Cipher& operator = (const Cipher&);
};
} } // namespace Poco::Crypto
class CryptoTransform;
class Crypto_API Cipher : public Poco::RefCountedObject
/// Represents the abstract base class from which all implementations of
/// symmetric/asymmetric encryption algorithms must inherit. Use the CipherFactory
/// class to obtain an instance of this class:
///
/// CipherFactory& factory = CipherFactory::defaultFactory();
/// // Creates a 256-bit AES cipher
/// Cipher* pCipher = factory.createCipher(CipherKey("aes-256"));
/// Cipher* pRSACipher = factory.createCipher(RSAKey(RSAKey::KL_1024, RSAKey::EXP_SMALL));
///
/// Check the different Key constructors on how to initialize/create
/// a key. The above example auto-generates random keys.
///
/// Note that you won't be able to decrypt data encrypted with a random key
/// once the Cipher is destroyed unless you persist the generated key and IV.
/// An example usage for random keys is to encrypt data saved in a temporary
/// file.
///
/// Once your key is set up, you can use the Cipher object to encrypt or
/// decrypt strings or, in conjunction with a CryptoInputStream or a
/// CryptoOutputStream, to encrypt streams of data.
///
/// Since encrypted strings will contain arbitrary binary data that will cause
/// problems in applications that are not binary-safe (eg., when sending
/// encrypted data in e-mails), the encryptString() and decryptString() can
/// encode (or decode, respectively) encrypted data using a "transport encoding".
/// Supported encodings are Base64 and BinHex.
///
/// The following example encrypts and decrypts a string utilizing Base64
/// encoding:
///
/// std::string plainText = "This is my secret information";
/// std::string encrypted = pCipher->encryptString(plainText, Cipher::ENC_BASE64);
/// std::string decrypted = pCipher->decryptString(encrypted, Cipher::ENC_BASE64);
///
/// In order to encrypt a stream of data (eg. to encrypt files), you can use
/// a CryptoStream:
///
/// // Create an output stream that will encrypt all data going through it
/// // and write pass it to the underlying file stream.
/// Poco::FileOutputStream sink("encrypted.dat");
/// CryptoOutputStream encryptor(sink, pCipher->createEncryptor());
///
/// Poco::FileInputStream source("source.txt");
/// Poco::StreamCopier::copyStream(source, encryptor);
///
/// // Always close output streams to flush all internal buffers
/// encryptor.close();
/// sink.close();
{
public:
typedef Poco::AutoPtr<Cipher> Ptr;
typedef std::vector<unsigned char> ByteVec;
enum Encoding
/// Transport encoding to use for encryptString() and decryptString().
{
ENC_NONE = 0x00, /// Plain binary output
ENC_BASE64 = 0x01, /// Base64-encoded output
ENC_BINHEX = 0x02, /// BinHex-encoded output
ENC_BASE64_NO_LF = 0x81, /// Base64-encoded output, no linefeeds
ENC_BINHEX_NO_LF = 0x82 /// BinHex-encoded output, no linefeeds
};
virtual ~Cipher();
/// Destroys the Cipher.
virtual const std::string & name() const = 0;
/// Returns the name of the Cipher.
virtual CryptoTransform * createEncryptor() = 0;
/// Creates an encryptor object to be used with a CryptoStream.
virtual CryptoTransform * createDecryptor() = 0;
/// Creates a decryptor object to be used with a CryptoStream.
virtual std::string encryptString(const std::string & str, Encoding encoding = ENC_NONE);
/// Directly encrypt a string and encode it using the given encoding.
virtual std::string decryptString(const std::string & str, Encoding encoding = ENC_NONE);
/// Directly decrypt a string that is encoded with the given encoding.
virtual void encrypt(std::istream & source, std::ostream & sink, Encoding encoding = ENC_NONE);
/// Directly encrypts an input stream and encodes it using the given encoding.
virtual void decrypt(std::istream & source, std::ostream & sink, Encoding encoding = ENC_NONE);
/// Directly decrypt an input stream that is encoded with the given encoding.
protected:
Cipher();
/// Creates a new Cipher object.
private:
Cipher(const Cipher &);
Cipher & operator=(const Cipher &);
};
}
} // namespace Poco::Crypto
#endif // Crypto_Cipher_INCLUDED

View File

@ -21,55 +21,58 @@
#include "Poco/Crypto/Crypto.h"
namespace Poco {
namespace Crypto {
class Cipher;
class CipherKey;
class RSAKey;
class Crypto_API CipherFactory
/// A factory for Cipher objects. See the Cipher class for examples on how to
/// use the CipherFactory.
namespace Poco
{
namespace Crypto
{
public:
CipherFactory();
/// Creates a new CipherFactory object.
virtual ~CipherFactory();
/// Destroys the CipherFactory.
Cipher* createCipher(const CipherKey& key);
/// Creates a Cipher object for the given Cipher name. Valid cipher
/// names depend on the OpenSSL version the library is linked with;
/// see the output of
///
/// openssl enc --help
///
/// for a list of supported block and stream ciphers.
///
/// Common examples are:
///
/// * AES: "aes-128", "aes-256"
/// * DES: "des", "des3"
/// * Blowfish: "bf"
Cipher* createCipher(const RSAKey& key, RSAPaddingMode paddingMode = RSA_PADDING_PKCS1);
/// Creates a RSACipher using the given RSA key and padding mode
/// for public key encryption/private key decryption.
static CipherFactory& defaultFactory();
/// Returns the default CipherFactory.
private:
CipherFactory(const CipherFactory&);
CipherFactory& operator = (const CipherFactory&);
};
} } // namespace Poco::Crypto
class Cipher;
class CipherKey;
class RSAKey;
class Crypto_API CipherFactory
/// A factory for Cipher objects. See the Cipher class for examples on how to
/// use the CipherFactory.
{
public:
CipherFactory();
/// Creates a new CipherFactory object.
virtual ~CipherFactory();
/// Destroys the CipherFactory.
Cipher * createCipher(const CipherKey & key);
/// Creates a Cipher object for the given Cipher name. Valid cipher
/// names depend on the OpenSSL version the library is linked with;
/// see the output of
///
/// openssl enc --help
///
/// for a list of supported block and stream ciphers.
///
/// Common examples are:
///
/// * AES: "aes-128", "aes-256"
/// * DES: "des", "des3"
/// * Blowfish: "bf"
Cipher * createCipher(const RSAKey & key, RSAPaddingMode paddingMode = RSA_PADDING_PKCS1);
/// Creates a RSACipher using the given RSA key and padding mode
/// for public key encryption/private key decryption.
static CipherFactory & defaultFactory();
/// Returns the default CipherFactory.
private:
CipherFactory(const CipherFactory &);
CipherFactory & operator=(const CipherFactory &);
};
}
} // namespace Poco::Crypto
#endif // Crypto_CipherFactory_INCLUDED

View File

@ -18,52 +18,55 @@
#define Crypto_CipherImpl_INCLUDED
#include "Poco/Crypto/Crypto.h"
#include <openssl/evp.h>
#include "Poco/Crypto/Cipher.h"
#include "Poco/Crypto/CipherKey.h"
#include "Poco/Crypto/Crypto.h"
#include "Poco/Crypto/OpenSSLInitializer.h"
#include <openssl/evp.h>
namespace Poco {
namespace Crypto {
class CipherImpl: public Cipher
/// An implementation of the Cipher class for OpenSSL's crypto library.
namespace Poco
{
public:
CipherImpl(const CipherKey& key);
/// Creates a new CipherImpl object for the given CipherKey.
virtual ~CipherImpl();
/// Destroys the CipherImpl.
const std::string& name() const;
/// Returns the name of the cipher.
CryptoTransform* createEncryptor();
/// Creates an encryptor object.
CryptoTransform* createDecryptor();
/// Creates a decryptor object.
private:
CipherKey _key;
OpenSSLInitializer _openSSLInitializer;
};
//
// Inlines
//
inline const std::string& CipherImpl::name() const
namespace Crypto
{
return _key.name();
class CipherImpl : public Cipher
/// An implementation of the Cipher class for OpenSSL's crypto library.
{
public:
CipherImpl(const CipherKey & key);
/// Creates a new CipherImpl object for the given CipherKey.
virtual ~CipherImpl();
/// Destroys the CipherImpl.
const std::string & name() const;
/// Returns the name of the cipher.
CryptoTransform * createEncryptor();
/// Creates an encryptor object.
CryptoTransform * createDecryptor();
/// Creates a decryptor object.
private:
CipherKey _key;
OpenSSLInitializer _openSSLInitializer;
};
//
// Inlines
//
inline const std::string & CipherImpl::name() const
{
return _key.name();
}
}
} } // namespace Poco::Crypto
} // namespace Poco::Crypto
#endif // Crypto_CipherImpl_INCLUDED

View File

@ -18,184 +18,186 @@
#define Crypto_CipherKey_INCLUDED
#include "Poco/Crypto/Crypto.h"
#include "Poco/Crypto/CipherKeyImpl.h"
#include "Poco/Crypto/Crypto.h"
namespace Poco {
namespace Crypto {
class Crypto_API CipherKey
/// CipherKey stores the key information for decryption/encryption of data.
/// To create a random key, using the following code:
///
/// CipherKey key("aes-256");
///
/// Note that you won't be able to decrypt data encrypted with a random key
/// once the Cipher is destroyed unless you persist the generated key and IV.
/// An example usage for random keys is to encrypt data saved in a temporary
/// file.
///
/// To create a key using a human-readable password
/// string, use the following code. We create a AES Cipher and
/// use a salt value to make the key more robust:
///
/// std::string password = "secret";
/// std::string salt("asdff8723lasdf(**923412");
/// CipherKey key("aes-256", password, salt);
///
/// You may also control the digest and the number of iterations used to generate the key
/// by specifying the specific values. Here we create a key with the same data as before,
/// except that we use 100 iterations instead of DEFAULT_ITERATION_COUNT, and sha1 instead of
/// the default md5:
///
/// std::string password = "secret";
/// std::string salt("asdff8723lasdf(**923412");
/// std::string digest ("sha1");
/// CipherKey key("aes-256", password, salt, 100, digest);
///
namespace Poco
{
public:
typedef CipherKeyImpl::Mode Mode;
typedef CipherKeyImpl::ByteVec ByteVec;
enum
{
DEFAULT_ITERATION_COUNT = 2000
/// Default iteration count to use with
/// generateKey(). RSA security recommends
/// an iteration count of at least 1000.
};
CipherKey(const std::string& name,
const std::string& passphrase,
const std::string& salt = "",
int iterationCount = DEFAULT_ITERATION_COUNT,
const std::string& digest = "md5");
/// Creates a new CipherKeyImpl object using the given
/// cipher name, passphrase, salt value, iteration count and digest.
CipherKey(const std::string& name,
const ByteVec& key,
const ByteVec& iv);
/// Creates a new CipherKeyImpl object using the given cipher
/// name, key and initialization vector (IV).
///
/// The size of the IV must match the cipher's expected
/// IV size (see ivSize()), except for GCM mode, which allows
/// a custom IV size.
CipherKey(const std::string& name);
/// Creates a new CipherKeyImpl object. Autoinitializes key and
/// initialization vector.
~CipherKey();
/// Destroys the CipherKeyImpl.
const std::string& name() const;
/// Returns the name of the Cipher.
int keySize() const;
/// Returns the key size of the Cipher.
int blockSize() const;
/// Returns the block size of the Cipher.
int ivSize() const;
/// Returns the IV size of the Cipher.
Mode mode() const;
/// Returns the Cipher's mode of operation.
const ByteVec& getKey() const;
/// Returns the key for the Cipher.
void setKey(const ByteVec& key);
/// Sets the key for the Cipher.
const ByteVec& getIV() const;
/// Returns the initialization vector (IV) for the Cipher.
void setIV(const ByteVec& iv);
/// Sets the initialization vector (IV) for the Cipher.
///
/// The size of the vector must match the cipher's expected
/// IV size (see ivSize()), except for GCM mode, which allows
/// a custom IV size.
CipherKeyImpl::Ptr impl();
/// Returns the impl object
private:
CipherKeyImpl::Ptr _pImpl;
};
//
// inlines
//
inline const std::string& CipherKey::name() const
namespace Crypto
{
return _pImpl->name();
class Crypto_API CipherKey
/// CipherKey stores the key information for decryption/encryption of data.
/// To create a random key, using the following code:
///
/// CipherKey key("aes-256");
///
/// Note that you won't be able to decrypt data encrypted with a random key
/// once the Cipher is destroyed unless you persist the generated key and IV.
/// An example usage for random keys is to encrypt data saved in a temporary
/// file.
///
/// To create a key using a human-readable password
/// string, use the following code. We create a AES Cipher and
/// use a salt value to make the key more robust:
///
/// std::string password = "secret";
/// std::string salt("asdff8723lasdf(**923412");
/// CipherKey key("aes-256", password, salt);
///
/// You may also control the digest and the number of iterations used to generate the key
/// by specifying the specific values. Here we create a key with the same data as before,
/// except that we use 100 iterations instead of DEFAULT_ITERATION_COUNT, and sha1 instead of
/// the default md5:
///
/// std::string password = "secret";
/// std::string salt("asdff8723lasdf(**923412");
/// std::string digest ("sha1");
/// CipherKey key("aes-256", password, salt, 100, digest);
///
{
public:
typedef CipherKeyImpl::Mode Mode;
typedef CipherKeyImpl::ByteVec ByteVec;
enum
{
DEFAULT_ITERATION_COUNT = 2000
/// Default iteration count to use with
/// generateKey(). RSA security recommends
/// an iteration count of at least 1000.
};
CipherKey(
const std::string & name,
const std::string & passphrase,
const std::string & salt = "",
int iterationCount = DEFAULT_ITERATION_COUNT,
const std::string & digest = "md5");
/// Creates a new CipherKeyImpl object using the given
/// cipher name, passphrase, salt value, iteration count and digest.
CipherKey(const std::string & name, const ByteVec & key, const ByteVec & iv);
/// Creates a new CipherKeyImpl object using the given cipher
/// name, key and initialization vector (IV).
///
/// The size of the IV must match the cipher's expected
/// IV size (see ivSize()), except for GCM mode, which allows
/// a custom IV size.
CipherKey(const std::string & name);
/// Creates a new CipherKeyImpl object. Autoinitializes key and
/// initialization vector.
~CipherKey();
/// Destroys the CipherKeyImpl.
const std::string & name() const;
/// Returns the name of the Cipher.
int keySize() const;
/// Returns the key size of the Cipher.
int blockSize() const;
/// Returns the block size of the Cipher.
int ivSize() const;
/// Returns the IV size of the Cipher.
Mode mode() const;
/// Returns the Cipher's mode of operation.
const ByteVec & getKey() const;
/// Returns the key for the Cipher.
void setKey(const ByteVec & key);
/// Sets the key for the Cipher.
const ByteVec & getIV() const;
/// Returns the initialization vector (IV) for the Cipher.
void setIV(const ByteVec & iv);
/// Sets the initialization vector (IV) for the Cipher.
///
/// The size of the vector must match the cipher's expected
/// IV size (see ivSize()), except for GCM mode, which allows
/// a custom IV size.
CipherKeyImpl::Ptr impl();
/// Returns the impl object
private:
CipherKeyImpl::Ptr _pImpl;
};
//
// inlines
//
inline const std::string & CipherKey::name() const
{
return _pImpl->name();
}
inline int CipherKey::keySize() const
{
return _pImpl->keySize();
}
inline int CipherKey::blockSize() const
{
return _pImpl->blockSize();
}
inline int CipherKey::ivSize() const
{
return _pImpl->ivSize();
}
inline CipherKey::Mode CipherKey::mode() const
{
return _pImpl->mode();
}
inline const CipherKey::ByteVec & CipherKey::getKey() const
{
return _pImpl->getKey();
}
inline void CipherKey::setKey(const CipherKey::ByteVec & key)
{
_pImpl->setKey(key);
}
inline const CipherKey::ByteVec & CipherKey::getIV() const
{
return _pImpl->getIV();
}
inline void CipherKey::setIV(const CipherKey::ByteVec & iv)
{
_pImpl->setIV(iv);
}
inline CipherKeyImpl::Ptr CipherKey::impl()
{
return _pImpl;
}
}
inline int CipherKey::keySize() const
{
return _pImpl->keySize();
}
inline int CipherKey::blockSize() const
{
return _pImpl->blockSize();
}
inline int CipherKey::ivSize() const
{
return _pImpl->ivSize();
}
inline CipherKey::Mode CipherKey::mode() const
{
return _pImpl->mode();
}
inline const CipherKey::ByteVec& CipherKey::getKey() const
{
return _pImpl->getKey();
}
inline void CipherKey::setKey(const CipherKey::ByteVec& key)
{
_pImpl->setKey(key);
}
inline const CipherKey::ByteVec& CipherKey::getIV() const
{
return _pImpl->getIV();
}
inline void CipherKey::setIV(const CipherKey::ByteVec& iv)
{
_pImpl->setIV(iv);
}
inline CipherKeyImpl::Ptr CipherKey::impl()
{
return _pImpl;
}
} } // namespace Poco::Crypto
} // namespace Poco::Crypto
#endif // Crypto_CipherKey_INCLUDED

View File

@ -18,151 +18,151 @@
#define Crypto_CipherKeyImpl_INCLUDED
#include <vector>
#include "Poco/AutoPtr.h"
#include "Poco/Crypto/Crypto.h"
#include "Poco/Crypto/OpenSSLInitializer.h"
#include "Poco/RefCountedObject.h"
#include "Poco/AutoPtr.h"
#include <vector>
struct evp_cipher_st;
typedef struct evp_cipher_st EVP_CIPHER;
namespace Poco {
namespace Crypto {
class CipherKeyImpl: public RefCountedObject
/// An implementation of the CipherKey class for OpenSSL's crypto library.
namespace Poco
{
public:
typedef std::vector<unsigned char> ByteVec;
typedef Poco::AutoPtr<CipherKeyImpl> Ptr;
enum Mode
/// Cipher mode of operation. This mode determines how multiple blocks
/// are connected; this is essential to improve security.
{
MODE_STREAM_CIPHER, /// Stream cipher
MODE_ECB, /// Electronic codebook (plain concatenation)
MODE_CBC, /// Cipher block chaining (default)
MODE_CFB, /// Cipher feedback
MODE_OFB, /// Output feedback
MODE_CTR, /// Counter mode
MODE_GCM, /// Galois/Counter mode
MODE_CCM /// Counter with CBC-MAC
};
CipherKeyImpl(const std::string& name,
const std::string& passphrase,
const std::string& salt,
int iterationCount,
const std::string& digest);
/// Creates a new CipherKeyImpl object, using
/// the given cipher name, passphrase, salt value
/// and iteration count.
CipherKeyImpl(const std::string& name,
const ByteVec& key,
const ByteVec& iv);
/// Creates a new CipherKeyImpl object, using the
/// given cipher name, key and initialization vector.
CipherKeyImpl(const std::string& name);
/// Creates a new CipherKeyImpl object. Autoinitializes key
/// and initialization vector.
virtual ~CipherKeyImpl();
/// Destroys the CipherKeyImpl.
const std::string& name() const;
/// Returns the name of the Cipher.
int keySize() const;
/// Returns the key size of the Cipher.
int blockSize() const;
/// Returns the block size of the Cipher.
int ivSize() const;
/// Returns the IV size of the Cipher.
Mode mode() const;
/// Returns the Cipher's mode of operation.
const ByteVec& getKey() const;
/// Returns the key for the Cipher.
void setKey(const ByteVec& key);
/// Sets the key for the Cipher.
const ByteVec& getIV() const;
/// Returns the initialization vector (IV) for the Cipher.
void setIV(const ByteVec& iv);
/// Sets the initialization vector (IV) for the Cipher.
const EVP_CIPHER* cipher();
/// Returns the cipher object
private:
void generateKey(const std::string& passphrase,
const std::string& salt,
int iterationCount);
/// Generates key and IV from a password and optional salt string.
void generateKey();
/// Generates key and IV from random data.
void getRandomBytes(ByteVec& vec, std::size_t count);
/// Stores random bytes in vec.
private:
const EVP_CIPHER* _pCipher;
const EVP_MD* _pDigest;
std::string _name;
ByteVec _key;
ByteVec _iv;
OpenSSLInitializer _openSSLInitializer;
};
//
// Inlines
//
inline const std::string& CipherKeyImpl::name() const
namespace Crypto
{
return _name;
class CipherKeyImpl : public RefCountedObject
/// An implementation of the CipherKey class for OpenSSL's crypto library.
{
public:
typedef std::vector<unsigned char> ByteVec;
typedef Poco::AutoPtr<CipherKeyImpl> Ptr;
enum Mode
/// Cipher mode of operation. This mode determines how multiple blocks
/// are connected; this is essential to improve security.
{
MODE_STREAM_CIPHER, /// Stream cipher
MODE_ECB, /// Electronic codebook (plain concatenation)
MODE_CBC, /// Cipher block chaining (default)
MODE_CFB, /// Cipher feedback
MODE_OFB, /// Output feedback
MODE_CTR, /// Counter mode
MODE_GCM, /// Galois/Counter mode
MODE_CCM /// Counter with CBC-MAC
};
CipherKeyImpl(
const std::string & name,
const std::string & passphrase,
const std::string & salt,
int iterationCount,
const std::string & digest);
/// Creates a new CipherKeyImpl object, using
/// the given cipher name, passphrase, salt value
/// and iteration count.
CipherKeyImpl(const std::string & name, const ByteVec & key, const ByteVec & iv);
/// Creates a new CipherKeyImpl object, using the
/// given cipher name, key and initialization vector.
CipherKeyImpl(const std::string & name);
/// Creates a new CipherKeyImpl object. Autoinitializes key
/// and initialization vector.
virtual ~CipherKeyImpl();
/// Destroys the CipherKeyImpl.
const std::string & name() const;
/// Returns the name of the Cipher.
int keySize() const;
/// Returns the key size of the Cipher.
int blockSize() const;
/// Returns the block size of the Cipher.
int ivSize() const;
/// Returns the IV size of the Cipher.
Mode mode() const;
/// Returns the Cipher's mode of operation.
const ByteVec & getKey() const;
/// Returns the key for the Cipher.
void setKey(const ByteVec & key);
/// Sets the key for the Cipher.
const ByteVec & getIV() const;
/// Returns the initialization vector (IV) for the Cipher.
void setIV(const ByteVec & iv);
/// Sets the initialization vector (IV) for the Cipher.
const EVP_CIPHER * cipher();
/// Returns the cipher object
private:
void generateKey(const std::string & passphrase, const std::string & salt, int iterationCount);
/// Generates key and IV from a password and optional salt string.
void generateKey();
/// Generates key and IV from random data.
void getRandomBytes(ByteVec & vec, std::size_t count);
/// Stores random bytes in vec.
private:
const EVP_CIPHER * _pCipher;
const EVP_MD * _pDigest;
std::string _name;
ByteVec _key;
ByteVec _iv;
OpenSSLInitializer _openSSLInitializer;
};
//
// Inlines
//
inline const std::string & CipherKeyImpl::name() const
{
return _name;
}
inline const CipherKeyImpl::ByteVec & CipherKeyImpl::getKey() const
{
return _key;
}
inline void CipherKeyImpl::setKey(const ByteVec & key)
{
poco_assert(key.size() == static_cast<ByteVec::size_type>(keySize()));
_key = key;
}
inline const CipherKeyImpl::ByteVec & CipherKeyImpl::getIV() const
{
return _iv;
}
inline const EVP_CIPHER * CipherKeyImpl::cipher()
{
return _pCipher;
}
}
inline const CipherKeyImpl::ByteVec& CipherKeyImpl::getKey() const
{
return _key;
}
inline void CipherKeyImpl::setKey(const ByteVec& key)
{
poco_assert(key.size() == static_cast<ByteVec::size_type>(keySize()));
_key = key;
}
inline const CipherKeyImpl::ByteVec& CipherKeyImpl::getIV() const
{
return _iv;
}
inline const EVP_CIPHER* CipherKeyImpl::cipher()
{
return _pCipher;
}
} } // namespace Poco::Crypto
} // namespace Poco::Crypto
#endif // Crypto_CipherKeyImpl_INCLUDED

View File

@ -24,39 +24,37 @@
#define POCO_EXTERNAL_OPENSSL_SLPRO 2
#include "Poco/Foundation.h"
#include <openssl/opensslv.h>
#include "Poco/Foundation.h"
#ifndef OPENSSL_VERSION_PREREQ
#if defined(OPENSSL_VERSION_MAJOR) && defined(OPENSSL_VERSION_MINOR)
#define OPENSSL_VERSION_PREREQ(maj, min) \
((OPENSSL_VERSION_MAJOR << 16) + OPENSSL_VERSION_MINOR >= ((maj) << 16) + (min))
#else
#define OPENSSL_VERSION_PREREQ(maj, min) \
(OPENSSL_VERSION_NUMBER >= (((maj) << 28) | ((min) << 20)))
#endif
# if defined(OPENSSL_VERSION_MAJOR) && defined(OPENSSL_VERSION_MINOR)
# define OPENSSL_VERSION_PREREQ(maj, min) ((OPENSSL_VERSION_MAJOR << 16) + OPENSSL_VERSION_MINOR >= ((maj) << 16) + (min))
# else
# define OPENSSL_VERSION_PREREQ(maj, min) (OPENSSL_VERSION_NUMBER >= (((maj) << 28) | ((min) << 20)))
# endif
#endif
enum RSAPaddingMode
/// The padding mode used for RSA public key encryption.
/// The padding mode used for RSA public key encryption.
{
RSA_PADDING_PKCS1,
/// PKCS #1 v1.5 padding. This currently is the most widely used mode.
RSA_PADDING_PKCS1_OAEP,
/// EME-OAEP as defined in PKCS #1 v2.0 with SHA-1, MGF1 and an empty
/// encoding parameter. This mode is recommended for all new applications.
RSA_PADDING_SSLV23,
/// PKCS #1 v1.5 padding with an SSL-specific modification that denotes
/// that the server is SSL3 capable.
RSA_PADDING_NONE
/// Raw RSA encryption. This mode should only be used to implement cryptographically
/// sound padding modes in the application code. Encrypting user data directly with RSA
/// is insecure.
RSA_PADDING_PKCS1,
/// PKCS #1 v1.5 padding. This currently is the most widely used mode.
RSA_PADDING_PKCS1_OAEP,
/// EME-OAEP as defined in PKCS #1 v2.0 with SHA-1, MGF1 and an empty
/// encoding parameter. This mode is recommended for all new applications.
RSA_PADDING_SSLV23,
/// PKCS #1 v1.5 padding with an SSL-specific modification that denotes
/// that the server is SSL3 capable.
RSA_PADDING_NONE
/// Raw RSA encryption. This mode should only be used to implement cryptographically
/// sound padding modes in the application code. Encrypting user data directly with RSA
/// is insecure.
};
@ -69,22 +67,22 @@ enum RSAPaddingMode
// defined with this macro as being exported.
//
#if defined(_WIN32)
#if defined(POCO_DLL)
#if defined(Crypto_EXPORTS)
#define Crypto_API __declspec(dllexport)
#else
#define Crypto_API __declspec(dllimport)
#endif
#endif
# if defined(POCO_DLL)
# if defined(Crypto_EXPORTS)
# define Crypto_API __declspec(dllexport)
# else
# define Crypto_API __declspec(dllimport)
# endif
# endif
#endif
#if !defined(Crypto_API)
#if !defined(POCO_NO_GCC_API_ATTRIBUTE) && defined (__GNUC__) && (__GNUC__ >= 4)
#define Crypto_API __attribute__ ((visibility ("default")))
#else
#define Crypto_API
#endif
# if !defined(POCO_NO_GCC_API_ATTRIBUTE) && defined(__GNUC__) && (__GNUC__ >= 4)
# define Crypto_API __attribute__((visibility("default")))
# else
# define Crypto_API
# endif
#endif
@ -92,104 +90,106 @@ enum RSAPaddingMode
// Automatically link Crypto and OpenSSL libraries.
//
#if defined(_MSC_VER)
#if !defined(POCO_NO_AUTOMATIC_LIBS)
#if defined(POCO_INTERNAL_OPENSSL_MSVC_VER)
#if defined(POCO_EXTERNAL_OPENSSL)
#pragma message("External OpenSSL defined but internal headers used - possible mismatch!")
#endif // POCO_EXTERNAL_OPENSSL
#if !defined(_DEBUG)
#define POCO_DEBUG_SUFFIX ""
#if !defined (_DLL)
#define POCO_STATIC_SUFFIX "mt"
#else // _DLL
#define POCO_STATIC_SUFFIX ""
#endif
#else // _DEBUG
#define POCO_DEBUG_SUFFIX "d"
#if !defined (_DLL)
#define POCO_STATIC_SUFFIX "mt"
#else // _DLL
#define POCO_STATIC_SUFFIX ""
#endif
#endif
#pragma comment(lib, "libcrypto" POCO_STATIC_SUFFIX POCO_DEBUG_SUFFIX ".lib")
#pragma comment(lib, "libssl" POCO_STATIC_SUFFIX POCO_DEBUG_SUFFIX ".lib")
#if !defined(_WIN64) && !defined (_DLL) && \
(POCO_INTERNAL_OPENSSL_MSVC_VER == 120) && \
(POCO_MSVC_VERSION < POCO_INTERNAL_OPENSSL_MSVC_VER)
#pragma comment(lib, "libPreVS2013CRT" POCO_STATIC_SUFFIX POCO_DEBUG_SUFFIX ".lib")
#endif
#if !defined (_DLL) && (POCO_MSVS_VERSION >= 2015)
#pragma comment(lib, "legacy_stdio_definitions.lib")
#pragma comment(lib, "legacy_stdio_wide_specifiers.lib")
#endif
#elif defined(POCO_EXTERNAL_OPENSSL)
#if POCO_EXTERNAL_OPENSSL == POCO_EXTERNAL_OPENSSL_SLPRO
#if defined(POCO_DLL)
#if OPENSSL_VERSION_PREREQ(1,1)
#pragma comment(lib, "libcrypto.lib")
#pragma comment(lib, "libssl.lib")
#else
#pragma comment(lib, "libeay32.lib")
#pragma comment(lib, "ssleay32.lib")
#endif
#else
#if OPENSSL_VERSION_PREREQ(1,1)
#if defined(_WIN64)
#pragma comment(lib, "libcrypto64" POCO_LIB_SUFFIX)
#pragma comment(lib, "libssl64" POCO_LIB_SUFFIX)
#else
#pragma comment(lib, "libcrypto32" POCO_LIB_SUFFIX)
#pragma comment(lib, "libssl32" POCO_LIB_SUFFIX)
#endif
#else
#pragma comment(lib, "libeay32" POCO_LIB_SUFFIX)
#pragma comment(lib, "ssleay32" POCO_LIB_SUFFIX)
#endif
#endif
#elif POCO_EXTERNAL_OPENSSL == POCO_EXTERNAL_OPENSSL_DEFAULT
#if OPENSSL_VERSION_PREREQ(1,1)
#pragma comment(lib, "libcrypto.lib")
#pragma comment(lib, "libssl.lib")
#else
#pragma comment(lib, "libeay32.lib")
#pragma comment(lib, "ssleay32.lib")
#endif
#endif
#endif // POCO_INTERNAL_OPENSSL_MSVC_VER
#if !defined(Crypto_EXPORTS)
#pragma comment(lib, "PocoCrypto" POCO_LIB_SUFFIX)
#endif
#endif // POCO_NO_AUTOMATIC_LIBS
# if !defined(POCO_NO_AUTOMATIC_LIBS)
# if defined(POCO_INTERNAL_OPENSSL_MSVC_VER)
# if defined(POCO_EXTERNAL_OPENSSL)
# pragma message("External OpenSSL defined but internal headers used - possible mismatch!")
# endif // POCO_EXTERNAL_OPENSSL
# if !defined(_DEBUG)
# define POCO_DEBUG_SUFFIX ""
# if !defined(_DLL)
# define POCO_STATIC_SUFFIX "mt"
# else // _DLL
# define POCO_STATIC_SUFFIX ""
# endif
# else // _DEBUG
# define POCO_DEBUG_SUFFIX "d"
# if !defined(_DLL)
# define POCO_STATIC_SUFFIX "mt"
# else // _DLL
# define POCO_STATIC_SUFFIX ""
# endif
# endif
# pragma comment(lib, "libcrypto" POCO_STATIC_SUFFIX POCO_DEBUG_SUFFIX ".lib")
# pragma comment(lib, "libssl" POCO_STATIC_SUFFIX POCO_DEBUG_SUFFIX ".lib")
# if !defined(_WIN64) && !defined(_DLL) && (POCO_INTERNAL_OPENSSL_MSVC_VER == 120) \
&& (POCO_MSVC_VERSION < POCO_INTERNAL_OPENSSL_MSVC_VER)
# pragma comment(lib, "libPreVS2013CRT" POCO_STATIC_SUFFIX POCO_DEBUG_SUFFIX ".lib")
# endif
# if !defined(_DLL) && (POCO_MSVS_VERSION >= 2015)
# pragma comment(lib, "legacy_stdio_definitions.lib")
# pragma comment(lib, "legacy_stdio_wide_specifiers.lib")
# endif
# elif defined(POCO_EXTERNAL_OPENSSL)
# if POCO_EXTERNAL_OPENSSL == POCO_EXTERNAL_OPENSSL_SLPRO
# if defined(POCO_DLL)
# if OPENSSL_VERSION_PREREQ(1, 1)
# pragma comment(lib, "libcrypto.lib")
# pragma comment(lib, "libssl.lib")
# else
# pragma comment(lib, "libeay32.lib")
# pragma comment(lib, "ssleay32.lib")
# endif
# else
# if OPENSSL_VERSION_PREREQ(1, 1)
# if defined(_WIN64)
# pragma comment(lib, "libcrypto64" POCO_LIB_SUFFIX)
# pragma comment(lib, "libssl64" POCO_LIB_SUFFIX)
# else
# pragma comment(lib, "libcrypto32" POCO_LIB_SUFFIX)
# pragma comment(lib, "libssl32" POCO_LIB_SUFFIX)
# endif
# else
# pragma comment(lib, "libeay32" POCO_LIB_SUFFIX)
# pragma comment(lib, "ssleay32" POCO_LIB_SUFFIX)
# endif
# endif
# elif POCO_EXTERNAL_OPENSSL == POCO_EXTERNAL_OPENSSL_DEFAULT
# if OPENSSL_VERSION_PREREQ(1, 1)
# pragma comment(lib, "libcrypto.lib")
# pragma comment(lib, "libssl.lib")
# else
# pragma comment(lib, "libeay32.lib")
# pragma comment(lib, "ssleay32.lib")
# endif
# endif
# endif // POCO_INTERNAL_OPENSSL_MSVC_VER
# if !defined(Crypto_EXPORTS)
# pragma comment(lib, "PocoCrypto" POCO_LIB_SUFFIX)
# endif
# endif // POCO_NO_AUTOMATIC_LIBS
#endif
namespace Poco {
namespace Crypto {
namespace Poco
{
namespace Crypto
{
void Crypto_API initializeCrypto();
/// Initialize the Crypto library, as well as the underlying OpenSSL
/// libraries, by calling OpenSSLInitializer::initialize().
///
/// Should be called before using any class from the Crypto library.
/// The Crypto library will be initialized automatically, through
/// OpenSSLInitializer instances held by various Crypto classes
/// (Cipher, CipherKey, RSAKey, X509Certificate).
/// However, it is recommended to call initializeCrypto()
/// in any case at application startup.
///
/// Can be called multiple times; however, for every call to
/// initializeCrypto(), a matching call to uninitializeCrypto()
/// must be performed.
void Crypto_API initializeCrypto();
/// Initialize the Crypto library, as well as the underlying OpenSSL
/// libraries, by calling OpenSSLInitializer::initialize().
///
/// Should be called before using any class from the Crypto library.
/// The Crypto library will be initialized automatically, through
/// OpenSSLInitializer instances held by various Crypto classes
/// (Cipher, CipherKey, RSAKey, X509Certificate).
/// However, it is recommended to call initializeCrypto()
/// in any case at application startup.
///
/// Can be called multiple times; however, for every call to
/// initializeCrypto(), a matching call to uninitializeCrypto()
/// must be performed.
void Crypto_API uninitializeCrypto();
/// Uninitializes the Crypto library by calling
/// OpenSSLInitializer::uninitialize().
void Crypto_API uninitializeCrypto();
/// Uninitializes the Crypto library by calling
/// OpenSSLInitializer::uninitialize().
} } // namespace Poco::Crypto
}
} // namespace Poco::Crypto
#endif // Crypto_Crypto_INCLUDED

View File

@ -23,34 +23,37 @@
#include "Poco/Exception.h"
namespace Poco {
namespace Crypto {
POCO_DECLARE_EXCEPTION(Crypto_API, CryptoException, Poco::Exception)
class Crypto_API OpenSSLException : public CryptoException
namespace Poco
{
namespace Crypto
{
public:
OpenSSLException(int code = 0);
OpenSSLException(const std::string& msg, int code = 0);
OpenSSLException(const std::string& msg, const std::string& arg, int code = 0);
OpenSSLException(const std::string& msg, const Poco::Exception& exc, int code = 0);
OpenSSLException(const OpenSSLException& exc);
~OpenSSLException() throw();
OpenSSLException& operator = (const OpenSSLException& exc);
const char* name() const throw();
const char* className() const throw();
Poco::Exception* clone() const;
void rethrow() const;
private:
void setExtMessage();
};
} } // namespace Poco::Crypto
POCO_DECLARE_EXCEPTION(Crypto_API, CryptoException, Poco::Exception)
class Crypto_API OpenSSLException : public CryptoException
{
public:
OpenSSLException(int code = 0);
OpenSSLException(const std::string & msg, int code = 0);
OpenSSLException(const std::string & msg, const std::string & arg, int code = 0);
OpenSSLException(const std::string & msg, const Poco::Exception & exc, int code = 0);
OpenSSLException(const OpenSSLException & exc);
~OpenSSLException() throw();
OpenSSLException & operator=(const OpenSSLException & exc);
const char * name() const throw();
const char * className() const throw();
Poco::Exception * clone() const;
void rethrow() const;
private:
void setExtMessage();
};
}
} // namespace Poco::Crypto
#endif // Crypto_CryptoException_INCLUDED

View File

@ -19,174 +19,177 @@
#define Crypto_CryptoStream_INCLUDED
#include "Poco/Crypto/Crypto.h"
#include "Poco/BufferedStreamBuf.h"
#include "Poco/Buffer.h"
#include <iostream>
#include "Poco/Buffer.h"
#include "Poco/BufferedStreamBuf.h"
#include "Poco/Crypto/Crypto.h"
namespace Poco {
namespace Crypto {
class CryptoTransform;
class Cipher;
class Crypto_API CryptoStreamBuf: public Poco::BufferedStreamBuf
/// This stream buffer performs cryptographic transformation on the data
/// going through it.
namespace Poco
{
public:
CryptoStreamBuf(std::istream& istr, CryptoTransform* pTransform, std::streamsize bufferSize = 8192);
CryptoStreamBuf(std::ostream& ostr, CryptoTransform* pTransform, std::streamsize bufferSize = 8192);
virtual ~CryptoStreamBuf();
void close();
/// Flushes all buffers and finishes the encryption.
protected:
int readFromDevice(char* buffer, std::streamsize length);
int writeToDevice(const char* buffer, std::streamsize length);
private:
CryptoTransform* _pTransform;
std::istream* _pIstr;
std::ostream* _pOstr;
bool _eof;
Poco::Buffer<unsigned char> _buffer;
CryptoStreamBuf(const CryptoStreamBuf&);
CryptoStreamBuf& operator = (const CryptoStreamBuf&);
};
class Crypto_API CryptoIOS: public virtual std::ios
/// The base class for CryptoInputStream and CryptoOutputStream.
///
/// This class is needed to ensure correct initialization order of the
/// stream buffer and base classes.
namespace Crypto
{
public:
CryptoIOS(std::istream& istr, CryptoTransform* pTransform, std::streamsize bufferSize = 8192);
CryptoIOS(std::ostream& ostr, CryptoTransform* pTransform, std::streamsize bufferSize = 8192);
~CryptoIOS();
CryptoStreamBuf* rdbuf();
protected:
CryptoStreamBuf _buf;
};
class Crypto_API CryptoInputStream: public CryptoIOS, public std::istream
/// This stream transforms all data passing through it using the given
/// CryptoTransform.
///
/// Use a CryptoTransform object provided by Cipher::createEncrytor() or
/// Cipher::createDecryptor() to create an encrypting or decrypting stream,
/// respectively.
{
public:
CryptoInputStream(std::istream& istr, CryptoTransform* pTransform, std::streamsize bufferSize = 8192);
/// Create a new CryptoInputStream object. The CryptoInputStream takes the
/// ownership of the given CryptoTransform object.
CryptoInputStream(std::istream& istr, Cipher& cipher, std::streamsize bufferSize = 8192);
/// Create a new encrypting CryptoInputStream object using the given cipher.
~CryptoInputStream();
/// Destroys the CryptoInputStream.
};
class CryptoTransform;
class Cipher;
class Crypto_API CryptoOutputStream: public CryptoIOS, public std::ostream
/// This stream transforms all data passing through it using the given
/// CryptoTransform.
///
/// Use a CryptoTransform object provided by Cipher::createEncrytor() or
/// Cipher::createDecryptor() to create an encrypting or decrypting stream,
/// respectively.
///
/// After all data has been passed through the stream, close() must be called
/// to ensure completion of cryptographic transformation.
{
public:
CryptoOutputStream(std::ostream& ostr, CryptoTransform* pTransform, std::streamsize bufferSize = 8192);
/// Create a new CryptoOutputStream object. The CryptoOutputStream takes the
/// ownership of the given CryptoTransform object.
class Crypto_API CryptoStreamBuf : public Poco::BufferedStreamBuf
/// This stream buffer performs cryptographic transformation on the data
/// going through it.
{
public:
CryptoStreamBuf(std::istream & istr, CryptoTransform * pTransform, std::streamsize bufferSize = 8192);
CryptoStreamBuf(std::ostream & ostr, CryptoTransform * pTransform, std::streamsize bufferSize = 8192);
CryptoOutputStream(std::ostream& ostr, Cipher& cipher, std::streamsize bufferSize = 8192);
/// Create a new decrypting CryptoOutputStream object using the given cipher.
virtual ~CryptoStreamBuf();
~CryptoOutputStream();
/// Destroys the CryptoOutputStream.
void close();
/// Flushes all buffers and finishes the encryption.
void close();
/// Flushes all buffers and finishes the encryption.
};
protected:
int readFromDevice(char * buffer, std::streamsize length);
int writeToDevice(const char * buffer, std::streamsize length);
private:
CryptoTransform * _pTransform;
std::istream * _pIstr;
std::ostream * _pOstr;
bool _eof;
Poco::Buffer<unsigned char> _buffer;
CryptoStreamBuf(const CryptoStreamBuf &);
CryptoStreamBuf & operator=(const CryptoStreamBuf &);
};
class Crypto_API DecryptingInputStream: public CryptoIOS, public std::istream
/// This stream decrypts all data passing through it using the given
/// Cipher.
{
public:
DecryptingInputStream(std::istream& istr, Cipher& cipher, std::streamsize bufferSize = 8192);
/// Create a new DecryptingInputStream object using the given cipher.
class Crypto_API CryptoIOS : public virtual std::ios
/// The base class for CryptoInputStream and CryptoOutputStream.
///
/// This class is needed to ensure correct initialization order of the
/// stream buffer and base classes.
{
public:
CryptoIOS(std::istream & istr, CryptoTransform * pTransform, std::streamsize bufferSize = 8192);
CryptoIOS(std::ostream & ostr, CryptoTransform * pTransform, std::streamsize bufferSize = 8192);
~CryptoIOS();
CryptoStreamBuf * rdbuf();
~DecryptingInputStream();
/// Destroys the DecryptingInputStream.
};
protected:
CryptoStreamBuf _buf;
};
class Crypto_API DecryptingOutputStream: public CryptoIOS, public std::ostream
/// This stream decrypts all data passing through it using the given
/// Cipher.
{
public:
DecryptingOutputStream(std::ostream& ostr, Cipher& cipher, std::streamsize bufferSize = 8192);
/// Create a new DecryptingOutputStream object using the given cipher.
class Crypto_API CryptoInputStream : public CryptoIOS, public std::istream
/// This stream transforms all data passing through it using the given
/// CryptoTransform.
///
/// Use a CryptoTransform object provided by Cipher::createEncrytor() or
/// Cipher::createDecryptor() to create an encrypting or decrypting stream,
/// respectively.
{
public:
CryptoInputStream(std::istream & istr, CryptoTransform * pTransform, std::streamsize bufferSize = 8192);
/// Create a new CryptoInputStream object. The CryptoInputStream takes the
/// ownership of the given CryptoTransform object.
~DecryptingOutputStream();
/// Destroys the DecryptingOutputStream.
CryptoInputStream(std::istream & istr, Cipher & cipher, std::streamsize bufferSize = 8192);
/// Create a new encrypting CryptoInputStream object using the given cipher.
void close();
/// Flushes all buffers and finishes the decryption.
};
~CryptoInputStream();
/// Destroys the CryptoInputStream.
};
class Crypto_API EncryptingInputStream: public CryptoIOS, public std::istream
/// This stream encrypts all data passing through it using the given
/// Cipher.
{
public:
EncryptingInputStream(std::istream& istr, Cipher& cipher, std::streamsize bufferSize = 8192);
/// Create a new EncryptingInputStream object using the given cipher.
class Crypto_API CryptoOutputStream : public CryptoIOS, public std::ostream
/// This stream transforms all data passing through it using the given
/// CryptoTransform.
///
/// Use a CryptoTransform object provided by Cipher::createEncrytor() or
/// Cipher::createDecryptor() to create an encrypting or decrypting stream,
/// respectively.
///
/// After all data has been passed through the stream, close() must be called
/// to ensure completion of cryptographic transformation.
{
public:
CryptoOutputStream(std::ostream & ostr, CryptoTransform * pTransform, std::streamsize bufferSize = 8192);
/// Create a new CryptoOutputStream object. The CryptoOutputStream takes the
/// ownership of the given CryptoTransform object.
~EncryptingInputStream();
/// Destroys the EncryptingInputStream.
};
CryptoOutputStream(std::ostream & ostr, Cipher & cipher, std::streamsize bufferSize = 8192);
/// Create a new decrypting CryptoOutputStream object using the given cipher.
~CryptoOutputStream();
/// Destroys the CryptoOutputStream.
void close();
/// Flushes all buffers and finishes the encryption.
};
class Crypto_API EncryptingOutputStream: public CryptoIOS, public std::ostream
/// This stream encrypts all data passing through it using the given
/// Cipher.
{
public:
EncryptingOutputStream(std::ostream& ostr, Cipher& cipher, std::streamsize bufferSize = 8192);
/// Create a new EncryptingOutputStream object using the given cipher.
class Crypto_API DecryptingInputStream : public CryptoIOS, public std::istream
/// This stream decrypts all data passing through it using the given
/// Cipher.
{
public:
DecryptingInputStream(std::istream & istr, Cipher & cipher, std::streamsize bufferSize = 8192);
/// Create a new DecryptingInputStream object using the given cipher.
~EncryptingOutputStream();
/// Destroys the EncryptingOutputStream.
void close();
/// Flushes all buffers and finishes the encryption.
};
~DecryptingInputStream();
/// Destroys the DecryptingInputStream.
};
} } // namespace Poco::Crypto
class Crypto_API DecryptingOutputStream : public CryptoIOS, public std::ostream
/// This stream decrypts all data passing through it using the given
/// Cipher.
{
public:
DecryptingOutputStream(std::ostream & ostr, Cipher & cipher, std::streamsize bufferSize = 8192);
/// Create a new DecryptingOutputStream object using the given cipher.
~DecryptingOutputStream();
/// Destroys the DecryptingOutputStream.
void close();
/// Flushes all buffers and finishes the decryption.
};
class Crypto_API EncryptingInputStream : public CryptoIOS, public std::istream
/// This stream encrypts all data passing through it using the given
/// Cipher.
{
public:
EncryptingInputStream(std::istream & istr, Cipher & cipher, std::streamsize bufferSize = 8192);
/// Create a new EncryptingInputStream object using the given cipher.
~EncryptingInputStream();
/// Destroys the EncryptingInputStream.
};
class Crypto_API EncryptingOutputStream : public CryptoIOS, public std::ostream
/// This stream encrypts all data passing through it using the given
/// Cipher.
{
public:
EncryptingOutputStream(std::ostream & ostr, Cipher & cipher, std::streamsize bufferSize = 8192);
/// Create a new EncryptingOutputStream object using the given cipher.
~EncryptingOutputStream();
/// Destroys the EncryptingOutputStream.
void close();
/// Flushes all buffers and finishes the encryption.
};
}
} // namespace Poco::Crypto
#endif // Crypto_CryptoStream_INCLUDED

View File

@ -18,70 +18,71 @@
#define Crypto_CryptoTransform_INCLUDED
#include "Poco/Crypto/Crypto.h"
#include <ios>
#include "Poco/Crypto/Crypto.h"
namespace Poco {
namespace Crypto {
class Crypto_API CryptoTransform
/// This interface represents the basic operations for cryptographic
/// transformations to be used with a CryptoInputStream or a
/// CryptoOutputStream.
///
/// Implementations of this class are returned by the Cipher class to
/// perform encryption or decryption of data.
namespace Poco
{
namespace Crypto
{
public:
CryptoTransform();
/// Creates a new CryptoTransform object.
virtual ~CryptoTransform();
/// Destroys the CryptoTransform.
virtual std::size_t blockSize() const = 0;
/// Returns the block size for this CryptoTransform.
virtual int setPadding(int padding);
/// Enables or disables padding. By default encryption operations are padded using standard block
/// padding and the padding is checked and removed when decrypting. If the padding parameter is zero then
/// no padding is performed, the total amount of data encrypted or decrypted must then be a multiple of
/// the block size or an error will occur.
virtual std::string getTag(std::size_t tagSize = 16) = 0;
/// Returns the GCM tag after encrypting using GCM mode.
///
/// Must be called after finalize().
virtual void setTag(const std::string& tag) = 0;
/// Sets the GCM tag for authenticated decryption using GCM mode.
///
/// Must be set before finalize() is called, otherwise
/// decryption will fail.
virtual std::streamsize transform(
const unsigned char* input,
std::streamsize inputLength,
unsigned char* output,
std::streamsize outputLength) = 0;
/// Transforms a chunk of data. The inputLength is arbitrary and does not
/// need to be a multiple of the block size. The output buffer has a maximum
/// capacity of the given outputLength that must be at least
/// inputLength + blockSize() - 1
/// Returns the number of bytes written to the output buffer.
virtual std::streamsize finalize(unsigned char* output, std::streamsize length) = 0;
/// Finalizes the transformation. The output buffer must contain enough
/// space for at least two blocks, ie.
/// length >= 2*blockSize()
/// must be true. Returns the number of bytes written to the output
/// buffer.
};
} } // namespace Poco::Crypto
class Crypto_API CryptoTransform
/// This interface represents the basic operations for cryptographic
/// transformations to be used with a CryptoInputStream or a
/// CryptoOutputStream.
///
/// Implementations of this class are returned by the Cipher class to
/// perform encryption or decryption of data.
{
public:
CryptoTransform();
/// Creates a new CryptoTransform object.
virtual ~CryptoTransform();
/// Destroys the CryptoTransform.
virtual std::size_t blockSize() const = 0;
/// Returns the block size for this CryptoTransform.
virtual int setPadding(int padding);
/// Enables or disables padding. By default encryption operations are padded using standard block
/// padding and the padding is checked and removed when decrypting. If the padding parameter is zero then
/// no padding is performed, the total amount of data encrypted or decrypted must then be a multiple of
/// the block size or an error will occur.
virtual std::string getTag(std::size_t tagSize = 16) = 0;
/// Returns the GCM tag after encrypting using GCM mode.
///
/// Must be called after finalize().
virtual void setTag(const std::string & tag) = 0;
/// Sets the GCM tag for authenticated decryption using GCM mode.
///
/// Must be set before finalize() is called, otherwise
/// decryption will fail.
virtual std::streamsize
transform(const unsigned char * input, std::streamsize inputLength, unsigned char * output, std::streamsize outputLength)
= 0;
/// Transforms a chunk of data. The inputLength is arbitrary and does not
/// need to be a multiple of the block size. The output buffer has a maximum
/// capacity of the given outputLength that must be at least
/// inputLength + blockSize() - 1
/// Returns the number of bytes written to the output buffer.
virtual std::streamsize finalize(unsigned char * output, std::streamsize length) = 0;
/// Finalizes the transformation. The output buffer must contain enough
/// space for at least two blocks, ie.
/// length >= 2*blockSize()
/// must be true. Returns the number of bytes written to the output
/// buffer.
};
}
} // namespace Poco::Crypto
#endif // Crypto_CryptoTransform_INCLUDED

View File

@ -18,63 +18,66 @@
#define Crypto_DigestEngine_INCLUDED
#include <openssl/evp.h>
#include "Poco/Crypto/Crypto.h"
#include "Poco/Crypto/OpenSSLInitializer.h"
#include "Poco/DigestEngine.h"
#include <openssl/evp.h>
namespace Poco {
namespace Crypto {
class Crypto_API DigestEngine: public Poco::DigestEngine
/// This class implements a Poco::DigestEngine for all
/// digest algorithms supported by OpenSSL.
namespace Poco
{
public:
DigestEngine(const std::string& name);
/// Creates a DigestEngine using the digest with the given name
/// (e.g., "MD5", "SHA1", "SHA256", "SHA512", etc.).
/// See the OpenSSL documentation for a list of supported digest algorithms.
///
/// Throws a Poco::NotFoundException if no algorithm with the given name exists.
~DigestEngine();
/// Destroys the DigestEngine.
const std::string& algorithm() const;
/// Returns the name of the digest algorithm.
int nid() const;
/// Returns the NID (OpenSSL object identifier) of the digest algorithm.
// DigestEngine
std::size_t digestLength() const;
void reset();
const Poco::DigestEngine::Digest& digest();
protected:
void updateImpl(const void* data, std::size_t length);
private:
std::string _name;
EVP_MD_CTX* _pContext;
Poco::DigestEngine::Digest _digest;
OpenSSLInitializer _openSSLInitializer;
};
//
// inlines
//
inline const std::string& DigestEngine::algorithm() const
namespace Crypto
{
return _name;
class Crypto_API DigestEngine : public Poco::DigestEngine
/// This class implements a Poco::DigestEngine for all
/// digest algorithms supported by OpenSSL.
{
public:
DigestEngine(const std::string & name);
/// Creates a DigestEngine using the digest with the given name
/// (e.g., "MD5", "SHA1", "SHA256", "SHA512", etc.).
/// See the OpenSSL documentation for a list of supported digest algorithms.
///
/// Throws a Poco::NotFoundException if no algorithm with the given name exists.
~DigestEngine();
/// Destroys the DigestEngine.
const std::string & algorithm() const;
/// Returns the name of the digest algorithm.
int nid() const;
/// Returns the NID (OpenSSL object identifier) of the digest algorithm.
// DigestEngine
std::size_t digestLength() const;
void reset();
const Poco::DigestEngine::Digest & digest();
protected:
void updateImpl(const void * data, std::size_t length);
private:
std::string _name;
EVP_MD_CTX * _pContext;
Poco::DigestEngine::Digest _digest;
OpenSSLInitializer _openSSLInitializer;
};
//
// inlines
//
inline const std::string & DigestEngine::algorithm() const
{
return _name;
}
}
} } // namespace Poco::Crypto
} // namespace Poco::Crypto
#endif // Crypto_DigestEngine_INCLUDED

View File

@ -19,83 +19,85 @@
#define Crypto_ECDSADigestEngine_INCLUDED
#include "Poco/Crypto/Crypto.h"
#include "Poco/Crypto/ECKey.h"
#include "Poco/DigestEngine.h"
#include "Poco/Crypto/DigestEngine.h"
#include <istream>
#include <ostream>
#include "Poco/Crypto/Crypto.h"
#include "Poco/Crypto/DigestEngine.h"
#include "Poco/Crypto/ECKey.h"
#include "Poco/DigestEngine.h"
namespace Poco {
namespace Crypto {
class Crypto_API ECDSADigestEngine: public Poco::DigestEngine
/// This class implements a Poco::DigestEngine that can be
/// used to compute a secure digital signature.
///
/// First another Poco::Crypto::DigestEngine is created and
/// used to compute a cryptographic hash of the data to be
/// signed. Then, the hash value is encrypted, using
/// the ECDSA private key.
///
/// To verify a signature, pass it to the verify()
/// member function. It will decrypt the signature
/// using the ECDSA public key and compare the resulting
/// hash with the actual hash of the data.
namespace Poco
{
namespace Crypto
{
public:
ECDSADigestEngine(const ECKey& key, const std::string &name);
/// Creates the ECDSADigestEngine with the given ECDSA key,
/// using the hash algorithm with the given name
/// (e.g., "SHA1", "SHA256", "SHA512", etc.).
/// See the OpenSSL documentation for a list of supported digest algorithms.
///
/// Throws a Poco::NotFoundException if no algorithm with the given name exists.
~ECDSADigestEngine();
/// Destroys the ECDSADigestEngine.
std::size_t digestLength() const;
/// Returns the length of the digest in bytes.
void reset();
/// Resets the engine so that a new
/// digest can be computed.
const DigestEngine::Digest& digest();
/// Finishes the computation of the digest
/// (the first time it's called) and
/// returns the message digest.
///
/// Can be called multiple times.
const DigestEngine::Digest& signature();
/// Signs the digest using the ECDSADSA algorithm
/// and the private key (the first time it's
/// called) and returns the result.
///
/// Can be called multiple times.
bool verify(const DigestEngine::Digest& signature);
/// Verifies the data against the signature.
///
/// Returns true if the signature can be verified, false otherwise.
protected:
void updateImpl(const void* data, std::size_t length);
private:
ECKey _key;
Poco::Crypto::DigestEngine _engine;
Poco::DigestEngine::Digest _digest;
Poco::DigestEngine::Digest _signature;
};
} } // namespace Poco::Crypto
class Crypto_API ECDSADigestEngine : public Poco::DigestEngine
/// This class implements a Poco::DigestEngine that can be
/// used to compute a secure digital signature.
///
/// First another Poco::Crypto::DigestEngine is created and
/// used to compute a cryptographic hash of the data to be
/// signed. Then, the hash value is encrypted, using
/// the ECDSA private key.
///
/// To verify a signature, pass it to the verify()
/// member function. It will decrypt the signature
/// using the ECDSA public key and compare the resulting
/// hash with the actual hash of the data.
{
public:
ECDSADigestEngine(const ECKey & key, const std::string & name);
/// Creates the ECDSADigestEngine with the given ECDSA key,
/// using the hash algorithm with the given name
/// (e.g., "SHA1", "SHA256", "SHA512", etc.).
/// See the OpenSSL documentation for a list of supported digest algorithms.
///
/// Throws a Poco::NotFoundException if no algorithm with the given name exists.
~ECDSADigestEngine();
/// Destroys the ECDSADigestEngine.
std::size_t digestLength() const;
/// Returns the length of the digest in bytes.
void reset();
/// Resets the engine so that a new
/// digest can be computed.
const DigestEngine::Digest & digest();
/// Finishes the computation of the digest
/// (the first time it's called) and
/// returns the message digest.
///
/// Can be called multiple times.
const DigestEngine::Digest & signature();
/// Signs the digest using the ECDSADSA algorithm
/// and the private key (the first time it's
/// called) and returns the result.
///
/// Can be called multiple times.
bool verify(const DigestEngine::Digest & signature);
/// Verifies the data against the signature.
///
/// Returns true if the signature can be verified, false otherwise.
protected:
void updateImpl(const void * data, std::size_t length);
private:
ECKey _key;
Poco::Crypto::DigestEngine _engine;
Poco::DigestEngine::Digest _digest;
Poco::DigestEngine::Digest _signature;
};
}
} // namespace Poco::Crypto
#endif // Crypto_ECDSADigestEngine_INCLUDED

View File

@ -20,117 +20,119 @@
#include "Poco/Crypto/Crypto.h"
#include "Poco/Crypto/KeyPair.h"
#include "Poco/Crypto/ECKeyImpl.h"
#include "Poco/Crypto/KeyPair.h"
namespace Poco {
namespace Crypto {
class X509Certificate;
class PKCS12Container;
class Crypto_API ECKey : public KeyPair
/// This class stores an EC key pair, consisting
/// of private and public key. Storage of the private
/// key is optional.
///
/// If a private key is available, the ECKey can be
/// used for decrypting data (encrypted with the public key)
/// or computing secure digital signatures.
namespace Poco
{
public:
ECKey(const EVPPKey& key);
/// Constructs ECKeyImpl by extracting the EC key.
ECKey(const X509Certificate& cert);
/// Extracts the EC public key from the given certificate.
ECKey(const PKCS12Container& cert);
/// Extracts the EC private key from the given certificate.
ECKey(const std::string& eccGroup);
/// Creates the ECKey. Creates a new public/private keypair using the given parameters.
/// Can be used to sign data and verify signatures.
ECKey(const std::string& publicKeyFile, const std::string& privateKeyFile, const std::string& privateKeyPassphrase = "");
/// Creates the ECKey, by reading public and private key from the given files and
/// using the given passphrase for the private key.
///
/// Cannot be used for signing or decryption unless a private key is available.
///
/// If a private key is specified, you don't need to specify a public key file.
/// OpenSSL will auto-create the public key from the private key.
ECKey(std::istream* pPublicKeyStream, std::istream* pPrivateKeyStream = 0, const std::string& privateKeyPassphrase = "");
/// Creates the ECKey, by reading public and private key from the given streams and
/// using the given passphrase for the private key.
///
/// Cannot be used for signing or decryption unless a private key is available.
///
/// If a private key is specified, you don't need to specify a public key file.
/// OpenSSL will auto-create the public key from the private key.
~ECKey();
/// Destroys the ECKey.
ECKeyImpl::Ptr impl() const;
/// Returns the impl object.
static std::string getCurveName(int nid = -1);
/// Returns elliptical curve name corresponding to
/// the given nid; if nid is not found, returns
/// empty string.
///
/// If nid is -1, returns first curve name.
///
/// If no curves are found, returns empty string;
static int getCurveNID(std::string& name);
/// Returns the NID of the specified curve.
///
/// If name is empty, returns the first curve NID
/// and updates the name accordingly.
static bool hasCurve(const std::string& name);
/// Returns true if the named curve is found,
/// false otherwise.
private:
ECKeyImpl::Ptr _pImpl;
};
//
// inlines
//
inline ECKeyImpl::Ptr ECKey::impl() const
namespace Crypto
{
return _pImpl;
class X509Certificate;
class PKCS12Container;
class Crypto_API ECKey : public KeyPair
/// This class stores an EC key pair, consisting
/// of private and public key. Storage of the private
/// key is optional.
///
/// If a private key is available, the ECKey can be
/// used for decrypting data (encrypted with the public key)
/// or computing secure digital signatures.
{
public:
ECKey(const EVPPKey & key);
/// Constructs ECKeyImpl by extracting the EC key.
ECKey(const X509Certificate & cert);
/// Extracts the EC public key from the given certificate.
ECKey(const PKCS12Container & cert);
/// Extracts the EC private key from the given certificate.
ECKey(const std::string & eccGroup);
/// Creates the ECKey. Creates a new public/private key pair using the given parameters.
/// Can be used to sign data and verify signatures.
ECKey(const std::string & publicKeyFile, const std::string & privateKeyFile, const std::string & privateKeyPassphrase = "");
/// Creates the ECKey, by reading public and private key from the given files and
/// using the given passphrase for the private key.
///
/// Cannot be used for signing or decryption unless a private key is available.
///
/// If a private key is specified, you don't need to specify a public key file.
/// OpenSSL will auto-create the public key from the private key.
ECKey(std::istream * pPublicKeyStream, std::istream * pPrivateKeyStream = 0, const std::string & privateKeyPassphrase = "");
/// Creates the ECKey, by reading public and private key from the given streams and
/// using the given passphrase for the private key.
///
/// Cannot be used for signing or decryption unless a private key is available.
///
/// If a private key is specified, you don't need to specify a public key file.
/// OpenSSL will auto-create the public key from the private key.
~ECKey();
/// Destroys the ECKey.
ECKeyImpl::Ptr impl() const;
/// Returns the impl object.
static std::string getCurveName(int nid = -1);
/// Returns elliptical curve name corresponding to
/// the given nid; if nid is not found, returns
/// empty string.
///
/// If nid is -1, returns first curve name.
///
/// If no curves are found, returns empty string;
static int getCurveNID(std::string & name);
/// Returns the NID of the specified curve.
///
/// If name is empty, returns the first curve NID
/// and updates the name accordingly.
static bool hasCurve(const std::string & name);
/// Returns true if the named curve is found,
/// false otherwise.
private:
ECKeyImpl::Ptr _pImpl;
};
//
// inlines
//
inline ECKeyImpl::Ptr ECKey::impl() const
{
return _pImpl;
}
inline std::string ECKey::getCurveName(int nid)
{
return ECKeyImpl::getCurveName(nid);
}
inline int ECKey::getCurveNID(std::string & name)
{
return ECKeyImpl::getCurveNID(name);
}
inline bool ECKey::hasCurve(const std::string & name)
{
return ECKeyImpl::hasCurve(name);
}
}
inline std::string ECKey::getCurveName(int nid)
{
return ECKeyImpl::getCurveName(nid);
}
inline int ECKey::getCurveNID(std::string& name)
{
return ECKeyImpl::getCurveNID(name);
}
inline bool ECKey::hasCurve(const std::string& name)
{
return ECKeyImpl::hasCurve(name);
}
} } // namespace Poco::Crypto
} // namespace Poco::Crypto
#endif // Crypto_ECKey_INCLUDED

View File

@ -19,156 +19,155 @@
#define Crypto_ECKeyImplImpl_INCLUDED
#include <istream>
#include <ostream>
#include <vector>
#include <openssl/ec.h>
#include <openssl/objects.h>
#include "Poco/AutoPtr.h"
#include "Poco/Crypto/Crypto.h"
#include "Poco/Crypto/EVPPKey.h"
#include "Poco/Crypto/KeyPairImpl.h"
#include "Poco/Crypto/OpenSSLInitializer.h"
#include "Poco/RefCountedObject.h"
#include "Poco/AutoPtr.h"
#include <istream>
#include <ostream>
#include <vector>
#include <openssl/objects.h>
#include <openssl/ec.h>
namespace Poco {
namespace Crypto {
class X509Certificate;
class PKCS12Container;
class ECKeyImpl: public KeyPairImpl
/// Elliptic Curve key clas implementation.
namespace Poco
{
public:
typedef Poco::AutoPtr<ECKeyImpl> Ptr;
typedef std::vector<unsigned char> ByteVec;
ECKeyImpl(const EVPPKey& key);
/// Constructs ECKeyImpl by extracting the EC key.
ECKeyImpl(const X509Certificate& cert);
/// Constructs ECKeyImpl by extracting the EC public key from the given certificate.
ECKeyImpl(const PKCS12Container& cert);
/// Constructs ECKeyImpl by extracting the EC private key from the given certificate.
ECKeyImpl(int eccGroup);
/// Creates the ECKey of the specified group. Creates a new public/private keypair using the given parameters.
/// Can be used to sign data and verify signatures.
ECKeyImpl(const std::string& publicKeyFile, const std::string& privateKeyFile, const std::string& privateKeyPassphrase);
/// Creates the ECKey, by reading public and private key from the given files and
/// using the given passphrase for the private key. Can only by used for signing if
/// a private key is available.
ECKeyImpl(std::istream* pPublicKeyStream, std::istream* pPrivateKeyStream, const std::string& privateKeyPassphrase);
/// Creates the ECKey. Can only by used for signing if pPrivKey
/// is not null. If a private key file is specified, you don't need to
/// specify a public key file. OpenSSL will auto-create it from the private key.
~ECKeyImpl();
/// Destroys the ECKeyImpl.
EC_KEY* getECKey();
/// Returns the OpenSSL EC key.
const EC_KEY* getECKey() const;
/// Returns the OpenSSL EC key.
int size() const;
/// Returns the EC key length in bits.
int groupId() const;
/// Returns the EC key group integer Id.
std::string groupName() const;
/// Returns the EC key group name.
void save(const std::string& publicKeyFile,
const std::string& privateKeyFile = "",
const std::string& privateKeyPassphrase = "") const;
/// Exports the public and private keys to the given files.
///
/// If an empty filename is specified, the corresponding key
/// is not exported.
void save(std::ostream* pPublicKeyStream,
std::ostream* pPrivateKeyStream = 0,
const std::string& privateKeyPassphrase = "") const;
/// Exports the public and private key to the given streams.
///
/// If a null pointer is passed for a stream, the corresponding
/// key is not exported.
static std::string getCurveName(int nid = -1);
/// Returns elliptical curve name corresponding to
/// the given nid; if nid is not found, returns
/// empty string.
///
/// If nid is -1, returns first curve name.
///
/// If no curves are found, returns empty string;
static int getCurveNID(std::string& name);
/// Returns the NID of the specified curve.
///
/// If name is empty, returns the first curve NID
/// and updates the name accordingly.
static bool hasCurve(const std::string& name);
/// Returns true if the named curve is found,
/// false otherwise.
private:
void checkEC(const std::string& method, const std::string& func) const;
void freeEC();
EC_KEY* _pEC;
};
//
// inlines
//
inline EC_KEY* ECKeyImpl::getECKey()
namespace Crypto
{
return _pEC;
class X509Certificate;
class PKCS12Container;
class ECKeyImpl : public KeyPairImpl
/// Elliptic Curve key clas implementation.
{
public:
typedef Poco::AutoPtr<ECKeyImpl> Ptr;
typedef std::vector<unsigned char> ByteVec;
ECKeyImpl(const EVPPKey & key);
/// Constructs ECKeyImpl by extracting the EC key.
ECKeyImpl(const X509Certificate & cert);
/// Constructs ECKeyImpl by extracting the EC public key from the given certificate.
ECKeyImpl(const PKCS12Container & cert);
/// Constructs ECKeyImpl by extracting the EC private key from the given certificate.
ECKeyImpl(int eccGroup);
/// Creates the ECKey of the specified group. Creates a new public/private keypair using the given parameters.
/// Can be used to sign data and verify signatures.
ECKeyImpl(const std::string & publicKeyFile, const std::string & privateKeyFile, const std::string & privateKeyPassphrase);
/// Creates the ECKey, by reading public and private key from the given files and
/// using the given passphrase for the private key. Can only by used for signing if
/// a private key is available.
ECKeyImpl(std::istream * pPublicKeyStream, std::istream * pPrivateKeyStream, const std::string & privateKeyPassphrase);
/// Creates the ECKey. Can only by used for signing if pPrivKey
/// is not null. If a private key file is specified, you don't need to
/// specify a public key file. OpenSSL will auto-create it from the private key.
~ECKeyImpl();
/// Destroys the ECKeyImpl.
EC_KEY * getECKey();
/// Returns the OpenSSL EC key.
const EC_KEY * getECKey() const;
/// Returns the OpenSSL EC key.
int size() const;
/// Returns the EC key length in bits.
int groupId() const;
/// Returns the EC key group integer Id.
std::string groupName() const;
/// Returns the EC key group name.
void save(const std::string & publicKeyFile, const std::string & privateKeyFile = "", const std::string & privateKeyPassphrase = "")
const;
/// Exports the public and private keys to the given files.
///
/// If an empty filename is specified, the corresponding key
/// is not exported.
void
save(std::ostream * pPublicKeyStream, std::ostream * pPrivateKeyStream = 0, const std::string & privateKeyPassphrase = "") const;
/// Exports the public and private key to the given streams.
///
/// If a null pointer is passed for a stream, the corresponding
/// key is not exported.
static std::string getCurveName(int nid = -1);
/// Returns elliptical curve name corresponding to
/// the given nid; if nid is not found, returns
/// empty string.
///
/// If nid is -1, returns first curve name.
///
/// If no curves are found, returns empty string;
static int getCurveNID(std::string & name);
/// Returns the NID of the specified curve.
///
/// If name is empty, returns the first curve NID
/// and updates the name accordingly.
static bool hasCurve(const std::string & name);
/// Returns true if the named curve is found,
/// false otherwise.
private:
void checkEC(const std::string & method, const std::string & func) const;
void freeEC();
EC_KEY * _pEC;
};
//
// inlines
//
inline EC_KEY * ECKeyImpl::getECKey()
{
return _pEC;
}
inline const EC_KEY * ECKeyImpl::getECKey() const
{
return _pEC;
}
inline std::string ECKeyImpl::groupName() const
{
return OBJ_nid2sn(groupId());
}
inline void
ECKeyImpl::save(const std::string & publicKeyFile, const std::string & privateKeyFile, const std::string & privateKeyPassphrase) const
{
EVPPKey(_pEC).save(publicKeyFile, privateKeyFile, privateKeyPassphrase);
}
inline void
ECKeyImpl::save(std::ostream * pPublicKeyStream, std::ostream * pPrivateKeyStream, const std::string & privateKeyPassphrase) const
{
EVPPKey(_pEC).save(pPublicKeyStream, pPrivateKeyStream, privateKeyPassphrase);
}
}
inline const EC_KEY* ECKeyImpl::getECKey() const
{
return _pEC;
}
inline std::string ECKeyImpl::groupName() const
{
return OBJ_nid2sn(groupId());
}
inline void ECKeyImpl::save(const std::string& publicKeyFile,
const std::string& privateKeyFile,
const std::string& privateKeyPassphrase) const
{
EVPPKey(_pEC).save(publicKeyFile, privateKeyFile, privateKeyPassphrase);
}
inline void ECKeyImpl::save(std::ostream* pPublicKeyStream,
std::ostream* pPrivateKeyStream,
const std::string& privateKeyPassphrase) const
{
EVPPKey(_pEC).save(pPublicKeyStream, pPrivateKeyStream, privateKeyPassphrase);
}
} } // namespace Poco::Crypto
} // namespace Poco::Crypto
#endif // Crypto_ECKeyImplImpl_INCLUDED

View File

@ -19,336 +19,351 @@
#define Crypto_EVPPKeyImpl_INCLUDED
#include <sstream>
#include <typeinfo>
#include <openssl/ec.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/rsa.h>
#include "Poco/Crypto/Crypto.h"
#include "Poco/Crypto/CryptoException.h"
#include "Poco/StreamCopier.h"
#include <openssl/ec.h>
#include <openssl/rsa.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <sstream>
#include <typeinfo>
namespace Poco {
namespace Crypto {
class ECKey;
class RSAKey;
class Crypto_API EVPPKey
/// Utility class for conversion of native keys to EVP.
/// Currently, only RSA and EC keys are supported.
namespace Poco
{
namespace Crypto
{
public:
explicit EVPPKey(const std::string& ecCurveName);
/// Constructs EVPPKey from ECC curve name.
///
/// Only EC keys can be wrapped by an EVPPKey
/// created using this constructor.
explicit EVPPKey(const char* ecCurveName);
/// Constructs EVPPKey from ECC curve name.
///
/// Only EC keys can be wrapped by an EVPPKey
/// created using this constructor.
explicit EVPPKey(EVP_PKEY* pEVPPKey);
/// Constructs EVPPKey from EVP_PKEY pointer.
/// The content behind the supplied pointer is internally duplicated.
class ECKey;
class RSAKey;
template<typename K>
explicit EVPPKey(K* pKey): _pEVPPKey(EVP_PKEY_new())
/// Constructs EVPPKey from a "native" OpenSSL (RSA or EC_KEY),
/// or a Poco wrapper (RSAKey, ECKey) key pointer.
{
if (!_pEVPPKey) throw OpenSSLException();
setKey(pKey);
}
EVPPKey(const std::string& publicKeyFile, const std::string& privateKeyFile, const std::string& privateKeyPassphrase = "");
/// Creates the EVPPKey, by reading public and private key from the given files and
/// using the given passphrase for the private key. Can only by used for signing if
/// a private key is available.
class Crypto_API EVPPKey
/// Utility class for conversion of native keys to EVP.
/// Currently, only RSA and EC keys are supported.
{
public:
explicit EVPPKey(const std::string & ecCurveName);
/// Constructs EVPPKey from ECC curve name.
///
/// Only EC keys can be wrapped by an EVPPKey
/// created using this constructor.
EVPPKey(std::istream* pPublicKeyStream, std::istream* pPrivateKeyStream, const std::string& privateKeyPassphrase = "");
/// Creates the EVPPKey. Can only by used for signing if pPrivKey
/// is not null. If a private key file is specified, you don't need to
/// specify a public key file. OpenSSL will auto-create it from the private key.
explicit EVPPKey(const char * ecCurveName);
/// Constructs EVPPKey from ECC curve name.
///
/// Only EC keys can be wrapped by an EVPPKey
/// created using this constructor.
EVPPKey(const EVPPKey& other);
/// Copy constructor.
explicit EVPPKey(EVP_PKEY * pEVPPKey);
/// Constructs EVPPKey from EVP_PKEY pointer.
/// The content behind the supplied pointer is internally duplicated.
EVPPKey& operator=(const EVPPKey& other);
/// Assignment operator.
template <typename K>
explicit EVPPKey(K * pKey) : _pEVPPKey(EVP_PKEY_new())
/// Constructs EVPPKey from a "native" OpenSSL (RSA or EC_KEY),
/// or a Poco wrapper (RSAKey, ECKey) key pointer.
{
if (!_pEVPPKey)
throw OpenSSLException();
setKey(pKey);
}
EVPPKey(const std::string & publicKeyFile, const std::string & privateKeyFile, const std::string & privateKeyPassphrase = "");
/// Creates the EVPPKey, by reading public and private key from the given files and
/// using the given passphrase for the private key. Can only by used for signing if
/// a private key is available.
EVPPKey(std::istream * pPublicKeyStream, std::istream * pPrivateKeyStream, const std::string & privateKeyPassphrase = "");
/// Creates the EVPPKey. Can only by used for signing if pPrivKey
/// is not null. If a private key file is specified, you don't need to
/// specify a public key file. OpenSSL will auto-create it from the private key.
EVPPKey(const EVPPKey & other);
/// Copy constructor.
EVPPKey & operator=(const EVPPKey & other);
/// Assignment operator.
#ifdef POCO_ENABLE_CPP11
EVPPKey(EVPPKey&& other);
/// Move constructor.
EVPPKey(EVPPKey && other);
/// Move constructor.
EVPPKey& operator=(EVPPKey&& other);
/// Assignment move operator.
EVPPKey & operator=(EVPPKey && other);
/// Assignment move operator.
#endif // POCO_ENABLE_CPP11
~EVPPKey();
/// Destroys the EVPPKey.
~EVPPKey();
/// Destroys the EVPPKey.
bool operator == (const EVPPKey& other) const;
/// Comparison operator.
/// Returns true if public key components and parameters
/// of the other key are equal to this key.
///
/// Works as expected when one key contains only public key,
/// while the other one contains private (thus also public) key.
bool operator==(const EVPPKey & other) const;
/// Comparison operator.
/// Returns true if public key components and parameters
/// of the other key are equal to this key.
///
/// Works as expected when one key contains only public key,
/// while the other one contains private (thus also public) key.
bool operator != (const EVPPKey& other) const;
/// Comparison operator.
/// Returns true if public key components and parameters
/// of the other key are different from this key.
///
/// Works as expected when one key contains only public key,
/// while the other one contains private (thus also public) key.
bool operator!=(const EVPPKey & other) const;
/// Comparison operator.
/// Returns true if public key components and parameters
/// of the other key are different from this key.
///
/// Works as expected when one key contains only public key,
/// while the other one contains private (thus also public) key.
void save(const std::string& publicKeyFile, const std::string& privateKeyFile = "", const std::string& privateKeyPassphrase = "") const;
/// Exports the public and/or private keys to the given files.
///
/// If an empty filename is specified, the corresponding key
/// is not exported.
void save(const std::string & publicKeyFile, const std::string & privateKeyFile = "", const std::string & privateKeyPassphrase = "")
const;
/// Exports the public and/or private keys to the given files.
///
/// If an empty filename is specified, the corresponding key
/// is not exported.
void save(std::ostream* pPublicKeyStream, std::ostream* pPrivateKeyStream = 0, const std::string& privateKeyPassphrase = "") const;
/// Exports the public and/or private key to the given streams.
///
/// If a null pointer is passed for a stream, the corresponding
/// key is not exported.
void
save(std::ostream * pPublicKeyStream, std::ostream * pPrivateKeyStream = 0, const std::string & privateKeyPassphrase = "") const;
/// Exports the public and/or private key to the given streams.
///
/// If a null pointer is passed for a stream, the corresponding
/// key is not exported.
int type() const;
/// Retuns the EVPPKey type NID.
int type() const;
/// Returns the EVPPKey type NID.
bool isSupported(int type) const;
/// Returns true if OpenSSL type is supported
bool isSupported(int type) const;
/// Returns true if OpenSSL type is supported
operator const EVP_PKEY*() const;
/// Returns const pointer to the OpenSSL EVP_PKEY structure.
operator const EVP_PKEY *() const;
/// Returns const pointer to the OpenSSL EVP_PKEY structure.
operator EVP_PKEY*();
/// Returns pointer to the OpenSSL EVP_PKEY structure.
operator EVP_PKEY *();
/// Returns pointer to the OpenSSL EVP_PKEY structure.
static EVP_PKEY* duplicate(const EVP_PKEY* pFromKey, EVP_PKEY** pToKey);
/// Duplicates pFromKey into *pToKey and returns
// the pointer to duplicated EVP_PKEY.
static EVP_PKEY * duplicate(const EVP_PKEY * pFromKey, EVP_PKEY ** pToKey);
/// Duplicates pFromKey into *pToKey and returns
// the pointer to duplicated EVP_PKEY.
private:
EVPPKey();
private:
EVPPKey();
static int type(const EVP_PKEY* pEVPPKey);
void newECKey(const char* group);
void duplicate(EVP_PKEY* pEVPPKey);
static int type(const EVP_PKEY * pEVPPKey);
void newECKey(const char * group);
void duplicate(EVP_PKEY * pEVPPKey);
void setKey(ECKey* pKey);
void setKey(RSAKey* pKey);
void setKey(EC_KEY* pKey);
void setKey(RSA* pKey);
static int passCB(char* buf, int size, int, void* pass);
void setKey(ECKey * pKey);
void setKey(RSAKey * pKey);
void setKey(EC_KEY * pKey);
void setKey(RSA * pKey);
static int passCB(char * buf, int size, int, void * pass);
typedef EVP_PKEY* (*PEM_read_FILE_Key_fn)(FILE*, EVP_PKEY**, pem_password_cb*, void*);
typedef EVP_PKEY* (*PEM_read_BIO_Key_fn)(BIO*, EVP_PKEY**, pem_password_cb*, void*);
typedef void* (*EVP_PKEY_get_Key_fn)(EVP_PKEY*);
typedef EVP_PKEY * (*PEM_read_FILE_Key_fn)(FILE *, EVP_PKEY **, pem_password_cb *, void *);
typedef EVP_PKEY * (*PEM_read_BIO_Key_fn)(BIO *, EVP_PKEY **, pem_password_cb *, void *);
typedef void * (*EVP_PKEY_get_Key_fn)(EVP_PKEY *);
// The following load*() functions are used by both native and EVP_PKEY type key
// loading from BIO/FILE.
// When used for EVP key loading, getFunc is null (ie. native key is not extracted
// from the loaded EVP_PKEY).
template <typename K, typename F>
static bool loadKey(K** ppKey,
PEM_read_FILE_Key_fn readFunc,
F getFunc,
const std::string& keyFile,
const std::string& pass = "")
{
poco_assert_dbg (((typeid(K*) == typeid(RSA*) || typeid(K*) == typeid(EC_KEY*)) && getFunc) ||
((typeid(K*) == typeid(EVP_PKEY*)) && !getFunc));
poco_check_ptr (ppKey);
poco_assert_dbg (!*ppKey);
// The following load*() functions are used by both native and EVP_PKEY type key
// loading from BIO/FILE.
// When used for EVP key loading, getFunc is null (ie. native key is not extracted
// from the loaded EVP_PKEY).
template <typename K, typename F>
static bool
loadKey(K ** ppKey, PEM_read_FILE_Key_fn readFunc, F getFunc, const std::string & keyFile, const std::string & pass = "")
{
poco_assert_dbg(
((typeid(K *) == typeid(RSA *) || typeid(K *) == typeid(EC_KEY *)) && getFunc)
|| ((typeid(K *) == typeid(EVP_PKEY *)) && !getFunc));
poco_check_ptr(ppKey);
poco_assert_dbg(!*ppKey);
FILE* pFile = 0;
if (!keyFile.empty())
{
if (!getFunc) *ppKey = (K*)EVP_PKEY_new();
EVP_PKEY* pKey = getFunc ? EVP_PKEY_new() : (EVP_PKEY*)*ppKey;
if (pKey)
{
pFile = fopen(keyFile.c_str(), "r");
if (pFile)
{
pem_password_cb* pCB = pass.empty() ? (pem_password_cb*)0 : &passCB;
void* pPassword = pass.empty() ? (void*)0 : (void*)pass.c_str();
if (readFunc(pFile, &pKey, pCB, pPassword))
{
fclose(pFile); pFile = 0;
if(getFunc)
{
*ppKey = (K*)getFunc(pKey);
EVP_PKEY_free(pKey);
}
else
{
poco_assert_dbg (typeid(K*) == typeid(EVP_PKEY*));
*ppKey = (K*)pKey;
}
if(!*ppKey) goto error;
return true;
}
goto error;
}
else
{
if (getFunc) EVP_PKEY_free(pKey);
throw IOException("ECKeyImpl, cannot open file", keyFile);
}
}
else goto error;
}
return false;
FILE * pFile = 0;
if (!keyFile.empty())
{
if (!getFunc)
*ppKey = (K *)EVP_PKEY_new();
EVP_PKEY * pKey = getFunc ? EVP_PKEY_new() : (EVP_PKEY *)*ppKey;
if (pKey)
{
pFile = fopen(keyFile.c_str(), "r");
if (pFile)
{
pem_password_cb * pCB = pass.empty() ? (pem_password_cb *)0 : &passCB;
void * pPassword = pass.empty() ? (void *)0 : (void *)pass.c_str();
if (readFunc(pFile, &pKey, pCB, pPassword))
{
fclose(pFile);
pFile = 0;
if (getFunc)
{
*ppKey = (K *)getFunc(pKey);
EVP_PKEY_free(pKey);
}
else
{
poco_assert_dbg(typeid(K *) == typeid(EVP_PKEY *));
*ppKey = (K *)pKey;
}
if (!*ppKey)
goto error;
return true;
}
goto error;
}
else
{
if (getFunc)
EVP_PKEY_free(pKey);
throw IOException("ECKeyImpl, cannot open file", keyFile);
}
}
else
goto error;
}
return false;
error:
if (pFile) fclose(pFile);
throw OpenSSLException("EVPKey::loadKey(string)");
}
error:
if (pFile)
fclose(pFile);
throw OpenSSLException("EVPKey::loadKey(string)");
}
template <typename K, typename F>
static bool loadKey(K** ppKey,
PEM_read_BIO_Key_fn readFunc,
F getFunc,
std::istream* pIstr,
const std::string& pass = "")
{
poco_assert_dbg (((typeid(K*) == typeid(RSA*) || typeid(K*) == typeid(EC_KEY*)) && getFunc) ||
((typeid(K*) == typeid(EVP_PKEY*)) && !getFunc));
poco_check_ptr(ppKey);
poco_assert_dbg(!*ppKey);
template <typename K, typename F>
static bool loadKey(K ** ppKey, PEM_read_BIO_Key_fn readFunc, F getFunc, std::istream * pIstr, const std::string & pass = "")
{
poco_assert_dbg(
((typeid(K *) == typeid(RSA *) || typeid(K *) == typeid(EC_KEY *)) && getFunc)
|| ((typeid(K *) == typeid(EVP_PKEY *)) && !getFunc));
poco_check_ptr(ppKey);
poco_assert_dbg(!*ppKey);
BIO* pBIO = 0;
if (pIstr)
{
std::ostringstream ostr;
Poco::StreamCopier::copyStream(*pIstr, ostr);
std::string key = ostr.str();
pBIO = BIO_new_mem_buf(const_cast<char*>(key.data()), static_cast<int>(key.size()));
if (pBIO)
{
if (!getFunc) *ppKey = (K*)EVP_PKEY_new();
EVP_PKEY* pKey = getFunc ? EVP_PKEY_new() : (EVP_PKEY*)*ppKey;
if (pKey)
{
pem_password_cb* pCB = pass.empty() ? (pem_password_cb*)0 : &passCB;
void* pPassword = pass.empty() ? (void*)0 : (void*)pass.c_str();
if (readFunc(pBIO, &pKey, pCB, pPassword))
{
BIO_free(pBIO); pBIO = 0;
if (getFunc)
{
*ppKey = (K*)getFunc(pKey);
EVP_PKEY_free(pKey);
}
else
{
poco_assert_dbg (typeid(K*) == typeid(EVP_PKEY*));
*ppKey = (K*)pKey;
}
if (!*ppKey) goto error;
return true;
}
if (getFunc) EVP_PKEY_free(pKey);
goto error;
}
else goto error;
}
else goto error;
}
return false;
BIO * pBIO = 0;
if (pIstr)
{
std::ostringstream ostr;
Poco::StreamCopier::copyStream(*pIstr, ostr);
std::string key = ostr.str();
pBIO = BIO_new_mem_buf(const_cast<char *>(key.data()), static_cast<int>(key.size()));
if (pBIO)
{
if (!getFunc)
*ppKey = (K *)EVP_PKEY_new();
EVP_PKEY * pKey = getFunc ? EVP_PKEY_new() : (EVP_PKEY *)*ppKey;
if (pKey)
{
pem_password_cb * pCB = pass.empty() ? (pem_password_cb *)0 : &passCB;
void * pPassword = pass.empty() ? (void *)0 : (void *)pass.c_str();
if (readFunc(pBIO, &pKey, pCB, pPassword))
{
BIO_free(pBIO);
pBIO = 0;
if (getFunc)
{
*ppKey = (K *)getFunc(pKey);
EVP_PKEY_free(pKey);
}
else
{
poco_assert_dbg(typeid(K *) == typeid(EVP_PKEY *));
*ppKey = (K *)pKey;
}
if (!*ppKey)
goto error;
return true;
}
if (getFunc)
EVP_PKEY_free(pKey);
goto error;
}
else
goto error;
}
else
goto error;
}
return false;
error:
if (pBIO) BIO_free(pBIO);
throw OpenSSLException("EVPKey::loadKey(stream)");
}
error:
if (pBIO)
BIO_free(pBIO);
throw OpenSSLException("EVPKey::loadKey(stream)");
}
EVP_PKEY* _pEVPPKey;
EVP_PKEY * _pEVPPKey;
friend class ECKeyImpl;
friend class RSAKeyImpl;
};
friend class ECKeyImpl;
friend class RSAKeyImpl;
};
//
// inlines
//
//
// inlines
//
inline bool EVPPKey::operator==(const EVPPKey & other) const
{
poco_check_ptr(other._pEVPPKey);
poco_check_ptr(_pEVPPKey);
return (1 == EVP_PKEY_cmp(_pEVPPKey, other._pEVPPKey));
}
inline bool EVPPKey::operator!=(const EVPPKey & other) const
{
return !(other == *this);
}
inline int EVPPKey::type(const EVP_PKEY * pEVPPKey)
{
if (!pEVPPKey)
return NID_undef;
return EVP_PKEY_type(EVP_PKEY_id(pEVPPKey));
}
inline int EVPPKey::type() const
{
return type(_pEVPPKey);
}
inline bool EVPPKey::isSupported(int type) const
{
return type == EVP_PKEY_EC || type == EVP_PKEY_RSA;
}
inline EVPPKey::operator const EVP_PKEY *() const
{
return _pEVPPKey;
}
inline EVPPKey::operator EVP_PKEY *()
{
return _pEVPPKey;
}
inline void EVPPKey::setKey(EC_KEY * pKey)
{
if (!EVP_PKEY_set1_EC_KEY(_pEVPPKey, pKey))
throw OpenSSLException();
}
inline void EVPPKey::setKey(RSA * pKey)
{
if (!EVP_PKEY_set1_RSA(_pEVPPKey, pKey))
throw OpenSSLException();
}
inline bool EVPPKey::operator == (const EVPPKey& other) const
{
poco_check_ptr (other._pEVPPKey);
poco_check_ptr (_pEVPPKey);
return (1 == EVP_PKEY_cmp(_pEVPPKey, other._pEVPPKey));
}
inline bool EVPPKey::operator != (const EVPPKey& other) const
{
return !(other == *this);
}
inline int EVPPKey::type(const EVP_PKEY* pEVPPKey)
{
if (!pEVPPKey) return NID_undef;
return EVP_PKEY_type(EVP_PKEY_id(pEVPPKey));
}
inline int EVPPKey::type() const
{
return type(_pEVPPKey);
}
inline bool EVPPKey::isSupported(int type) const
{
return type == EVP_PKEY_EC || type == EVP_PKEY_RSA;
}
inline EVPPKey::operator const EVP_PKEY*() const
{
return _pEVPPKey;
}
inline EVPPKey::operator EVP_PKEY*()
{
return _pEVPPKey;
}
inline void EVPPKey::setKey(EC_KEY* pKey)
{
if (!EVP_PKEY_set1_EC_KEY(_pEVPPKey, pKey))
throw OpenSSLException();
}
inline void EVPPKey::setKey(RSA* pKey)
{
if (!EVP_PKEY_set1_RSA(_pEVPPKey, pKey))
throw OpenSSLException();
}
} } // namespace Poco::Crypto
} // namespace Poco::Crypto
#endif // Crypto_EVPPKeyImpl_INCLUDED

View File

@ -23,111 +23,114 @@
#include "Poco/Crypto/KeyPairImpl.h"
namespace Poco {
namespace Crypto {
class X509Certificate;
class Crypto_API KeyPair
/// This is a parent class for classes storing a key pair, consisting
/// of private and public key. Storage of the private key is optional.
///
/// If a private key is available, the KeyPair can be
/// used for decrypting data (encrypted with the public key)
/// or computing secure digital signatures.
namespace Poco
{
public:
enum Type
{
KT_RSA = KeyPairImpl::KT_RSA_IMPL,
KT_EC = KeyPairImpl::KT_EC_IMPL
};
explicit KeyPair(KeyPairImpl::Ptr pKeyPairImpl = 0);
/// Extracts the RSA public key from the given certificate.
virtual ~KeyPair();
/// Destroys the KeyPair.
virtual int size() const;
/// Returns the RSA modulus size.
virtual void save(const std::string& publicKeyPairFile,
const std::string& privateKeyPairFile = "",
const std::string& privateKeyPairPassphrase = "") const;
/// Exports the public and private keys to the given files.
///
/// If an empty filename is specified, the corresponding key
/// is not exported.
virtual void save(std::ostream* pPublicKeyPairStream,
std::ostream* pPrivateKeyPairStream = 0,
const std::string& privateKeyPairPassphrase = "") const;
/// Exports the public and private key to the given streams.
///
/// If a null pointer is passed for a stream, the corresponding
/// key is not exported.
KeyPairImpl::Ptr impl() const;
/// Returns the impl object.
const std::string& name() const;
/// Returns key pair name
Type type() const;
/// Returns key pair type
private:
KeyPairImpl::Ptr _pImpl;
};
//
// inlines
//
inline int KeyPair::size() const
namespace Crypto
{
return _pImpl->size();
class X509Certificate;
class Crypto_API KeyPair
/// This is a parent class for classes storing a key pair, consisting
/// of private and public key. Storage of the private key is optional.
///
/// If a private key is available, the KeyPair can be
/// used for decrypting data (encrypted with the public key)
/// or computing secure digital signatures.
{
public:
enum Type
{
KT_RSA = KeyPairImpl::KT_RSA_IMPL,
KT_EC = KeyPairImpl::KT_EC_IMPL
};
explicit KeyPair(KeyPairImpl::Ptr pKeyPairImpl = 0);
/// Extracts the RSA public key from the given certificate.
virtual ~KeyPair();
/// Destroys the KeyPair.
virtual int size() const;
/// Returns the RSA modulus size.
virtual void save(
const std::string & publicKeyPairFile,
const std::string & privateKeyPairFile = "",
const std::string & privateKeyPairPassphrase = "") const;
/// Exports the public and private keys to the given files.
///
/// If an empty filename is specified, the corresponding key
/// is not exported.
virtual void save(
std::ostream * pPublicKeyPairStream,
std::ostream * pPrivateKeyPairStream = 0,
const std::string & privateKeyPairPassphrase = "") const;
/// Exports the public and private key to the given streams.
///
/// If a null pointer is passed for a stream, the corresponding
/// key is not exported.
KeyPairImpl::Ptr impl() const;
/// Returns the impl object.
const std::string & name() const;
/// Returns key pair name
Type type() const;
/// Returns key pair type
private:
KeyPairImpl::Ptr _pImpl;
};
//
// inlines
//
inline int KeyPair::size() const
{
return _pImpl->size();
}
inline void
KeyPair::save(const std::string & publicKeyFile, const std::string & privateKeyFile, const std::string & privateKeyPassphrase) const
{
_pImpl->save(publicKeyFile, privateKeyFile, privateKeyPassphrase);
}
inline void
KeyPair::save(std::ostream * pPublicKeyStream, std::ostream * pPrivateKeyStream, const std::string & privateKeyPassphrase) const
{
_pImpl->save(pPublicKeyStream, pPrivateKeyStream, privateKeyPassphrase);
}
inline const std::string & KeyPair::name() const
{
return _pImpl->name();
}
inline KeyPairImpl::Ptr KeyPair::impl() const
{
return _pImpl;
}
inline KeyPair::Type KeyPair::type() const
{
return (KeyPair::Type)impl()->type();
}
}
inline void KeyPair::save(const std::string& publicKeyFile,
const std::string& privateKeyFile,
const std::string& privateKeyPassphrase) const
{
_pImpl->save(publicKeyFile, privateKeyFile, privateKeyPassphrase);
}
inline void KeyPair::save(std::ostream* pPublicKeyStream,
std::ostream* pPrivateKeyStream,
const std::string& privateKeyPassphrase) const
{
_pImpl->save(pPublicKeyStream, pPrivateKeyStream, privateKeyPassphrase);
}
inline const std::string& KeyPair::name() const
{
return _pImpl->name();
}
inline KeyPairImpl::Ptr KeyPair::impl() const
{
return _pImpl;
}
inline KeyPair::Type KeyPair::type() const
{
return (KeyPair::Type)impl()->type();
}
} } // namespace Poco::Crypto
} // namespace Poco::Crypto
#endif // Crypto_KeyPair_INCLUDED

View File

@ -19,89 +19,92 @@
#define Crypto_KeyPairImplImpl_INCLUDED
#include <string>
#include <vector>
#include "Poco/AutoPtr.h"
#include "Poco/Crypto/Crypto.h"
#include "Poco/Crypto/OpenSSLInitializer.h"
#include "Poco/RefCountedObject.h"
#include "Poco/AutoPtr.h"
#include <string>
#include <vector>
namespace Poco {
namespace Crypto {
class KeyPairImpl: public Poco::RefCountedObject
/// Class KeyPairImpl
namespace Poco
{
public:
enum Type
{
KT_RSA_IMPL = 0,
KT_EC_IMPL
};
typedef Poco::AutoPtr<KeyPairImpl> Ptr;
typedef std::vector<unsigned char> ByteVec;
KeyPairImpl(const std::string& name, Type type);
/// Create KeyPairImpl with specified type and name.
virtual ~KeyPairImpl();
/// Destroys the KeyPairImpl.
virtual int size() const = 0;
/// Returns the key size.
virtual void save(const std::string& publicKeyFile,
const std::string& privateKeyFile = "",
const std::string& privateKeyPassphrase = "") const = 0;
/// Exports the public and private keys to the given files.
///
/// If an empty filename is specified, the corresponding key
/// is not exported.
virtual void save(std::ostream* pPublicKeyStream,
std::ostream* pPrivateKeyStream = 0,
const std::string& privateKeyPassphrase = "") const = 0;
/// Exports the public and private key to the given streams.
///
/// If a null pointer is passed for a stream, the corresponding
/// key is not exported.
const std::string& name() const;
/// Returns key pair name
Type type() const;
/// Returns key pair type
private:
KeyPairImpl();
std::string _name;
Type _type;
OpenSSLInitializer _openSSLInitializer;
};
//
// inlines
//
inline const std::string& KeyPairImpl::name() const
namespace Crypto
{
return _name;
class KeyPairImpl : public Poco::RefCountedObject
/// Class KeyPairImpl
{
public:
enum Type
{
KT_RSA_IMPL = 0,
KT_EC_IMPL
};
typedef Poco::AutoPtr<KeyPairImpl> Ptr;
typedef std::vector<unsigned char> ByteVec;
KeyPairImpl(const std::string & name, Type type);
/// Create KeyPairImpl with specified type and name.
virtual ~KeyPairImpl();
/// Destroys the KeyPairImpl.
virtual int size() const = 0;
/// Returns the key size.
virtual void save(
const std::string & publicKeyFile,
const std::string & privateKeyFile = "",
const std::string & privateKeyPassphrase = "") const = 0;
/// Exports the public and private keys to the given files.
///
/// If an empty filename is specified, the corresponding key
/// is not exported.
virtual void save(
std::ostream * pPublicKeyStream, std::ostream * pPrivateKeyStream = 0, const std::string & privateKeyPassphrase = "") const = 0;
/// Exports the public and private key to the given streams.
///
/// If a null pointer is passed for a stream, the corresponding
/// key is not exported.
const std::string & name() const;
/// Returns key pair name
Type type() const;
/// Returns key pair type
private:
KeyPairImpl();
std::string _name;
Type _type;
OpenSSLInitializer _openSSLInitializer;
};
//
// inlines
//
inline const std::string & KeyPairImpl::name() const
{
return _name;
}
inline KeyPairImpl::Type KeyPairImpl::type() const
{
return _type;
}
}
inline KeyPairImpl::Type KeyPairImpl::type() const
{
return _type;
}
} } // namespace Poco::Crypto
} // namespace Poco::Crypto
#endif // Crypto_KeyPairImplImpl_INCLUDED

View File

@ -18,98 +18,100 @@
#define Crypto_OpenSSLInitializer_INCLUDED
#include <openssl/crypto.h>
#include "Poco/AtomicCounter.h"
#include "Poco/Crypto/Crypto.h"
#include "Poco/Mutex.h"
#include "Poco/AtomicCounter.h"
#include <openssl/crypto.h>
#if defined(OPENSSL_FIPS) && OPENSSL_VERSION_NUMBER < 0x010001000L
#include <openssl/fips.h>
# include <openssl/fips.h>
#endif
extern "C"
extern "C" {
struct CRYPTO_dynlock_value
{
struct CRYPTO_dynlock_value
{
Poco::FastMutex _mutex;
};
}
namespace Poco {
namespace Crypto {
class Crypto_API OpenSSLInitializer
/// Initalizes the OpenSSL library.
///
/// The class ensures the earliest initialization and the
/// latest shutdown of the OpenSSL library.
{
public:
OpenSSLInitializer();
/// Automatically initialize OpenSSL on startup.
~OpenSSLInitializer();
/// Automatically shut down OpenSSL on exit.
static void initialize();
/// Initializes the OpenSSL machinery.
static void uninitialize();
/// Shuts down the OpenSSL machinery.
static bool isFIPSEnabled();
// Returns true if FIPS mode is enabled, false otherwise.
static void enableFIPSMode(bool enabled);
// Enable or disable FIPS mode. If FIPS is not available, this method doesn't do anything.
protected:
enum
{
SEEDSIZE = 256
};
// OpenSSL multithreading support
static void lock(int mode, int n, const char* file, int line);
static unsigned long id();
static struct CRYPTO_dynlock_value* dynlockCreate(const char* file, int line);
static void dynlock(int mode, struct CRYPTO_dynlock_value* lock, const char* file, int line);
static void dynlockDestroy(struct CRYPTO_dynlock_value* lock, const char* file, int line);
private:
static Poco::FastMutex* _mutexes;
static Poco::AtomicCounter _rc;
Poco::FastMutex _mutex;
};
}
//
// inlines
//
inline bool OpenSSLInitializer::isFIPSEnabled()
namespace Poco
{
namespace Crypto
{
class Crypto_API OpenSSLInitializer
/// Initializes the OpenSSL library.
///
/// The class ensures the earliest initialization and the
/// latest shutdown of the OpenSSL library.
{
public:
OpenSSLInitializer();
/// Automatically initialize OpenSSL on startup.
~OpenSSLInitializer();
/// Automatically shut down OpenSSL on exit.
static void initialize();
/// Initializes the OpenSSL machinery.
static void uninitialize();
/// Shuts down the OpenSSL machinery.
static bool isFIPSEnabled();
// Returns true if FIPS mode is enabled, false otherwise.
static void enableFIPSMode(bool enabled);
// Enable or disable FIPS mode. If FIPS is not available, this method doesn't do anything.
protected:
enum
{
SEEDSIZE = 256
};
// OpenSSL multithreading support
static void lock(int mode, int n, const char * file, int line);
static unsigned long id();
static struct CRYPTO_dynlock_value * dynlockCreate(const char * file, int line);
static void dynlock(int mode, struct CRYPTO_dynlock_value * lock, const char * file, int line);
static void dynlockDestroy(struct CRYPTO_dynlock_value * lock, const char * file, int line);
private:
static Poco::FastMutex * _mutexes;
static Poco::AtomicCounter _rc;
};
//
// inlines
//
inline bool OpenSSLInitializer::isFIPSEnabled()
{
#ifdef OPENSSL_FIPS
return FIPS_mode() ? true : false;
return FIPS_mode() ? true : false;
#else
return false;
return false;
#endif
}
}
#ifdef OPENSSL_FIPS
inline void OpenSSLInitializer::enableFIPSMode(bool enabled)
{
FIPS_mode_set(enabled);
}
inline void OpenSSLInitializer::enableFIPSMode(bool enabled)
{
FIPS_mode_set(enabled);
}
#else
inline void OpenSSLInitializer::enableFIPSMode(bool /*enabled*/)
{
}
inline void OpenSSLInitializer::enableFIPSMode(bool /*enabled*/)
{
}
#endif
} } // namespace Poco::Crypto
}
} // namespace Poco::Crypto
#endif // Crypto_OpenSSLInitializer_INCLUDED

View File

@ -18,142 +18,145 @@
#define Crypto_PKCS12Container_INCLUDED
#include <istream>
#include <memory>
#include <openssl/pkcs12.h>
#include "Poco/Crypto/Crypto.h"
#include "Poco/Crypto/EVPPKey.h"
#include "Poco/Crypto/OpenSSLInitializer.h"
#include "Poco/Crypto/X509Certificate.h"
#include "Poco/Crypto/EVPPKey.h"
#include "Poco/Path.h"
#include <memory>
#include <istream>
#include <openssl/pkcs12.h>
namespace Poco {
namespace Crypto {
class Crypto_API PKCS12Container
/// This class implements PKCS#12 container functionality.
namespace Poco
{
namespace Crypto
{
public:
typedef X509Certificate::List CAList;
typedef std::vector<std::string> CANameList;
explicit PKCS12Container(std::istream& istr, const std::string& password = "");
/// Creates the PKCS12Container object from a stream.
explicit PKCS12Container(const std::string& path, const std::string& password = "");
/// Creates the PKCS12Container object from a file.
class Crypto_API PKCS12Container
/// This class implements PKCS#12 container functionality.
{
public:
typedef X509Certificate::List CAList;
typedef std::vector<std::string> CANameList;
PKCS12Container(const PKCS12Container& cont);
/// Copy constructor.
explicit PKCS12Container(std::istream & istr, const std::string & password = "");
/// Creates the PKCS12Container object from a stream.
PKCS12Container& operator = (const PKCS12Container& cont);
/// Assignment operator.
explicit PKCS12Container(const std::string & path, const std::string & password = "");
/// Creates the PKCS12Container object from a file.
PKCS12Container(const PKCS12Container & cont);
/// Copy constructor.
PKCS12Container & operator=(const PKCS12Container & cont);
/// Assignment operator.
#ifdef POCO_ENABLE_CPP11
PKCS12Container(PKCS12Container&& cont);
/// Move constructor.
PKCS12Container(PKCS12Container && cont);
/// Move constructor.
PKCS12Container& operator = (PKCS12Container&& cont);
/// Move assignment operator.
PKCS12Container & operator=(PKCS12Container && cont);
/// Move assignment operator.
#endif // POCO_ENABLE_CPP11
~PKCS12Container();
/// Destroys the PKCS12Container.
~PKCS12Container();
/// Destroys the PKCS12Container.
bool hasKey() const;
/// Returns true if container contains the key.
bool hasKey() const;
/// Returns true if container contains the key.
EVPPKey getKey() const;
/// Return key as openssl EVP_PKEY wrapper object.
EVPPKey getKey() const;
/// Return key as openssl EVP_PKEY wrapper object.
bool hasX509Certificate() const;
/// Returns true if container has X509 certificate.
bool hasX509Certificate() const;
/// Returns true if container has X509 certificate.
const X509Certificate& getX509Certificate() const;
/// Returns the X509 certificate.
/// Throws NotFoundException if there is no certificate.
const X509Certificate & getX509Certificate() const;
/// Returns the X509 certificate.
/// Throws NotFoundException if there is no certificate.
const CAList& getCACerts() const;
/// Returns the list of CA certificates in this container.
const CAList & getCACerts() const;
/// Returns the list of CA certificates in this container.
const std::string& getFriendlyName() const;
/// Returns the friendly name of the certificate bag.
const std::string & getFriendlyName() const;
/// Returns the friendly name of the certificate bag.
const CANameList& getFriendlyNamesCA() const;
/// Returns a list of CA certificates friendly names.
const CANameList & getFriendlyNamesCA() const;
/// Returns a list of CA certificates friendly names.
private:
void load(PKCS12* pPKCS12, const std::string& password = "");
std::string extractFriendlyName(X509* pCert);
private:
void load(PKCS12 * pPKCS12, const std::string & password = "");
std::string extractFriendlyName(X509 * pCert);
#ifdef POCO_ENABLE_CPP11
typedef std::unique_ptr<X509Certificate> CertPtr;
typedef std::unique_ptr<X509Certificate> CertPtr;
#else
typedef std::auto_ptr<X509Certificate> CertPtr;
typedef std::auto_ptr<X509Certificate> CertPtr;
#endif // #ifdef POCO_ENABLE_CPP11
OpenSSLInitializer _openSSLInitializer;
EVP_PKEY* _pKey;
CertPtr _pX509Cert;
CAList _caCertList;
CANameList _caCertNames;
std::string _pkcsFriendlyName;
};
OpenSSLInitializer _openSSLInitializer;
EVP_PKEY * _pKey;
CertPtr _pX509Cert;
CAList _caCertList;
CANameList _caCertNames;
std::string _pkcsFriendlyName;
};
//
// inlines
//
//
// inlines
//
inline bool PKCS12Container::hasX509Certificate() const
{
return _pX509Cert.get() != 0;
}
inline const X509Certificate & PKCS12Container::getX509Certificate() const
{
if (!hasX509Certificate())
throw NotFoundException("PKCS12Container X509 certificate");
return *_pX509Cert;
}
inline const std::string & PKCS12Container::getFriendlyName() const
{
return _pkcsFriendlyName;
}
inline const PKCS12Container::CAList & PKCS12Container::getCACerts() const
{
return _caCertList;
}
inline const PKCS12Container::CANameList & PKCS12Container::getFriendlyNamesCA() const
{
return _caCertNames;
}
inline bool PKCS12Container::hasKey() const
{
return _pKey != 0;
}
inline EVPPKey PKCS12Container::getKey() const
{
return EVPPKey(_pKey);
}
inline bool PKCS12Container::hasX509Certificate() const
{
return _pX509Cert.get() != 0;
}
inline const X509Certificate& PKCS12Container::getX509Certificate() const
{
if (!hasX509Certificate())
throw NotFoundException("PKCS12Container X509 certificate");
return *_pX509Cert;
}
inline const std::string& PKCS12Container::getFriendlyName() const
{
return _pkcsFriendlyName;
}
inline const PKCS12Container::CAList& PKCS12Container::getCACerts() const
{
return _caCertList;
}
inline const PKCS12Container::CANameList& PKCS12Container::getFriendlyNamesCA() const
{
return _caCertNames;
}
inline bool PKCS12Container::hasKey() const
{
return _pKey != 0;
}
inline EVPPKey PKCS12Container::getKey() const
{
return EVPPKey(_pKey);
}
} } // namespace Poco::Crypto
} // namespace Poco::Crypto
#endif // Crypto_PKCS12Container_INCLUDED

View File

@ -18,60 +18,63 @@
#define Crypto_RSACipherImpl_INCLUDED
#include "Poco/Crypto/Crypto.h"
#include "Poco/Crypto/Cipher.h"
#include "Poco/Crypto/RSAKey.h"
#include "Poco/Crypto/OpenSSLInitializer.h"
#include <openssl/evp.h>
#include "Poco/Crypto/Cipher.h"
#include "Poco/Crypto/Crypto.h"
#include "Poco/Crypto/OpenSSLInitializer.h"
#include "Poco/Crypto/RSAKey.h"
namespace Poco {
namespace Crypto {
class RSACipherImpl: public Cipher
/// An implementation of the Cipher class for
/// asymmetric (public-private key) encryption
/// based on the the RSA algorithm in OpenSSL's
/// crypto library.
///
/// Encryption is using the public key, decryption
/// requires the private key.
namespace Poco
{
public:
RSACipherImpl(const RSAKey& key, RSAPaddingMode paddingMode);
/// Creates a new RSACipherImpl object for the given RSAKey
/// and using the given padding mode.
virtual ~RSACipherImpl();
/// Destroys the RSACipherImpl.
const std::string& name() const;
/// Returns the name of the Cipher.
CryptoTransform* createEncryptor();
/// Creates an encryptor object.
CryptoTransform* createDecryptor();
/// Creates a decryptor object.
private:
RSAKey _key;
RSAPaddingMode _paddingMode;
OpenSSLInitializer _openSSLInitializer;
};
//
// Inlines
//
inline const std::string& RSACipherImpl::name() const
namespace Crypto
{
return _key.name();
class RSACipherImpl : public Cipher
/// An implementation of the Cipher class for
/// asymmetric (public-private key) encryption
/// based on the the RSA algorithm in OpenSSL's
/// crypto library.
///
/// Encryption is using the public key, decryption
/// requires the private key.
{
public:
RSACipherImpl(const RSAKey & key, RSAPaddingMode paddingMode);
/// Creates a new RSACipherImpl object for the given RSAKey
/// and using the given padding mode.
virtual ~RSACipherImpl();
/// Destroys the RSACipherImpl.
const std::string & name() const;
/// Returns the name of the Cipher.
CryptoTransform * createEncryptor();
/// Creates an encryptor object.
CryptoTransform * createDecryptor();
/// Creates a decryptor object.
private:
RSAKey _key;
RSAPaddingMode _paddingMode;
OpenSSLInitializer _openSSLInitializer;
};
//
// Inlines
//
inline const std::string & RSACipherImpl::name() const
{
return _key.name();
}
}
} } // namespace Poco::Crypto
} // namespace Poco::Crypto
#endif // Crypto_RSACipherImpl_INCLUDED

View File

@ -18,94 +18,97 @@
#define Crypto_RSADigestEngine_INCLUDED
#include "Poco/Crypto/Crypto.h"
#include "Poco/Crypto/RSAKey.h"
#include "Poco/DigestEngine.h"
#include "Poco/Crypto/DigestEngine.h"
#include <istream>
#include <ostream>
#include "Poco/Crypto/Crypto.h"
#include "Poco/Crypto/DigestEngine.h"
#include "Poco/Crypto/RSAKey.h"
#include "Poco/DigestEngine.h"
namespace Poco {
namespace Crypto {
class Crypto_API RSADigestEngine: public Poco::DigestEngine
/// This class implements a Poco::DigestEngine that can be
/// used to compute a secure digital signature.
///
/// First another Poco::Crypto::DigestEngine is created and
/// used to compute a cryptographic hash of the data to be
/// signed. Then, the hash value is encrypted, using
/// the RSA private key.
///
/// To verify a signature, pass it to the verify()
/// member function. It will decrypt the signature
/// using the RSA public key and compare the resulting
/// hash with the actual hash of the data.
namespace Poco
{
namespace Crypto
{
public:
enum DigestType
{
DIGEST_MD5,
DIGEST_SHA1
};
//@ deprecated
RSADigestEngine(const RSAKey& key, DigestType digestType = DIGEST_SHA1);
/// Creates the RSADigestEngine with the given RSA key,
/// using the MD5 or SHA-1 hash algorithm.
/// Kept for backward compatibility
RSADigestEngine(const RSAKey& key, const std::string &name);
/// Creates the RSADigestEngine with the given RSA key,
/// using the hash algorithm with the given name
/// (e.g., "MD5", "SHA1", "SHA256", "SHA512", etc.).
/// See the OpenSSL documentation for a list of supported digest algorithms.
///
/// Throws a Poco::NotFoundException if no algorithm with the given name exists.
~RSADigestEngine();
/// Destroys the RSADigestEngine.
std::size_t digestLength() const;
/// Returns the length of the digest in bytes.
void reset();
/// Resets the engine so that a new
/// digest can be computed.
const DigestEngine::Digest& digest();
/// Finishes the computation of the digest
/// (the first time it's called) and
/// returns the message digest.
///
/// Can be called multiple times.
const DigestEngine::Digest& signature();
/// Signs the digest using the RSA algorithm
/// and the private key (the first time it's
/// called) and returns the result.
///
/// Can be called multiple times.
bool verify(const DigestEngine::Digest& signature);
/// Verifies the data against the signature.
///
/// Returns true if the signature can be verified, false otherwise.
protected:
void updateImpl(const void* data, std::size_t length);
private:
RSAKey _key;
Poco::Crypto::DigestEngine _engine;
Poco::DigestEngine::Digest _digest;
Poco::DigestEngine::Digest _signature;
};
} } // namespace Poco::Crypto
class Crypto_API RSADigestEngine : public Poco::DigestEngine
/// This class implements a Poco::DigestEngine that can be
/// used to compute a secure digital signature.
///
/// First another Poco::Crypto::DigestEngine is created and
/// used to compute a cryptographic hash of the data to be
/// signed. Then, the hash value is encrypted, using
/// the RSA private key.
///
/// To verify a signature, pass it to the verify()
/// member function. It will decrypt the signature
/// using the RSA public key and compare the resulting
/// hash with the actual hash of the data.
{
public:
enum DigestType
{
DIGEST_MD5,
DIGEST_SHA1
};
//@ deprecated
RSADigestEngine(const RSAKey & key, DigestType digestType = DIGEST_SHA1);
/// Creates the RSADigestEngine with the given RSA key,
/// using the MD5 or SHA-1 hash algorithm.
/// Kept for backward compatibility
RSADigestEngine(const RSAKey & key, const std::string & name);
/// Creates the RSADigestEngine with the given RSA key,
/// using the hash algorithm with the given name
/// (e.g., "MD5", "SHA1", "SHA256", "SHA512", etc.).
/// See the OpenSSL documentation for a list of supported digest algorithms.
///
/// Throws a Poco::NotFoundException if no algorithm with the given name exists.
~RSADigestEngine();
/// Destroys the RSADigestEngine.
std::size_t digestLength() const;
/// Returns the length of the digest in bytes.
void reset();
/// Resets the engine so that a new
/// digest can be computed.
const DigestEngine::Digest & digest();
/// Finishes the computation of the digest
/// (the first time it's called) and
/// returns the message digest.
///
/// Can be called multiple times.
const DigestEngine::Digest & signature();
/// Signs the digest using the RSA algorithm
/// and the private key (the first time it's
/// called) and returns the result.
///
/// Can be called multiple times.
bool verify(const DigestEngine::Digest & signature);
/// Verifies the data against the signature.
///
/// Returns true if the signature can be verified, false otherwise.
protected:
void updateImpl(const void * data, std::size_t length);
private:
RSAKey _key;
Poco::Crypto::DigestEngine _engine;
Poco::DigestEngine::Digest _digest;
Poco::DigestEngine::Digest _signature;
};
}
} // namespace Poco::Crypto
#endif // Crypto_RSADigestEngine_INCLUDED

View File

@ -23,103 +23,102 @@
#include "Poco/Crypto/RSAKeyImpl.h"
namespace Poco {
namespace Crypto {
class X509Certificate;
class PKCS12Container;
class Crypto_API RSAKey : public KeyPair
/// This class stores an RSA key pair, consisting
/// of private and public key. Storage of the private
/// key is optional.
///
/// If a private key is available, the RSAKey can be
/// used for decrypting data (encrypted with the public key)
/// or computing secure digital signatures.
namespace Poco
{
public:
enum KeyLength
{
KL_512 = 512,
KL_1024 = 1024,
KL_2048 = 2048,
KL_4096 = 4096
};
enum Exponent
{
EXP_SMALL = 0,
EXP_LARGE
};
RSAKey(const EVPPKey& key);
/// Constructs ECKeyImpl by extracting the EC key.
RSAKey(const X509Certificate& cert);
/// Extracts the RSA public key from the given certificate.
RSAKey(const PKCS12Container& cert);
/// Extracts the RSA private key from the given certificate.
RSAKey(KeyLength keyLength, Exponent exp);
/// Creates the RSAKey. Creates a new public/private keypair using the given parameters.
/// Can be used to sign data and verify signatures.
RSAKey(const std::string& publicKeyFile,
const std::string& privateKeyFile = "",
const std::string& privateKeyPassphrase = "");
/// Creates the RSAKey, by reading public and private key from the given files and
/// using the given passphrase for the private key.
///
/// Cannot be used for signing or decryption unless a private key is available.
///
/// If a private key is specified, you don't need to specify a public key file.
/// OpenSSL will auto-create the public key from the private key.
RSAKey(std::istream* pPublicKeyStream,
std::istream* pPrivateKeyStream = 0,
const std::string& privateKeyPassphrase = "");
/// Creates the RSAKey, by reading public and private key from the given streams and
/// using the given passphrase for the private key.
///
/// Cannot be used for signing or decryption unless a private key is available.
///
/// If a private key is specified, you don't need to specify a public key file.
/// OpenSSL will auto-create the public key from the private key.
~RSAKey();
/// Destroys the RSAKey.
RSAKeyImpl::ByteVec modulus() const;
/// Returns the RSA modulus.
RSAKeyImpl::ByteVec encryptionExponent() const;
/// Returns the RSA encryption exponent.
RSAKeyImpl::ByteVec decryptionExponent() const;
/// Returns the RSA decryption exponent.
RSAKeyImpl::Ptr impl() const;
/// Returns the impl object.
private:
RSAKeyImpl::Ptr _pImpl;
};
//
// inlines
//
inline RSAKeyImpl::Ptr RSAKey::impl() const
namespace Crypto
{
return _pImpl;
class X509Certificate;
class PKCS12Container;
class Crypto_API RSAKey : public KeyPair
/// This class stores an RSA key pair, consisting
/// of private and public key. Storage of the private
/// key is optional.
///
/// If a private key is available, the RSAKey can be
/// used for decrypting data (encrypted with the public key)
/// or computing secure digital signatures.
{
public:
enum KeyLength
{
KL_512 = 512,
KL_1024 = 1024,
KL_2048 = 2048,
KL_4096 = 4096
};
enum Exponent
{
EXP_SMALL = 0,
EXP_LARGE
};
RSAKey(const EVPPKey & key);
/// Constructs ECKeyImpl by extracting the EC key.
RSAKey(const X509Certificate & cert);
/// Extracts the RSA public key from the given certificate.
RSAKey(const PKCS12Container & cert);
/// Extracts the RSA private key from the given certificate.
RSAKey(KeyLength keyLength, Exponent exp);
/// Creates the RSAKey. Creates a new public/private keypair using the given parameters.
/// Can be used to sign data and verify signatures.
RSAKey(const std::string & publicKeyFile, const std::string & privateKeyFile = "", const std::string & privateKeyPassphrase = "");
/// Creates the RSAKey, by reading public and private key from the given files and
/// using the given passphrase for the private key.
///
/// Cannot be used for signing or decryption unless a private key is available.
///
/// If a private key is specified, you don't need to specify a public key file.
/// OpenSSL will auto-create the public key from the private key.
RSAKey(std::istream * pPublicKeyStream, std::istream * pPrivateKeyStream = 0, const std::string & privateKeyPassphrase = "");
/// Creates the RSAKey, by reading public and private key from the given streams and
/// using the given passphrase for the private key.
///
/// Cannot be used for signing or decryption unless a private key is available.
///
/// If a private key is specified, you don't need to specify a public key file.
/// OpenSSL will auto-create the public key from the private key.
~RSAKey();
/// Destroys the RSAKey.
RSAKeyImpl::ByteVec modulus() const;
/// Returns the RSA modulus.
RSAKeyImpl::ByteVec encryptionExponent() const;
/// Returns the RSA encryption exponent.
RSAKeyImpl::ByteVec decryptionExponent() const;
/// Returns the RSA decryption exponent.
RSAKeyImpl::Ptr impl() const;
/// Returns the impl object.
private:
RSAKeyImpl::Ptr _pImpl;
};
//
// inlines
//
inline RSAKeyImpl::Ptr RSAKey::impl() const
{
return _pImpl;
}
}
} } // namespace Poco::Crypto
} // namespace Poco::Crypto
#endif // Crypto_RSAKey_INCLUDED

View File

@ -18,15 +18,15 @@
#define Crypto_RSAKeyImplImpl_INCLUDED
#include <istream>
#include <ostream>
#include <vector>
#include "Poco/AutoPtr.h"
#include "Poco/Crypto/Crypto.h"
#include "Poco/Crypto/EVPPKey.h"
#include "Poco/Crypto/KeyPairImpl.h"
#include "Poco/Crypto/OpenSSLInitializer.h"
#include "Poco/RefCountedObject.h"
#include "Poco/AutoPtr.h"
#include <istream>
#include <ostream>
#include <vector>
struct bignum_st;
@ -35,107 +35,108 @@ typedef struct bignum_st BIGNUM;
typedef struct rsa_st RSA;
namespace Poco {
namespace Crypto {
class X509Certificate;
class PKCS12Container;
class RSAKeyImpl: public KeyPairImpl
/// class RSAKeyImpl
namespace Poco
{
public:
typedef Poco::AutoPtr<RSAKeyImpl> Ptr;
typedef std::vector<unsigned char> ByteVec;
RSAKeyImpl(const EVPPKey& key);
/// Constructs ECKeyImpl by extracting the EC key.
RSAKeyImpl(const X509Certificate& cert);
/// Extracts the RSA public key from the given certificate.
RSAKeyImpl(const PKCS12Container& cert);
/// Extracts the EC private key from the given certificate.
RSAKeyImpl(int keyLength, unsigned long exponent);
/// Creates the RSAKey. Creates a new public/private keypair using the given parameters.
/// Can be used to sign data and verify signatures.
RSAKeyImpl(const std::string& publicKeyFile, const std::string& privateKeyFile, const std::string& privateKeyPassphrase);
/// Creates the RSAKey, by reading public and private key from the given files and
/// using the given passphrase for the private key. Can only by used for signing if
/// a private key is available.
RSAKeyImpl(std::istream* pPublicKeyStream, std::istream* pPrivateKeyStream, const std::string& privateKeyPassphrase);
/// Creates the RSAKey. Can only by used for signing if pPrivKey
/// is not null. If a private key file is specified, you don't need to
/// specify a public key file. OpenSSL will auto-create it from the private key.
~RSAKeyImpl();
/// Destroys the RSAKeyImpl.
RSA* getRSA();
/// Returns the OpenSSL RSA object.
const RSA* getRSA() const;
/// Returns the OpenSSL RSA object.
int size() const;
/// Returns the RSA modulus size.
ByteVec modulus() const;
/// Returns the RSA modulus.
ByteVec encryptionExponent() const;
/// Returns the RSA encryption exponent.
ByteVec decryptionExponent() const;
/// Returns the RSA decryption exponent.
void save(const std::string& publicKeyFile,
const std::string& privateKeyFile = "",
const std::string& privateKeyPassphrase = "") const;
/// Exports the public and private keys to the given files.
///
/// If an empty filename is specified, the corresponding key
/// is not exported.
void save(std::ostream* pPublicKeyStream,
std::ostream* pPrivateKeyStream = 0,
const std::string& privateKeyPassphrase = "") const;
/// Exports the public and private key to the given streams.
///
/// If a null pointer is passed for a stream, the corresponding
/// key is not exported.
private:
RSAKeyImpl();
void freeRSA();
static ByteVec convertToByteVec(const BIGNUM* bn);
RSA* _pRSA;
};
//
// inlines
//
inline RSA* RSAKeyImpl::getRSA()
namespace Crypto
{
return _pRSA;
class X509Certificate;
class PKCS12Container;
class RSAKeyImpl : public KeyPairImpl
/// class RSAKeyImpl
{
public:
typedef Poco::AutoPtr<RSAKeyImpl> Ptr;
typedef std::vector<unsigned char> ByteVec;
RSAKeyImpl(const EVPPKey & key);
/// Constructs ECKeyImpl by extracting the EC key.
RSAKeyImpl(const X509Certificate & cert);
/// Extracts the RSA public key from the given certificate.
RSAKeyImpl(const PKCS12Container & cert);
/// Extracts the EC private key from the given certificate.
RSAKeyImpl(int keyLength, unsigned long exponent);
/// Creates the RSAKey. Creates a new public/private keypair using the given parameters.
/// Can be used to sign data and verify signatures.
RSAKeyImpl(const std::string & publicKeyFile, const std::string & privateKeyFile, const std::string & privateKeyPassphrase);
/// Creates the RSAKey, by reading public and private key from the given files and
/// using the given passphrase for the private key. Can only by used for signing if
/// a private key is available.
RSAKeyImpl(std::istream * pPublicKeyStream, std::istream * pPrivateKeyStream, const std::string & privateKeyPassphrase);
/// Creates the RSAKey. Can only by used for signing if pPrivKey
/// is not null. If a private key file is specified, you don't need to
/// specify a public key file. OpenSSL will auto-create it from the private key.
~RSAKeyImpl();
/// Destroys the RSAKeyImpl.
RSA * getRSA();
/// Returns the OpenSSL RSA object.
const RSA * getRSA() const;
/// Returns the OpenSSL RSA object.
int size() const;
/// Returns the RSA modulus size.
ByteVec modulus() const;
/// Returns the RSA modulus.
ByteVec encryptionExponent() const;
/// Returns the RSA encryption exponent.
ByteVec decryptionExponent() const;
/// Returns the RSA decryption exponent.
void save(const std::string & publicKeyFile, const std::string & privateKeyFile = "", const std::string & privateKeyPassphrase = "")
const;
/// Exports the public and private keys to the given files.
///
/// If an empty filename is specified, the corresponding key
/// is not exported.
void
save(std::ostream * pPublicKeyStream, std::ostream * pPrivateKeyStream = 0, const std::string & privateKeyPassphrase = "") const;
/// Exports the public and private key to the given streams.
///
/// If a null pointer is passed for a stream, the corresponding
/// key is not exported.
private:
RSAKeyImpl();
void freeRSA();
static ByteVec convertToByteVec(const BIGNUM * bn);
RSA * _pRSA;
};
//
// inlines
//
inline RSA * RSAKeyImpl::getRSA()
{
return _pRSA;
}
inline const RSA * RSAKeyImpl::getRSA() const
{
return _pRSA;
}
}
inline const RSA* RSAKeyImpl::getRSA() const
{
return _pRSA;
}
} } // namespace Poco::Crypto
} // namespace Poco::Crypto
#endif // Crypto_RSAKeyImplImpl_INCLUDED

View File

@ -18,228 +18,231 @@
#define Crypto_X509Certificate_INCLUDED
#include <istream>
#include <set>
#include <vector>
#include <openssl/ssl.h>
#include "Poco/Crypto/Crypto.h"
#include "Poco/Crypto/OpenSSLInitializer.h"
#include "Poco/DateTime.h"
#include "Poco/SharedPtr.h"
#include <vector>
#include <set>
#include <istream>
#include <openssl/ssl.h>
namespace Poco {
namespace Crypto {
class Crypto_API X509Certificate
/// This class represents a X509 Certificate.
namespace Poco
{
public:
typedef std::vector<X509Certificate> List;
enum NID
/// Name identifier for extracting information from
/// a certificate subject's or issuer's distinguished name.
{
NID_COMMON_NAME = 13,
NID_COUNTRY = 14,
NID_LOCALITY_NAME = 15,
NID_STATE_OR_PROVINCE = 16,
NID_ORGANIZATION_NAME = 17,
NID_ORGANIZATION_UNIT_NAME = 18,
NID_PKCS9_EMAIL_ADDRESS = 48,
NID_SERIAL_NUMBER = 105
};
explicit X509Certificate(std::istream& istr);
/// Creates the X509Certificate object by reading
/// a certificate in PEM format from a stream.
explicit X509Certificate(const std::string& path);
/// Creates the X509Certificate object by reading
/// a certificate in PEM format from a file.
explicit X509Certificate(X509* pCert);
/// Creates the X509Certificate from an existing
/// OpenSSL certificate. Ownership is taken of
/// the certificate.
X509Certificate(X509* pCert, bool shared);
/// Creates the X509Certificate from an existing
/// OpenSSL certificate. Ownership is taken of
/// the certificate. If shared is true, the
/// certificate's reference count is incremented.
X509Certificate(const X509Certificate& cert);
/// Creates the certificate by copying another one.
X509Certificate& operator = (const X509Certificate& cert);
/// Assigns a certificate.
void swap(X509Certificate& cert);
/// Exchanges the certificate with another one.
~X509Certificate();
/// Destroys the X509Certificate.
long version() const;
/// Returns the version of the certificate.
const std::string& serialNumber() const;
/// Returns the certificate serial number as a
/// string in decimal encoding.
const std::string& issuerName() const;
/// Returns the certificate issuer's distinguished name.
std::string issuerName(NID nid) const;
/// Extracts the information specified by the given
/// NID (name identifier) from the certificate issuer's
/// distinguished name.
const std::string& subjectName() const;
/// Returns the certificate subject's distinguished name.
std::string subjectName(NID nid) const;
/// Extracts the information specified by the given
/// NID (name identifier) from the certificate subject's
/// distinguished name.
std::string commonName() const;
/// Returns the common name stored in the certificate
/// subject's distinguished name.
void extractNames(std::string& commonName, std::set<std::string>& domainNames) const;
/// Extracts the common name and the alias domain names from the
/// certificate.
Poco::DateTime validFrom() const;
/// Returns the date and time the certificate is valid from.
Poco::DateTime expiresOn() const;
/// Returns the date and time the certificate expires.
void save(std::ostream& stream) const;
/// Writes the certificate to the given stream.
/// The certificate is written in PEM format.
void save(const std::string& path) const;
/// Writes the certificate to the file given by path.
/// The certificate is written in PEM format.
bool issuedBy(const X509Certificate& issuerCertificate) const;
/// Checks whether the certificate has been issued by
/// the issuer given by issuerCertificate. This can be
/// used to validate a certificate chain.
///
/// Verifies if the certificate has been signed with the
/// issuer's private key, using the public key from the issuer
/// certificate.
///
/// Returns true if verification against the issuer certificate
/// was successful, false otherwise.
bool equals(const X509Certificate& otherCertificate) const;
/// Checks whether the certificate is equal to
/// the other certificate, by comparing the hashes
/// of both certificates.
///
/// Returns true if both certificates are identical,
/// otherwise false.
const X509* certificate() const;
/// Returns the underlying OpenSSL certificate.
X509* dup() const;
/// Duplicates and returns the underlying OpenSSL certificate. Note that
/// the caller assumes responsibility for the lifecycle of the created
/// certificate.
std::string signatureAlgorithm() const;
/// Returns the certificate signature algorithm long name.
void print(std::ostream& out) const;
/// Prints the certificate information to ostream.
static List readPEM(const std::string& pemFileName);
/// Reads and returns a list of certificates from
/// the specified PEM file.
static void writePEM(const std::string& pemFileName, const List& list);
/// Writes the list of certificates to the specified PEM file.
protected:
void load(std::istream& stream);
/// Loads the certificate from the given stream. The
/// certificate must be in PEM format.
void load(const std::string& path);
/// Loads the certificate from the given file. The
/// certificate must be in PEM format.
void init();
/// Extracts issuer and subject name from the certificate.
private:
enum
{
NAME_BUFFER_SIZE = 256
};
std::string _issuerName;
std::string _subjectName;
std::string _serialNumber;
X509* _pCert;
OpenSSLInitializer _openSSLInitializer;
};
//
// inlines
//
inline long X509Certificate::version() const
namespace Crypto
{
// This is defined by standards (X.509 et al) to be
// one less than the certificate version.
// So, eg. a version 3 certificate will return 2.
return X509_get_version(_pCert) + 1;
class Crypto_API X509Certificate
/// This class represents a X509 Certificate.
{
public:
typedef std::vector<X509Certificate> List;
enum NID
/// Name identifier for extracting information from
/// a certificate subject's or issuer's distinguished name.
{
NID_COMMON_NAME = 13,
NID_COUNTRY = 14,
NID_LOCALITY_NAME = 15,
NID_STATE_OR_PROVINCE = 16,
NID_ORGANIZATION_NAME = 17,
NID_ORGANIZATION_UNIT_NAME = 18,
NID_PKCS9_EMAIL_ADDRESS = 48,
NID_SERIAL_NUMBER = 105
};
explicit X509Certificate(std::istream & istr);
/// Creates the X509Certificate object by reading
/// a certificate in PEM format from a stream.
explicit X509Certificate(const std::string & path);
/// Creates the X509Certificate object by reading
/// a certificate in PEM format from a file.
explicit X509Certificate(X509 * pCert);
/// Creates the X509Certificate from an existing
/// OpenSSL certificate. Ownership is taken of
/// the certificate.
X509Certificate(X509 * pCert, bool shared);
/// Creates the X509Certificate from an existing
/// OpenSSL certificate. Ownership is taken of
/// the certificate. If shared is true, the
/// certificate's reference count is incremented.
X509Certificate(const X509Certificate & cert);
/// Creates the certificate by copying another one.
X509Certificate & operator=(const X509Certificate & cert);
/// Assigns a certificate.
void swap(X509Certificate & cert);
/// Exchanges the certificate with another one.
~X509Certificate();
/// Destroys the X509Certificate.
long version() const;
/// Returns the version of the certificate.
const std::string & serialNumber() const;
/// Returns the certificate serial number as a
/// string in decimal encoding.
const std::string & issuerName() const;
/// Returns the certificate issuer's distinguished name.
std::string issuerName(NID nid) const;
/// Extracts the information specified by the given
/// NID (name identifier) from the certificate issuer's
/// distinguished name.
const std::string & subjectName() const;
/// Returns the certificate subject's distinguished name.
std::string subjectName(NID nid) const;
/// Extracts the information specified by the given
/// NID (name identifier) from the certificate subject's
/// distinguished name.
std::string commonName() const;
/// Returns the common name stored in the certificate
/// subject's distinguished name.
void extractNames(std::string & commonName, std::set<std::string> & domainNames) const;
/// Extracts the common name and the alias domain names from the
/// certificate.
Poco::DateTime validFrom() const;
/// Returns the date and time the certificate is valid from.
Poco::DateTime expiresOn() const;
/// Returns the date and time the certificate expires.
void save(std::ostream & stream) const;
/// Writes the certificate to the given stream.
/// The certificate is written in PEM format.
void save(const std::string & path) const;
/// Writes the certificate to the file given by path.
/// The certificate is written in PEM format.
bool issuedBy(const X509Certificate & issuerCertificate) const;
/// Checks whether the certificate has been issued by
/// the issuer given by issuerCertificate. This can be
/// used to validate a certificate chain.
///
/// Verifies if the certificate has been signed with the
/// issuer's private key, using the public key from the issuer
/// certificate.
///
/// Returns true if verification against the issuer certificate
/// was successful, false otherwise.
bool equals(const X509Certificate & otherCertificate) const;
/// Checks whether the certificate is equal to
/// the other certificate, by comparing the hashes
/// of both certificates.
///
/// Returns true if both certificates are identical,
/// otherwise false.
const X509 * certificate() const;
/// Returns the underlying OpenSSL certificate.
X509 * dup() const;
/// Duplicates and returns the underlying OpenSSL certificate. Note that
/// the caller assumes responsibility for the lifecycle of the created
/// certificate.
std::string signatureAlgorithm() const;
/// Returns the certificate signature algorithm long name.
void print(std::ostream & out) const;
/// Prints the certificate information to ostream.
static List readPEM(const std::string & pemFileName);
/// Reads and returns a list of certificates from
/// the specified PEM file.
static void writePEM(const std::string & pemFileName, const List & list);
/// Writes the list of certificates to the specified PEM file.
protected:
void load(std::istream & stream);
/// Loads the certificate from the given stream. The
/// certificate must be in PEM format.
void load(const std::string & path);
/// Loads the certificate from the given file. The
/// certificate must be in PEM format.
void init();
/// Extracts issuer and subject name from the certificate.
private:
enum
{
NAME_BUFFER_SIZE = 256
};
std::string _issuerName;
std::string _subjectName;
std::string _serialNumber;
X509 * _pCert;
OpenSSLInitializer _openSSLInitializer;
};
//
// inlines
//
inline long X509Certificate::version() const
{
// This is defined by standards (X.509 et al) to be
// one less than the certificate version.
// So, eg. a version 3 certificate will return 2.
return X509_get_version(_pCert) + 1;
}
inline const std::string & X509Certificate::serialNumber() const
{
return _serialNumber;
}
inline const std::string & X509Certificate::issuerName() const
{
return _issuerName;
}
inline const std::string & X509Certificate::subjectName() const
{
return _subjectName;
}
inline const X509 * X509Certificate::certificate() const
{
return _pCert;
}
inline X509 * X509Certificate::dup() const
{
return X509_dup(_pCert);
}
}
inline const std::string& X509Certificate::serialNumber() const
{
return _serialNumber;
}
inline const std::string& X509Certificate::issuerName() const
{
return _issuerName;
}
inline const std::string& X509Certificate::subjectName() const
{
return _subjectName;
}
inline const X509* X509Certificate::certificate() const
{
return _pCert;
}
inline X509* X509Certificate::dup() const
{
return X509_dup(_pCert);
}
} } // namespace Poco::Crypto
} // namespace Poco::Crypto
#endif // Crypto_X509Certificate_INCLUDED

View File

@ -111,7 +111,7 @@ int CryptoStreamBuf::readFromDevice(char* buffer, std::streamsize length)
{
int m = (static_cast<int>(length) - count)/2 - static_cast<int>(_pTransform->blockSize());
// Make sure we can read at least one more block. Explicitely check
// Make sure we can read at least one more block. Explicitly check
// for m < 0 since blockSize() returns an unsigned int and the
// comparison might give false results for m < 0.
if (m <= 0)

View File

@ -142,7 +142,7 @@ void X509Certificate::load(const std::string& path)
_pCert = PEM_read_bio_X509(pBIO, 0, 0, 0);
BIO_free(pBIO);
if (!_pCert) throw Poco::ReadFileException("Faild to load certificate from", path);
if (!_pCert) throw Poco::ReadFileException("Failed to load certificate from", path);
init();
}

File diff suppressed because it is too large Load Diff

View File

@ -18,79 +18,84 @@
#define Data_ODBC_ConnectionHandle_INCLUDED
#include "Poco/Data/ODBC/ODBC.h"
#include "Poco/Data/ODBC/EnvironmentHandle.h"
#include "Poco/Data/ODBC/ODBC.h"
#ifdef POCO_OS_FAMILY_WINDOWS
#include <windows.h>
# include <windows.h>
#endif
#include <sqltypes.h>
namespace Poco {
namespace Data {
namespace ODBC {
class ODBC_API ConnectionHandle
/// ODBC connection handle class
namespace Poco
{
public:
ConnectionHandle(EnvironmentHandle* pEnvironment = 0);
/// Creates the ConnectionHandle.
~ConnectionHandle();
/// Creates the ConnectionHandle.
operator const SQLHDBC& () const;
/// Const conversion operator into reference to native type.
const SQLHDBC& handle() const;
/// Returns const reference to handle;
private:
operator SQLHDBC& ();
/// Conversion operator into reference to native type.
SQLHDBC& handle();
/// Returns reference to handle;
ConnectionHandle(const ConnectionHandle&);
const ConnectionHandle& operator=(const ConnectionHandle&);
const EnvironmentHandle* _pEnvironment;
SQLHDBC _hdbc;
bool _ownsEnvironment;
};
//
// inlines
//
inline ConnectionHandle::operator const SQLHDBC& () const
namespace Data
{
return handle();
namespace ODBC
{
class ODBC_API ConnectionHandle
/// ODBC connection handle class
{
public:
ConnectionHandle(EnvironmentHandle * pEnvironment = 0);
/// Creates the ConnectionHandle.
~ConnectionHandle();
/// Creates the ConnectionHandle.
operator const SQLHDBC &() const;
/// Const conversion operator into reference to native type.
const SQLHDBC & handle() const;
/// Returns const reference to handle;
private:
operator SQLHDBC &();
/// Conversion operator into reference to native type.
SQLHDBC & handle();
/// Returns reference to handle;
ConnectionHandle(const ConnectionHandle &);
const ConnectionHandle & operator=(const ConnectionHandle &);
const EnvironmentHandle * _pEnvironment;
SQLHDBC _hdbc;
bool _ownsEnvironment;
};
//
// inlines
//
inline ConnectionHandle::operator const SQLHDBC &() const
{
return handle();
}
inline const SQLHDBC & ConnectionHandle::handle() const
{
return _hdbc;
}
inline ConnectionHandle::operator SQLHDBC &()
{
return handle();
}
inline SQLHDBC & ConnectionHandle::handle()
{
return _hdbc;
}
}
}
inline const SQLHDBC& ConnectionHandle::handle() const
{
return _hdbc;
}
inline ConnectionHandle::operator SQLHDBC& ()
{
return handle();
}
inline SQLHDBC& ConnectionHandle::handle()
{
return _hdbc;
}
} } } // namespace Poco::Data::ODBC
} // namespace Poco::Data::ODBC
#endif

View File

@ -18,79 +18,84 @@
#define Data_ODBC_Connector_INCLUDED
#include "Poco/Data/ODBC/ODBC.h"
#include "Poco/Data/Connector.h"
#include "Poco/Data/ODBC/ODBC.h"
namespace Poco {
namespace Data {
namespace ODBC {
class ODBC_API Connector: public Poco::Data::Connector
/// Connector instantiates SqLite SessionImpl objects.
namespace Poco
{
public:
static const std::string KEY;
/// Keyword for creating ODBC sessions.
Connector();
/// Creates the Connector.
~Connector();
/// Destroys the Connector.
const std::string& name() const;
/// Returns the name associated with this connector.
Poco::AutoPtr<Poco::Data::SessionImpl> createSession(const std::string& connectionString,
std::size_t timeout = Poco::Data::SessionImpl::LOGIN_TIMEOUT_DEFAULT);
/// Creates a ODBC SessionImpl object and initializes it with the given connectionString.
static void registerConnector();
/// Registers the Connector under the Keyword Connector::KEY at the Poco::Data::SessionFactory
static void unregisterConnector();
/// Unregisters the Connector under the Keyword Connector::KEY at the Poco::Data::SessionFactory
static void bindStringToLongVarChar(bool flag = true);
/// If set to true (default), std::string is bound to SQL_LONGVARCHAR.
///
/// This can cause issues with SQL Server, resulting in an error
/// ("The data types varchar and text are incompatible in the equal to operator")
/// when comparing against a VARCHAR.
///
/// Set this to false to bind std::string to SQL_VARCHAR.
///
/// NOTE: This is a global setting, affecting all sessions.
/// This setting should not be changed after the first Session has
/// been created.
static bool stringBoundToLongVarChar();
/// Returns true if std::string is bound to SQL_LONGVARCHAR,
/// otherwise false (bound to SQL_VARCHAR).
private:
static bool _bindStringToLongVarChar;
};
///
/// inlines
///
inline const std::string& Connector::name() const
namespace Data
{
return KEY;
namespace ODBC
{
class ODBC_API Connector : public Poco::Data::Connector
/// Connector instantiates SqLite SessionImpl objects.
{
public:
static const std::string KEY;
/// Keyword for creating ODBC sessions.
Connector();
/// Creates the Connector.
~Connector();
/// Destroys the Connector.
const std::string & name() const;
/// Returns the name associated with this connector.
Poco::AutoPtr<Poco::Data::SessionImpl>
createSession(const std::string & connectionString, std::size_t timeout = Poco::Data::SessionImpl::LOGIN_TIMEOUT_DEFAULT);
/// Creates a ODBC SessionImpl object and initializes it with the given connectionString.
static void registerConnector();
/// Registers the Connector under the Keyword Connector::KEY at the Poco::Data::SessionFactory
static void unregisterConnector();
/// Unregisters the Connector under the Keyword Connector::KEY at the Poco::Data::SessionFactory
static void bindStringToLongVarChar(bool flag = true);
/// If set to true (default), std::string is bound to SQL_LONGVARCHAR.
///
/// This can cause issues with SQL Server, resulting in an error
/// ("The data types varchar and text are incompatible in the equal to operator")
/// when comparing against a VARCHAR.
///
/// Set this to false to bind std::string to SQL_VARCHAR.
///
/// NOTE: This is a global setting, affecting all sessions.
/// This setting should not be changed after the first Session has
/// been created.
static bool stringBoundToLongVarChar();
/// Returns true if std::string is bound to SQL_LONGVARCHAR,
/// otherwise false (bound to SQL_VARCHAR).
private:
static bool _bindStringToLongVarChar;
};
///
/// inlines
///
inline const std::string & Connector::name() const
{
return KEY;
}
inline bool Connector::stringBoundToLongVarChar()
{
return _bindStringToLongVarChar;
}
}
}
inline bool Connector::stringBoundToLongVarChar()
{
return _bindStringToLongVarChar;
}
} } } // namespace Poco::Data::ODBC
} // namespace Poco::Data::ODBC
#endif // Data_ODBC_Connector_INCLUDED

View File

@ -18,222 +18,203 @@
#define Data_ODBC_Diagnostics_INCLUDED
#include "Poco/Data/ODBC/ODBC.h"
#include <vector>
#include <cstring>
#include <vector>
#include "Poco/Data/ODBC/ODBC.h"
#include "Poco/Data/ODBC/Utility.h"
#ifdef POCO_OS_FAMILY_WINDOWS
#include <windows.h>
# include <windows.h>
#endif
#include <sqlext.h>
namespace Poco {
namespace Data {
namespace ODBC {
template <typename H, SQLSMALLINT handleType>
class Diagnostics
/// Utility class providing functionality for retrieving ODBC diagnostic
/// records. Diagnostics object must be created with corresponding handle
/// as constructor argument. During construction, diagnostic records fields
/// are populated and the object is ready for querying.
namespace Poco
{
public:
static const unsigned int SQL_STATE_SIZE = SQL_SQLSTATE_SIZE + 1;
static const unsigned int SQL_MESSAGE_LENGTH = SQL_MAX_MESSAGE_LENGTH + 1;
static const unsigned int SQL_NAME_LENGTH = 128;
static const std::string DATA_TRUNCATED;
struct DiagnosticFields
{
/// SQLGetDiagRec fields
SQLCHAR _sqlState[SQL_STATE_SIZE];
SQLCHAR _message[SQL_MESSAGE_LENGTH];
SQLINTEGER _nativeError;
};
typedef std::vector<DiagnosticFields> FieldVec;
typedef typename FieldVec::const_iterator Iterator;
explicit Diagnostics(const H& handle): _handle(handle)
/// Creates and initializes the Diagnostics.
{
std::memset(_connectionName, 0, sizeof(_connectionName));
std::memset(_serverName, 0, sizeof(_serverName));
diagnostics();
}
~Diagnostics()
/// Destroys the Diagnostics.
{
}
std::string sqlState(int index) const
/// Returns SQL state.
{
poco_assert (index < count());
return std::string((char*) _fields[index]._sqlState);
}
std::string message(int index) const
/// Returns error message.
{
poco_assert (index < count());
return std::string((char*) _fields[index]._message);
}
long nativeError(int index) const
/// Returns native error code.
{
poco_assert (index < count());
return _fields[index]._nativeError;
}
std::string connectionName() const
/// Returns the connection name.
/// If there is no active connection, connection name defaults to NONE.
/// If connection name is not applicable for query context (such as when querying environment handle),
/// connection name defaults to NOT_APPLICABLE.
{
return std::string((char*) _connectionName);
}
std::string serverName() const
/// Returns the server name.
/// If the connection has not been established, server name defaults to NONE.
/// If server name is not applicable for query context (such as when querying environment handle),
/// connection name defaults to NOT_APPLICABLE.
{
return std::string((char*) _serverName);
}
int count() const
/// Returns the number of contained diagnostic records.
{
return (int) _fields.size();
}
void reset()
/// Resets the diagnostic fields container.
{
_fields.clear();
}
const FieldVec& fields() const
{
return _fields;
}
Iterator begin() const
{
return _fields.begin();
}
Iterator end() const
{
return _fields.end();
}
const Diagnostics& diagnostics()
{
DiagnosticFields df;
SQLSMALLINT count = 1;
SQLSMALLINT messageLength = 0;
static const std::string none = "None";
static const std::string na = "Not applicable";
reset();
while (!Utility::isError(SQLGetDiagRec(handleType,
_handle,
count,
df._sqlState,
&df._nativeError,
df._message,
SQL_MESSAGE_LENGTH,
&messageLength)))
{
if (1 == count)
{
// success of the following two calls is optional
// (they fail if connection has not been established yet
// or return empty string if not applicable for the context)
if (Utility::isError(SQLGetDiagField(handleType,
_handle,
count,
SQL_DIAG_CONNECTION_NAME,
_connectionName,
sizeof(_connectionName),
&messageLength)))
{
std::size_t len = sizeof(_connectionName) > none.length() ?
none.length() : sizeof(_connectionName) - 1;
std::memcpy(_connectionName, none.c_str(), len);
}
else if (0 == _connectionName[0])
{
std::size_t len = sizeof(_connectionName) > na.length() ?
na.length() : sizeof(_connectionName) - 1;
std::memcpy(_connectionName, na.c_str(), len);
}
if (Utility::isError(SQLGetDiagField(handleType,
_handle,
count,
SQL_DIAG_SERVER_NAME,
_serverName,
sizeof(_serverName),
&messageLength)))
{
std::size_t len = sizeof(_serverName) > none.length() ?
none.length() : sizeof(_serverName) - 1;
std::memcpy(_serverName, none.c_str(), len);
}
else if (0 == _serverName[0])
{
std::size_t len = sizeof(_serverName) > na.length() ?
na.length() : sizeof(_serverName) - 1;
std::memcpy(_serverName, na.c_str(), len);
}
}
_fields.push_back(df);
std::memset(df._sqlState, 0, SQL_STATE_SIZE);
std::memset(df._message, 0, SQL_MESSAGE_LENGTH);
df._nativeError = 0;
++count;
}
return *this;
}
private:
Diagnostics();
/// SQLGetDiagField fields
SQLCHAR _connectionName[SQL_NAME_LENGTH];
SQLCHAR _serverName[SQL_NAME_LENGTH];
/// Diagnostics container
FieldVec _fields;
/// Context handle
const H& _handle;
};
namespace Data
{
namespace ODBC
{
typedef Diagnostics<SQLHENV, SQL_HANDLE_ENV> EnvironmentDiagnostics;
typedef Diagnostics<SQLHDBC, SQL_HANDLE_DBC> ConnectionDiagnostics;
typedef Diagnostics<SQLHSTMT, SQL_HANDLE_STMT> StatementDiagnostics;
typedef Diagnostics<SQLHDESC, SQL_HANDLE_DESC> DescriptorDiagnostics;
template <typename H, SQLSMALLINT handleType>
class Diagnostics
/// Utility class providing functionality for retrieving ODBC diagnostic
/// records. Diagnostics object must be created with corresponding handle
/// as constructor argument. During construction, diagnostic records fields
/// are populated and the object is ready for querying.
{
public:
static const unsigned int SQL_STATE_SIZE = SQL_SQLSTATE_SIZE + 1;
static const unsigned int SQL_MESSAGE_LENGTH = SQL_MAX_MESSAGE_LENGTH + 1;
static const unsigned int SQL_NAME_LENGTH = 128;
static const std::string DATA_TRUNCATED;
struct DiagnosticFields
{
/// SQLGetDiagRec fields
SQLCHAR _sqlState[SQL_STATE_SIZE];
SQLCHAR _message[SQL_MESSAGE_LENGTH];
SQLINTEGER _nativeError;
};
typedef std::vector<DiagnosticFields> FieldVec;
typedef typename FieldVec::const_iterator Iterator;
explicit Diagnostics(const H & handle) : _handle(handle)
/// Creates and initializes the Diagnostics.
{
std::memset(_connectionName, 0, sizeof(_connectionName));
std::memset(_serverName, 0, sizeof(_serverName));
diagnostics();
}
~Diagnostics()
/// Destroys the Diagnostics.
{
}
std::string sqlState(int index) const
/// Returns SQL state.
{
poco_assert(index < count());
return std::string((char *)_fields[index]._sqlState);
}
std::string message(int index) const
/// Returns error message.
{
poco_assert(index < count());
return std::string((char *)_fields[index]._message);
}
long nativeError(int index) const
/// Returns native error code.
{
poco_assert(index < count());
return _fields[index]._nativeError;
}
std::string connectionName() const
/// Returns the connection name.
/// If there is no active connection, connection name defaults to NONE.
/// If connection name is not applicable for query context (such as when querying environment handle),
/// connection name defaults to NOT_APPLICABLE.
{
return std::string((char *)_connectionName);
}
std::string serverName() const
/// Returns the server name.
/// If the connection has not been established, server name defaults to NONE.
/// If server name is not applicable for query context (such as when querying environment handle),
/// connection name defaults to NOT_APPLICABLE.
{
return std::string((char *)_serverName);
}
int count() const
/// Returns the number of contained diagnostic records.
{
return (int)_fields.size();
}
void reset()
/// Resets the diagnostic fields container.
{
_fields.clear();
}
const FieldVec & fields() const { return _fields; }
Iterator begin() const { return _fields.begin(); }
Iterator end() const { return _fields.end(); }
const Diagnostics & diagnostics()
{
DiagnosticFields df;
SQLSMALLINT count = 1;
SQLSMALLINT messageLength = 0;
static const std::string none = "None";
static const std::string na = "Not applicable";
reset();
while (!Utility::isError(SQLGetDiagRec(
handleType, _handle, count, df._sqlState, &df._nativeError, df._message, SQL_MESSAGE_LENGTH, &messageLength)))
{
if (1 == count)
{
// success of the following two calls is optional
// (they fail if connection has not been established yet
// or return empty string if not applicable for the context)
if (Utility::isError(SQLGetDiagField(
handleType,
_handle,
count,
SQL_DIAG_CONNECTION_NAME,
_connectionName,
sizeof(_connectionName),
&messageLength)))
{
std::size_t len = sizeof(_connectionName) > none.length() ? none.length() : sizeof(_connectionName) - 1;
std::memcpy(_connectionName, none.c_str(), len);
}
else if (0 == _connectionName[0])
{
std::size_t len = sizeof(_connectionName) > na.length() ? na.length() : sizeof(_connectionName) - 1;
std::memcpy(_connectionName, na.c_str(), len);
}
if (Utility::isError(SQLGetDiagField(
handleType, _handle, count, SQL_DIAG_SERVER_NAME, _serverName, sizeof(_serverName), &messageLength)))
{
std::size_t len = sizeof(_serverName) > none.length() ? none.length() : sizeof(_serverName) - 1;
std::memcpy(_serverName, none.c_str(), len);
}
else if (0 == _serverName[0])
{
std::size_t len = sizeof(_serverName) > na.length() ? na.length() : sizeof(_serverName) - 1;
std::memcpy(_serverName, na.c_str(), len);
}
}
_fields.push_back(df);
std::memset(df._sqlState, 0, SQL_STATE_SIZE);
std::memset(df._message, 0, SQL_MESSAGE_LENGTH);
df._nativeError = 0;
++count;
}
return *this;
}
private:
Diagnostics();
/// SQLGetDiagField fields
SQLCHAR _connectionName[SQL_NAME_LENGTH];
SQLCHAR _serverName[SQL_NAME_LENGTH];
/// Diagnostics container
FieldVec _fields;
/// Context handle
const H & _handle;
};
} } } // namespace Poco::Data::ODBC
typedef Diagnostics<SQLHENV, SQL_HANDLE_ENV> EnvironmentDiagnostics;
typedef Diagnostics<SQLHDBC, SQL_HANDLE_DBC> ConnectionDiagnostics;
typedef Diagnostics<SQLHSTMT, SQL_HANDLE_STMT> StatementDiagnostics;
typedef Diagnostics<SQLHDESC, SQL_HANDLE_DESC> DescriptorDiagnostics;
}
}
} // namespace Poco::Data::ODBC
#endif

View File

@ -20,75 +20,80 @@
#include "Poco/Data/ODBC/ODBC.h"
#ifdef POCO_OS_FAMILY_WINDOWS
#include <windows.h>
# include <windows.h>
#endif
#include <sqltypes.h>
namespace Poco {
namespace Data {
namespace ODBC {
class ODBC_API EnvironmentHandle
/// ODBC environment handle class
namespace Poco
{
public:
EnvironmentHandle();
/// Creates the EnvironmentHandle.
~EnvironmentHandle();
/// Destroys the EnvironmentHandle.
operator const SQLHENV& () const;
/// Const conversion operator into reference to native type.
const SQLHENV& handle() const;
/// Returns const reference to handle.
private:
operator SQLHENV& ();
/// Conversion operator into reference to native type.
SQLHENV& handle();
/// Returns reference to handle.
EnvironmentHandle(const EnvironmentHandle&);
const EnvironmentHandle& operator=(const EnvironmentHandle&);
SQLHENV _henv;
bool _isOwner;
};
///
/// inlines
///
inline EnvironmentHandle::operator const SQLHENV& () const
namespace Data
{
return handle();
namespace ODBC
{
class ODBC_API EnvironmentHandle
/// ODBC environment handle class
{
public:
EnvironmentHandle();
/// Creates the EnvironmentHandle.
~EnvironmentHandle();
/// Destroys the EnvironmentHandle.
operator const SQLHENV &() const;
/// Const conversion operator into reference to native type.
const SQLHENV & handle() const;
/// Returns const reference to handle.
private:
operator SQLHENV &();
/// Conversion operator into reference to native type.
SQLHENV & handle();
/// Returns reference to handle.
EnvironmentHandle(const EnvironmentHandle &);
const EnvironmentHandle & operator=(const EnvironmentHandle &);
SQLHENV _henv;
bool _isOwner;
};
///
/// inlines
///
inline EnvironmentHandle::operator const SQLHENV &() const
{
return handle();
}
inline const SQLHENV & EnvironmentHandle::handle() const
{
return _henv;
}
inline EnvironmentHandle::operator SQLHENV &()
{
return handle();
}
inline SQLHENV & EnvironmentHandle::handle()
{
return _henv;
}
}
}
inline const SQLHENV& EnvironmentHandle::handle() const
{
return _henv;
}
inline EnvironmentHandle::operator SQLHENV& ()
{
return handle();
}
inline SQLHENV& EnvironmentHandle::handle()
{
return _henv;
}
} } } // namespace Poco::Data::ODBC
} // namespace Poco::Data::ODBC
#endif

View File

@ -18,107 +18,110 @@
#define Data_ODBC_Error_INCLUDED
#include <vector>
#include "Poco/Data/ODBC/Diagnostics.h"
#include "Poco/Data/ODBC/ODBC.h"
#include "Poco/Data/ODBC/Utility.h"
#include "Poco/Data/ODBC/Diagnostics.h"
#include "Poco/Format.h"
#include <vector>
#ifdef POCO_OS_FAMILY_WINDOWS
#include <windows.h>
# include <windows.h>
#endif
#include <sqlext.h>
namespace Poco {
namespace Data {
namespace ODBC {
template <typename H, SQLSMALLINT handleType>
class Error
/// Class encapsulating ODBC diagnostic record collection. Collection is generated
/// during construction. Class provides access and string generation for the collection
/// as well as individual diagnostic records.
namespace Poco
{
public:
explicit Error(const H& handle) : _diagnostics(handle)
/// Creates the Error.
{
}
~Error()
/// Destroys the Error.
{
}
const Diagnostics<H, handleType>& diagnostics() const
/// Returns the associated diagnostics.
{
return _diagnostics;
}
int count() const
/// Returns the count of diagnostic records.
{
return (int) _diagnostics.count();
}
std::string& toString(int index, std::string& str) const
/// Generates the string for the diagnostic record.
{
if ((index < 0) || (index > (count() - 1)))
return str;
std::string s;
Poco::format(s,
"===========================\n"
"ODBC Diagnostic record #%d:\n"
"===========================\n"
"SQLSTATE = %s\nNative Error Code = %ld\n%s\n\n",
index + 1,
_diagnostics.sqlState(index),
_diagnostics.nativeError(index),
_diagnostics.message(index));
str.append(s);
return str;
}
std::string toString() const
/// Generates the string for the diagnostic record collection.
{
std::string str;
Poco::format(str,
"Connection:%s\nServer:%s\n",
_diagnostics.connectionName(),
_diagnostics.serverName());
std::string s;
for (int i = 0; i < count(); ++i)
{
s.clear();
str.append(toString(i, s));
}
return str;
}
private:
Error();
Diagnostics<H, handleType> _diagnostics;
};
namespace Data
{
namespace ODBC
{
typedef Error<SQLHENV, SQL_HANDLE_ENV> EnvironmentError;
typedef Error<SQLHDBC, SQL_HANDLE_DBC> ConnectionError;
typedef Error<SQLHSTMT, SQL_HANDLE_STMT> StatementError;
typedef Error<SQLHSTMT, SQL_HANDLE_DESC> DescriptorError;
template <typename H, SQLSMALLINT handleType>
class Error
/// Class encapsulating ODBC diagnostic record collection. Collection is generated
/// during construction. Class provides access and string generation for the collection
/// as well as individual diagnostic records.
{
public:
explicit Error(const H & handle) : _diagnostics(handle)
/// Creates the Error.
{
}
~Error()
/// Destroys the Error.
{
}
const Diagnostics<H, handleType> & diagnostics() const
/// Returns the associated diagnostics.
{
return _diagnostics;
}
int count() const
/// Returns the count of diagnostic records.
{
return (int)_diagnostics.count();
}
std::string & toString(int index, std::string & str) const
/// Generates the string for the diagnostic record.
{
if ((index < 0) || (index > (count() - 1)))
return str;
std::string s;
Poco::format(
s,
"===========================\n"
"ODBC Diagnostic record #%d:\n"
"===========================\n"
"SQLSTATE = %s\nNative Error Code = %ld\n%s\n\n",
index + 1,
_diagnostics.sqlState(index),
_diagnostics.nativeError(index),
_diagnostics.message(index));
str.append(s);
return str;
}
std::string toString() const
/// Generates the string for the diagnostic record collection.
{
std::string str;
Poco::format(str, "Connection:%s\nServer:%s\n", _diagnostics.connectionName(), _diagnostics.serverName());
std::string s;
for (int i = 0; i < count(); ++i)
{
s.clear();
str.append(toString(i, s));
}
return str;
}
private:
Error();
Diagnostics<H, handleType> _diagnostics;
};
} } } // namespace Poco::Data::ODBC
typedef Error<SQLHENV, SQL_HANDLE_ENV> EnvironmentError;
typedef Error<SQLHDBC, SQL_HANDLE_DBC> ConnectionError;
typedef Error<SQLHSTMT, SQL_HANDLE_STMT> StatementError;
typedef Error<SQLHSTMT, SQL_HANDLE_DESC> DescriptorError;
}
}
} // namespace Poco::Data::ODBC
#endif

File diff suppressed because it is too large Load Diff

View File

@ -18,96 +18,97 @@
#define Data_ODBC_Handle_INCLUDED
#include "Poco/Data/ODBC/ODBC.h"
#include "Poco/Data/ODBC/EnvironmentHandle.h"
#include "Poco/Data/ODBC/ConnectionHandle.h"
#include "Poco/Data/ODBC/EnvironmentHandle.h"
#include "Poco/Data/ODBC/ODBC.h"
#include "Poco/Data/ODBC/ODBCException.h"
#include "Poco/Data/ODBC/Utility.h"
#ifdef POCO_OS_FAMILY_WINDOWS
#include <windows.h>
# include <windows.h>
#endif
#include <sqltypes.h>
namespace Poco {
namespace Data {
namespace ODBC {
template <typename H, SQLSMALLINT handleType>
class Handle
/// ODBC handle class template
namespace Poco
{
public:
Handle(const ConnectionHandle& rConnection):
_rConnection(rConnection),
_handle(0)
/// Creates the Handle.
{
if (Utility::isError(SQLAllocHandle(handleType,
_rConnection,
&_handle)))
{
throw ODBCException("Could not allocate statement handle.");
}
}
~Handle()
/// Destroys the Handle.
{
try
{
SQLRETURN rc = SQLFreeHandle(handleType, _handle);
// N.B. Destructors should not throw, but neither do we want to
// leak resources. So, we throw here in debug mode if things go bad.
poco_assert_dbg (!Utility::isError(rc));
}
catch (...)
{
poco_unexpected();
}
}
operator const H& () const
/// Const conversion operator into reference to native type.
{
return handle();
}
const H& handle() const
/// Returns const reference to native type.
{
return _handle;
}
private:
Handle(const Handle&);
const Handle& operator=(const Handle&);
operator H& ()
/// Conversion operator into reference to native type.
{
return handle();
}
H& handle()
/// Returns reference to native type.
{
return _handle;
}
const ConnectionHandle& _rConnection;
H _handle;
friend class ODBCStatementImpl;
};
namespace Data
{
namespace ODBC
{
typedef Handle<SQLHSTMT, SQL_HANDLE_STMT> StatementHandle;
typedef Handle<SQLHDESC, SQL_HANDLE_DESC> DescriptorHandle;
template <typename H, SQLSMALLINT handleType>
class Handle
/// ODBC handle class template
{
public:
Handle(const ConnectionHandle & rConnection) : _rConnection(rConnection), _handle(0)
/// Creates the Handle.
{
if (Utility::isError(SQLAllocHandle(handleType, _rConnection, &_handle)))
{
throw ODBCException("Could not allocate statement handle.");
}
}
~Handle()
/// Destroys the Handle.
{
try
{
SQLRETURN rc = SQLFreeHandle(handleType, _handle);
// N.B. Destructors should not throw, but neither do we want to
// leak resources. So, we throw here in debug mode if things go bad.
poco_assert_dbg(!Utility::isError(rc));
}
catch (...)
{
poco_unexpected();
}
}
operator const H &() const
/// Const conversion operator into reference to native type.
{
return handle();
}
const H & handle() const
/// Returns const reference to native type.
{
return _handle;
}
private:
Handle(const Handle &);
const Handle & operator=(const Handle &);
operator H &()
/// Conversion operator into reference to native type.
{
return handle();
}
H & handle()
/// Returns reference to native type.
{
return _handle;
}
const ConnectionHandle & _rConnection;
H _handle;
friend class ODBCStatementImpl;
};
} } } // namespace Poco::Data::ODBC
typedef Handle<SQLHSTMT, SQL_HANDLE_STMT> StatementHandle;
typedef Handle<SQLHDESC, SQL_HANDLE_DESC> DescriptorHandle;
}
}
} // namespace Poco::Data::ODBC
#endif

View File

@ -22,7 +22,7 @@
#include "Poco/Foundation.h"
#ifdef POCO_OS_FAMILY_WINDOWS
#include <windows.h>
# include <windows.h>
#endif
@ -31,28 +31,27 @@
// from a DLL simpler. All files within this DLL are compiled with the ODBC_EXPORTS
// symbol defined on the command line. this symbol should not be defined on any project
// that uses this DLL. This way any other project whose source files include this file see
// ODBC_API functions as being imported from a DLL, wheras this DLL sees symbols
// ODBC_API functions as being imported from a DLL, whereas this DLL sees symbols
// defined with this macro as being exported.
//
#if defined(_WIN32) && defined(POCO_DLL)
#if defined(ODBC_EXPORTS)
#define ODBC_API __declspec(dllexport)
#else
#define ODBC_API __declspec(dllimport)
#endif
# if defined(ODBC_EXPORTS)
# define ODBC_API __declspec(dllexport)
# else
# define ODBC_API __declspec(dllimport)
# endif
#endif
#if !defined(ODBC_API)
#if !defined(POCO_NO_GCC_API_ATTRIBUTE) && defined (__GNUC__) && (__GNUC__ >= 4)
#define ODBC_API __attribute__ ((visibility ("default")))
#else
#define ODBC_API
#endif
# if !defined(POCO_NO_GCC_API_ATTRIBUTE) && defined(__GNUC__) && (__GNUC__ >= 4)
# define ODBC_API __attribute__((visibility("default")))
# else
# define ODBC_API
# endif
#endif
#include "Poco/Data/ODBC/Unicode.h"
@ -60,9 +59,9 @@
// Automatically link Data library.
//
#if defined(_MSC_VER)
#if !defined(POCO_NO_AUTOMATIC_LIBS) && !defined(ODBC_EXPORTS)
#pragma comment(lib, "PocoDataODBC" POCO_LIB_SUFFIX)
#endif
# if !defined(POCO_NO_AUTOMATIC_LIBS) && !defined(ODBC_EXPORTS)
# pragma comment(lib, "PocoDataODBC" POCO_LIB_SUFFIX)
# endif
#endif

View File

@ -18,133 +18,130 @@
#define Data_ODBC_ODBCException_INCLUDED
#include "Poco/Data/ODBC/ODBC.h"
#include "Poco/Data/ODBC/Utility.h"
#include "Poco/Data/DataException.h"
#include "Poco/Data/ODBC/Diagnostics.h"
#include "Poco/Data/ODBC/Error.h"
#include "Poco/Data/DataException.h"
#include "Poco/Data/ODBC/ODBC.h"
#include "Poco/Data/ODBC/Utility.h"
#include "Poco/Format.h"
namespace Poco {
namespace Data {
namespace ODBC {
POCO_DECLARE_EXCEPTION(ODBC_API, ODBCException, Poco::Data::DataException)
POCO_DECLARE_EXCEPTION(ODBC_API, InsufficientStorageException, ODBCException)
POCO_DECLARE_EXCEPTION(ODBC_API, UnknownDataLengthException, ODBCException)
POCO_DECLARE_EXCEPTION(ODBC_API, DataTruncatedException, ODBCException)
template <class H, SQLSMALLINT handleType>
class HandleException: public ODBCException
namespace Poco
{
public:
HandleException(const H& handle): _error(handle)
/// Creates HandleException
{
message(_error.toString());
}
HandleException(const H& handle, const std::string& msg):
ODBCException(msg),
_error(handle)
/// Creates HandleException
{
extendedMessage(_error.toString());
}
HandleException(const H& handle, const std::string& msg, const std::string& arg):
ODBCException(msg, arg),
_error(handle)
/// Creates HandleException
{
}
HandleException(const H& handle, const std::string& msg, const Poco::Exception& exc):
ODBCException(msg, exc),
_error(handle)
/// Creates HandleException
{
}
HandleException(const HandleException& exc):
ODBCException(exc),
_error(exc._error)
/// Creates HandleException
{
}
~HandleException() throw()
/// Destroys HandleException
{
}
HandleException& operator = (const HandleException& exc)
/// Assignment operator
{
if (&exc != this) _error = exc._error;
return *this;
}
const char* name() const throw()
/// Returns the name of the exception
{
return "ODBC handle exception";
}
const char* className() const throw()
/// Returns the HandleException class name.
{
return typeid(*this).name();
}
Poco::Exception* clone() const
/// Clones the HandleException
{
return new HandleException(*this);
}
void rethrow() const
/// Re-throws the HandleException.
{
throw *this;
}
const Diagnostics<H, handleType>& diagnostics() const
/// Returns error diagnostics.
{
return _error.diagnostics();
}
std::string toString() const
/// Returns the formatted error diagnostics for the handle.
{
return Poco::format("ODBC Error: %s\n===================\n%s\n",
std::string(what()),
_error.toString());
}
static std::string errorString(const H& handle)
/// Returns the error diagnostics string for the handle.
{
return Error<H, handleType>(handle).toString();
}
private:
Error<H, handleType> _error;
};
namespace Data
{
namespace ODBC
{
typedef HandleException<SQLHENV, SQL_HANDLE_ENV> EnvironmentException;
typedef HandleException<SQLHDBC, SQL_HANDLE_DBC> ConnectionException;
typedef HandleException<SQLHSTMT, SQL_HANDLE_STMT> StatementException;
typedef HandleException<SQLHDESC, SQL_HANDLE_DESC> DescriptorException;
POCO_DECLARE_EXCEPTION(ODBC_API, ODBCException, Poco::Data::DataException)
POCO_DECLARE_EXCEPTION(ODBC_API, InsufficientStorageException, ODBCException)
POCO_DECLARE_EXCEPTION(ODBC_API, UnknownDataLengthException, ODBCException)
POCO_DECLARE_EXCEPTION(ODBC_API, DataTruncatedException, ODBCException)
} } } // namespace Poco::Data::ODBC
template <class H, SQLSMALLINT handleType>
class HandleException : public ODBCException
{
public:
HandleException(const H & handle) : _error(handle)
/// Creates HandleException
{
message(_error.toString());
}
HandleException(const H & handle, const std::string & msg) : ODBCException(msg), _error(handle)
/// Creates HandleException
{
extendedMessage(_error.toString());
}
HandleException(const H & handle, const std::string & msg, const std::string & arg) : ODBCException(msg, arg), _error(handle)
/// Creates HandleException
{
}
HandleException(const H & handle, const std::string & msg, const Poco::Exception & exc)
: ODBCException(msg, exc), _error(handle)
/// Creates HandleException
{
}
HandleException(const HandleException & exc) : ODBCException(exc), _error(exc._error)
/// Creates HandleException
{
}
~HandleException() throw()
/// Destroys HandleException
{
}
HandleException & operator=(const HandleException & exc)
/// Assignment operator
{
if (&exc != this)
_error = exc._error;
return *this;
}
const char * name() const throw()
/// Returns the name of the exception
{
return "ODBC handle exception";
}
const char * className() const throw()
/// Returns the HandleException class name.
{
return typeid(*this).name();
}
Poco::Exception * clone() const
/// Clones the HandleException
{
return new HandleException(*this);
}
void rethrow() const
/// Re-throws the HandleException.
{
throw *this;
}
const Diagnostics<H, handleType> & diagnostics() const
/// Returns error diagnostics.
{
return _error.diagnostics();
}
std::string toString() const
/// Returns the formatted error diagnostics for the handle.
{
return Poco::format("ODBC Error: %s\n===================\n%s\n", std::string(what()), _error.toString());
}
static std::string errorString(const H & handle)
/// Returns the error diagnostics string for the handle.
{
return Error<H, handleType>(handle).toString();
}
private:
Error<H, handleType> _error;
};
typedef HandleException<SQLHENV, SQL_HANDLE_ENV> EnvironmentException;
typedef HandleException<SQLHDBC, SQL_HANDLE_DBC> ConnectionException;
typedef HandleException<SQLHSTMT, SQL_HANDLE_STMT> StatementException;
typedef HandleException<SQLHDESC, SQL_HANDLE_DESC> DescriptorException;
}
}
} // namespace Poco::Data::ODBC
#endif

View File

@ -18,75 +18,80 @@
#define Data_ODBC_ODBCColumn_INCLUDED
#include "Poco/Data/ODBC/ODBC.h"
#include "Poco/Data/MetaColumn.h"
#include "Poco/Data/ODBC/Error.h"
#include "Poco/Data/ODBC/Handle.h"
#include "Poco/Data/ODBC/ODBC.h"
#include "Poco/Data/ODBC/ODBCException.h"
#include "Poco/Data/MetaColumn.h"
#ifdef POCO_OS_FAMILY_WINDOWS
#include <windows.h>
# include <windows.h>
#endif
#include <sqlext.h>
namespace Poco {
namespace Data {
namespace ODBC {
class ODBC_API ODBCMetaColumn: public MetaColumn
namespace Poco
{
public:
explicit ODBCMetaColumn(const StatementHandle& rStmt, std::size_t position);
/// Creates the ODBCMetaColumn.
~ODBCMetaColumn();
/// Destroys the ODBCMetaColumn.
std::size_t dataLength() const;
/// A numeric value that is either the maximum or actual character length of a character
/// string or binary data type. It is the maximum character length for a fixed-length data type,
/// or the actual character length for a variable-length data type. Its value always excludes the
/// null-termination byte that ends the character string.
/// This information is returned from the SQL_DESC_LENGTH record field of the IRD.
bool isUnsigned() const;
/// Returns true if column is unsigned or a non-numeric data type.
private:
ODBCMetaColumn();
static const int NAME_BUFFER_LENGTH = 2048;
struct ColumnDescription
{
SQLCHAR name[NAME_BUFFER_LENGTH];
SQLSMALLINT nameBufferLength;
SQLSMALLINT dataType;
SQLULEN size;
SQLSMALLINT decimalDigits;
SQLSMALLINT isNullable;
};
void init();
void getDescription();
SQLLEN _dataLength;
const StatementHandle& _rStmt;
ColumnDescription _columnDesc;
};
///
/// inlines
///
inline std::size_t ODBCMetaColumn::dataLength() const
namespace Data
{
return _dataLength;
namespace ODBC
{
class ODBC_API ODBCMetaColumn : public MetaColumn
{
public:
explicit ODBCMetaColumn(const StatementHandle & rStmt, std::size_t position);
/// Creates the ODBCMetaColumn.
~ODBCMetaColumn();
/// Destroys the ODBCMetaColumn.
std::size_t dataLength() const;
/// A numeric value that is either the maximum or actual character length of a character
/// string or binary data type. It is the maximum character length for a fixed-length data type,
/// or the actual character length for a variable-length data type. Its value always excludes the
/// null-termination byte that ends the character string.
/// This information is returned from the SQL_DESC_LENGTH record field of the IRD.
bool isUnsigned() const;
/// Returns true if column is unsigned or a non-numeric data type.
private:
ODBCMetaColumn();
static const int NAME_BUFFER_LENGTH = 2048;
struct ColumnDescription
{
SQLCHAR name[NAME_BUFFER_LENGTH];
SQLSMALLINT nameBufferLength;
SQLSMALLINT dataType;
SQLULEN size;
SQLSMALLINT decimalDigits;
SQLSMALLINT isNullable;
};
void init();
void getDescription();
SQLLEN _dataLength;
const StatementHandle & _rStmt;
ColumnDescription _columnDesc;
};
///
/// inlines
///
inline std::size_t ODBCMetaColumn::dataLength() const
{
return _dataLength;
}
}
}
} } } // namespace Poco::Data::ODBC
} // namespace Poco::Data::ODBC
#endif

View File

@ -18,189 +18,194 @@
#define Data_ODBC_ODBCStatementImpl_INCLUDED
#include "Poco/Data/ODBC/ODBC.h"
#include "Poco/Data/ODBC/SessionImpl.h"
#include <sstream>
#include "Poco/Data/Column.h"
#include "Poco/Data/ODBC/Binder.h"
#include "Poco/Data/ODBC/Extractor.h"
#include "Poco/Data/ODBC/Preparator.h"
#include "Poco/Data/ODBC/ODBC.h"
#include "Poco/Data/ODBC/ODBCMetaColumn.h"
#include "Poco/Data/ODBC/Preparator.h"
#include "Poco/Data/ODBC/SessionImpl.h"
#include "Poco/Data/StatementImpl.h"
#include "Poco/Data/Column.h"
#include "Poco/SharedPtr.h"
#include "Poco/Format.h"
#include <sstream>
#include "Poco/SharedPtr.h"
#ifdef POCO_OS_FAMILY_WINDOWS
#include <windows.h>
# include <windows.h>
#endif
#include <sqltypes.h>
namespace Poco {
namespace Data {
namespace ODBC {
class ODBC_API ODBCStatementImpl: public Poco::Data::StatementImpl
/// Implements statement functionality needed for ODBC
namespace Poco
{
public:
ODBCStatementImpl(SessionImpl& rSession);
/// Creates the ODBCStatementImpl.
~ODBCStatementImpl();
/// Destroys the ODBCStatementImpl.
protected:
std::size_t columnsReturned() const;
/// Returns number of columns returned by query.
int affectedRowCount() const;
/// Returns the number of affected rows.
/// Used to find out the number of rows affected by insert or update.
const MetaColumn& metaColumn(std::size_t pos) const;
/// Returns column meta data.
bool hasNext();
/// Returns true if a call to next() will return data.
std::size_t next();
/// Retrieves the next row or set of rows from the resultset.
/// Returns the number of rows retrieved.
/// Will throw, if the resultset is empty.
bool canBind() const;
/// Returns true if a valid statement is set and we can bind.
bool canCompile() const;
/// Returns true if another compile is possible.
void compileImpl();
/// Compiles the statement, doesn't bind yet.
/// Does nothing if the statement has already been compiled.
void bindImpl();
/// Binds all parameters and executes the statement.
AbstractExtraction::ExtractorPtr extractor();
/// Returns the concrete extractor used by the statement.
AbstractBinding::BinderPtr binder();
/// Returns the concrete binder used by the statement.
std::string nativeSQL();
/// Returns the SQL string as modified by the driver.
private:
typedef Poco::Data::AbstractBindingVec Bindings;
typedef Poco::SharedPtr<Binder> BinderPtr;
typedef Poco::Data::AbstractExtractionVec Extractions;
typedef Poco::SharedPtr<Preparator> PreparatorPtr;
typedef std::vector<PreparatorPtr> PreparatorVec;
typedef Poco::SharedPtr<Extractor> ExtractorPtr;
typedef std::vector<ExtractorPtr> ExtractorVec;
typedef std::vector<ODBCMetaColumn*> ColumnPtrVec;
typedef std::vector<ColumnPtrVec> ColumnPtrVecVec;
static const std::string INVALID_CURSOR_STATE;
void clear();
/// Closes the cursor and resets indicator variables.
void doBind();
/// Binds parameters.
void makeInternalExtractors();
/// Creates internal extractors if none were supplied from the user.
bool isStoredProcedure() const;
/// Returns true if SQL is a stored procedure call.
void doPrepare();
/// Prepares placeholders for data returned by statement.
/// It is called during statement compilation for SQL statements
/// returning data. For stored procedures returning datasets,
/// it is called upon the first check for data availability
/// (see hasNext() function).
bool hasData() const;
/// Returns true if statement returns data.
void makeStep();
/// Fetches the next row of data.
bool nextRowReady() const;
/// Returns true if there is a row fetched but not yet extracted.
void putData();
/// Called whenever SQLExecute returns SQL_NEED_DATA. This is expected
/// behavior for PB_AT_EXEC binding mode.
void getData();
void addPreparator();
void fillColumns();
void checkError(SQLRETURN rc, const std::string& msg="");
const SQLHDBC& _rConnection;
const StatementHandle _stmt;
PreparatorVec _preparations;
BinderPtr _pBinder;
ExtractorVec _extractors;
bool _stepCalled;
int _nextResponse;
ColumnPtrVecVec _columnPtrs;
bool _prepared;
mutable std::size_t _affectedRowCount;
bool _canCompile;
};
//
// inlines
//
inline AbstractExtraction::ExtractorPtr ODBCStatementImpl::extractor()
namespace Data
{
poco_assert_dbg (currentDataSet() < _extractors.size());
poco_assert_dbg (_extractors[currentDataSet()]);
return _extractors[currentDataSet()];
namespace ODBC
{
class ODBC_API ODBCStatementImpl : public Poco::Data::StatementImpl
/// Implements statement functionality needed for ODBC
{
public:
ODBCStatementImpl(SessionImpl & rSession);
/// Creates the ODBCStatementImpl.
~ODBCStatementImpl();
/// Destroys the ODBCStatementImpl.
protected:
std::size_t columnsReturned() const;
/// Returns number of columns returned by query.
int affectedRowCount() const;
/// Returns the number of affected rows.
/// Used to find out the number of rows affected by insert or update.
const MetaColumn & metaColumn(std::size_t pos) const;
/// Returns column meta data.
bool hasNext();
/// Returns true if a call to next() will return data.
std::size_t next();
/// Retrieves the next row or set of rows from the resultset.
/// Returns the number of rows retrieved.
/// Will throw, if the resultset is empty.
bool canBind() const;
/// Returns true if a valid statement is set and we can bind.
bool canCompile() const;
/// Returns true if another compile is possible.
void compileImpl();
/// Compiles the statement, doesn't bind yet.
/// Does nothing if the statement has already been compiled.
void bindImpl();
/// Binds all parameters and executes the statement.
AbstractExtraction::ExtractorPtr extractor();
/// Returns the concrete extractor used by the statement.
AbstractBinding::BinderPtr binder();
/// Returns the concrete binder used by the statement.
std::string nativeSQL();
/// Returns the SQL string as modified by the driver.
private:
typedef Poco::Data::AbstractBindingVec Bindings;
typedef Poco::SharedPtr<Binder> BinderPtr;
typedef Poco::Data::AbstractExtractionVec Extractions;
typedef Poco::SharedPtr<Preparator> PreparatorPtr;
typedef std::vector<PreparatorPtr> PreparatorVec;
typedef Poco::SharedPtr<Extractor> ExtractorPtr;
typedef std::vector<ExtractorPtr> ExtractorVec;
typedef std::vector<ODBCMetaColumn *> ColumnPtrVec;
typedef std::vector<ColumnPtrVec> ColumnPtrVecVec;
static const std::string INVALID_CURSOR_STATE;
void clear();
/// Closes the cursor and resets indicator variables.
void doBind();
/// Binds parameters.
void makeInternalExtractors();
/// Creates internal extractors if none were supplied from the user.
bool isStoredProcedure() const;
/// Returns true if SQL is a stored procedure call.
void doPrepare();
/// Prepares placeholders for data returned by statement.
/// It is called during statement compilation for SQL statements
/// returning data. For stored procedures returning datasets,
/// it is called upon the first check for data availability
/// (see hasNext() function).
bool hasData() const;
/// Returns true if statement returns data.
void makeStep();
/// Fetches the next row of data.
bool nextRowReady() const;
/// Returns true if there is a row fetched but not yet extracted.
void putData();
/// Called whenever SQLExecute returns SQL_NEED_DATA. This is expected
/// behavior for PB_AT_EXEC binding mode.
void getData();
void addPreparator();
void fillColumns();
void checkError(SQLRETURN rc, const std::string & msg = "");
const SQLHDBC & _rConnection;
const StatementHandle _stmt;
PreparatorVec _preparations;
BinderPtr _pBinder;
ExtractorVec _extractors;
bool _stepCalled;
int _nextResponse;
ColumnPtrVecVec _columnPtrs;
bool _prepared;
mutable std::size_t _affectedRowCount;
bool _canCompile;
};
//
// inlines
//
inline AbstractExtraction::ExtractorPtr ODBCStatementImpl::extractor()
{
poco_assert_dbg(currentDataSet() < _extractors.size());
poco_assert_dbg(_extractors[currentDataSet()]);
return _extractors[currentDataSet()];
}
inline AbstractBinding::BinderPtr ODBCStatementImpl::binder()
{
poco_assert_dbg(!_pBinder.isNull());
return _pBinder;
}
inline std::size_t ODBCStatementImpl::columnsReturned() const
{
poco_assert_dbg(currentDataSet() < _preparations.size());
poco_assert_dbg(_preparations[currentDataSet()]);
return static_cast<std::size_t>(_preparations[currentDataSet()]->columns());
}
inline bool ODBCStatementImpl::hasData() const
{
return (columnsReturned() > 0);
}
inline bool ODBCStatementImpl::nextRowReady() const
{
return (!Utility::isError(_nextResponse));
}
inline bool ODBCStatementImpl::canCompile() const
{
return _canCompile;
}
}
}
inline AbstractBinding::BinderPtr ODBCStatementImpl::binder()
{
poco_assert_dbg (!_pBinder.isNull());
return _pBinder;
}
inline std::size_t ODBCStatementImpl::columnsReturned() const
{
poco_assert_dbg (currentDataSet() < _preparations.size());
poco_assert_dbg (_preparations[currentDataSet()]);
return static_cast<std::size_t>(_preparations[currentDataSet()]->columns());
}
inline bool ODBCStatementImpl::hasData() const
{
return (columnsReturned() > 0);
}
inline bool ODBCStatementImpl::nextRowReady() const
{
return (!Utility::isError(_nextResponse));
}
inline bool ODBCStatementImpl::canCompile() const
{
return _canCompile;
}
} } } // namespace Poco::Data::ODBC
} // namespace Poco::Data::ODBC
#endif // Data_ODBC_ODBCStatementImpl_INCLUDED

View File

@ -18,94 +18,99 @@
#define Data_ODBC_Parameter_INCLUDED
#include "Poco/Data/ODBC/ODBC.h"
#include "Poco/Data/ODBC/Handle.h"
#include "Poco/Data/ODBC/ODBC.h"
#ifdef POCO_OS_FAMILY_WINDOWS
#include <windows.h>
# include <windows.h>
#endif
#include <sqlext.h>
namespace Poco {
namespace Data {
namespace ODBC {
class ODBC_API Parameter
namespace Poco
{
public:
explicit Parameter(const StatementHandle& rStmt, std::size_t colNum);
/// Creates the Parameter.
~Parameter();
/// Destroys the Parameter.
std::size_t number() const;
/// Returns the column number.
std::size_t dataType() const;
/// Returns the SQL data type.
std::size_t columnSize() const;
/// Returns the the size of the column or expression of the corresponding
/// parameter marker as defined by the data source.
std::size_t decimalDigits() const;
/// Returns the number of decimal digits of the column or expression
/// of the corresponding parameter as defined by the data source.
bool isNullable() const;
/// Returns true if column allows null values, false otherwise.
private:
Parameter();
void init();
SQLSMALLINT _dataType;
SQLULEN _columnSize;
SQLSMALLINT _decimalDigits;
SQLSMALLINT _isNullable;
const StatementHandle& _rStmt;
std::size_t _number;
};
///
/// inlines
///
inline std::size_t Parameter::number() const
namespace Data
{
return _number;
namespace ODBC
{
class ODBC_API Parameter
{
public:
explicit Parameter(const StatementHandle & rStmt, std::size_t colNum);
/// Creates the Parameter.
~Parameter();
/// Destroys the Parameter.
std::size_t number() const;
/// Returns the column number.
std::size_t dataType() const;
/// Returns the SQL data type.
std::size_t columnSize() const;
/// Returns the the size of the column or expression of the corresponding
/// parameter marker as defined by the data source.
std::size_t decimalDigits() const;
/// Returns the number of decimal digits of the column or expression
/// of the corresponding parameter as defined by the data source.
bool isNullable() const;
/// Returns true if column allows null values, false otherwise.
private:
Parameter();
void init();
SQLSMALLINT _dataType;
SQLULEN _columnSize;
SQLSMALLINT _decimalDigits;
SQLSMALLINT _isNullable;
const StatementHandle & _rStmt;
std::size_t _number;
};
///
/// inlines
///
inline std::size_t Parameter::number() const
{
return _number;
}
inline std::size_t Parameter::dataType() const
{
return _dataType;
}
inline std::size_t Parameter::columnSize() const
{
return _columnSize;
}
inline std::size_t Parameter::decimalDigits() const
{
return _decimalDigits;
}
inline bool Parameter::isNullable() const
{
return SQL_NULLABLE == _isNullable;
}
}
}
inline std::size_t Parameter::dataType() const
{
return _dataType;
}
inline std::size_t Parameter::columnSize() const
{
return _columnSize;
}
inline std::size_t Parameter::decimalDigits() const
{
return _decimalDigits;
}
inline bool Parameter::isNullable() const
{
return SQL_NULLABLE == _isNullable;
}
} } } // namespace Poco::Data::ODBC
} // namespace Poco::Data::ODBC
#endif

File diff suppressed because it is too large Load Diff

View File

@ -18,273 +18,280 @@
#define Data_ODBC_SessionImpl_INCLUDED
#include "Poco/Data/ODBC/ODBC.h"
#include "Poco/Data/ODBC/Connector.h"
#include "Poco/Data/ODBC/TypeInfo.h"
#include "Poco/Data/ODBC/Binder.h"
#include "Poco/Data/ODBC/Handle.h"
#include "Poco/Data/ODBC/ODBCException.h"
#include "Poco/Data/AbstractSessionImpl.h"
#include "Poco/SharedPtr.h"
#include "Poco/Data/ODBC/Binder.h"
#include "Poco/Data/ODBC/Connector.h"
#include "Poco/Data/ODBC/Handle.h"
#include "Poco/Data/ODBC/ODBC.h"
#include "Poco/Data/ODBC/ODBCException.h"
#include "Poco/Data/ODBC/TypeInfo.h"
#include "Poco/Mutex.h"
#include "Poco/SharedPtr.h"
#ifdef POCO_OS_FAMILY_WINDOWS
#include <windows.h>
# include <windows.h>
#endif
#include <sqltypes.h>
namespace Poco {
namespace Data {
namespace ODBC {
class ODBC_API SessionImpl: public Poco::Data::AbstractSessionImpl<SessionImpl>
/// Implements SessionImpl interface
namespace Poco
{
public:
static const std::size_t ODBC_MAX_FIELD_SIZE = 1024u;
enum TransactionCapability
{
ODBC_TXN_CAPABILITY_UNKNOWN = -1,
ODBC_TXN_CAPABILITY_FALSE = 0,
ODBC_TXN_CAPABILITY_TRUE = 1
};
SessionImpl(const std::string& connect,
std::size_t loginTimeout,
std::size_t maxFieldSize = ODBC_MAX_FIELD_SIZE,
bool autoBind = true,
bool autoExtract = true);
/// Creates the SessionImpl. Opens a connection to the database.
/// Throws NotConnectedException if connection was not succesful.
//@ deprecated
SessionImpl(const std::string& connect,
Poco::Any maxFieldSize = ODBC_MAX_FIELD_SIZE,
bool enforceCapability=false,
bool autoBind = true,
bool autoExtract = true);
/// Creates the SessionImpl. Opens a connection to the database.
~SessionImpl();
/// Destroys the SessionImpl.
Poco::Data::StatementImpl* createStatementImpl();
/// Returns an ODBC StatementImpl
void open(const std::string& connect = "");
/// Opens a connection to the Database
void close();
/// Closes the connection
bool isConnected();
/// Returns true if session is connected
void setConnectionTimeout(std::size_t timeout);
/// Sets the session connection timeout value.
std::size_t getConnectionTimeout();
/// Returns the session connection timeout value.
void begin();
/// Starts a transaction
void commit();
/// Commits and ends a transaction
void rollback();
/// Aborts a transaction
bool isTransaction();
/// Returns true iff a transaction is in progress.
const std::string& connectorName() const;
/// Returns the name of the connector.
bool canTransact();
/// Returns true if connection is transaction-capable.
void setTransactionIsolation(Poco::UInt32 ti);
/// Sets the transaction isolation level.
Poco::UInt32 getTransactionIsolation();
/// Returns the transaction isolation level.
bool hasTransactionIsolation(Poco::UInt32);
/// Returns true iff the transaction isolation level corresponding
/// to the supplied bitmask is supported.
bool isTransactionIsolation(Poco::UInt32);
/// Returns true iff the transaction isolation level corresponds
/// to the supplied bitmask.
void autoCommit(const std::string&, bool val);
/// Sets autocommit property for the session.
bool isAutoCommit(const std::string& name="");
/// Returns autocommit property value.
void autoBind(const std::string&, bool val);
/// Sets automatic binding for the session.
bool isAutoBind(const std::string& name="");
/// Returns true if binding is automatic for this session.
void autoExtract(const std::string&, bool val);
/// Sets automatic extraction for the session.
bool isAutoExtract(const std::string& name="");
/// Returns true if extraction is automatic for this session.
void setMaxFieldSize(const std::string& rName, const Poco::Any& rValue);
/// Sets the max field size (the default used when column size is unknown).
Poco::Any getMaxFieldSize(const std::string& rName="");
/// Returns the max field size (the default used when column size is unknown).
int maxStatementLength();
/// Returns maximum length of SQL statement allowed by driver.
void setQueryTimeout(const std::string&, const Poco::Any& value);
/// Sets the timeout (in seconds) for queries.
/// Value must be of type int.
Poco::Any getQueryTimeout(const std::string&);
/// Returns the timeout (in seconds) for queries,
/// or -1 if no timeout has been set.
int queryTimeout() const;
/// Returns the timeout (in seconds) for queries,
/// or -1 if no timeout has been set.
const ConnectionHandle& dbc() const;
/// Returns the connection handle.
Poco::Any dataTypeInfo(const std::string& rName="");
/// Returns the data types information.
private:
void setDataTypeInfo(const std::string& rName, const Poco::Any& rValue);
/// No-op. Throws InvalidAccessException.
static const int FUNCTIONS = SQL_API_ODBC3_ALL_FUNCTIONS_SIZE;
void checkError(SQLRETURN rc, const std::string& msg="");
Poco::UInt32 getDefaultTransactionIsolation();
Poco::UInt32 transactionIsolation(SQLULEN isolation);
std::string _connector;
const ConnectionHandle _db;
Poco::Any _maxFieldSize;
bool _autoBind;
bool _autoExtract;
TypeInfo _dataTypes;
char _canTransact;
bool _inTransaction;
int _queryTimeout;
Poco::FastMutex _mutex;
};
///
/// inlines
///
inline void SessionImpl::checkError(SQLRETURN rc, const std::string& msg)
namespace Data
{
if (Utility::isError(rc))
throw ConnectionException(_db, msg);
namespace ODBC
{
class ODBC_API SessionImpl : public Poco::Data::AbstractSessionImpl<SessionImpl>
/// Implements SessionImpl interface
{
public:
static const std::size_t ODBC_MAX_FIELD_SIZE = 1024u;
enum TransactionCapability
{
ODBC_TXN_CAPABILITY_UNKNOWN = -1,
ODBC_TXN_CAPABILITY_FALSE = 0,
ODBC_TXN_CAPABILITY_TRUE = 1
};
SessionImpl(
const std::string & connect,
std::size_t loginTimeout,
std::size_t maxFieldSize = ODBC_MAX_FIELD_SIZE,
bool autoBind = true,
bool autoExtract = true);
/// Creates the SessionImpl. Opens a connection to the database.
/// Throws NotConnectedException if connection was not successful.
//@ deprecated
SessionImpl(
const std::string & connect,
Poco::Any maxFieldSize = ODBC_MAX_FIELD_SIZE,
bool enforceCapability = false,
bool autoBind = true,
bool autoExtract = true);
/// Creates the SessionImpl. Opens a connection to the database.
~SessionImpl();
/// Destroys the SessionImpl.
Poco::Data::StatementImpl * createStatementImpl();
/// Returns an ODBC StatementImpl
void open(const std::string & connect = "");
/// Opens a connection to the Database
void close();
/// Closes the connection
bool isConnected();
/// Returns true if session is connected
void setConnectionTimeout(std::size_t timeout);
/// Sets the session connection timeout value.
std::size_t getConnectionTimeout();
/// Returns the session connection timeout value.
void begin();
/// Starts a transaction
void commit();
/// Commits and ends a transaction
void rollback();
/// Aborts a transaction
bool isTransaction();
/// Returns true iff a transaction is in progress.
const std::string & connectorName() const;
/// Returns the name of the connector.
bool canTransact();
/// Returns true if connection is transaction-capable.
void setTransactionIsolation(Poco::UInt32 ti);
/// Sets the transaction isolation level.
Poco::UInt32 getTransactionIsolation();
/// Returns the transaction isolation level.
bool hasTransactionIsolation(Poco::UInt32);
/// Returns true iff the transaction isolation level corresponding
/// to the supplied bitmask is supported.
bool isTransactionIsolation(Poco::UInt32);
/// Returns true iff the transaction isolation level corresponds
/// to the supplied bitmask.
void autoCommit(const std::string &, bool val);
/// Sets autocommit property for the session.
bool isAutoCommit(const std::string & name = "");
/// Returns autocommit property value.
void autoBind(const std::string &, bool val);
/// Sets automatic binding for the session.
bool isAutoBind(const std::string & name = "");
/// Returns true if binding is automatic for this session.
void autoExtract(const std::string &, bool val);
/// Sets automatic extraction for the session.
bool isAutoExtract(const std::string & name = "");
/// Returns true if extraction is automatic for this session.
void setMaxFieldSize(const std::string & rName, const Poco::Any & rValue);
/// Sets the max field size (the default used when column size is unknown).
Poco::Any getMaxFieldSize(const std::string & rName = "");
/// Returns the max field size (the default used when column size is unknown).
int maxStatementLength();
/// Returns maximum length of SQL statement allowed by driver.
void setQueryTimeout(const std::string &, const Poco::Any & value);
/// Sets the timeout (in seconds) for queries.
/// Value must be of type int.
Poco::Any getQueryTimeout(const std::string &);
/// Returns the timeout (in seconds) for queries,
/// or -1 if no timeout has been set.
int queryTimeout() const;
/// Returns the timeout (in seconds) for queries,
/// or -1 if no timeout has been set.
const ConnectionHandle & dbc() const;
/// Returns the connection handle.
Poco::Any dataTypeInfo(const std::string & rName = "");
/// Returns the data types information.
private:
void setDataTypeInfo(const std::string & rName, const Poco::Any & rValue);
/// No-op. Throws InvalidAccessException.
static const int FUNCTIONS = SQL_API_ODBC3_ALL_FUNCTIONS_SIZE;
void checkError(SQLRETURN rc, const std::string & msg = "");
Poco::UInt32 getDefaultTransactionIsolation();
Poco::UInt32 transactionIsolation(SQLULEN isolation);
std::string _connector;
const ConnectionHandle _db;
Poco::Any _maxFieldSize;
bool _autoBind;
bool _autoExtract;
TypeInfo _dataTypes;
char _canTransact;
bool _inTransaction;
int _queryTimeout;
Poco::FastMutex _mutex;
};
///
/// inlines
///
inline void SessionImpl::checkError(SQLRETURN rc, const std::string & msg)
{
if (Utility::isError(rc))
throw ConnectionException(_db, msg);
}
inline const ConnectionHandle & SessionImpl::dbc() const
{
return _db;
}
inline void SessionImpl::setMaxFieldSize(const std::string & rName, const Poco::Any & rValue)
{
_maxFieldSize = rValue;
}
inline Poco::Any SessionImpl::getMaxFieldSize(const std::string & rName)
{
return _maxFieldSize;
}
inline void SessionImpl::setDataTypeInfo(const std::string & rName, const Poco::Any & rValue)
{
throw InvalidAccessException();
}
inline Poco::Any SessionImpl::dataTypeInfo(const std::string & rName)
{
return &_dataTypes;
}
inline void SessionImpl::autoBind(const std::string &, bool val)
{
_autoBind = val;
}
inline bool SessionImpl::isAutoBind(const std::string & name)
{
return _autoBind;
}
inline void SessionImpl::autoExtract(const std::string &, bool val)
{
_autoExtract = val;
}
inline bool SessionImpl::isAutoExtract(const std::string & name)
{
return _autoExtract;
}
inline const std::string & SessionImpl::connectorName() const
{
return _connector;
}
inline bool SessionImpl::isTransactionIsolation(Poco::UInt32 ti)
{
return 0 != (ti & getTransactionIsolation());
}
inline void SessionImpl::setQueryTimeout(const std::string &, const Poco::Any & value)
{
_queryTimeout = Poco::AnyCast<int>(value);
}
inline Poco::Any SessionImpl::getQueryTimeout(const std::string &)
{
return _queryTimeout;
}
inline int SessionImpl::queryTimeout() const
{
return _queryTimeout;
}
}
}
inline const ConnectionHandle& SessionImpl::dbc() const
{
return _db;
}
inline void SessionImpl::setMaxFieldSize(const std::string& rName, const Poco::Any& rValue)
{
_maxFieldSize = rValue;
}
inline Poco::Any SessionImpl::getMaxFieldSize(const std::string& rName)
{
return _maxFieldSize;
}
inline void SessionImpl::setDataTypeInfo(const std::string& rName, const Poco::Any& rValue)
{
throw InvalidAccessException();
}
inline Poco::Any SessionImpl::dataTypeInfo(const std::string& rName)
{
return &_dataTypes;
}
inline void SessionImpl::autoBind(const std::string&, bool val)
{
_autoBind = val;
}
inline bool SessionImpl::isAutoBind(const std::string& name)
{
return _autoBind;
}
inline void SessionImpl::autoExtract(const std::string&, bool val)
{
_autoExtract = val;
}
inline bool SessionImpl::isAutoExtract(const std::string& name)
{
return _autoExtract;
}
inline const std::string& SessionImpl::connectorName() const
{
return _connector;
}
inline bool SessionImpl::isTransactionIsolation(Poco::UInt32 ti)
{
return 0 != (ti & getTransactionIsolation());
}
inline void SessionImpl::setQueryTimeout(const std::string&, const Poco::Any& value)
{
_queryTimeout = Poco::AnyCast<int>(value);
}
inline Poco::Any SessionImpl::getQueryTimeout(const std::string&)
{
return _queryTimeout;
}
inline int SessionImpl::queryTimeout() const
{
return _queryTimeout;
}
} } } // namespace Poco::Data::ODBC
} // namespace Poco::Data::ODBC
#endif // Data_ODBC_SessionImpl_INCLUDED

View File

@ -18,100 +18,107 @@
#define Data_ODBC_DataTypes_INCLUDED
#include "Poco/Data/ODBC/ODBC.h"
#include "Poco/NamedTuple.h"
#include "Poco/DynamicAny.h"
#include <vector>
#include <map>
#include <vector>
#include "Poco/Data/ODBC/ODBC.h"
#include "Poco/DynamicAny.h"
#include "Poco/NamedTuple.h"
#ifdef POCO_OS_FAMILY_WINDOWS
#include <windows.h>
# include <windows.h>
#endif
#include <sqlext.h>
namespace Poco {
namespace Data {
namespace ODBC {
class ODBC_API TypeInfo
/// Datatypes mapping utility class.
///
/// This class provides mapping between C and SQL datatypes as well
/// as datatypes supported by the underlying database. In order for database
/// types to be available, a valid conection handle must be supplied at either
/// object construction time, or at a later point in time, through call to
/// fillTypeInfo member function.
///
/// Class also provides a convenient debugging function that prints
/// tabulated data to an output stream.
namespace Poco
{
public:
typedef std::map<int, int> DataTypeMap;
typedef DataTypeMap::value_type ValueType;
typedef Poco::NamedTuple<std::string,
SQLSMALLINT,
SQLINTEGER,
std::string,
std::string,
std::string,
SQLSMALLINT,
SQLSMALLINT,
SQLSMALLINT,
SQLSMALLINT,
SQLSMALLINT,
SQLSMALLINT,
std::string,
SQLSMALLINT,
SQLSMALLINT,
SQLSMALLINT,
SQLSMALLINT,
SQLINTEGER,
SQLSMALLINT> TypeInfoTup;
typedef std::vector<TypeInfoTup> TypeInfoVec;
explicit TypeInfo(SQLHDBC* pHDBC=0);
/// Creates the TypeInfo.
~TypeInfo();
/// Destroys the TypeInfo.
int cDataType(int sqlDataType) const;
/// Returns C data type corresponding to supplied SQL data type.
int sqlDataType(int cDataType) const;
/// Returns SQL data type corresponding to supplied C data type.
void fillTypeInfo(SQLHDBC pHDBC);
/// Fills the data type info structure for the database.
DynamicAny getInfo(SQLSMALLINT type, const std::string& param) const;
/// Returns information about specified data type as specified by parameter 'type'.
/// The requested information is specified by parameter 'param'.
/// Will fail with a Poco::NotFoundException thrown if the param is not found
bool tryGetInfo(SQLSMALLINT type, const std::string& param, DynamicAny& result) const;
/// Returns information about specified data type as specified by parameter 'type' in param result.
/// The requested information is specified by parameter 'param'.
/// Will return false if the param is not found. The value of result will be not changed in this case.
void print(std::ostream& ostr);
/// Prints all the types (as reported by the underlying database)
/// to the supplied output stream.
private:
void fillCTypes();
void fillSQLTypes();
DataTypeMap _cDataTypes;
DataTypeMap _sqlDataTypes;
TypeInfoVec _typeInfo;
SQLHDBC* _pHDBC;
};
namespace Data
{
namespace ODBC
{
} } } // namespace Poco::Data::ODBC
class ODBC_API TypeInfo
/// Datatypes mapping utility class.
///
/// This class provides mapping between C and SQL datatypes as well
/// as datatypes supported by the underlying database. In order for database
/// types to be available, a valid connection handle must be supplied at either
/// object construction time, or at a later point in time, through call to
/// fillTypeInfo member function.
///
/// Class also provides a convenient debugging function that prints
/// tabulated data to an output stream.
{
public:
typedef std::map<int, int> DataTypeMap;
typedef DataTypeMap::value_type ValueType;
typedef Poco::NamedTuple<
std::string,
SQLSMALLINT,
SQLINTEGER,
std::string,
std::string,
std::string,
SQLSMALLINT,
SQLSMALLINT,
SQLSMALLINT,
SQLSMALLINT,
SQLSMALLINT,
SQLSMALLINT,
std::string,
SQLSMALLINT,
SQLSMALLINT,
SQLSMALLINT,
SQLSMALLINT,
SQLINTEGER,
SQLSMALLINT>
TypeInfoTup;
typedef std::vector<TypeInfoTup> TypeInfoVec;
explicit TypeInfo(SQLHDBC * pHDBC = 0);
/// Creates the TypeInfo.
~TypeInfo();
/// Destroys the TypeInfo.
int cDataType(int sqlDataType) const;
/// Returns C data type corresponding to supplied SQL data type.
int sqlDataType(int cDataType) const;
/// Returns SQL data type corresponding to supplied C data type.
void fillTypeInfo(SQLHDBC pHDBC);
/// Fills the data type info structure for the database.
DynamicAny getInfo(SQLSMALLINT type, const std::string & param) const;
/// Returns information about specified data type as specified by parameter 'type'.
/// The requested information is specified by parameter 'param'.
/// Will fail with a Poco::NotFoundException thrown if the param is not found
bool tryGetInfo(SQLSMALLINT type, const std::string & param, DynamicAny & result) const;
/// Returns information about specified data type as specified by parameter 'type' in param result.
/// The requested information is specified by parameter 'param'.
/// Will return false if the param is not found. The value of result will be not changed in this case.
void print(std::ostream & ostr);
/// Prints all the types (as reported by the underlying database)
/// to the supplied output stream.
private:
void fillCTypes();
void fillSQLTypes();
DataTypeMap _cDataTypes;
DataTypeMap _sqlDataTypes;
TypeInfoVec _typeInfo;
SQLHDBC * _pHDBC;
};
}
}
} // namespace Poco::Data::ODBC
#endif

File diff suppressed because it is too large Load Diff

View File

@ -18,34 +18,39 @@
#define Data_ODBC_Unicode_UNIX_INCLUDED
namespace Poco {
namespace Data {
namespace ODBC {
void makeUTF16(SQLCHAR* pSQLChar, SQLINTEGER length, std::string& target);
/// Utility function for conversion from UTF-8 to UTF-16
inline void makeUTF16(SQLCHAR* pSQLChar, SQLSMALLINT length, std::string& target)
/// Utility function for conversion from UTF-8 to UTF-16.
namespace Poco
{
makeUTF16(pSQLChar, (SQLINTEGER) length, target);
}
void makeUTF8(Poco::Buffer<SQLWCHAR>& buffer, SQLINTEGER length, SQLPOINTER pTarget, SQLINTEGER targetLength);
/// Utility function for conversion from UTF-16 to UTF-8.
inline void makeUTF8(Poco::Buffer<SQLWCHAR>& buffer, int length, SQLPOINTER pTarget, SQLSMALLINT targetLength)
/// Utility function for conversion from UTF-16 to UTF-8.
namespace Data
{
makeUTF8(buffer, length, pTarget, (SQLINTEGER) targetLength);
namespace ODBC
{
void makeUTF16(SQLCHAR * pSQLChar, SQLINTEGER length, std::string & target);
/// Utility function for conversion from UTF-8 to UTF-16
inline void makeUTF16(SQLCHAR * pSQLChar, SQLSMALLINT length, std::string & target)
/// Utility function for conversion from UTF-8 to UTF-16.
{
makeUTF16(pSQLChar, (SQLINTEGER)length, target);
}
void makeUTF8(Poco::Buffer<SQLWCHAR> & buffer, SQLINTEGER length, SQLPOINTER pTarget, SQLINTEGER targetLength);
/// Utility function for conversion from UTF-16 to UTF-8.
inline void makeUTF8(Poco::Buffer<SQLWCHAR> & buffer, int length, SQLPOINTER pTarget, SQLSMALLINT targetLength)
/// Utility function for conversion from UTF-16 to UTF-8.
{
makeUTF8(buffer, length, pTarget, (SQLINTEGER)targetLength);
}
}
}
} } } // namespace Poco::Data::ODBC
} // namespace Poco::Data::ODBC
#endif // Data_ODBC_Unicode_UNIX_INCLUDED

View File

@ -18,40 +18,45 @@
#define Data_ODBC_Unicode_WIN32_INCLUDED
namespace Poco {
namespace Data {
namespace ODBC {
inline void makeUTF16(SQLCHAR* pSQLChar, SQLINTEGER length, std::wstring& target)
/// Utility function for conversion from UTF-8 to UTF-16
namespace Poco
{
int len = length;
if (SQL_NTS == len)
len = (int) std::strlen((const char *) pSQLChar);
UnicodeConverter::toUTF16((const char *) pSQLChar, len, target);
}
inline void makeUTF8(Poco::Buffer<wchar_t>& buffer, SQLINTEGER length, SQLPOINTER pTarget, SQLINTEGER targetLength)
/// Utility function for conversion from UTF-16 to UTF-8. Length is in bytes.
namespace Data
{
if (buffer.sizeBytes() < length)
throw InvalidArgumentException("Specified length exceeds available length.");
else if ((length % 2) != 0)
throw InvalidArgumentException("Length must be an even number.");
namespace ODBC
{
length /= sizeof(wchar_t);
std::string result;
UnicodeConverter::toUTF8(buffer.begin(), length, result);
std::memset(pTarget, 0, targetLength);
std::strncpy((char*) pTarget, result.c_str(), result.size() < targetLength ? result.size() : targetLength);
inline void makeUTF16(SQLCHAR * pSQLChar, SQLINTEGER length, std::wstring & target)
/// Utility function for conversion from UTF-8 to UTF-16
{
int len = length;
if (SQL_NTS == len)
len = (int)std::strlen((const char *)pSQLChar);
UnicodeConverter::toUTF16((const char *)pSQLChar, len, target);
}
inline void makeUTF8(Poco::Buffer<wchar_t> & buffer, SQLINTEGER length, SQLPOINTER pTarget, SQLINTEGER targetLength)
/// Utility function for conversion from UTF-16 to UTF-8. Length is in bytes.
{
if (buffer.sizeBytes() < length)
throw InvalidArgumentException("Specified length exceeds available length.");
else if ((length % 2) != 0)
throw InvalidArgumentException("Length must be an even number.");
length /= sizeof(wchar_t);
std::string result;
UnicodeConverter::toUTF8(buffer.begin(), length, result);
std::memset(pTarget, 0, targetLength);
std::strncpy((char *)pTarget, result.c_str(), result.size() < targetLength ? result.size() : targetLength);
}
}
}
} } } // namespace Poco::Data::ODBC
} // namespace Poco::Data::ODBC
#endif // Data_ODBC_Unicode_WIN32_INCLUDED

View File

@ -18,190 +18,207 @@
#define Data_ODBC_Utility_INCLUDED
#include <map>
#include <sstream>
#include <sqltypes.h>
#include "Poco/Data/Date.h"
#include "Poco/Data/ODBC/ODBC.h"
#include "Poco/Data/ODBC/TypeInfo.h"
#include "Poco/Data/Date.h"
#include "Poco/Data/Time.h"
#include "Poco/DateTime.h"
#include <sstream>
#include <map>
#include <sqltypes.h>
namespace Poco {
namespace Data {
namespace ODBC {
class ODBC_API Utility
/// Various utility functions
namespace Poco
{
public:
typedef std::map<std::string, std::string> DSNMap;
typedef DSNMap DriverMap;
static bool isError(SQLRETURN rc);
/// Returns true if return code is error
static DriverMap& drivers(DriverMap& driverMap);
/// Returns driver-attributes map of available ODBC drivers.
static DSNMap& dataSources(DSNMap& dsnMap);
/// Returns DSN-description map of available ODBC data sources.
template<typename MapType, typename KeyArgType, typename ValueArgType>
static typename MapType::iterator mapInsert(MapType& m, const KeyArgType& k, const ValueArgType& v)
/// Utility map "insert or replace" function (from S. Meyers: Effective STL, Item 24)
{
typename MapType::iterator lb = m.lower_bound(k);
if (lb != m.end() && !(m.key_comp()(k, lb->first)))
{
lb->second = v;
return lb;
}
else
{
typedef typename MapType::value_type MVT;
return m.insert(lb, MVT(k,v));
}
}
static int cDataType(int sqlDataType);
/// Returns C data type corresponding to supplied SQL data type.
static int sqlDataType(int cDataType);
/// Returns SQL data type corresponding to supplied C data type.
static void dateSync(Date& dt, const SQL_DATE_STRUCT& ts);
/// Transfers data from ODBC SQL_DATE_STRUCT to Poco::DateTime.
template <typename T, typename F>
static void dateSync(T& d, const F& ds)
/// Transfers data from ODBC SQL_DATE_STRUCT container to Poco::DateTime container.
{
std::size_t size = ds.size();
if (d.size() != size) d.resize(size);
typename T::iterator dIt = d.begin();
typename F::const_iterator it = ds.begin();
typename F::const_iterator end = ds.end();
for (; it != end; ++it, ++dIt) dateSync(*dIt, *it);
}
static void timeSync(Time& dt, const SQL_TIME_STRUCT& ts);
/// Transfers data from ODBC SQL_TIME_STRUCT to Poco::DateTime.
template <typename T, typename F>
static void timeSync(T& t, const F& ts)
/// Transfers data from ODBC SQL_TIME_STRUCT container to Poco::DateTime container.
{
std::size_t size = ts.size();
if (t.size() != size) t.resize(size);
typename T::iterator dIt = t.begin();
typename F::const_iterator it = ts.begin();
typename F::const_iterator end = ts.end();
for (; it != end; ++it, ++dIt) timeSync(*dIt, *it);
}
static void dateTimeSync(Poco::DateTime& dt, const SQL_TIMESTAMP_STRUCT& ts);
/// Transfers data from ODBC SQL_TIMESTAMP_STRUCT to Poco::DateTime.
template <typename T, typename F>
static void dateTimeSync(T& dt, const F& ts)
/// Transfers data from ODBC SQL_TIMESTAMP_STRUCT container to Poco::DateTime container.
{
std::size_t size = ts.size();
if (dt.size() != size) dt.resize(size);
typename T::iterator dIt = dt.begin();
typename F::const_iterator it = ts.begin();
typename F::const_iterator end = ts.end();
for (; it != end; ++it, ++dIt) dateTimeSync(*dIt, *it);
}
static void dateSync(SQL_DATE_STRUCT& ts, const Date& dt);
/// Transfers data from Poco::Data::Date to ODBC SQL_DATE_STRUCT.
template <typename C>
static void dateSync(std::vector<SQL_DATE_STRUCT>& ds, const C& d)
/// Transfers data from Poco::Data::Date vector to ODBC SQL_DATE_STRUCT container.
{
std::size_t size = d.size();
if (ds.size() != size) ds.resize(size);
std::vector<SQL_DATE_STRUCT>::iterator dIt = ds.begin();
typename C::const_iterator it = d.begin();
typename C::const_iterator end = d.end();
for (; it != end; ++it, ++dIt) dateSync(*dIt, *it);
}
static void timeSync(SQL_TIME_STRUCT& ts, const Time& dt);
/// Transfers data from Poco::Data::Time to ODBC SQL_TIME_STRUCT.
template <typename C>
static void timeSync(std::vector<SQL_TIME_STRUCT>& ts, const C& t)
/// Transfers data from Poco::Data::Time container to ODBC SQL_TIME_STRUCT vector.
{
std::size_t size = t.size();
if (ts.size() != size) ts.resize(size);
std::vector<SQL_TIME_STRUCT>::iterator tIt = ts.begin();
typename C::const_iterator it = t.begin();
typename C::const_iterator end = t.end();
for (; it != end; ++it, ++tIt) timeSync(*tIt, *it);
}
static void dateTimeSync(SQL_TIMESTAMP_STRUCT& ts, const Poco::DateTime& dt);
/// Transfers data from Poco::DateTime to ODBC SQL_TIMESTAMP_STRUCT.
template <typename C>
static void dateTimeSync(std::vector<SQL_TIMESTAMP_STRUCT>& ts, const C& dt)
/// Transfers data from Poco::DateTime to ODBC SQL_TIMESTAMP_STRUCT.
{
std::size_t size = dt.size();
if (ts.size() != size) ts.resize(size);
std::vector<SQL_TIMESTAMP_STRUCT>::iterator tIt = ts.begin();
typename C::const_iterator it = dt.begin();
typename C::const_iterator end = dt.end();
for (; it != end; ++it, ++tIt) dateTimeSync(*tIt, *it);
}
private:
static const TypeInfo _dataTypes;
/// C <==> SQL data type mapping
};
///
/// inlines
///
inline bool Utility::isError(SQLRETURN rc)
namespace Data
{
return (0 != (rc & (~1)));
namespace ODBC
{
class ODBC_API Utility
/// Various utility functions
{
public:
typedef std::map<std::string, std::string> DSNMap;
typedef DSNMap DriverMap;
static bool isError(SQLRETURN rc);
/// Returns true if return code is error
static DriverMap & drivers(DriverMap & driverMap);
/// Returns driver-attributes map of available ODBC drivers.
static DSNMap & dataSources(DSNMap & dsnMap);
/// Returns DSN-description map of available ODBC data sources.
template <typename MapType, typename KeyArgType, typename ValueArgType>
static typename MapType::iterator mapInsert(MapType & m, const KeyArgType & k, const ValueArgType & v)
/// Utility map "insert or replace" function (from S. Meyers: Effective STL, Item 24)
{
typename MapType::iterator lb = m.lower_bound(k);
if (lb != m.end() && !(m.key_comp()(k, lb->first)))
{
lb->second = v;
return lb;
}
else
{
typedef typename MapType::value_type MVT;
return m.insert(lb, MVT(k, v));
}
}
static int cDataType(int sqlDataType);
/// Returns C data type corresponding to supplied SQL data type.
static int sqlDataType(int cDataType);
/// Returns SQL data type corresponding to supplied C data type.
static void dateSync(Date & dt, const SQL_DATE_STRUCT & ts);
/// Transfers data from ODBC SQL_DATE_STRUCT to Poco::DateTime.
template <typename T, typename F>
static void dateSync(T & d, const F & ds)
/// Transfers data from ODBC SQL_DATE_STRUCT container to Poco::DateTime container.
{
std::size_t size = ds.size();
if (d.size() != size)
d.resize(size);
typename T::iterator dIt = d.begin();
typename F::const_iterator it = ds.begin();
typename F::const_iterator end = ds.end();
for (; it != end; ++it, ++dIt)
dateSync(*dIt, *it);
}
static void timeSync(Time & dt, const SQL_TIME_STRUCT & ts);
/// Transfers data from ODBC SQL_TIME_STRUCT to Poco::DateTime.
template <typename T, typename F>
static void timeSync(T & t, const F & ts)
/// Transfers data from ODBC SQL_TIME_STRUCT container to Poco::DateTime container.
{
std::size_t size = ts.size();
if (t.size() != size)
t.resize(size);
typename T::iterator dIt = t.begin();
typename F::const_iterator it = ts.begin();
typename F::const_iterator end = ts.end();
for (; it != end; ++it, ++dIt)
timeSync(*dIt, *it);
}
static void dateTimeSync(Poco::DateTime & dt, const SQL_TIMESTAMP_STRUCT & ts);
/// Transfers data from ODBC SQL_TIMESTAMP_STRUCT to Poco::DateTime.
template <typename T, typename F>
static void dateTimeSync(T & dt, const F & ts)
/// Transfers data from ODBC SQL_TIMESTAMP_STRUCT container to Poco::DateTime container.
{
std::size_t size = ts.size();
if (dt.size() != size)
dt.resize(size);
typename T::iterator dIt = dt.begin();
typename F::const_iterator it = ts.begin();
typename F::const_iterator end = ts.end();
for (; it != end; ++it, ++dIt)
dateTimeSync(*dIt, *it);
}
static void dateSync(SQL_DATE_STRUCT & ts, const Date & dt);
/// Transfers data from Poco::Data::Date to ODBC SQL_DATE_STRUCT.
template <typename C>
static void dateSync(std::vector<SQL_DATE_STRUCT> & ds, const C & d)
/// Transfers data from Poco::Data::Date vector to ODBC SQL_DATE_STRUCT container.
{
std::size_t size = d.size();
if (ds.size() != size)
ds.resize(size);
std::vector<SQL_DATE_STRUCT>::iterator dIt = ds.begin();
typename C::const_iterator it = d.begin();
typename C::const_iterator end = d.end();
for (; it != end; ++it, ++dIt)
dateSync(*dIt, *it);
}
static void timeSync(SQL_TIME_STRUCT & ts, const Time & dt);
/// Transfers data from Poco::Data::Time to ODBC SQL_TIME_STRUCT.
template <typename C>
static void timeSync(std::vector<SQL_TIME_STRUCT> & ts, const C & t)
/// Transfers data from Poco::Data::Time container to ODBC SQL_TIME_STRUCT vector.
{
std::size_t size = t.size();
if (ts.size() != size)
ts.resize(size);
std::vector<SQL_TIME_STRUCT>::iterator tIt = ts.begin();
typename C::const_iterator it = t.begin();
typename C::const_iterator end = t.end();
for (; it != end; ++it, ++tIt)
timeSync(*tIt, *it);
}
static void dateTimeSync(SQL_TIMESTAMP_STRUCT & ts, const Poco::DateTime & dt);
/// Transfers data from Poco::DateTime to ODBC SQL_TIMESTAMP_STRUCT.
template <typename C>
static void dateTimeSync(std::vector<SQL_TIMESTAMP_STRUCT> & ts, const C & dt)
/// Transfers data from Poco::DateTime to ODBC SQL_TIMESTAMP_STRUCT.
{
std::size_t size = dt.size();
if (ts.size() != size)
ts.resize(size);
std::vector<SQL_TIMESTAMP_STRUCT>::iterator tIt = ts.begin();
typename C::const_iterator it = dt.begin();
typename C::const_iterator end = dt.end();
for (; it != end; ++it, ++tIt)
dateTimeSync(*tIt, *it);
}
private:
static const TypeInfo _dataTypes;
/// C <==> SQL data type mapping
};
///
/// inlines
///
inline bool Utility::isError(SQLRETURN rc)
{
return (0 != (rc & (~1)));
}
inline int Utility::cDataType(int sqlDataType)
{
return _dataTypes.cDataType(sqlDataType);
}
inline int Utility::sqlDataType(int cDataType)
{
return _dataTypes.sqlDataType(cDataType);
}
inline void Utility::dateSync(Date & d, const SQL_DATE_STRUCT & ts)
{
d.assign(ts.year, ts.month, ts.day);
}
inline void Utility::timeSync(Time & t, const SQL_TIME_STRUCT & ts)
{
t.assign(ts.hour, ts.minute, ts.second);
}
}
}
inline int Utility::cDataType(int sqlDataType)
{
return _dataTypes.cDataType(sqlDataType);
}
inline int Utility::sqlDataType(int cDataType)
{
return _dataTypes.sqlDataType(cDataType);
}
inline void Utility::dateSync(Date& d, const SQL_DATE_STRUCT& ts)
{
d.assign(ts.year, ts.month, ts.day);
}
inline void Utility::timeSync(Time& t, const SQL_TIME_STRUCT& ts)
{
t.assign(ts.hour, ts.minute, ts.second);
}
} } } // namespace Poco::Data::ODBC
} // namespace Poco::Data::ODBC
#endif

View File

@ -382,7 +382,7 @@ std::string ODBCStatementImpl::nativeSQL()
delete [] pNative;
throw ConnectionException(_rConnection, "SQLNativeSql()");
}
++retlen;//accomodate for terminating '\0'
++retlen;//accommodate for terminating '\0'
}while (retlen > length);
std::string sql(pNative);

View File

@ -156,7 +156,7 @@ std::size_t Preparator::maxDataSize(std::size_t pos) const
ODBCMetaColumn mc(_rStmt, pos);
sz = mc.length();
// accomodate for terminating zero (non-bulk only!)
// accommodate for terminating zero (non-bulk only!)
MetaColumn::ColumnDataType type = mc.type();
if (!isBulk() && ((ODBCMetaColumn::FDT_WSTRING == type) || (ODBCMetaColumn::FDT_STRING == type))) ++sz;
}

View File

@ -18,356 +18,360 @@
#define Data_AbstractBinder_INCLUDED
#include "Poco/Data/Data.h"
#include "Poco/Data/Date.h"
#include "Poco/Data/Time.h"
#include "Poco/Data/LOB.h"
#include "Poco/DateTime.h"
#include "Poco/Nullable.h"
#include "Poco/Any.h"
#include "Poco/Dynamic/Var.h"
#include "Poco/UTFString.h"
#include <vector>
#include <cstddef>
#include <deque>
#include <list>
#include <cstddef>
#include <vector>
#include "Poco/Any.h"
#include "Poco/Data/Data.h"
#include "Poco/Data/Date.h"
#include "Poco/Data/LOB.h"
#include "Poco/Data/Time.h"
#include "Poco/DateTime.h"
#include "Poco/Dynamic/Var.h"
#include "Poco/Nullable.h"
#include "Poco/UTFString.h"
namespace Poco {
namespace Data {
typedef NullType NullData;
namespace Keywords {
static const NullData null = NULL_GENERIC;
} // namespace Keywords
class Data_API AbstractBinder
/// Interface for Binding data types to placeholders.
namespace Poco
{
namespace Data
{
public:
typedef SharedPtr<AbstractBinder> Ptr;
enum Direction
/// Binding direction for a parameter.
{
PD_IN,
PD_OUT,
PD_IN_OUT
};
AbstractBinder();
/// Creates the AbstractBinder.
typedef NullType NullData;
virtual ~AbstractBinder();
/// Destroys the AbstractBinder.
virtual void bind(std::size_t pos, const Poco::Int8& val, Direction dir = PD_IN) = 0;
/// Binds an Int8.
namespace Keywords
{
virtual void bind(std::size_t pos, const std::vector<Poco::Int8>& val, Direction dir = PD_IN);
/// Binds an Int8 vector.
virtual void bind(std::size_t pos, const std::deque<Poco::Int8>& val, Direction dir = PD_IN);
/// Binds an Int8 deque.
static const NullData null = NULL_GENERIC;
virtual void bind(std::size_t pos, const std::list<Poco::Int8>& val, Direction dir = PD_IN);
/// Binds an Int8 list.
virtual void bind(std::size_t pos, const Poco::UInt8& val, Direction dir = PD_IN) = 0;
/// Binds an UInt8.
} // namespace Keywords
virtual void bind(std::size_t pos, const std::vector<Poco::UInt8>& val, Direction dir = PD_IN);
/// Binds an UInt8 vector.
virtual void bind(std::size_t pos, const std::deque<Poco::UInt8>& val, Direction dir = PD_IN);
/// Binds an UInt8 deque.
class Data_API AbstractBinder
/// Interface for Binding data types to placeholders.
{
public:
typedef SharedPtr<AbstractBinder> Ptr;
virtual void bind(std::size_t pos, const std::list<Poco::UInt8>& val, Direction dir = PD_IN);
/// Binds an UInt8 list.
enum Direction
/// Binding direction for a parameter.
{
PD_IN,
PD_OUT,
PD_IN_OUT
};
virtual void bind(std::size_t pos, const Poco::Int16& val, Direction dir = PD_IN) = 0;
/// Binds an Int16.
AbstractBinder();
/// Creates the AbstractBinder.
virtual void bind(std::size_t pos, const std::vector<Poco::Int16>& val, Direction dir = PD_IN);
/// Binds an Int16 vector.
virtual ~AbstractBinder();
/// Destroys the AbstractBinder.
virtual void bind(std::size_t pos, const std::deque<Poco::Int16>& val, Direction dir = PD_IN);
/// Binds an Int16 deque.
virtual void bind(std::size_t pos, const Poco::Int8 & val, Direction dir = PD_IN) = 0;
/// Binds an Int8.
virtual void bind(std::size_t pos, const std::list<Poco::Int16>& val, Direction dir = PD_IN);
/// Binds an Int16 list.
virtual void bind(std::size_t pos, const std::vector<Poco::Int8> & val, Direction dir = PD_IN);
/// Binds an Int8 vector.
virtual void bind(std::size_t pos, const Poco::UInt16& val, Direction dir = PD_IN) = 0;
/// Binds an UInt16.
virtual void bind(std::size_t pos, const std::deque<Poco::Int8> & val, Direction dir = PD_IN);
/// Binds an Int8 deque.
virtual void bind(std::size_t pos, const std::vector<Poco::UInt16>& val, Direction dir = PD_IN);
/// Binds an UInt16 vector.
virtual void bind(std::size_t pos, const std::list<Poco::Int8> & val, Direction dir = PD_IN);
/// Binds an Int8 list.
virtual void bind(std::size_t pos, const std::deque<Poco::UInt16>& val, Direction dir = PD_IN);
/// Binds an UInt16 deque.
virtual void bind(std::size_t pos, const Poco::UInt8 & val, Direction dir = PD_IN) = 0;
/// Binds an UInt8.
virtual void bind(std::size_t pos, const std::list<Poco::UInt16>& val, Direction dir = PD_IN);
/// Binds an UInt16 list.
virtual void bind(std::size_t pos, const std::vector<Poco::UInt8> & val, Direction dir = PD_IN);
/// Binds an UInt8 vector.
virtual void bind(std::size_t pos, const Poco::Int32& val, Direction dir = PD_IN) = 0;
/// Binds an Int32.
virtual void bind(std::size_t pos, const std::deque<Poco::UInt8> & val, Direction dir = PD_IN);
/// Binds an UInt8 deque.
virtual void bind(std::size_t pos, const std::vector<Poco::Int32>& val, Direction dir = PD_IN);
/// Binds an Int32 vector.
virtual void bind(std::size_t pos, const std::list<Poco::UInt8> & val, Direction dir = PD_IN);
/// Binds an UInt8 list.
virtual void bind(std::size_t pos, const std::deque<Poco::Int32>& val, Direction dir = PD_IN);
/// Binds an Int32 deque.
virtual void bind(std::size_t pos, const Poco::Int16 & val, Direction dir = PD_IN) = 0;
/// Binds an Int16.
virtual void bind(std::size_t pos, const std::list<Poco::Int32>& val, Direction dir = PD_IN);
/// Binds an Int32 list.
virtual void bind(std::size_t pos, const std::vector<Poco::Int16> & val, Direction dir = PD_IN);
/// Binds an Int16 vector.
virtual void bind(std::size_t pos, const Poco::UInt32& val, Direction dir = PD_IN) = 0;
/// Binds an UInt32.
virtual void bind(std::size_t pos, const std::deque<Poco::Int16> & val, Direction dir = PD_IN);
/// Binds an Int16 deque.
virtual void bind(std::size_t pos, const std::vector<Poco::UInt32>& val, Direction dir = PD_IN);
/// Binds an UInt32 vector.
virtual void bind(std::size_t pos, const std::list<Poco::Int16> & val, Direction dir = PD_IN);
/// Binds an Int16 list.
virtual void bind(std::size_t pos, const std::deque<Poco::UInt32>& val, Direction dir = PD_IN);
/// Binds an UInt32 deque.
virtual void bind(std::size_t pos, const Poco::UInt16 & val, Direction dir = PD_IN) = 0;
/// Binds an UInt16.
virtual void bind(std::size_t pos, const std::list<Poco::UInt32>& val, Direction dir = PD_IN);
/// Binds an UInt32 list.
virtual void bind(std::size_t pos, const Poco::Int64& val, Direction dir = PD_IN) = 0;
/// Binds an Int64.
virtual void bind(std::size_t pos, const std::vector<Poco::UInt16> & val, Direction dir = PD_IN);
/// Binds an UInt16 vector.
virtual void bind(std::size_t pos, const std::vector<Poco::Int64>& val, Direction dir = PD_IN);
/// Binds an Int64 vector.
virtual void bind(std::size_t pos, const std::deque<Poco::UInt16> & val, Direction dir = PD_IN);
/// Binds an UInt16 deque.
virtual void bind(std::size_t pos, const std::deque<Poco::Int64>& val, Direction dir = PD_IN);
/// Binds an Int64 deque.
virtual void bind(std::size_t pos, const std::list<Poco::UInt16> & val, Direction dir = PD_IN);
/// Binds an UInt16 list.
virtual void bind(std::size_t pos, const std::list<Poco::Int64>& val, Direction dir = PD_IN);
/// Binds an Int64 list.
virtual void bind(std::size_t pos, const Poco::Int32 & val, Direction dir = PD_IN) = 0;
/// Binds an Int32.
virtual void bind(std::size_t pos, const Poco::UInt64& val, Direction dir = PD_IN) = 0;
/// Binds an UInt64.
virtual void bind(std::size_t pos, const std::vector<Poco::Int32> & val, Direction dir = PD_IN);
/// Binds an Int32 vector.
virtual void bind(std::size_t pos, const std::vector<Poco::UInt64>& val, Direction dir = PD_IN);
/// Binds an UInt64 vector.
virtual void bind(std::size_t pos, const std::deque<Poco::Int32> & val, Direction dir = PD_IN);
/// Binds an Int32 deque.
virtual void bind(std::size_t pos, const std::deque<Poco::UInt64>& val, Direction dir = PD_IN);
/// Binds an UInt64 deque.
virtual void bind(std::size_t pos, const std::list<Poco::Int32> & val, Direction dir = PD_IN);
/// Binds an Int32 list.
virtual void bind(std::size_t pos, const std::list<Poco::UInt64>& val, Direction dir = PD_IN);
/// Binds an UInt64 list.
virtual void bind(std::size_t pos, const Poco::UInt32 & val, Direction dir = PD_IN) = 0;
/// Binds an UInt32.
virtual void bind(std::size_t pos, const std::vector<Poco::UInt32> & val, Direction dir = PD_IN);
/// Binds an UInt32 vector.
virtual void bind(std::size_t pos, const std::deque<Poco::UInt32> & val, Direction dir = PD_IN);
/// Binds an UInt32 deque.
virtual void bind(std::size_t pos, const std::list<Poco::UInt32> & val, Direction dir = PD_IN);
/// Binds an UInt32 list.
virtual void bind(std::size_t pos, const Poco::Int64 & val, Direction dir = PD_IN) = 0;
/// Binds an Int64.
virtual void bind(std::size_t pos, const std::vector<Poco::Int64> & val, Direction dir = PD_IN);
/// Binds an Int64 vector.
virtual void bind(std::size_t pos, const std::deque<Poco::Int64> & val, Direction dir = PD_IN);
/// Binds an Int64 deque.
virtual void bind(std::size_t pos, const std::list<Poco::Int64> & val, Direction dir = PD_IN);
/// Binds an Int64 list.
virtual void bind(std::size_t pos, const Poco::UInt64 & val, Direction dir = PD_IN) = 0;
/// Binds an UInt64.
virtual void bind(std::size_t pos, const std::vector<Poco::UInt64> & val, Direction dir = PD_IN);
/// Binds an UInt64 vector.
virtual void bind(std::size_t pos, const std::deque<Poco::UInt64> & val, Direction dir = PD_IN);
/// Binds an UInt64 deque.
virtual void bind(std::size_t pos, const std::list<Poco::UInt64> & val, Direction dir = PD_IN);
/// Binds an UInt64 list.
#ifndef POCO_LONG_IS_64_BIT
virtual void bind(std::size_t pos, const long& val, Direction dir = PD_IN) = 0;
/// Binds a long.
virtual void bind(std::size_t pos, const long & val, Direction dir = PD_IN) = 0;
/// Binds a long.
virtual void bind(std::size_t pos, const unsigned long& val, Direction dir = PD_IN) = 0;
/// Binds an unsiged long.
virtual void bind(std::size_t pos, const unsigned long & val, Direction dir = PD_IN) = 0;
/// Binds an unsigned long.
virtual void bind(std::size_t pos, const std::vector<long>& val, Direction dir = PD_IN);
/// Binds a long vector.
virtual void bind(std::size_t pos, const std::vector<long> & val, Direction dir = PD_IN);
/// Binds a long vector.
virtual void bind(std::size_t pos, const std::deque<long>& val, Direction dir = PD_IN);
/// Binds a long deque.
virtual void bind(std::size_t pos, const std::deque<long> & val, Direction dir = PD_IN);
/// Binds a long deque.
virtual void bind(std::size_t pos, const std::list<long>& val, Direction dir = PD_IN);
/// Binds a long list.
virtual void bind(std::size_t pos, const std::list<long> & val, Direction dir = PD_IN);
/// Binds a long list.
#endif
virtual void bind(std::size_t pos, const bool& val, Direction dir = PD_IN) = 0;
/// Binds a boolean.
virtual void bind(std::size_t pos, const bool & val, Direction dir = PD_IN) = 0;
/// Binds a boolean.
virtual void bind(std::size_t pos, const std::vector<bool>& val, Direction dir = PD_IN);
/// Binds a boolean vector.
virtual void bind(std::size_t pos, const std::vector<bool> & val, Direction dir = PD_IN);
/// Binds a boolean vector.
virtual void bind(std::size_t pos, const std::deque<bool>& val, Direction dir = PD_IN);
/// Binds a boolean deque.
virtual void bind(std::size_t pos, const std::deque<bool> & val, Direction dir = PD_IN);
/// Binds a boolean deque.
virtual void bind(std::size_t pos, const std::list<bool>& val, Direction dir = PD_IN);
/// Binds a boolean list.
virtual void bind(std::size_t pos, const std::list<bool> & val, Direction dir = PD_IN);
/// Binds a boolean list.
virtual void bind(std::size_t pos, const float& val, Direction dir = PD_IN) = 0;
/// Binds a float.
virtual void bind(std::size_t pos, const float & val, Direction dir = PD_IN) = 0;
/// Binds a float.
virtual void bind(std::size_t pos, const std::vector<float>& val, Direction dir = PD_IN);
/// Binds a float vector.
virtual void bind(std::size_t pos, const std::vector<float> & val, Direction dir = PD_IN);
/// Binds a float vector.
virtual void bind(std::size_t pos, const std::deque<float>& val, Direction dir = PD_IN);
/// Binds a float deque.
virtual void bind(std::size_t pos, const std::deque<float> & val, Direction dir = PD_IN);
/// Binds a float deque.
virtual void bind(std::size_t pos, const std::list<float>& val, Direction dir = PD_IN);
/// Binds a float list.
virtual void bind(std::size_t pos, const std::list<float> & val, Direction dir = PD_IN);
/// Binds a float list.
virtual void bind(std::size_t pos, const double& val, Direction dir = PD_IN) = 0;
/// Binds a double.
virtual void bind(std::size_t pos, const double & val, Direction dir = PD_IN) = 0;
/// Binds a double.
virtual void bind(std::size_t pos, const std::vector<double>& val, Direction dir = PD_IN);
/// Binds a double vector.
virtual void bind(std::size_t pos, const std::vector<double> & val, Direction dir = PD_IN);
/// Binds a double vector.
virtual void bind(std::size_t pos, const std::deque<double>& val, Direction dir = PD_IN);
/// Binds a double deque.
virtual void bind(std::size_t pos, const std::deque<double> & val, Direction dir = PD_IN);
/// Binds a double deque.
virtual void bind(std::size_t pos, const std::list<double>& val, Direction dir = PD_IN);
/// Binds a double list.
virtual void bind(std::size_t pos, const std::list<double> & val, Direction dir = PD_IN);
/// Binds a double list.
virtual void bind(std::size_t pos, const char& val, Direction dir = PD_IN) = 0;
/// Binds a single character.
virtual void bind(std::size_t pos, const char & val, Direction dir = PD_IN) = 0;
/// Binds a single character.
virtual void bind(std::size_t pos, const std::vector<char>& val, Direction dir = PD_IN);
/// Binds a character vector.
virtual void bind(std::size_t pos, const std::vector<char> & val, Direction dir = PD_IN);
/// Binds a character vector.
virtual void bind(std::size_t pos, const std::deque<char>& val, Direction dir = PD_IN);
/// Binds a character deque.
virtual void bind(std::size_t pos, const std::deque<char> & val, Direction dir = PD_IN);
/// Binds a character deque.
virtual void bind(std::size_t pos, const std::list<char>& val, Direction dir = PD_IN);
/// Binds a character list.
virtual void bind(std::size_t pos, const std::list<char> & val, Direction dir = PD_IN);
/// Binds a character list.
virtual void bind(std::size_t pos, const char* const& pVal, Direction dir = PD_IN) = 0;
/// Binds a const char ptr.
virtual void bind(std::size_t pos, const char * const & pVal, Direction dir = PD_IN) = 0;
/// Binds a const char ptr.
virtual void bind(std::size_t pos, const std::string& val, Direction dir = PD_IN) = 0;
/// Binds a string.
virtual void bind(std::size_t pos, const std::string & val, Direction dir = PD_IN) = 0;
/// Binds a string.
virtual void bind(std::size_t pos, const std::vector<std::string>& val, Direction dir = PD_IN);
/// Binds a string vector.
virtual void bind(std::size_t pos, const std::vector<std::string> & val, Direction dir = PD_IN);
/// Binds a string vector.
virtual void bind(std::size_t pos, const std::deque<std::string>& val, Direction dir = PD_IN);
/// Binds a string deque.
virtual void bind(std::size_t pos, const std::deque<std::string> & val, Direction dir = PD_IN);
/// Binds a string deque.
virtual void bind(std::size_t pos, const std::list<std::string>& val, Direction dir = PD_IN);
/// Binds a string list.
virtual void bind(std::size_t pos, const std::list<std::string> & val, Direction dir = PD_IN);
/// Binds a string list.
virtual void bind(std::size_t pos, const UTF16String& val, Direction dir = PD_IN);
/// Binds a UTF-16 Unicode string.
virtual void bind(std::size_t pos, const UTF16String & val, Direction dir = PD_IN);
/// Binds a UTF-16 Unicode string.
virtual void bind(std::size_t pos, const std::vector<UTF16String>& val, Direction dir = PD_IN);
/// Binds a UTF-16 Unicode string vector.
virtual void bind(std::size_t pos, const std::vector<UTF16String> & val, Direction dir = PD_IN);
/// Binds a UTF-16 Unicode string vector.
virtual void bind(std::size_t pos, const std::deque<UTF16String>& val, Direction dir = PD_IN);
/// Binds a UTF-16 Unicode string deque.
virtual void bind(std::size_t pos, const std::deque<UTF16String> & val, Direction dir = PD_IN);
/// Binds a UTF-16 Unicode string deque.
virtual void bind(std::size_t pos, const std::list<UTF16String>& val, Direction dir = PD_IN);
/// Binds a UTF-16 Unicode string list.
virtual void bind(std::size_t pos, const std::list<UTF16String> & val, Direction dir = PD_IN);
/// Binds a UTF-16 Unicode string list.
virtual void bind(std::size_t pos, const BLOB& val, Direction dir = PD_IN) = 0;
/// Binds a BLOB.
virtual void bind(std::size_t pos, const BLOB & val, Direction dir = PD_IN) = 0;
/// Binds a BLOB.
virtual void bind(std::size_t pos, const CLOB& val, Direction dir = PD_IN) = 0;
/// Binds a CLOB.
virtual void bind(std::size_t pos, const CLOB & val, Direction dir = PD_IN) = 0;
/// Binds a CLOB.
virtual void bind(std::size_t pos, const std::vector<BLOB>& val, Direction dir = PD_IN);
/// Binds a BLOB vector.
virtual void bind(std::size_t pos, const std::vector<BLOB> & val, Direction dir = PD_IN);
/// Binds a BLOB vector.
virtual void bind(std::size_t pos, const std::deque<BLOB>& val, Direction dir = PD_IN);
/// Binds a BLOB deque.
virtual void bind(std::size_t pos, const std::deque<BLOB> & val, Direction dir = PD_IN);
/// Binds a BLOB deque.
virtual void bind(std::size_t pos, const std::list<BLOB>& val, Direction dir = PD_IN);
/// Binds a BLOB list.
virtual void bind(std::size_t pos, const std::list<BLOB> & val, Direction dir = PD_IN);
/// Binds a BLOB list.
virtual void bind(std::size_t pos, const std::vector<CLOB>& val, Direction dir = PD_IN);
/// Binds a CLOB vector.
virtual void bind(std::size_t pos, const std::vector<CLOB> & val, Direction dir = PD_IN);
/// Binds a CLOB vector.
virtual void bind(std::size_t pos, const std::deque<CLOB>& val, Direction dir = PD_IN);
/// Binds a CLOB deque.
virtual void bind(std::size_t pos, const std::deque<CLOB> & val, Direction dir = PD_IN);
/// Binds a CLOB deque.
virtual void bind(std::size_t pos, const std::list<CLOB>& val, Direction dir = PD_IN);
/// Binds a CLOB list.
virtual void bind(std::size_t pos, const std::list<CLOB> & val, Direction dir = PD_IN);
/// Binds a CLOB list.
virtual void bind(std::size_t pos, const DateTime& val, Direction dir = PD_IN) = 0;
/// Binds a DateTime.
virtual void bind(std::size_t pos, const DateTime & val, Direction dir = PD_IN) = 0;
/// Binds a DateTime.
virtual void bind(std::size_t pos, const std::vector<DateTime>& val, Direction dir = PD_IN);
/// Binds a DateTime vector.
virtual void bind(std::size_t pos, const std::vector<DateTime> & val, Direction dir = PD_IN);
/// Binds a DateTime vector.
virtual void bind(std::size_t pos, const std::deque<DateTime>& val, Direction dir = PD_IN);
/// Binds a DateTime deque.
virtual void bind(std::size_t pos, const std::deque<DateTime> & val, Direction dir = PD_IN);
/// Binds a DateTime deque.
virtual void bind(std::size_t pos, const std::list<DateTime>& val, Direction dir = PD_IN);
/// Binds a DateTime list.
virtual void bind(std::size_t pos, const std::list<DateTime> & val, Direction dir = PD_IN);
/// Binds a DateTime list.
virtual void bind(std::size_t pos, const Date& val, Direction dir = PD_IN) = 0;
/// Binds a Date.
virtual void bind(std::size_t pos, const Date & val, Direction dir = PD_IN) = 0;
/// Binds a Date.
virtual void bind(std::size_t pos, const std::vector<Date>& val, Direction dir = PD_IN);
/// Binds a Date vector.
virtual void bind(std::size_t pos, const std::vector<Date> & val, Direction dir = PD_IN);
/// Binds a Date vector.
virtual void bind(std::size_t pos, const std::deque<Date>& val, Direction dir = PD_IN);
/// Binds a Date deque.
virtual void bind(std::size_t pos, const std::deque<Date> & val, Direction dir = PD_IN);
/// Binds a Date deque.
virtual void bind(std::size_t pos, const std::list<Date>& val, Direction dir = PD_IN);
/// Binds a Date list.
virtual void bind(std::size_t pos, const std::list<Date> & val, Direction dir = PD_IN);
/// Binds a Date list.
virtual void bind(std::size_t pos, const Time& val, Direction dir = PD_IN) = 0;
/// Binds a Time.
virtual void bind(std::size_t pos, const Time & val, Direction dir = PD_IN) = 0;
/// Binds a Time.
virtual void bind(std::size_t pos, const std::vector<Time>& val, Direction dir = PD_IN);
/// Binds a Time vector.
virtual void bind(std::size_t pos, const std::vector<Time> & val, Direction dir = PD_IN);
/// Binds a Time vector.
virtual void bind(std::size_t pos, const std::deque<Time>& val, Direction dir = PD_IN);
/// Binds a Time deque.
virtual void bind(std::size_t pos, const std::deque<Time> & val, Direction dir = PD_IN);
/// Binds a Time deque.
virtual void bind(std::size_t pos, const std::list<Time>& val, Direction dir = PD_IN);
/// Binds a Time list.
virtual void bind(std::size_t pos, const std::list<Time> & val, Direction dir = PD_IN);
/// Binds a Time list.
virtual void bind(std::size_t pos, const NullData& val, Direction dir = PD_IN) = 0;
/// Binds a null.
virtual void bind(std::size_t pos, const NullData & val, Direction dir = PD_IN) = 0;
/// Binds a null.
virtual void bind(std::size_t pos, const std::vector<NullData>& val, Direction dir = PD_IN);
/// Binds a null vector.
virtual void bind(std::size_t pos, const std::vector<NullData> & val, Direction dir = PD_IN);
/// Binds a null vector.
virtual void bind(std::size_t pos, const std::deque<NullData>& val, Direction dir = PD_IN);
/// Binds a null deque.
virtual void bind(std::size_t pos, const std::deque<NullData> & val, Direction dir = PD_IN);
/// Binds a null deque.
virtual void bind(std::size_t pos, const std::list<NullData>& val, Direction dir = PD_IN);
/// Binds a null list.
virtual void bind(std::size_t pos, const std::list<NullData> & val, Direction dir = PD_IN);
/// Binds a null list.
void bind(std::size_t pos, const Any& val, Direction dir = PD_IN);
/// Binds an Any.
void bind(std::size_t pos, const Poco::Dynamic::Var& val, Direction dir = PD_IN);
/// Binds a Var.
void bind(std::size_t pos, const Any & val, Direction dir = PD_IN);
/// Binds an Any.
virtual void reset();
/// Resets a binder. No-op by default. Implement for binders that cache data.
void bind(std::size_t pos, const Poco::Dynamic::Var & val, Direction dir = PD_IN);
/// Binds a Var.
static bool isOutBound(Direction dir);
/// Returns true if direction is out bound;
virtual void reset();
/// Resets a binder. No-op by default. Implement for binders that cache data.
static bool isInBound(Direction dir);
/// Returns true if direction is in bound;
};
static bool isOutBound(Direction dir);
/// Returns true if direction is out bound;
static bool isInBound(Direction dir);
/// Returns true if direction is in bound;
};
//
// inlines
//
inline void AbstractBinder::reset()
{
//no-op
}
inline bool AbstractBinder::isOutBound(Direction dir)
{
return PD_OUT == dir || PD_IN_OUT == dir;
}
inline bool AbstractBinder::isInBound(Direction dir)
{
return PD_IN == dir || PD_IN_OUT == dir;
}
//
// inlines
//
inline void AbstractBinder::reset()
{
//no-op
}
inline bool AbstractBinder::isOutBound(Direction dir)
{
return PD_OUT == dir || PD_IN_OUT == dir;
}
inline bool AbstractBinder::isInBound(Direction dir)
{
return PD_IN == dir || PD_IN_OUT == dir;
}
} } // namespace Poco::Data
} // namespace Poco::Data
#endif // Data_AbstractBinder_INCLUDED

View File

@ -18,127 +18,130 @@
#define Data_AbstractBinding_INCLUDED
#include "Poco/Data/Data.h"
#include "Poco/Data/AbstractBinder.h"
#include "Poco/Any.h"
#include "Poco/RefCountedObject.h"
#include "Poco/AutoPtr.h"
#include <vector>
#include <list>
#include <deque>
#include <cstddef>
#include <deque>
#include <list>
#include <vector>
#include "Poco/Any.h"
#include "Poco/AutoPtr.h"
#include "Poco/Data/AbstractBinder.h"
#include "Poco/Data/Data.h"
#include "Poco/RefCountedObject.h"
namespace Poco {
namespace Data {
class Data_API AbstractBinding
/// AbstractBinding connects a value with a placeholder via an AbstractBinder interface.
namespace Poco
{
public:
typedef SharedPtr<AbstractBinding> Ptr;
typedef AbstractBinder::Ptr BinderPtr;
enum Direction
{
PD_IN = AbstractBinder::PD_IN,
PD_OUT = AbstractBinder::PD_OUT,
PD_IN_OUT = AbstractBinder::PD_IN_OUT
};
AbstractBinding(const std::string& name = "", Direction direction = PD_IN, Poco::UInt32 bulkSize = 0);
/// Creates the AbstractBinding.
virtual ~AbstractBinding();
/// Destroys the AbstractBinding.
void setBinder(BinderPtr pBinder);
/// Sets the object used for binding; object does NOT take ownership of the pointer.
BinderPtr getBinder() const;
/// Returns the AbstractBinder used for binding data.
virtual std::size_t numOfColumnsHandled() const = 0;
/// Returns the number of columns that the binding handles.
///
/// The trivial case will be one single column but when
/// complex types are used this value can be larger than one.
virtual std::size_t numOfRowsHandled() const = 0;
/// Returns the number of rows that the binding handles.
///
/// The trivial case will be one single row but
/// for collection data types it can be larger.
virtual bool canBind() const = 0;
/// Returns true if we have enough data to bind
virtual void bind(std::size_t pos) = 0;
/// Binds a value to the given column position
virtual void reset() = 0;
/// Allows a binding to be reused.
AbstractBinder::Direction getDirection() const;
/// Returns the binding direction.
const std::string& name() const;
/// Returns the name for this binding.
bool isBulk() const;
/// Returns true if extraction is bulk.
Poco::UInt32 bulkSize() const;
/// Returns the size of the bulk binding.
private:
BinderPtr _pBinder;
std::string _name;
Direction _direction;
Poco::UInt32 _bulkSize;
};
typedef std::vector<AbstractBinding::Ptr> AbstractBindingVec;
typedef std::deque<AbstractBinding::Ptr> AbstractBindingDeq;
typedef std::list<AbstractBinding::Ptr> AbstractBindingLst;
//
// inlines
//
inline AbstractBinder::Ptr AbstractBinding::getBinder() const
namespace Data
{
return _pBinder;
class Data_API AbstractBinding
/// AbstractBinding connects a value with a placeholder via an AbstractBinder interface.
{
public:
typedef SharedPtr<AbstractBinding> Ptr;
typedef AbstractBinder::Ptr BinderPtr;
enum Direction
{
PD_IN = AbstractBinder::PD_IN,
PD_OUT = AbstractBinder::PD_OUT,
PD_IN_OUT = AbstractBinder::PD_IN_OUT
};
AbstractBinding(const std::string & name = "", Direction direction = PD_IN, Poco::UInt32 bulkSize = 0);
/// Creates the AbstractBinding.
virtual ~AbstractBinding();
/// Destroys the AbstractBinding.
void setBinder(BinderPtr pBinder);
/// Sets the object used for binding; object does NOT take ownership of the pointer.
BinderPtr getBinder() const;
/// Returns the AbstractBinder used for binding data.
virtual std::size_t numOfColumnsHandled() const = 0;
/// Returns the number of columns that the binding handles.
///
/// The trivial case will be one single column but when
/// complex types are used this value can be larger than one.
virtual std::size_t numOfRowsHandled() const = 0;
/// Returns the number of rows that the binding handles.
///
/// The trivial case will be one single row but
/// for collection data types it can be larger.
virtual bool canBind() const = 0;
/// Returns true if we have enough data to bind
virtual void bind(std::size_t pos) = 0;
/// Binds a value to the given column position
virtual void reset() = 0;
/// Allows a binding to be reused.
AbstractBinder::Direction getDirection() const;
/// Returns the binding direction.
const std::string & name() const;
/// Returns the name for this binding.
bool isBulk() const;
/// Returns true if extraction is bulk.
Poco::UInt32 bulkSize() const;
/// Returns the size of the bulk binding.
private:
BinderPtr _pBinder;
std::string _name;
Direction _direction;
Poco::UInt32 _bulkSize;
};
typedef std::vector<AbstractBinding::Ptr> AbstractBindingVec;
typedef std::deque<AbstractBinding::Ptr> AbstractBindingDeq;
typedef std::list<AbstractBinding::Ptr> AbstractBindingLst;
//
// inlines
//
inline AbstractBinder::Ptr AbstractBinding::getBinder() const
{
return _pBinder;
}
inline const std::string & AbstractBinding::name() const
{
return _name;
}
inline AbstractBinder::Direction AbstractBinding::getDirection() const
{
return (AbstractBinder::Direction)_direction;
}
inline bool AbstractBinding::isBulk() const
{
return _bulkSize > 0;
}
inline Poco::UInt32 AbstractBinding::bulkSize() const
{
return _bulkSize;
}
}
inline const std::string& AbstractBinding::name() const
{
return _name;
}
inline AbstractBinder::Direction AbstractBinding::getDirection() const
{
return (AbstractBinder::Direction) _direction;
}
inline bool AbstractBinding::isBulk() const
{
return _bulkSize > 0;
}
inline Poco::UInt32 AbstractBinding::bulkSize() const
{
return _bulkSize;
}
} } // namespace Poco::Data
} // namespace Poco::Data
#endif // Data_AbstractBinding_INCLUDED

View File

@ -18,261 +18,264 @@
#define Data_AbstractExtraction_INCLUDED
#include "Poco/Data/Data.h"
#include <cstddef>
#include <deque>
#include <list>
#include <vector>
#include "Poco/AutoPtr.h"
#include "Poco/Data/AbstractExtractor.h"
#include "Poco/Data/AbstractPreparation.h"
#include "Poco/Data/Data.h"
#include "Poco/Data/Limit.h"
#include "Poco/RefCountedObject.h"
#include "Poco/UTFString.h"
#include "Poco/AutoPtr.h"
#include <vector>
#include <deque>
#include <list>
#include <cstddef>
namespace Poco {
namespace Data {
class AbstractPreparator;
class Data_API AbstractExtraction
/// AbstractExtraction is the interface class that connects output positions to concrete values
/// retrieved via an AbstractExtractor.
namespace Poco
{
public:
typedef SharedPtr<AbstractExtraction> Ptr;
typedef SharedPtr<AbstractExtractor> ExtractorPtr;
typedef SharedPtr<AbstractPreparator> PreparatorPtr;
AbstractExtraction(Poco::UInt32 limit = Limit::LIMIT_UNLIMITED,
Poco::UInt32 position = 0, bool bulk = false);
/// Creates the AbstractExtraction. A limit value equal to EXTRACT_UNLIMITED (0xffffffffu)
/// means that we extract as much data as possible during one execute.
/// Otherwise the limit value is used to partition data extracting to a limited amount of rows.
virtual ~AbstractExtraction();
/// Destroys the AbstractExtraction.
void setExtractor(ExtractorPtr pExtractor);
/// Sets the class used for extracting the data. Does not take ownership of the pointer.
ExtractorPtr getExtractor() const;
/// Retrieves the extractor object
Poco::UInt32 position() const;
/// Returns the extraction position.
virtual std::size_t numOfColumnsHandled() const = 0;
/// Returns the number of columns that the extraction handles.
///
/// The trivial case will be one single column but when
/// complex types are used this value can be larger than one.
virtual std::size_t numOfRowsHandled() const = 0;
/// Returns the number of rows that the extraction handles.
///
/// The trivial case will be one single row but
/// for collection data types (ie vector) it can be larger.
virtual std::size_t numOfRowsAllowed() const = 0;
/// Returns the upper limit on number of rows that the extraction will handle.
virtual std::size_t extract(std::size_t pos) = 0;
/// Extracts a value from the param, starting at the given column position.
/// Returns the number of rows extracted.
virtual void reset();
/// Resets the extractor so that it can be re-used.
/// Does nothing in this implementation.
/// Implementations should override it for different behavior.
virtual bool canExtract() const;
/// Returns true. Implementations should override it for different behavior.
virtual AbstractPreparation::Ptr createPreparation(PreparatorPtr& pPrep, std::size_t pos) = 0;
/// Creates and returns shared pointer to Preparation object for the extracting object.
void setLimit(Poco::UInt32 limit);
/// Sets the limit.
Poco::UInt32 getLimit() const;
/// Gets the limit.
virtual bool isNull(std::size_t row) const;
/// In implementations, this function returns true if value at row is null,
/// false otherwise.
/// Normal behavior is to replace nulls with default values.
/// However, extraction implementations may remember the underlying database
/// null values and be able to later provide information about them.
/// Here, this function throws NotImplementedException.
bool isBulk() const;
/// Returns true if this is bulk extraction.
void setEmptyStringIsNull(bool emptyStringIsNull);
/// Sets the empty string handling flag.
bool getEmptyStringIsNull() const;
/// Returns the empty string handling flag.
void setForceEmptyString(bool forceEmptyString);
/// Sets the force empty string flag.
bool getForceEmptyString() const;
/// Returns the force empty string flag.
template <typename T>
bool isValueNull(const T& str, bool deflt)
/// Utility function to determine the nullness of the value.
/// This generic version always returns default value
/// (i.e. does nothing). The std::string overload does
/// the actual work.
///
{
return deflt;
}
bool isValueNull(const std::string& str, bool deflt);
/// Overload for const reference to std::string.
///
/// Returns true when folowing conditions are met:
///
/// - string is empty
/// - getEmptyStringIsNull() returns true
bool isValueNull(const Poco::UTF16String& str, bool deflt);
/// Overload for const reference to UTF16String.
///
/// Returns true when folowing conditions are met:
///
/// - string is empty
/// - getEmptyStringIsNull() returns true
private:
template <typename S>
bool isStringNull(const S& str, bool deflt)
{
if (getForceEmptyString()) return false;
if (getEmptyStringIsNull() && str.empty())
return true;
return deflt;
}
ExtractorPtr _pExtractor;
Poco::UInt32 _limit;
Poco::UInt32 _position;
bool _bulk;
bool _emptyStringIsNull;
bool _forceEmptyString;
};
typedef std::vector<AbstractExtraction::Ptr> AbstractExtractionVec;
typedef std::vector<AbstractExtractionVec> AbstractExtractionVecVec;
typedef std::deque<AbstractExtraction::Ptr> AbstractExtractionDeq;
typedef std::vector<AbstractExtractionDeq> AbstractExtractionDeqVec;
typedef std::list<AbstractExtraction::Ptr> AbstractExtractionLst;
typedef std::vector<AbstractExtractionLst> AbstractExtractionLstVec;
//
// inlines
//
inline void AbstractExtraction::setExtractor(ExtractorPtr pExtractor)
namespace Data
{
_pExtractor = pExtractor;
class AbstractPreparator;
class Data_API AbstractExtraction
/// AbstractExtraction is the interface class that connects output positions to concrete values
/// retrieved via an AbstractExtractor.
{
public:
typedef SharedPtr<AbstractExtraction> Ptr;
typedef SharedPtr<AbstractExtractor> ExtractorPtr;
typedef SharedPtr<AbstractPreparator> PreparatorPtr;
AbstractExtraction(Poco::UInt32 limit = Limit::LIMIT_UNLIMITED, Poco::UInt32 position = 0, bool bulk = false);
/// Creates the AbstractExtraction. A limit value equal to EXTRACT_UNLIMITED (0xffffffffu)
/// means that we extract as much data as possible during one execute.
/// Otherwise the limit value is used to partition data extracting to a limited amount of rows.
virtual ~AbstractExtraction();
/// Destroys the AbstractExtraction.
void setExtractor(ExtractorPtr pExtractor);
/// Sets the class used for extracting the data. Does not take ownership of the pointer.
ExtractorPtr getExtractor() const;
/// Retrieves the extractor object
Poco::UInt32 position() const;
/// Returns the extraction position.
virtual std::size_t numOfColumnsHandled() const = 0;
/// Returns the number of columns that the extraction handles.
///
/// The trivial case will be one single column but when
/// complex types are used this value can be larger than one.
virtual std::size_t numOfRowsHandled() const = 0;
/// Returns the number of rows that the extraction handles.
///
/// The trivial case will be one single row but
/// for collection data types (ie vector) it can be larger.
virtual std::size_t numOfRowsAllowed() const = 0;
/// Returns the upper limit on number of rows that the extraction will handle.
virtual std::size_t extract(std::size_t pos) = 0;
/// Extracts a value from the param, starting at the given column position.
/// Returns the number of rows extracted.
virtual void reset();
/// Resets the extractor so that it can be re-used.
/// Does nothing in this implementation.
/// Implementations should override it for different behavior.
virtual bool canExtract() const;
/// Returns true. Implementations should override it for different behavior.
virtual AbstractPreparation::Ptr createPreparation(PreparatorPtr & pPrep, std::size_t pos) = 0;
/// Creates and returns shared pointer to Preparation object for the extracting object.
void setLimit(Poco::UInt32 limit);
/// Sets the limit.
Poco::UInt32 getLimit() const;
/// Gets the limit.
virtual bool isNull(std::size_t row) const;
/// In implementations, this function returns true if value at row is null,
/// false otherwise.
/// Normal behavior is to replace nulls with default values.
/// However, extraction implementations may remember the underlying database
/// null values and be able to later provide information about them.
/// Here, this function throws NotImplementedException.
bool isBulk() const;
/// Returns true if this is bulk extraction.
void setEmptyStringIsNull(bool emptyStringIsNull);
/// Sets the empty string handling flag.
bool getEmptyStringIsNull() const;
/// Returns the empty string handling flag.
void setForceEmptyString(bool forceEmptyString);
/// Sets the force empty string flag.
bool getForceEmptyString() const;
/// Returns the force empty string flag.
template <typename T>
bool isValueNull(const T & str, bool deflt)
/// Utility function to determine the nullness of the value.
/// This generic version always returns default value
/// (i.e. does nothing). The std::string overload does
/// the actual work.
///
{
return deflt;
}
bool isValueNull(const std::string & str, bool deflt);
/// Overload for const reference to std::string.
///
/// Returns true when following conditions are met:
///
/// - string is empty
/// - getEmptyStringIsNull() returns true
bool isValueNull(const Poco::UTF16String & str, bool deflt);
/// Overload for const reference to UTF16String.
///
/// Returns true when following conditions are met:
///
/// - string is empty
/// - getEmptyStringIsNull() returns true
private:
template <typename S>
bool isStringNull(const S & str, bool deflt)
{
if (getForceEmptyString())
return false;
if (getEmptyStringIsNull() && str.empty())
return true;
return deflt;
}
ExtractorPtr _pExtractor;
Poco::UInt32 _limit;
Poco::UInt32 _position;
bool _bulk;
bool _emptyStringIsNull;
bool _forceEmptyString;
};
typedef std::vector<AbstractExtraction::Ptr> AbstractExtractionVec;
typedef std::vector<AbstractExtractionVec> AbstractExtractionVecVec;
typedef std::deque<AbstractExtraction::Ptr> AbstractExtractionDeq;
typedef std::vector<AbstractExtractionDeq> AbstractExtractionDeqVec;
typedef std::list<AbstractExtraction::Ptr> AbstractExtractionLst;
typedef std::vector<AbstractExtractionLst> AbstractExtractionLstVec;
//
// inlines
//
inline void AbstractExtraction::setExtractor(ExtractorPtr pExtractor)
{
_pExtractor = pExtractor;
}
inline AbstractExtraction::ExtractorPtr AbstractExtraction::getExtractor() const
{
return _pExtractor;
}
inline void AbstractExtraction::setLimit(Poco::UInt32 limit)
{
_limit = limit;
}
inline Poco::UInt32 AbstractExtraction::getLimit() const
{
return _limit;
}
inline bool AbstractExtraction::isNull(std::size_t row) const
{
throw NotImplementedException("Check for null values not implemented.");
}
inline Poco::UInt32 AbstractExtraction::position() const
{
return _position;
}
inline bool AbstractExtraction::isBulk() const
{
return _bulk;
}
inline void AbstractExtraction::reset()
{
}
inline bool AbstractExtraction::canExtract() const
{
return true;
}
inline void AbstractExtraction::setEmptyStringIsNull(bool emptyStringIsNull)
{
_emptyStringIsNull = emptyStringIsNull;
}
inline bool AbstractExtraction::getEmptyStringIsNull() const
{
return _emptyStringIsNull;
}
inline void AbstractExtraction::setForceEmptyString(bool forceEmptyString)
{
_forceEmptyString = forceEmptyString;
}
inline bool AbstractExtraction::getForceEmptyString() const
{
return _forceEmptyString;
}
inline bool AbstractExtraction::isValueNull(const std::string & str, bool deflt)
{
return isStringNull(str, deflt);
}
inline bool AbstractExtraction::isValueNull(const Poco::UTF16String & str, bool deflt)
{
return isStringNull(str, deflt);
}
}
inline AbstractExtraction::ExtractorPtr AbstractExtraction::getExtractor() const
{
return _pExtractor;
}
inline void AbstractExtraction::setLimit(Poco::UInt32 limit)
{
_limit = limit;
}
inline Poco::UInt32 AbstractExtraction::getLimit() const
{
return _limit;
}
inline bool AbstractExtraction::isNull(std::size_t row) const
{
throw NotImplementedException("Check for null values not implemented.");
}
inline Poco::UInt32 AbstractExtraction::position() const
{
return _position;
}
inline bool AbstractExtraction::isBulk() const
{
return _bulk;
}
inline void AbstractExtraction::reset()
{
}
inline bool AbstractExtraction::canExtract() const
{
return true;
}
inline void AbstractExtraction::setEmptyStringIsNull(bool emptyStringIsNull)
{
_emptyStringIsNull = emptyStringIsNull;
}
inline bool AbstractExtraction::getEmptyStringIsNull() const
{
return _emptyStringIsNull;
}
inline void AbstractExtraction::setForceEmptyString(bool forceEmptyString)
{
_forceEmptyString = forceEmptyString;
}
inline bool AbstractExtraction::getForceEmptyString() const
{
return _forceEmptyString;
}
inline bool AbstractExtraction::isValueNull(const std::string& str, bool deflt)
{
return isStringNull(str, deflt);
}
inline bool AbstractExtraction::isValueNull(const Poco::UTF16String& str, bool deflt)
{
return isStringNull(str, deflt);
}
} } // namespace Poco::Data
} // namespace Poco::Data
#endif // Data_AbstractExtraction_INCLUDED

View File

@ -18,334 +18,338 @@
#define Data_AbstractExtractor_INCLUDED
#include "Poco/Data/Data.h"
#include "Poco/Data/Constants.h"
#include "Poco/Data/LOB.h"
#include "Poco/UTFString.h"
#include <vector>
#include <cstddef>
#include <deque>
#include <list>
#include <string>
#include <cstddef>
#include <vector>
#include "Poco/Data/Constants.h"
#include "Poco/Data/Data.h"
#include "Poco/Data/LOB.h"
#include "Poco/UTFString.h"
namespace Poco {
namespace Poco
{
class DateTime;
class Any;
namespace Dynamic {
class Var;
namespace Dynamic
{
class Var;
}
namespace Data {
class Date;
class Time;
class Data_API AbstractExtractor
/// Interface used to extract data from a single result row.
/// If an extractor receives null it is not allowed to change val!
namespace Data
{
public:
typedef SharedPtr<AbstractExtractor> Ptr;
AbstractExtractor();
/// Creates the AbstractExtractor.
virtual ~AbstractExtractor();
/// Destroys the AbstractExtractor.
class Date;
class Time;
virtual bool extract(std::size_t pos, Poco::Int8& val) = 0;
/// Extracts an Int8. Returns false if null was received.
virtual bool extract(std::size_t pos, std::vector<Poco::Int8>& val);
/// Extracts an Int8 vector.
class Data_API AbstractExtractor
/// Interface used to extract data from a single result row.
/// If an extractor receives null it is not allowed to change val!
{
public:
typedef SharedPtr<AbstractExtractor> Ptr;
virtual bool extract(std::size_t pos, std::deque<Poco::Int8>& val);
/// Extracts an Int8 deque.
AbstractExtractor();
/// Creates the AbstractExtractor.
virtual bool extract(std::size_t pos, std::list<Poco::Int8>& val);
/// Extracts an Int8 list.
virtual ~AbstractExtractor();
/// Destroys the AbstractExtractor.
virtual bool extract(std::size_t pos, Poco::UInt8& val) = 0;
/// Extracts an UInt8. Returns false if null was received.
virtual bool extract(std::size_t pos, Poco::Int8 & val) = 0;
/// Extracts an Int8. Returns false if null was received.
virtual bool extract(std::size_t pos, std::vector<Poco::UInt8>& val);
/// Extracts an UInt8 vector.
virtual bool extract(std::size_t pos, std::vector<Poco::Int8> & val);
/// Extracts an Int8 vector.
virtual bool extract(std::size_t pos, std::deque<Poco::UInt8>& val);
/// Extracts an UInt8 deque.
virtual bool extract(std::size_t pos, std::deque<Poco::Int8> & val);
/// Extracts an Int8 deque.
virtual bool extract(std::size_t pos, std::list<Poco::UInt8>& val);
/// Extracts an UInt8 list.
virtual bool extract(std::size_t pos, std::list<Poco::Int8> & val);
/// Extracts an Int8 list.
virtual bool extract(std::size_t pos, Poco::Int16& val) = 0;
/// Extracts an Int16. Returns false if null was received.
virtual bool extract(std::size_t pos, Poco::UInt8 & val) = 0;
/// Extracts an UInt8. Returns false if null was received.
virtual bool extract(std::size_t pos, std::vector<Poco::Int16>& val);
/// Extracts an Int16 vector.
virtual bool extract(std::size_t pos, std::vector<Poco::UInt8> & val);
/// Extracts an UInt8 vector.
virtual bool extract(std::size_t pos, std::deque<Poco::Int16>& val);
/// Extracts an Int16 deque.
virtual bool extract(std::size_t pos, std::deque<Poco::UInt8> & val);
/// Extracts an UInt8 deque.
virtual bool extract(std::size_t pos, std::list<Poco::Int16>& val);
/// Extracts an Int16 list.
virtual bool extract(std::size_t pos, std::list<Poco::UInt8> & val);
/// Extracts an UInt8 list.
virtual bool extract(std::size_t pos, Poco::UInt16& val) = 0;
/// Extracts an UInt16. Returns false if null was received.
virtual bool extract(std::size_t pos, Poco::Int16 & val) = 0;
/// Extracts an Int16. Returns false if null was received.
virtual bool extract(std::size_t pos, std::vector<Poco::UInt16>& val);
/// Extracts an UInt16 vector.
virtual bool extract(std::size_t pos, std::vector<Poco::Int16> & val);
/// Extracts an Int16 vector.
virtual bool extract(std::size_t pos, std::deque<Poco::UInt16>& val);
/// Extracts an UInt16 deque.
virtual bool extract(std::size_t pos, std::deque<Poco::Int16> & val);
/// Extracts an Int16 deque.
virtual bool extract(std::size_t pos, std::list<Poco::UInt16>& val);
/// Extracts an UInt16 list.
virtual bool extract(std::size_t pos, std::list<Poco::Int16> & val);
/// Extracts an Int16 list.
virtual bool extract(std::size_t pos, Poco::Int32& val) = 0;
/// Extracts an Int32. Returns false if null was received.
virtual bool extract(std::size_t pos, Poco::UInt16 & val) = 0;
/// Extracts an UInt16. Returns false if null was received.
virtual bool extract(std::size_t pos, std::vector<Poco::Int32>& val);
/// Extracts an Int32 vector.
virtual bool extract(std::size_t pos, std::vector<Poco::UInt16> & val);
/// Extracts an UInt16 vector.
virtual bool extract(std::size_t pos, std::deque<Poco::Int32>& val);
/// Extracts an Int32 deque.
virtual bool extract(std::size_t pos, std::deque<Poco::UInt16> & val);
/// Extracts an UInt16 deque.
virtual bool extract(std::size_t pos, std::list<Poco::Int32>& val);
/// Extracts an Int32 list.
virtual bool extract(std::size_t pos, std::list<Poco::UInt16> & val);
/// Extracts an UInt16 list.
virtual bool extract(std::size_t pos, Poco::UInt32& val) = 0;
/// Extracts an UInt32. Returns false if null was received.
virtual bool extract(std::size_t pos, Poco::Int32 & val) = 0;
/// Extracts an Int32. Returns false if null was received.
virtual bool extract(std::size_t pos, std::vector<Poco::UInt32>& val);
/// Extracts an UInt32 vector.
virtual bool extract(std::size_t pos, std::vector<Poco::Int32> & val);
/// Extracts an Int32 vector.
virtual bool extract(std::size_t pos, std::deque<Poco::UInt32>& val);
/// Extracts an UInt32 deque.
virtual bool extract(std::size_t pos, std::deque<Poco::Int32> & val);
/// Extracts an Int32 deque.
virtual bool extract(std::size_t pos, std::list<Poco::UInt32>& val);
/// Extracts an UInt32 list.
virtual bool extract(std::size_t pos, std::list<Poco::Int32> & val);
/// Extracts an Int32 list.
virtual bool extract(std::size_t pos, Poco::Int64& val) = 0;
/// Extracts an Int64. Returns false if null was received.
virtual bool extract(std::size_t pos, Poco::UInt32 & val) = 0;
/// Extracts an UInt32. Returns false if null was received.
virtual bool extract(std::size_t pos, std::vector<Poco::Int64>& val);
/// Extracts an Int64 vector.
virtual bool extract(std::size_t pos, std::vector<Poco::UInt32> & val);
/// Extracts an UInt32 vector.
virtual bool extract(std::size_t pos, std::deque<Poco::Int64>& val);
/// Extracts an Int64 deque.
virtual bool extract(std::size_t pos, std::deque<Poco::UInt32> & val);
/// Extracts an UInt32 deque.
virtual bool extract(std::size_t pos, std::list<Poco::Int64>& val);
/// Extracts an Int64 list.
virtual bool extract(std::size_t pos, std::list<Poco::UInt32> & val);
/// Extracts an UInt32 list.
virtual bool extract(std::size_t pos, Poco::UInt64& val) = 0;
/// Extracts an UInt64. Returns false if null was received.
virtual bool extract(std::size_t pos, Poco::Int64 & val) = 0;
/// Extracts an Int64. Returns false if null was received.
virtual bool extract(std::size_t pos, std::vector<Poco::UInt64>& val);
/// Extracts an UInt64 vector.
virtual bool extract(std::size_t pos, std::vector<Poco::Int64> & val);
/// Extracts an Int64 vector.
virtual bool extract(std::size_t pos, std::deque<Poco::UInt64>& val);
/// Extracts an UInt64 deque.
virtual bool extract(std::size_t pos, std::deque<Poco::Int64> & val);
/// Extracts an Int64 deque.
virtual bool extract(std::size_t pos, std::list<Poco::UInt64>& val);
/// Extracts an UInt64 list.
virtual bool extract(std::size_t pos, std::list<Poco::Int64> & val);
/// Extracts an Int64 list.
virtual bool extract(std::size_t pos, Poco::UInt64 & val) = 0;
/// Extracts an UInt64. Returns false if null was received.
virtual bool extract(std::size_t pos, std::vector<Poco::UInt64> & val);
/// Extracts an UInt64 vector.
virtual bool extract(std::size_t pos, std::deque<Poco::UInt64> & val);
/// Extracts an UInt64 deque.
virtual bool extract(std::size_t pos, std::list<Poco::UInt64> & val);
/// Extracts an UInt64 list.
#ifndef POCO_LONG_IS_64_BIT
virtual bool extract(std::size_t pos, long& val) = 0;
/// Extracts a long. Returns false if null was received.
virtual bool extract(std::size_t pos, long & val) = 0;
/// Extracts a long. Returns false if null was received.
virtual bool extract(std::size_t pos, unsigned long& val) = 0;
/// Extracts an unsigned long. Returns false if null was received.
virtual bool extract(std::size_t pos, unsigned long & val) = 0;
/// Extracts an unsigned long. Returns false if null was received.
virtual bool extract(std::size_t pos, std::vector<long>& val);
/// Extracts a long vector.
virtual bool extract(std::size_t pos, std::vector<long> & val);
/// Extracts a long vector.
virtual bool extract(std::size_t pos, std::deque<long>& val);
/// Extracts a long deque.
virtual bool extract(std::size_t pos, std::deque<long> & val);
/// Extracts a long deque.
virtual bool extract(std::size_t pos, std::list<long>& val);
/// Extracts a long list.
virtual bool extract(std::size_t pos, std::list<long> & val);
/// Extracts a long list.
#endif
virtual bool extract(std::size_t pos, bool& val) = 0;
/// Extracts a boolean. Returns false if null was received.
virtual bool extract(std::size_t pos, bool & val) = 0;
/// Extracts a boolean. Returns false if null was received.
virtual bool extract(std::size_t pos, std::vector<bool>& val);
/// Extracts a boolean vector.
virtual bool extract(std::size_t pos, std::vector<bool> & val);
/// Extracts a boolean vector.
virtual bool extract(std::size_t pos, std::deque<bool>& val);
/// Extracts a boolean deque.
virtual bool extract(std::size_t pos, std::deque<bool> & val);
/// Extracts a boolean deque.
virtual bool extract(std::size_t pos, std::list<bool>& val);
/// Extracts a boolean list.
virtual bool extract(std::size_t pos, std::list<bool> & val);
/// Extracts a boolean list.
virtual bool extract(std::size_t pos, float& val) = 0;
/// Extracts a float. Returns false if null was received.
virtual bool extract(std::size_t pos, float & val) = 0;
/// Extracts a float. Returns false if null was received.
virtual bool extract(std::size_t pos, std::vector<float>& val);
/// Extracts a float vector.
virtual bool extract(std::size_t pos, std::vector<float> & val);
/// Extracts a float vector.
virtual bool extract(std::size_t pos, std::deque<float>& val);
/// Extracts a float deque.
virtual bool extract(std::size_t pos, std::deque<float> & val);
/// Extracts a float deque.
virtual bool extract(std::size_t pos, std::list<float>& val);
/// Extracts a float list.
virtual bool extract(std::size_t pos, std::list<float> & val);
/// Extracts a float list.
virtual bool extract(std::size_t pos, double& val) = 0;
/// Extracts a double. Returns false if null was received.
virtual bool extract(std::size_t pos, double & val) = 0;
/// Extracts a double. Returns false if null was received.
virtual bool extract(std::size_t pos, std::vector<double>& val);
/// Extracts a double vector.
virtual bool extract(std::size_t pos, std::vector<double> & val);
/// Extracts a double vector.
virtual bool extract(std::size_t pos, std::deque<double>& val);
/// Extracts a double deque.
virtual bool extract(std::size_t pos, std::deque<double> & val);
/// Extracts a double deque.
virtual bool extract(std::size_t pos, std::list<double>& val);
/// Extracts a double list.
virtual bool extract(std::size_t pos, std::list<double> & val);
/// Extracts a double list.
virtual bool extract(std::size_t pos, char& val) = 0;
/// Extracts a single character. Returns false if null was received.
virtual bool extract(std::size_t pos, char & val) = 0;
/// Extracts a single character. Returns false if null was received.
virtual bool extract(std::size_t pos, std::vector<char>& val);
/// Extracts a character vector.
virtual bool extract(std::size_t pos, std::vector<char> & val);
/// Extracts a character vector.
virtual bool extract(std::size_t pos, std::deque<char>& val);
/// Extracts a character deque.
virtual bool extract(std::size_t pos, std::deque<char> & val);
/// Extracts a character deque.
virtual bool extract(std::size_t pos, std::list<char>& val);
/// Extracts a character list.
virtual bool extract(std::size_t pos, std::list<char> & val);
/// Extracts a character list.
virtual bool extract(std::size_t pos, std::string& val) = 0;
/// Extracts a string. Returns false if null was received.
virtual bool extract(std::size_t pos, std::string & val) = 0;
/// Extracts a string. Returns false if null was received.
virtual bool extract(std::size_t pos, std::vector<std::string>& val);
/// Extracts a string vector.
virtual bool extract(std::size_t pos, std::vector<std::string> & val);
/// Extracts a string vector.
virtual bool extract(std::size_t pos, std::deque<std::string>& val);
/// Extracts a string deque.
virtual bool extract(std::size_t pos, std::deque<std::string> & val);
/// Extracts a string deque.
virtual bool extract(std::size_t pos, std::list<std::string>& val);
/// Extracts a string list.
virtual bool extract(std::size_t pos, std::list<std::string> & val);
/// Extracts a string list.
virtual bool extract(std::size_t pos, UTF16String& val);
/// Extracts a UTF16String. Returns false if null was received.
virtual bool extract(std::size_t pos, UTF16String & val);
/// Extracts a UTF16String. Returns false if null was received.
virtual bool extract(std::size_t pos, std::vector<UTF16String>& val);
/// Extracts a UTF16String vector.
virtual bool extract(std::size_t pos, std::vector<UTF16String> & val);
/// Extracts a UTF16String vector.
virtual bool extract(std::size_t pos, std::deque<UTF16String>& val);
/// Extracts a UTF16String deque.
virtual bool extract(std::size_t pos, std::deque<UTF16String> & val);
/// Extracts a UTF16String deque.
virtual bool extract(std::size_t pos, std::list<UTF16String>& val);
/// Extracts a UTF16String list.
virtual bool extract(std::size_t pos, std::list<UTF16String> & val);
/// Extracts a UTF16String list.
virtual bool extract(std::size_t pos, BLOB& val) = 0;
/// Extracts a BLOB. Returns false if null was received.
virtual bool extract(std::size_t pos, BLOB & val) = 0;
/// Extracts a BLOB. Returns false if null was received.
virtual bool extract(std::size_t pos, CLOB& val) = 0;
/// Extracts a CLOB. Returns false if null was received.
virtual bool extract(std::size_t pos, CLOB & val) = 0;
/// Extracts a CLOB. Returns false if null was received.
virtual bool extract(std::size_t pos, std::vector<BLOB>& val);
/// Extracts a BLOB vector.
virtual bool extract(std::size_t pos, std::vector<BLOB> & val);
/// Extracts a BLOB vector.
virtual bool extract(std::size_t pos, std::deque<BLOB>& val);
/// Extracts a BLOB deque.
virtual bool extract(std::size_t pos, std::deque<BLOB> & val);
/// Extracts a BLOB deque.
virtual bool extract(std::size_t pos, std::list<BLOB>& val);
/// Extracts a BLOB list.
virtual bool extract(std::size_t pos, std::list<BLOB> & val);
/// Extracts a BLOB list.
virtual bool extract(std::size_t pos, std::vector<CLOB>& val);
/// Extracts a CLOB vector.
virtual bool extract(std::size_t pos, std::vector<CLOB> & val);
/// Extracts a CLOB vector.
virtual bool extract(std::size_t pos, std::deque<CLOB>& val);
/// Extracts a CLOB deque.
virtual bool extract(std::size_t pos, std::deque<CLOB> & val);
/// Extracts a CLOB deque.
virtual bool extract(std::size_t pos, std::list<CLOB>& val);
/// Extracts a CLOB list.
virtual bool extract(std::size_t pos, std::list<CLOB> & val);
/// Extracts a CLOB list.
virtual bool extract(std::size_t pos, DateTime& val) = 0;
/// Extracts a DateTime. Returns false if null was received.
virtual bool extract(std::size_t pos, DateTime & val) = 0;
/// Extracts a DateTime. Returns false if null was received.
virtual bool extract(std::size_t pos, std::vector<DateTime>& val);
/// Extracts a DateTime vector.
virtual bool extract(std::size_t pos, std::vector<DateTime> & val);
/// Extracts a DateTime vector.
virtual bool extract(std::size_t pos, std::deque<DateTime>& val);
/// Extracts a DateTime deque.
virtual bool extract(std::size_t pos, std::deque<DateTime> & val);
/// Extracts a DateTime deque.
virtual bool extract(std::size_t pos, std::list<DateTime>& val);
/// Extracts a DateTime list.
virtual bool extract(std::size_t pos, std::list<DateTime> & val);
/// Extracts a DateTime list.
virtual bool extract(std::size_t pos, Date& val) = 0;
/// Extracts a Date. Returns false if null was received.
virtual bool extract(std::size_t pos, Date & val) = 0;
/// Extracts a Date. Returns false if null was received.
virtual bool extract(std::size_t pos, std::vector<Date>& val);
/// Extracts a Date vector.
virtual bool extract(std::size_t pos, std::vector<Date> & val);
/// Extracts a Date vector.
virtual bool extract(std::size_t pos, std::deque<Date>& val);
/// Extracts a Date deque.
virtual bool extract(std::size_t pos, std::deque<Date> & val);
/// Extracts a Date deque.
virtual bool extract(std::size_t pos, std::list<Date>& val);
/// Extracts a Date list.
virtual bool extract(std::size_t pos, std::list<Date> & val);
/// Extracts a Date list.
virtual bool extract(std::size_t pos, Time& val) = 0;
/// Extracts a Time. Returns false if null was received.
virtual bool extract(std::size_t pos, Time & val) = 0;
/// Extracts a Time. Returns false if null was received.
virtual bool extract(std::size_t pos, std::vector<Time>& val);
/// Extracts a Time vector.
virtual bool extract(std::size_t pos, std::vector<Time> & val);
/// Extracts a Time vector.
virtual bool extract(std::size_t pos, std::deque<Time>& val);
/// Extracts a Time deque.
virtual bool extract(std::size_t pos, std::deque<Time> & val);
/// Extracts a Time deque.
virtual bool extract(std::size_t pos, std::list<Time>& val);
/// Extracts a Time list.
virtual bool extract(std::size_t pos, std::list<Time> & val);
/// Extracts a Time list.
virtual bool extract(std::size_t pos, Any& val) = 0;
/// Extracts an Any. Returns false if null was received.
virtual bool extract(std::size_t pos, Any & val) = 0;
/// Extracts an Any. Returns false if null was received.
virtual bool extract(std::size_t pos, std::vector<Any>& val);
/// Extracts an Any vector.
virtual bool extract(std::size_t pos, std::vector<Any> & val);
/// Extracts an Any vector.
virtual bool extract(std::size_t pos, std::deque<Any>& val);
/// Extracts an Any deque.
virtual bool extract(std::size_t pos, std::deque<Any> & val);
/// Extracts an Any deque.
virtual bool extract(std::size_t pos, std::list<Any>& val);
/// Extracts an Any list.
virtual bool extract(std::size_t pos, std::list<Any> & val);
/// Extracts an Any list.
virtual bool extract(std::size_t pos, Poco::Dynamic::Var& val) = 0;
/// Extracts a Var. Returns false if null was received.
virtual bool extract(std::size_t pos, Poco::Dynamic::Var & val) = 0;
/// Extracts a Var. Returns false if null was received.
virtual bool extract(std::size_t pos, std::vector<Poco::Dynamic::Var>& val);
/// Extracts a Var vector.
virtual bool extract(std::size_t pos, std::vector<Poco::Dynamic::Var> & val);
/// Extracts a Var vector.
virtual bool extract(std::size_t pos, std::deque<Poco::Dynamic::Var>& val);
/// Extracts a Var deque.
virtual bool extract(std::size_t pos, std::deque<Poco::Dynamic::Var> & val);
/// Extracts a Var deque.
virtual bool extract(std::size_t pos, std::list<Poco::Dynamic::Var>& val);
/// Extracts a Var list.
virtual bool extract(std::size_t pos, std::list<Poco::Dynamic::Var> & val);
/// Extracts a Var list.
virtual bool isNull(std::size_t col, std::size_t row = POCO_DATA_INVALID_ROW) = 0;
/// Returns true if the value at [col,row] position is null.
virtual bool isNull(std::size_t col, std::size_t row = POCO_DATA_INVALID_ROW) = 0;
/// Returns true if the value at [col,row] position is null.
virtual void reset();
/// Resets any information internally cached by the extractor.
};
virtual void reset();
/// Resets any information internally cached by the extractor.
};
///
/// inlines
///
inline void AbstractExtractor::reset()
{
//default no-op
}
///
/// inlines
///
inline void AbstractExtractor::reset()
{
//default no-op
}
} } // namespace Poco::Data
} // namespace Poco::Data
#endif // Data_AbstractExtractor_INCLUDED

View File

@ -18,54 +18,57 @@
#define Data_AbstractPreparation_INCLUDED
#include "Poco/Data/Data.h"
#include "Poco/Data/AbstractPreparator.h"
#include "Poco/SharedPtr.h"
#include <cstddef>
#include "Poco/Data/AbstractPreparator.h"
#include "Poco/Data/Data.h"
#include "Poco/SharedPtr.h"
namespace Poco {
namespace Data {
class Data_API AbstractPreparation
/// Interface for calling the appropriate AbstractPreparator method
namespace Poco
{
public:
typedef SharedPtr<AbstractPreparation> Ptr;
typedef AbstractPreparator::Ptr PreparatorPtr;
AbstractPreparation(PreparatorPtr pPreparator);
/// Creates the AbstractPreparation.
virtual ~AbstractPreparation();
/// Destroys the AbstractPreparation.
virtual void prepare() = 0;
/// Prepares data.
protected:
AbstractPreparation();
AbstractPreparation(const AbstractPreparation&);
AbstractPreparation& operator = (const AbstractPreparation&);
PreparatorPtr preparation();
/// Returns the preparation object
PreparatorPtr _pPreparator;
};
//
// inlines
//
inline AbstractPreparation::PreparatorPtr AbstractPreparation::preparation()
namespace Data
{
return _pPreparator;
class Data_API AbstractPreparation
/// Interface for calling the appropriate AbstractPreparator method
{
public:
typedef SharedPtr<AbstractPreparation> Ptr;
typedef AbstractPreparator::Ptr PreparatorPtr;
AbstractPreparation(PreparatorPtr pPreparator);
/// Creates the AbstractPreparation.
virtual ~AbstractPreparation();
/// Destroys the AbstractPreparation.
virtual void prepare() = 0;
/// Prepares data.
protected:
AbstractPreparation();
AbstractPreparation(const AbstractPreparation &);
AbstractPreparation & operator=(const AbstractPreparation &);
PreparatorPtr preparation();
/// Returns the preparation object
PreparatorPtr _pPreparator;
};
//
// inlines
//
inline AbstractPreparation::PreparatorPtr AbstractPreparation::preparation()
{
return _pPreparator;
}
}
} } // namespace Poco::Data
} // namespace Poco::Data
#endif // Data_AbstractPreparation_INCLUDED

View File

@ -18,371 +18,375 @@
#define Data_AbstractPreparator_INCLUDED
#include "Poco/Data/Data.h"
#include "Poco/RefCountedObject.h"
#include "Poco/Data/LOB.h"
#include "Poco/UTFString.h"
#include <vector>
#include <cstddef>
#include <deque>
#include <list>
#include <cstddef>
#include <vector>
#include "Poco/Data/Data.h"
#include "Poco/Data/LOB.h"
#include "Poco/RefCountedObject.h"
#include "Poco/UTFString.h"
namespace Poco {
namespace Poco
{
class DateTime;
class Any;
namespace Dynamic {
class Var;
namespace Dynamic
{
class Var;
}
namespace Data {
class Date;
class Time;
class Data_API AbstractPreparator
/// Interface used for database preparation where we first have to register all data types
/// (and memory output locations) before extracting data, e.g. ODBC.
/// Extract works as two-phase extract: first we call prepare once, then extract n-times.
/// There are cases (bulk operations using std::vector storage) when extract is called only once.
/// The value passed to a prepare() call is not used by the prepare, serving only as an indication
/// of the data type being prepared, thus all values are passed as const references.
/// Implementing this interface is not mandatory for a connector. Connectors that only extract data
/// after SQL execution (e.g. SQLite) do not need this functionality at all.
namespace Data
{
public:
typedef SharedPtr<AbstractPreparator> Ptr;
AbstractPreparator(Poco::UInt32 length = 1u);
/// Creates the AbstractPreparator.
virtual ~AbstractPreparator();
/// Destroys the AbstractPreparator.
class Date;
class Time;
virtual void prepare(std::size_t pos, const Poco::Int8&) = 0;
/// Prepares an Int8.
virtual void prepare(std::size_t pos, const std::vector<Poco::Int8>& val);
/// Prepares an Int8 vector.
class Data_API AbstractPreparator
/// Interface used for database preparation where we first have to register all data types
/// (and memory output locations) before extracting data, e.g. ODBC.
/// Extract works as two-phase extract: first we call prepare once, then extract n-times.
/// There are cases (bulk operations using std::vector storage) when extract is called only once.
/// The value passed to a prepare() call is not used by the prepare, serving only as an indication
/// of the data type being prepared, thus all values are passed as const references.
/// Implementing this interface is not mandatory for a connector. Connectors that only extract data
/// after SQL execution (e.g. SQLite) do not need this functionality at all.
{
public:
typedef SharedPtr<AbstractPreparator> Ptr;
virtual void prepare(std::size_t pos, const std::deque<Poco::Int8>& val);
/// Prepares an Int8 deque.
AbstractPreparator(Poco::UInt32 length = 1u);
/// Creates the AbstractPreparator.
virtual void prepare(std::size_t pos, const std::list<Poco::Int8>& val);
/// Prepares an Int8 list.
virtual ~AbstractPreparator();
/// Destroys the AbstractPreparator.
virtual void prepare(std::size_t pos, const Poco::UInt8&) = 0;
/// Prepares an UInt8.
virtual void prepare(std::size_t pos, const Poco::Int8 &) = 0;
/// Prepares an Int8.
virtual void prepare(std::size_t pos, const std::vector<Poco::UInt8>& val);
/// Prepares an UInt8 vector.
virtual void prepare(std::size_t pos, const std::vector<Poco::Int8> & val);
/// Prepares an Int8 vector.
virtual void prepare(std::size_t pos, const std::deque<Poco::UInt8>& val);
/// Prepares an UInt8 deque.
virtual void prepare(std::size_t pos, const std::deque<Poco::Int8> & val);
/// Prepares an Int8 deque.
virtual void prepare(std::size_t pos, const std::list<Poco::UInt8>& val);
/// Prepares an UInt8 list.
virtual void prepare(std::size_t pos, const std::list<Poco::Int8> & val);
/// Prepares an Int8 list.
virtual void prepare(std::size_t pos, const Poco::Int16&) = 0;
/// Prepares an Int16.
virtual void prepare(std::size_t pos, const Poco::UInt8 &) = 0;
/// Prepares an UInt8.
virtual void prepare(std::size_t pos, const std::vector<Poco::Int16>& val);
/// Prepares an Int16 vector.
virtual void prepare(std::size_t pos, const std::vector<Poco::UInt8> & val);
/// Prepares an UInt8 vector.
virtual void prepare(std::size_t pos, const std::deque<Poco::Int16>& val);
/// Prepares an Int16 deque.
virtual void prepare(std::size_t pos, const std::deque<Poco::UInt8> & val);
/// Prepares an UInt8 deque.
virtual void prepare(std::size_t pos, const std::list<Poco::Int16>& val);
/// Prepares an Int16 list.
virtual void prepare(std::size_t pos, const std::list<Poco::UInt8> & val);
/// Prepares an UInt8 list.
virtual void prepare(std::size_t pos, const Poco::UInt16&) = 0;
/// Prepares an UInt16.
virtual void prepare(std::size_t pos, const Poco::Int16 &) = 0;
/// Prepares an Int16.
virtual void prepare(std::size_t pos, const std::vector<Poco::UInt16>& val);
/// Prepares an UInt16 vector.
virtual void prepare(std::size_t pos, const std::vector<Poco::Int16> & val);
/// Prepares an Int16 vector.
virtual void prepare(std::size_t pos, const std::deque<Poco::UInt16>& val);
/// Prepares an UInt16 deque.
virtual void prepare(std::size_t pos, const std::deque<Poco::Int16> & val);
/// Prepares an Int16 deque.
virtual void prepare(std::size_t pos, const std::list<Poco::UInt16>& val);
/// Prepares an UInt16 list.
virtual void prepare(std::size_t pos, const std::list<Poco::Int16> & val);
/// Prepares an Int16 list.
virtual void prepare(std::size_t pos, const Poco::Int32&) = 0;
/// Prepares an Int32.
virtual void prepare(std::size_t pos, const Poco::UInt16 &) = 0;
/// Prepares an UInt16.
virtual void prepare(std::size_t pos, const std::vector<Poco::Int32>& val);
/// Prepares an Int32 vector.
virtual void prepare(std::size_t pos, const std::vector<Poco::UInt16> & val);
/// Prepares an UInt16 vector.
virtual void prepare(std::size_t pos, const std::deque<Poco::Int32>& val);
/// Prepares an Int32 deque.
virtual void prepare(std::size_t pos, const std::deque<Poco::UInt16> & val);
/// Prepares an UInt16 deque.
virtual void prepare(std::size_t pos, const std::list<Poco::Int32>& val);
/// Prepares an Int32 list.
virtual void prepare(std::size_t pos, const std::list<Poco::UInt16> & val);
/// Prepares an UInt16 list.
virtual void prepare(std::size_t pos, const Poco::UInt32&) = 0;
/// Prepares an UInt32.
virtual void prepare(std::size_t pos, const Poco::Int32 &) = 0;
/// Prepares an Int32.
virtual void prepare(std::size_t pos, const std::vector<Poco::UInt32>& val);
/// Prepares an UInt32 vector.
virtual void prepare(std::size_t pos, const std::vector<Poco::Int32> & val);
/// Prepares an Int32 vector.
virtual void prepare(std::size_t pos, const std::deque<Poco::UInt32>& val);
/// Prepares an UInt32 deque.
virtual void prepare(std::size_t pos, const std::deque<Poco::Int32> & val);
/// Prepares an Int32 deque.
virtual void prepare(std::size_t pos, const std::list<Poco::UInt32>& val);
/// Prepares an UInt32 list.
virtual void prepare(std::size_t pos, const std::list<Poco::Int32> & val);
/// Prepares an Int32 list.
virtual void prepare(std::size_t pos, const Poco::Int64&) = 0;
/// Prepares an Int64.
virtual void prepare(std::size_t pos, const Poco::UInt32 &) = 0;
/// Prepares an UInt32.
virtual void prepare(std::size_t pos, const std::vector<Poco::Int64>& val);
/// Prepares an Int64 vector.
virtual void prepare(std::size_t pos, const std::vector<Poco::UInt32> & val);
/// Prepares an UInt32 vector.
virtual void prepare(std::size_t pos, const std::deque<Poco::Int64>& val);
/// Prepares an Int64 deque.
virtual void prepare(std::size_t pos, const std::deque<Poco::UInt32> & val);
/// Prepares an UInt32 deque.
virtual void prepare(std::size_t pos, const std::list<Poco::Int64>& val);
/// Prepares an Int64 list.
virtual void prepare(std::size_t pos, const std::list<Poco::UInt32> & val);
/// Prepares an UInt32 list.
virtual void prepare(std::size_t pos, const Poco::UInt64&) = 0;
/// Prepares an UInt64.
virtual void prepare(std::size_t pos, const Poco::Int64 &) = 0;
/// Prepares an Int64.
virtual void prepare(std::size_t pos, const std::vector<Poco::UInt64>& val);
/// Prepares an UInt64 vector.
virtual void prepare(std::size_t pos, const std::vector<Poco::Int64> & val);
/// Prepares an Int64 vector.
virtual void prepare(std::size_t pos, const std::deque<Poco::UInt64>& val);
/// Prepares an UInt64 deque.
virtual void prepare(std::size_t pos, const std::deque<Poco::Int64> & val);
/// Prepares an Int64 deque.
virtual void prepare(std::size_t pos, const std::list<Poco::UInt64>& val);
/// Prepares an UInt64 list.
virtual void prepare(std::size_t pos, const std::list<Poco::Int64> & val);
/// Prepares an Int64 list.
virtual void prepare(std::size_t pos, const Poco::UInt64 &) = 0;
/// Prepares an UInt64.
virtual void prepare(std::size_t pos, const std::vector<Poco::UInt64> & val);
/// Prepares an UInt64 vector.
virtual void prepare(std::size_t pos, const std::deque<Poco::UInt64> & val);
/// Prepares an UInt64 deque.
virtual void prepare(std::size_t pos, const std::list<Poco::UInt64> & val);
/// Prepares an UInt64 list.
#ifndef POCO_LONG_IS_64_BIT
virtual void prepare(std::size_t pos, const long&) = 0;
/// Prepares a long.
virtual void prepare(std::size_t pos, const long &) = 0;
/// Prepares a long.
virtual void prepare(std::size_t pos, const unsigned long&) = 0;
/// Prepares an unsigned long.
virtual void prepare(std::size_t pos, const unsigned long &) = 0;
/// Prepares an unsigned long.
virtual void prepare(std::size_t pos, const std::vector<long>& val);
/// Prepares a long vector.
virtual void prepare(std::size_t pos, const std::vector<long> & val);
/// Prepares a long vector.
virtual void prepare(std::size_t pos, const std::deque<long>& val);
/// Prepares a long deque.
virtual void prepare(std::size_t pos, const std::deque<long> & val);
/// Prepares a long deque.
virtual void prepare(std::size_t pos, const std::list<long>& val);
/// Prepares a long list.
virtual void prepare(std::size_t pos, const std::list<long> & val);
/// Prepares a long list.
#endif
virtual void prepare(std::size_t pos, const bool&) = 0;
/// Prepares a boolean.
virtual void prepare(std::size_t pos, const bool &) = 0;
/// Prepares a boolean.
virtual void prepare(std::size_t pos, const std::vector<bool>& val);
/// Prepares a boolean vector.
virtual void prepare(std::size_t pos, const std::vector<bool> & val);
/// Prepares a boolean vector.
virtual void prepare(std::size_t pos, const std::deque<bool>& val);
/// Prepares a boolean deque.
virtual void prepare(std::size_t pos, const std::deque<bool> & val);
/// Prepares a boolean deque.
virtual void prepare(std::size_t pos, const std::list<bool>& val);
/// Prepares a boolean list.
virtual void prepare(std::size_t pos, const std::list<bool> & val);
/// Prepares a boolean list.
virtual void prepare(std::size_t pos, const float&) = 0;
/// Prepares a float.
virtual void prepare(std::size_t pos, const float &) = 0;
/// Prepares a float.
virtual void prepare(std::size_t pos, const std::vector<float>& val);
/// Prepares a float vector.
virtual void prepare(std::size_t pos, const std::vector<float> & val);
/// Prepares a float vector.
virtual void prepare(std::size_t pos, const std::deque<float>& val);
/// Prepares a float deque.
virtual void prepare(std::size_t pos, const std::deque<float> & val);
/// Prepares a float deque.
virtual void prepare(std::size_t pos, const std::list<float>& val);
/// Prepares a float list.
virtual void prepare(std::size_t pos, const std::list<float> & val);
/// Prepares a float list.
virtual void prepare(std::size_t pos, const double&) = 0;
/// Prepares a double.
virtual void prepare(std::size_t pos, const double &) = 0;
/// Prepares a double.
virtual void prepare(std::size_t pos, const std::vector<double>& val);
/// Prepares a double vector.
virtual void prepare(std::size_t pos, const std::vector<double> & val);
/// Prepares a double vector.
virtual void prepare(std::size_t pos, const std::deque<double>& val);
/// Prepares a double deque.
virtual void prepare(std::size_t pos, const std::deque<double> & val);
/// Prepares a double deque.
virtual void prepare(std::size_t pos, const std::list<double>& val);
/// Prepares a double list.
virtual void prepare(std::size_t pos, const std::list<double> & val);
/// Prepares a double list.
virtual void prepare(std::size_t pos, const char&) = 0;
/// Prepares a single character.
virtual void prepare(std::size_t pos, const char &) = 0;
/// Prepares a single character.
virtual void prepare(std::size_t pos, const std::vector<char>& val);
/// Prepares a character vector.
virtual void prepare(std::size_t pos, const std::vector<char> & val);
/// Prepares a character vector.
virtual void prepare(std::size_t pos, const std::deque<char>& val);
/// Prepares a character deque.
virtual void prepare(std::size_t pos, const std::deque<char> & val);
/// Prepares a character deque.
virtual void prepare(std::size_t pos, const std::list<char>& val);
/// Prepares a character list.
virtual void prepare(std::size_t pos, const std::list<char> & val);
/// Prepares a character list.
virtual void prepare(std::size_t pos, const std::string&) = 0;
/// Prepares a string.
virtual void prepare(std::size_t pos, const std::string &) = 0;
/// Prepares a string.
virtual void prepare(std::size_t pos, const std::vector<std::string>& val);
/// Prepares a string vector.
virtual void prepare(std::size_t pos, const std::vector<std::string> & val);
/// Prepares a string vector.
virtual void prepare(std::size_t pos, const std::deque<std::string>& val);
/// Prepares a string deque.
virtual void prepare(std::size_t pos, const std::deque<std::string> & val);
/// Prepares a string deque.
virtual void prepare(std::size_t pos, const std::list<std::string>& val);
/// Prepares a character list.
virtual void prepare(std::size_t pos, const std::list<std::string> & val);
/// Prepares a character list.
virtual void prepare(std::size_t pos, const UTF16String&);
/// Prepares a UTF16String.
virtual void prepare(std::size_t pos, const UTF16String &);
/// Prepares a UTF16String.
virtual void prepare(std::size_t pos, const std::vector<UTF16String>& val);
/// Prepares a UTF16String vector.
virtual void prepare(std::size_t pos, const std::vector<UTF16String> & val);
/// Prepares a UTF16String vector.
virtual void prepare(std::size_t pos, const std::deque<UTF16String>& val);
/// Prepares a UTF16String deque.
virtual void prepare(std::size_t pos, const std::deque<UTF16String> & val);
/// Prepares a UTF16String deque.
virtual void prepare(std::size_t pos, const std::list<UTF16String>& val);
/// Prepares a UTF16String list.
virtual void prepare(std::size_t pos, const std::list<UTF16String> & val);
/// Prepares a UTF16String list.
virtual void prepare(std::size_t pos, const BLOB&) = 0;
/// Prepares a BLOB.
virtual void prepare(std::size_t pos, const BLOB &) = 0;
/// Prepares a BLOB.
virtual void prepare(std::size_t pos, const CLOB&) = 0;
/// Prepares a CLOB.
virtual void prepare(std::size_t pos, const CLOB &) = 0;
/// Prepares a CLOB.
virtual void prepare(std::size_t pos, const std::vector<BLOB>& val);
/// Prepares a BLOB vector.
virtual void prepare(std::size_t pos, const std::vector<BLOB> & val);
/// Prepares a BLOB vector.
virtual void prepare(std::size_t pos, const std::deque<BLOB>& val);
/// Prepares a BLOB deque.
virtual void prepare(std::size_t pos, const std::deque<BLOB> & val);
/// Prepares a BLOB deque.
virtual void prepare(std::size_t pos, const std::list<BLOB>& val);
/// Prepares a BLOB list.
virtual void prepare(std::size_t pos, const std::list<BLOB> & val);
/// Prepares a BLOB list.
virtual void prepare(std::size_t pos, const std::vector<CLOB>& val);
/// Prepares a CLOB vector.
virtual void prepare(std::size_t pos, const std::vector<CLOB> & val);
/// Prepares a CLOB vector.
virtual void prepare(std::size_t pos, const std::deque<CLOB>& val);
/// Prepares a CLOB deque.
virtual void prepare(std::size_t pos, const std::deque<CLOB> & val);
/// Prepares a CLOB deque.
virtual void prepare(std::size_t pos, const std::list<CLOB>& val);
/// Prepares a CLOB list.
virtual void prepare(std::size_t pos, const std::list<CLOB> & val);
/// Prepares a CLOB list.
virtual void prepare(std::size_t pos, const DateTime&) = 0;
/// Prepares a DateTime.
virtual void prepare(std::size_t pos, const DateTime &) = 0;
/// Prepares a DateTime.
virtual void prepare(std::size_t pos, const std::vector<DateTime>& val);
/// Prepares a DateTime vector.
virtual void prepare(std::size_t pos, const std::vector<DateTime> & val);
/// Prepares a DateTime vector.
virtual void prepare(std::size_t pos, const std::deque<DateTime>& val);
/// Prepares a DateTime deque.
virtual void prepare(std::size_t pos, const std::deque<DateTime> & val);
/// Prepares a DateTime deque.
virtual void prepare(std::size_t pos, const std::list<DateTime>& val);
/// Prepares a DateTime list.
virtual void prepare(std::size_t pos, const std::list<DateTime> & val);
/// Prepares a DateTime list.
virtual void prepare(std::size_t pos, const Date&) = 0;
/// Prepares a Date.
virtual void prepare(std::size_t pos, const Date &) = 0;
/// Prepares a Date.
virtual void prepare(std::size_t pos, const std::vector<Date>& val);
/// Prepares a Date vector.
virtual void prepare(std::size_t pos, const std::vector<Date> & val);
/// Prepares a Date vector.
virtual void prepare(std::size_t pos, const std::deque<Date>& val);
/// Prepares a Date deque.
virtual void prepare(std::size_t pos, const std::deque<Date> & val);
/// Prepares a Date deque.
virtual void prepare(std::size_t pos, const std::list<Date>& val);
/// Prepares a Date list.
virtual void prepare(std::size_t pos, const std::list<Date> & val);
/// Prepares a Date list.
virtual void prepare(std::size_t pos, const Time&) = 0;
/// Prepares a Time.
virtual void prepare(std::size_t pos, const Time &) = 0;
/// Prepares a Time.
virtual void prepare(std::size_t pos, const std::vector<Time>& val);
/// Prepares a Time vector.
virtual void prepare(std::size_t pos, const std::vector<Time> & val);
/// Prepares a Time vector.
virtual void prepare(std::size_t pos, const std::deque<Time>& val);
/// Prepares a Time deque.
virtual void prepare(std::size_t pos, const std::list<Time>& val);
/// Prepares a Time list.
virtual void prepare(std::size_t pos, const std::deque<Time> & val);
/// Prepares a Time deque.
virtual void prepare(std::size_t pos, const Any&) = 0;
/// Prepares an Any.
virtual void prepare(std::size_t pos, const std::list<Time> & val);
/// Prepares a Time list.
virtual void prepare(std::size_t pos, const std::vector<Any>& val);
/// Prepares an Any vector.
virtual void prepare(std::size_t pos, const Any &) = 0;
/// Prepares an Any.
virtual void prepare(std::size_t pos, const std::deque<Any>& val);
/// Prepares an Any deque.
virtual void prepare(std::size_t pos, const std::vector<Any> & val);
/// Prepares an Any vector.
virtual void prepare(std::size_t pos, const std::list<Any>& val);
/// Prepares an Any list.
virtual void prepare(std::size_t pos, const std::deque<Any> & val);
/// Prepares an Any deque.
virtual void prepare(std::size_t pos, const Poco::Dynamic::Var&) = 0;
/// Prepares a Var.
virtual void prepare(std::size_t pos, const std::list<Any> & val);
/// Prepares an Any list.
virtual void prepare(std::size_t pos, const std::vector<Poco::Dynamic::Var>& val);
/// Prepares a Var vector.
virtual void prepare(std::size_t pos, const Poco::Dynamic::Var &) = 0;
/// Prepares a Var.
virtual void prepare(std::size_t pos, const std::deque<Poco::Dynamic::Var>& val);
/// Prepares a Var deque.
virtual void prepare(std::size_t pos, const std::vector<Poco::Dynamic::Var> & val);
/// Prepares a Var vector.
virtual void prepare(std::size_t pos, const std::list<Poco::Dynamic::Var>& val);
/// Prepares a Var list.
virtual void prepare(std::size_t pos, const std::deque<Poco::Dynamic::Var> & val);
/// Prepares a Var deque.
void setLength(Poco::UInt32 length);
/// Sets the length of prepared data.
/// Needed only for data lengths greater than 1 (i.e. for
/// bulk operations).
virtual void prepare(std::size_t pos, const std::list<Poco::Dynamic::Var> & val);
/// Prepares a Var list.
Poco::UInt32 getLength() const;
/// Returns the length of prepared data. Defaults to 1.
/// The length is greater than one for bulk operations.
void setLength(Poco::UInt32 length);
/// Sets the length of prepared data.
/// Needed only for data lengths greater than 1 (i.e. for
/// bulk operations).
void setBulk(bool bulkPrep = true);
/// Sets bulk operation flag (always false at object creation time)
Poco::UInt32 getLength() const;
/// Returns the length of prepared data. Defaults to 1.
/// The length is greater than one for bulk operations.
bool isBulk() const;
/// Returns bulk operation flag.
void setBulk(bool bulkPrep = true);
/// Sets bulk operation flag (always false at object creation time)
private:
Poco::UInt32 _length;
bool _bulk;
};
bool isBulk() const;
/// Returns bulk operation flag.
private:
Poco::UInt32 _length;
bool _bulk;
};
///
/// inlines
///
inline void AbstractPreparator::setLength(Poco::UInt32 length)
{
_length = length;
}
inline Poco::UInt32 AbstractPreparator::getLength() const
{
return _length;
}
inline void AbstractPreparator::setBulk(bool bulkPrep)
{
_bulk = bulkPrep;
}
inline bool AbstractPreparator::isBulk() const
{
return _bulk;
}
///
/// inlines
///
inline void AbstractPreparator::setLength(Poco::UInt32 length)
{
_length = length;
}
inline Poco::UInt32 AbstractPreparator::getLength() const
{
return _length;
}
inline void AbstractPreparator::setBulk(bool bulkPrep)
{
_bulk = bulkPrep;
}
inline bool AbstractPreparator::isBulk() const
{
return _bulk;
}
} } // namespace Poco::Data
} // namespace Poco::Data
#endif // Data_AbstractPreparator_INCLUDED

View File

@ -18,298 +18,295 @@
#define Data_AbstractSessionImpl_INCLUDED
#include "Poco/Data/Data.h"
#include "Poco/Data/SessionImpl.h"
#include "Poco/Data/DataException.h"
#include <map>
#include "Poco/Data/Data.h"
#include "Poco/Data/DataException.h"
#include "Poco/Data/SessionImpl.h"
namespace Poco {
namespace Data {
template <class C>
class AbstractSessionImpl: public SessionImpl
/// A partial implementation of SessionImpl, providing
/// features and properties management.
///
/// To implement a certain feature or property, a subclass
/// must provide setter and getter methods and register
/// them with addFeature() or addProperty().
namespace Poco
{
namespace Data
{
public:
typedef void (C::*FeatureSetter)(const std::string&, bool);
/// The setter method for a feature.
typedef bool (C::*FeatureGetter)(const std::string&);
/// The getter method for a feature.
typedef void (C::*PropertySetter)(const std::string&, const Poco::Any&);
/// The setter method for a property.
typedef Poco::Any (C::*PropertyGetter)(const std::string&);
/// The getter method for a property.
AbstractSessionImpl(const std::string& connectionString,
std::size_t timeout = LOGIN_TIMEOUT_DEFAULT): SessionImpl(connectionString, timeout),
_storage(std::string("deque")),
_bulk(false),
_emptyStringIsNull(false),
_forceEmptyString(false)
/// Creates the AbstractSessionImpl.
///
/// Adds "storage" property and sets the default internal storage container
/// type to std::deque.
/// The storage is created by statements automatically whenever a query
/// returning results is executed but external storage is provided by the user.
/// Storage type can be reconfigured at runtime both globally (for the
/// duration of the session) and locally (for a single statement execution only).
/// See StatementImpl for details on how this property is used at runtime.
///
/// Adds "handle" property which, if set by the back end, returns native handle
/// for the back end DB.
///
/// Adds "bulk" feature and sets it to false.
/// Bulk feature determines whether the session is capable of bulk operations.
/// Connectors that are capable of it must set this feature prior to attempting
/// bulk operations.
///
/// Adds "emptyStringIsNull" feature and sets it to false. This feature should be
/// set to true in order to modify the behavior of the databases that distinguish
/// between zero-length character strings as nulls. Setting this feature to true
/// shall disregard any difference between empty character strings and nulls,
/// causing the framework to treat them the same (i.e. behave like Oracle).
///
/// Adds "forceEmptyString" feature and sets it to false. This feature should be set
/// to true in order to force the databases that do not distinguish empty strings from
/// nulls (e.g. Oracle) to always report empty string.
///
/// The "emptyStringIsNull" and "forceEmptyString" features are mutually exclusive.
/// While these features can not both be true at the same time, they can both be false,
/// resulting in default underlying database behavior.
///
{
addProperty("storage",
&AbstractSessionImpl<C>::setStorage,
&AbstractSessionImpl<C>::getStorage);
addProperty("handle",
&AbstractSessionImpl<C>::setHandle,
&AbstractSessionImpl<C>::getHandle);
addFeature("bulk",
&AbstractSessionImpl<C>::setBulk,
&AbstractSessionImpl<C>::getBulk);
addFeature("emptyStringIsNull",
&AbstractSessionImpl<C>::setEmptyStringIsNull,
&AbstractSessionImpl<C>::getEmptyStringIsNull);
addFeature("forceEmptyString",
&AbstractSessionImpl<C>::setForceEmptyString,
&AbstractSessionImpl<C>::getForceEmptyString);
}
~AbstractSessionImpl()
/// Destroys the AbstractSessionImpl.
{
}
void setFeature(const std::string& name, bool state)
/// Looks a feature up in the features map
/// and calls the feature's setter, if there is one.
{
typename FeatureMap::const_iterator it = _features.find(name);
if (it != _features.end())
{
if (it->second.setter)
(static_cast<C*>(this)->*it->second.setter)(name, state);
else
throw NotImplementedException("set", name);
}
else throw NotSupportedException(name);
}
bool getFeature(const std::string& name)
/// Looks a feature up in the features map
/// and calls the feature's getter, if there is one.
{
typename FeatureMap::const_iterator it = _features.find(name);
if (it != _features.end())
{
if (it->second.getter)
return (static_cast<C*>(this)->*it->second.getter)(name);
else
throw NotImplementedException("get", name);
}
else throw NotSupportedException(name);
}
void setProperty(const std::string& name, const Poco::Any& value)
/// Looks a property up in the properties map
/// and calls the property's setter, if there is one.
{
typename PropertyMap::const_iterator it = _properties.find(name);
if (it != _properties.end())
{
if (it->second.setter)
(static_cast<C*>(this)->*it->second.setter)(name, value);
else
throw NotImplementedException("set", name);
}
else throw NotSupportedException(name);
}
Poco::Any getProperty(const std::string& name)
/// Looks a property up in the properties map
/// and calls the property's getter, if there is one.
{
typename PropertyMap::const_iterator it = _properties.find(name);
if (it != _properties.end())
{
if (it->second.getter)
return (static_cast<C*>(this)->*it->second.getter)(name);
else
throw NotImplementedException("set", name);
}
else throw NotSupportedException(name);
}
void setStorage(const std::string& value)
/// Sets the storage type.
{
_storage = value;
}
void setStorage(const std::string& name, const Poco::Any& value)
/// Sets the storage type.
{
_storage = Poco::RefAnyCast<std::string>(value);
}
Poco::Any getStorage(const std::string& name="")
/// Returns the storage type
{
return _storage;
}
void setHandle(const std::string& name, const Poco::Any& handle)
/// Sets the native session handle.
{
_handle = handle;
}
Poco::Any getHandle(const std::string& name="")
/// Returns the native session handle.
{
return _handle;
}
void setBulk(const std::string& name, bool bulk)
/// Sets the execution type.
{
_bulk = bulk;
}
bool getBulk(const std::string& name="")
/// Returns the execution type
{
return _bulk;
}
void setEmptyStringIsNull(const std::string& name, bool emptyStringIsNull)
/// Sets the behavior regarding empty variable length strings.
/// Those are treated as NULL by Oracle and as empty string by
/// most other databases.
/// When this feature is true, empty strings are treated as NULL.
{
if (emptyStringIsNull && _forceEmptyString)
throw InvalidAccessException("Features mutually exclusive");
_emptyStringIsNull = emptyStringIsNull;
}
bool getEmptyStringIsNull(const std::string& name="")
/// Returns the setting for the behavior regarding empty variable
/// length strings. See setEmptyStringIsNull(const std::string&, bool)
/// and this class documentation for feature rationale and details.
{
return _emptyStringIsNull;
}
void setForceEmptyString(const std::string& name, bool forceEmptyString)
/// Sets the behavior regarding empty variable length strings.
/// Those are treated as NULL by Oracle and as empty string by
/// most other databases.
/// When this feature is true, both empty strings and NULL values
/// are reported as empty strings.
{
if (forceEmptyString && _emptyStringIsNull)
throw InvalidAccessException("Features mutually exclusive");
_forceEmptyString = forceEmptyString;
}
bool getForceEmptyString(const std::string& name="")
/// Returns the setting for the behavior regarding empty variable
/// length strings. See setForceEmptyString(const std::string&, bool)
/// and this class documentation for feature rationale and details.
{
return _forceEmptyString;
}
protected:
void addFeature(const std::string& name, FeatureSetter setter, FeatureGetter getter)
/// Adds a feature to the map of supported features.
///
/// The setter or getter can be null, in case setting or getting a feature
/// is not supported.
{
Feature feature;
feature.setter = setter;
feature.getter = getter;
_features[name] = feature;
}
void addProperty(const std::string& name, PropertySetter setter, PropertyGetter getter)
/// Adds a property to the map of supported properties.
///
/// The setter or getter can be null, in case setting or getting a property
/// is not supported.
{
Property property;
property.setter = setter;
property.getter = getter;
_properties[name] = property;
}
private:
struct Feature
{
FeatureSetter setter;
FeatureGetter getter;
};
struct Property
{
PropertySetter setter;
PropertyGetter getter;
};
typedef std::map<std::string, Feature> FeatureMap;
typedef std::map<std::string, Property> PropertyMap;
FeatureMap _features;
PropertyMap _properties;
std::string _storage;
bool _bulk;
bool _emptyStringIsNull;
bool _forceEmptyString;
Poco::Any _handle;
};
} } // namespace Poco::Data
template <class C>
class AbstractSessionImpl : public SessionImpl
/// A partial implementation of SessionImpl, providing
/// features and properties management.
///
/// To implement a certain feature or property, a subclass
/// must provide setter and getter methods and register
/// them with addFeature() or addProperty().
{
public:
typedef void (C::*FeatureSetter)(const std::string &, bool);
/// The setter method for a feature.
typedef bool (C::*FeatureGetter)(const std::string &);
/// The getter method for a feature.
typedef void (C::*PropertySetter)(const std::string &, const Poco::Any &);
/// The setter method for a property.
typedef Poco::Any (C::*PropertyGetter)(const std::string &);
/// The getter method for a property.
AbstractSessionImpl(const std::string & connectionString, std::size_t timeout = LOGIN_TIMEOUT_DEFAULT)
: SessionImpl(connectionString, timeout)
, _storage(std::string("deque"))
, _bulk(false)
, _emptyStringIsNull(false)
, _forceEmptyString(false)
/// Creates the AbstractSessionImpl.
///
/// Adds "storage" property and sets the default internal storage container
/// type to std::deque.
/// The storage is created by statements automatically whenever a query
/// returning results is executed but external storage is provided by the user.
/// Storage type can be reconfigured at runtime both globally (for the
/// duration of the session) and locally (for a single statement execution only).
/// See StatementImpl for details on how this property is used at runtime.
///
/// Adds "handle" property which, if set by the back end, returns native handle
/// for the back end DB.
///
/// Adds "bulk" feature and sets it to false.
/// Bulk feature determines whether the session is capable of bulk operations.
/// Connectors that are capable of it must set this feature prior to attempting
/// bulk operations.
///
/// Adds "emptyStringIsNull" feature and sets it to false. This feature should be
/// set to true in order to modify the behavior of the databases that distinguish
/// between zero-length character strings as nulls. Setting this feature to true
/// shall disregard any difference between empty character strings and nulls,
/// causing the framework to treat them the same (i.e. behave like Oracle).
///
/// Adds "forceEmptyString" feature and sets it to false. This feature should be set
/// to true in order to force the databases that do not distinguish empty strings from
/// nulls (e.g. Oracle) to always report empty string.
///
/// The "emptyStringIsNull" and "forceEmptyString" features are mutually exclusive.
/// While these features can not both be true at the same time, they can both be false,
/// resulting in default underlying database behavior.
///
{
addProperty("storage", &AbstractSessionImpl<C>::setStorage, &AbstractSessionImpl<C>::getStorage);
addProperty("handle", &AbstractSessionImpl<C>::setHandle, &AbstractSessionImpl<C>::getHandle);
addFeature("bulk", &AbstractSessionImpl<C>::setBulk, &AbstractSessionImpl<C>::getBulk);
addFeature("emptyStringIsNull", &AbstractSessionImpl<C>::setEmptyStringIsNull, &AbstractSessionImpl<C>::getEmptyStringIsNull);
addFeature("forceEmptyString", &AbstractSessionImpl<C>::setForceEmptyString, &AbstractSessionImpl<C>::getForceEmptyString);
}
~AbstractSessionImpl()
/// Destroys the AbstractSessionImpl.
{
}
void setFeature(const std::string & name, bool state)
/// Looks a feature up in the features map
/// and calls the feature's setter, if there is one.
{
typename FeatureMap::const_iterator it = _features.find(name);
if (it != _features.end())
{
if (it->second.setter)
(static_cast<C *>(this)->*it->second.setter)(name, state);
else
throw NotImplementedException("set", name);
}
else
throw NotSupportedException(name);
}
bool getFeature(const std::string & name)
/// Looks a feature up in the features map
/// and calls the feature's getter, if there is one.
{
typename FeatureMap::const_iterator it = _features.find(name);
if (it != _features.end())
{
if (it->second.getter)
return (static_cast<C *>(this)->*it->second.getter)(name);
else
throw NotImplementedException("get", name);
}
else
throw NotSupportedException(name);
}
void setProperty(const std::string & name, const Poco::Any & value)
/// Looks a property up in the properties map
/// and calls the property's setter, if there is one.
{
typename PropertyMap::const_iterator it = _properties.find(name);
if (it != _properties.end())
{
if (it->second.setter)
(static_cast<C *>(this)->*it->second.setter)(name, value);
else
throw NotImplementedException("set", name);
}
else
throw NotSupportedException(name);
}
Poco::Any getProperty(const std::string & name)
/// Looks a property up in the properties map
/// and calls the property's getter, if there is one.
{
typename PropertyMap::const_iterator it = _properties.find(name);
if (it != _properties.end())
{
if (it->second.getter)
return (static_cast<C *>(this)->*it->second.getter)(name);
else
throw NotImplementedException("set", name);
}
else
throw NotSupportedException(name);
}
void setStorage(const std::string & value)
/// Sets the storage type.
{
_storage = value;
}
void setStorage(const std::string & name, const Poco::Any & value)
/// Sets the storage type.
{
_storage = Poco::RefAnyCast<std::string>(value);
}
Poco::Any getStorage(const std::string & name = "")
/// Returns the storage type
{
return _storage;
}
void setHandle(const std::string & name, const Poco::Any & handle)
/// Sets the native session handle.
{
_handle = handle;
}
Poco::Any getHandle(const std::string & name = "")
/// Returns the native session handle.
{
return _handle;
}
void setBulk(const std::string & name, bool bulk)
/// Sets the execution type.
{
_bulk = bulk;
}
bool getBulk(const std::string & name = "")
/// Returns the execution type
{
return _bulk;
}
void setEmptyStringIsNull(const std::string & name, bool emptyStringIsNull)
/// Sets the behavior regarding empty variable length strings.
/// Those are treated as NULL by Oracle and as empty string by
/// most other databases.
/// When this feature is true, empty strings are treated as NULL.
{
if (emptyStringIsNull && _forceEmptyString)
throw InvalidAccessException("Features mutually exclusive");
_emptyStringIsNull = emptyStringIsNull;
}
bool getEmptyStringIsNull(const std::string & name = "")
/// Returns the setting for the behavior regarding empty variable
/// length strings. See setEmptyStringIsNull(const std::string&, bool)
/// and this class documentation for feature rationale and details.
{
return _emptyStringIsNull;
}
void setForceEmptyString(const std::string & name, bool forceEmptyString)
/// Sets the behavior regarding empty variable length strings.
/// Those are treated as NULL by Oracle and as empty string by
/// most other databases.
/// When this feature is true, both empty strings and NULL values
/// are reported as empty strings.
{
if (forceEmptyString && _emptyStringIsNull)
throw InvalidAccessException("Features mutually exclusive");
_forceEmptyString = forceEmptyString;
}
bool getForceEmptyString(const std::string & name = "")
/// Returns the setting for the behavior regarding empty variable
/// length strings. See setForceEmptyString(const std::string&, bool)
/// and this class documentation for feature rationale and details.
{
return _forceEmptyString;
}
protected:
void addFeature(const std::string & name, FeatureSetter setter, FeatureGetter getter)
/// Adds a feature to the map of supported features.
///
/// The setter or getter can be null, in case setting or getting a feature
/// is not supported.
{
Feature feature;
feature.setter = setter;
feature.getter = getter;
_features[name] = feature;
}
void addProperty(const std::string & name, PropertySetter setter, PropertyGetter getter)
/// Adds a property to the map of supported properties.
///
/// The setter or getter can be null, in case setting or getting a property
/// is not supported.
{
Property property;
property.setter = setter;
property.getter = getter;
_properties[name] = property;
}
private:
struct Feature
{
FeatureSetter setter;
FeatureGetter getter;
};
struct Property
{
PropertySetter setter;
PropertyGetter getter;
};
typedef std::map<std::string, Feature> FeatureMap;
typedef std::map<std::string, Property> PropertyMap;
FeatureMap _features;
PropertyMap _properties;
std::string _storage;
bool _bulk;
bool _emptyStringIsNull;
bool _forceEmptyString;
Poco::Any _handle;
};
}
} // namespace Poco::Data
#endif // Data_AbstractSessionImpl_INCLUDED

View File

@ -21,202 +21,206 @@
#include "Poco/Data/Data.h"
#include "Poco/Data/Session.h"
#include "Poco/DateTime.h"
#include "Poco/Timespan.h"
#include "Poco/Dynamic/Var.h"
#include "Poco/SharedPtr.h"
#include "Poco/Timespan.h"
namespace Poco {
namespace Data {
class Data_API ArchiveStrategy
/// The ArchiveStrategy is used by SQLChannel to archive log rows.
namespace Poco
{
public:
static const std::string DEFAULT_ARCHIVE_DESTINATION;
ArchiveStrategy(const std::string& connector,
const std::string& connect,
const std::string& source,
const std::string& destination = DEFAULT_ARCHIVE_DESTINATION);
/// Creates archive strategy.
virtual ~ArchiveStrategy();
/// Destroys archive strategy.
void open();
/// Opens the session.
virtual void archive() = 0;
/// Archives the rows.
const std::string& getSource() const;
/// Returns the name of the source table containing rows to be archived.
void setSource(const std::string& source);
/// Sets the name of the source table.
const std::string& getDestination() const;
/// Returns the name of the destination table for rows to be archived.
void setDestination(const std::string& destination);
/// Sets the name of the destination table.
virtual const std::string& getThreshold() const = 0;
/// Returns the archive threshold.
virtual void setThreshold(const std::string& threshold) = 0;
/// Sets the archive threshold.
protected:
typedef Poco::SharedPtr<Session> SessionPtr;
typedef Poco::SharedPtr<Statement> StatementPtr;
Session& session();
void setCopyStatement();
void setDeleteStatement();
void setCountStatement();
Statement& getCopyStatement();
Statement& getDeleteStatement();
Statement& getCountStatement();
private:
ArchiveStrategy();
ArchiveStrategy(const ArchiveStrategy&);
ArchiveStrategy& operator = (const ArchiveStrategy&);
std::string _connector;
std::string _connect;
SessionPtr _pSession;
StatementPtr _pCopyStatement;
StatementPtr _pDeleteStatement;
StatementPtr _pCountStatement;
std::string _source;
std::string _destination;
};
//
// inlines
//
inline const std::string& ArchiveStrategy::getSource() const
namespace Data
{
return _source;
class Data_API ArchiveStrategy
/// The ArchiveStrategy is used by SQLChannel to archive log rows.
{
public:
static const std::string DEFAULT_ARCHIVE_DESTINATION;
ArchiveStrategy(
const std::string & connector,
const std::string & connect,
const std::string & source,
const std::string & destination = DEFAULT_ARCHIVE_DESTINATION);
/// Creates archive strategy.
virtual ~ArchiveStrategy();
/// Destroys archive strategy.
void open();
/// Opens the session.
virtual void archive() = 0;
/// Archives the rows.
const std::string & getSource() const;
/// Returns the name of the source table containing rows to be archived.
void setSource(const std::string & source);
/// Sets the name of the source table.
const std::string & getDestination() const;
/// Returns the name of the destination table for rows to be archived.
void setDestination(const std::string & destination);
/// Sets the name of the destination table.
virtual const std::string & getThreshold() const = 0;
/// Returns the archive threshold.
virtual void setThreshold(const std::string & threshold) = 0;
/// Sets the archive threshold.
protected:
typedef Poco::SharedPtr<Session> SessionPtr;
typedef Poco::SharedPtr<Statement> StatementPtr;
Session & session();
void setCopyStatement();
void setDeleteStatement();
void setCountStatement();
Statement & getCopyStatement();
Statement & getDeleteStatement();
Statement & getCountStatement();
private:
ArchiveStrategy();
ArchiveStrategy(const ArchiveStrategy &);
ArchiveStrategy & operator=(const ArchiveStrategy &);
std::string _connector;
std::string _connect;
SessionPtr _pSession;
StatementPtr _pCopyStatement;
StatementPtr _pDeleteStatement;
StatementPtr _pCountStatement;
std::string _source;
std::string _destination;
};
//
// inlines
//
inline const std::string & ArchiveStrategy::getSource() const
{
return _source;
}
inline void ArchiveStrategy::setSource(const std::string & source)
{
_source = source;
}
inline void ArchiveStrategy::setDestination(const std::string & destination)
{
_destination = destination;
}
inline const std::string & ArchiveStrategy::getDestination() const
{
return _destination;
}
inline Session & ArchiveStrategy::session()
{
return *_pSession;
}
inline void ArchiveStrategy::setCopyStatement()
{
_pCopyStatement = new Statement(*_pSession);
}
inline void ArchiveStrategy::setDeleteStatement()
{
_pDeleteStatement = new Statement(*_pSession);
}
inline void ArchiveStrategy::setCountStatement()
{
_pCountStatement = new Statement(*_pSession);
}
inline Statement & ArchiveStrategy::getCopyStatement()
{
return *_pCopyStatement;
}
inline Statement & ArchiveStrategy::getDeleteStatement()
{
return *_pDeleteStatement;
}
inline Statement & ArchiveStrategy::getCountStatement()
{
return *_pCountStatement;
}
//
// ArchiveByAgeStrategy
//
class Data_API ArchiveByAgeStrategy : public ArchiveStrategy
/// Archives rows scheduled for archiving.
{
public:
ArchiveByAgeStrategy(
const std::string & connector,
const std::string & connect,
const std::string & sourceTable,
const std::string & destinationTable = DEFAULT_ARCHIVE_DESTINATION);
~ArchiveByAgeStrategy();
void archive();
const std::string & getThreshold() const;
/// Returns the archive threshold.
void setThreshold(const std::string & threshold);
/// Sets the archive threshold.
private:
ArchiveByAgeStrategy();
ArchiveByAgeStrategy(const ArchiveByAgeStrategy &);
ArchiveByAgeStrategy & operator=(const ArchiveByAgeStrategy &);
void initStatements();
Timespan _maxAge;
std::string _ageString;
DateTime _archiveDateTime;
Poco::Dynamic::Var _archiveCount;
};
//
// inlines
//
inline const std::string & ArchiveByAgeStrategy::getThreshold() const
{
return _ageString;
}
}
inline void ArchiveStrategy::setSource(const std::string& source)
{
_source = source;
}
inline void ArchiveStrategy::setDestination(const std::string& destination)
{
_destination = destination;
}
inline const std::string& ArchiveStrategy::getDestination() const
{
return _destination;
}
inline Session& ArchiveStrategy::session()
{
return *_pSession;
}
inline void ArchiveStrategy::setCopyStatement()
{
_pCopyStatement = new Statement(*_pSession);
}
inline void ArchiveStrategy::setDeleteStatement()
{
_pDeleteStatement = new Statement(*_pSession);
}
inline void ArchiveStrategy::setCountStatement()
{
_pCountStatement = new Statement(*_pSession);
}
inline Statement& ArchiveStrategy::getCopyStatement()
{
return *_pCopyStatement;
}
inline Statement& ArchiveStrategy::getDeleteStatement()
{
return *_pDeleteStatement;
}
inline Statement& ArchiveStrategy::getCountStatement()
{
return *_pCountStatement;
}
//
// ArchiveByAgeStrategy
//
class Data_API ArchiveByAgeStrategy: public ArchiveStrategy
/// Archives rows scheduled for archiving.
{
public:
ArchiveByAgeStrategy(const std::string& connector,
const std::string& connect,
const std::string& sourceTable,
const std::string& destinationTable = DEFAULT_ARCHIVE_DESTINATION);
~ArchiveByAgeStrategy();
void archive();
const std::string& getThreshold() const;
/// Returns the archive threshold.
void setThreshold(const std::string& threshold);
/// Sets the archive threshold.
private:
ArchiveByAgeStrategy();
ArchiveByAgeStrategy(const ArchiveByAgeStrategy&);
ArchiveByAgeStrategy& operator = (const ArchiveByAgeStrategy&);
void initStatements();
Timespan _maxAge;
std::string _ageString;
DateTime _archiveDateTime;
Poco::Dynamic::Var _archiveCount;
};
//
// inlines
//
inline const std::string& ArchiveByAgeStrategy::getThreshold() const
{
return _ageString;
}
} } // namespace Poco::Data
} // namespace Poco::Data
#endif // Data_ArchiveStrategy_INCLUDED

View File

@ -14,7 +14,6 @@
//
#ifndef Data_AutoTransaction_INCLUDED
#define Data_AutoTransaction_INCLUDED
@ -22,14 +21,17 @@
#include "Poco/Data/Transaction.h"
namespace Poco {
namespace Data {
namespace Poco
{
namespace Data
{
typedef Transaction AutoTransaction;
typedef Transaction AutoTransaction;
} } // namespace Poco::Data
}
} // namespace Poco::Data
#endif // Data_AutoTransaction_INCLUDED

File diff suppressed because it is too large Load Diff

View File

@ -18,79 +18,83 @@
#define Data_Bulk_INCLUDED
#include "Poco/Void.h"
#include "Poco/Data/Limit.h"
#include "Poco/Void.h"
namespace Poco {
namespace Data {
class Data_API Bulk
namespace Poco
{
public:
Bulk(const Limit& limit);
/// Creates the Bulk.
Bulk(Poco::UInt32 value);
/// Creates the Bulk.
~Bulk();
/// Destroys the bulk.
const Limit& limit() const;
/// Returns the limit asociated with this bulk object.
Poco::UInt32 size() const;
/// Returns the value of the limit asociated with
/// this bulk object.
private:
Bulk();
Limit _limit;
};
///
/// inlines
///
inline const Limit& Bulk::limit() const
{
return _limit;
}
inline Poco::UInt32 Bulk::size() const
{
return _limit.value();
}
namespace Keywords {
inline Bulk bulk(const Limit& limit = Limit(Limit::LIMIT_UNLIMITED, false, false))
/// Convenience function for creation of bulk.
namespace Data
{
return Bulk(limit);
class Data_API Bulk
{
public:
Bulk(const Limit & limit);
/// Creates the Bulk.
Bulk(Poco::UInt32 value);
/// Creates the Bulk.
~Bulk();
/// Destroys the bulk.
const Limit & limit() const;
/// Returns the limit associated with this bulk object.
Poco::UInt32 size() const;
/// Returns the value of the limit associated with
/// this bulk object.
private:
Bulk();
Limit _limit;
};
///
/// inlines
///
inline const Limit & Bulk::limit() const
{
return _limit;
}
inline Poco::UInt32 Bulk::size() const
{
return _limit.value();
}
namespace Keywords
{
inline Bulk bulk(const Limit & limit = Limit(Limit::LIMIT_UNLIMITED, false, false))
/// Convenience function for creation of bulk.
{
return Bulk(limit);
}
inline void bulk(Void)
/// Dummy bulk function. Used for bulk binding creation
/// (see BulkBinding) and bulk extraction signalling to Statement.
{
}
} // namespace Keywords
typedef void (*BulkFnType)(Void);
}
inline void bulk(Void)
/// Dummy bulk function. Used for bulk binding creation
/// (see BulkBinding) and bulk extraction signalling to Statement.
{
}
} // namespace Keywords
typedef void (*BulkFnType)(Void);
} } // namespace Poco::Data
} // namespace Poco::Data
#endif // Data_Bulk_INCLUDED

View File

@ -18,131 +18,124 @@
#define Data_BulkBinding_INCLUDED
#include "Poco/Data/Data.h"
#include "Poco/Data/AbstractBinding.h"
#include "Poco/Data/DataException.h"
#include "Poco/Data/TypeHandler.h"
#include "Poco/Data/Bulk.h"
#include <vector>
#include <cstddef>
#include <deque>
#include <list>
#include <cstddef>
#include <vector>
#include "Poco/Data/AbstractBinding.h"
#include "Poco/Data/Bulk.h"
#include "Poco/Data/Data.h"
#include "Poco/Data/DataException.h"
#include "Poco/Data/TypeHandler.h"
namespace Poco {
namespace Data {
template <class T>
class BulkBinding: public AbstractBinding
/// A BulkBinding maps a value to a column.
/// Bulk binding support is provided only for std::vector.
namespace Poco
{
public:
BulkBinding(const T& val, Poco::UInt32 bulkSize, const std::string& name = "", Direction direction = PD_IN):
AbstractBinding(name, direction, bulkSize),
_val(val),
_bound(false)
/// Creates the BulkBinding.
{
if (0 == _val.size())
throw BindingException("Zero size containers not allowed.");
}
~BulkBinding()
/// Destroys the BulkBinding.
{
}
std::size_t numOfColumnsHandled() const
{
return 1;
}
std::size_t numOfRowsHandled() const
{
return _val.size();
}
bool canBind() const
{
return !_bound;
}
void bind(std::size_t pos)
{
poco_assert_dbg(!getBinder().isNull());
TypeHandler<T>::bind(pos, _val, getBinder(), getDirection());
_bound = true;
}
void reset ()
{
_bound = false;
getBinder()->reset();
}
private:
const T& _val;
bool _bound;
};
namespace Keywords {
template <typename T>
AbstractBinding::Ptr use(const std::vector<T>& t, BulkFnType, const std::string& name = "")
/// Convenience function for a more compact BulkBinding creation for std::vector.
namespace Data
{
return new BulkBinding<std::vector<T> >(t, static_cast<Poco::UInt32>(t.size()), name);
template <class T>
class BulkBinding : public AbstractBinding
/// A BulkBinding maps a value to a column.
/// Bulk binding support is provided only for std::vector.
{
public:
BulkBinding(const T & val, Poco::UInt32 bulkSize, const std::string & name = "", Direction direction = PD_IN)
: AbstractBinding(name, direction, bulkSize), _val(val), _bound(false)
/// Creates the BulkBinding.
{
if (0 == _val.size())
throw BindingException("Zero size containers not allowed.");
}
~BulkBinding()
/// Destroys the BulkBinding.
{
}
std::size_t numOfColumnsHandled() const { return 1; }
std::size_t numOfRowsHandled() const { return _val.size(); }
bool canBind() const { return !_bound; }
void bind(std::size_t pos)
{
poco_assert_dbg(!getBinder().isNull());
TypeHandler<T>::bind(pos, _val, getBinder(), getDirection());
_bound = true;
}
void reset()
{
_bound = false;
getBinder()->reset();
}
private:
const T & _val;
bool _bound;
};
namespace Keywords
{
template <typename T>
AbstractBinding::Ptr use(const std::vector<T> & t, BulkFnType, const std::string & name = "")
/// Convenience function for a more compact BulkBinding creation for std::vector.
{
return new BulkBinding<std::vector<T>>(t, static_cast<Poco::UInt32>(t.size()), name);
}
template <typename T>
AbstractBinding::Ptr in(const std::vector<T> & t, BulkFnType, const std::string & name = "")
/// Convenience function for a more compact BulkBinding creation for std::vector.
{
return new BulkBinding<std::vector<T>>(t, static_cast<Poco::UInt32>(t.size()), name);
}
template <typename T>
AbstractBinding::Ptr use(const std::deque<T> & t, BulkFnType, const std::string & name = "")
/// Convenience function for a more compact BulkBinding creation for std::deque.
{
return new BulkBinding<std::deque<T>>(t, static_cast<Poco::UInt32>(t.size()), name);
}
template <typename T>
AbstractBinding::Ptr in(const std::deque<T> & t, BulkFnType, const std::string & name = "")
/// Convenience function for a more compact BulkBinding creation for std::deque.
{
return new BulkBinding<std::deque<T>>(t, static_cast<Poco::UInt32>(t.size()), name);
}
template <typename T>
AbstractBinding::Ptr use(const std::list<T> & t, BulkFnType, const std::string & name = "")
/// Convenience function for a more compact BulkBinding creation for std::list.
{
return new BulkBinding<std::list<T>>(t, static_cast<Poco::UInt32>(t.size()), name);
}
template <typename T>
AbstractBinding::Ptr in(const std::list<T> & t, BulkFnType, const std::string & name = "")
/// Convenience function for a more compact BulkBinding creation for std::list.
{
return new BulkBinding<std::list<T>>(t, static_cast<Poco::UInt32>(t.size()), name);
}
} // namespace Keywords
}
template <typename T>
AbstractBinding::Ptr in(const std::vector<T>& t, BulkFnType, const std::string& name = "")
/// Convenience function for a more compact BulkBinding creation for std::vector.
{
return new BulkBinding<std::vector<T> >(t, static_cast<Poco::UInt32>(t.size()), name);
}
template <typename T>
AbstractBinding::Ptr use(const std::deque<T>& t, BulkFnType, const std::string& name = "")
/// Convenience function for a more compact BulkBinding creation for std::deque.
{
return new BulkBinding<std::deque<T> >(t, static_cast<Poco::UInt32>(t.size()), name);
}
template <typename T>
AbstractBinding::Ptr in(const std::deque<T>& t, BulkFnType, const std::string& name = "")
/// Convenience function for a more compact BulkBinding creation for std::deque.
{
return new BulkBinding<std::deque<T> >(t, static_cast<Poco::UInt32>(t.size()), name);
}
template <typename T>
AbstractBinding::Ptr use(const std::list<T>& t, BulkFnType, const std::string& name = "")
/// Convenience function for a more compact BulkBinding creation for std::list.
{
return new BulkBinding<std::list<T> >(t, static_cast<Poco::UInt32>(t.size()), name);
}
template <typename T>
AbstractBinding::Ptr in(const std::list<T>& t, BulkFnType, const std::string& name = "")
/// Convenience function for a more compact BulkBinding creation for std::list.
{
return new BulkBinding<std::list<T> >(t, static_cast<Poco::UInt32>(t.size()), name);
}
} // namespace Keywords
} } // namespace Poco::Data
} // namespace Poco::Data
#endif // Data_BulkBinding_INCLUDED

View File

@ -18,259 +18,236 @@
#define Data_BulkExtraction_INCLUDED
#include "Poco/Data/Data.h"
#include <vector>
#include "Poco/Data/AbstractExtraction.h"
#include "Poco/Data/Bulk.h"
#include "Poco/Data/Column.h"
#include "Poco/Data/Data.h"
#include "Poco/Data/Position.h"
#include "Poco/Data/Preparation.h"
#include <vector>
namespace Poco {
namespace Data {
template <class C>
class BulkExtraction: public AbstractExtraction
/// Specialization for bulk extraction of values from a query result set.
/// Bulk extraction support is provided only for following STL containers:
/// - std::vector
/// - std::deque
/// - std::list
namespace Poco
{
public:
typedef C ValType;
typedef typename C::value_type CValType;
typedef SharedPtr<ValType> ValPtr;
typedef BulkExtraction<ValType> Type;
typedef SharedPtr<Type> Ptr;
BulkExtraction(C& result, Poco::UInt32 limit, const Position& pos = Position(0)):
AbstractExtraction(limit, pos.value(), true),
_rResult(result),
_default()
{
if (static_cast<Poco::UInt32>(result.size()) != limit)
result.resize(limit);
}
BulkExtraction(C& result, const CValType& def, Poco::UInt32 limit, const Position& pos = Position(0)):
AbstractExtraction(limit, pos.value(), true),
_rResult(result),
_default(def)
{
if (static_cast<Poco::UInt32>(result.size()) != limit)
result.resize(limit);
}
virtual ~BulkExtraction()
{
}
std::size_t numOfColumnsHandled() const
{
return TypeHandler<C>::size();
}
std::size_t numOfRowsHandled() const
{
return _rResult.size();
}
std::size_t numOfRowsAllowed() const
{
return getLimit();
}
bool isNull(std::size_t row) const
{
try
{
return _nulls.at(row);
}
catch (std::out_of_range& ex)
{
throw RangeException(ex.what());
}
}
std::size_t extract(std::size_t col)
{
AbstractExtractor::Ptr pExt = getExtractor();
TypeHandler<C>::extract(col, _rResult, _default, pExt);
typename C::iterator it = _rResult.begin();
typename C::iterator end = _rResult.end();
for (int row = 0; it !=end; ++it, ++row)
{
_nulls.push_back(isValueNull(*it, pExt->isNull(col, row)));
}
return _rResult.size();
}
virtual void reset()
{
}
AbstractPreparation::Ptr createPreparation(AbstractPreparator::Ptr& pPrep, std::size_t col)
{
Poco::UInt32 limit = getLimit();
if (limit != _rResult.size()) _rResult.resize(limit);
pPrep->setLength(limit);
pPrep->setBulk(true);
return new Preparation<C>(pPrep, col, _rResult);
}
protected:
const C& result() const
{
return _rResult;
}
private:
C& _rResult;
CValType _default;
std::deque<bool> _nulls;
};
template <class C>
class InternalBulkExtraction: public BulkExtraction<C>
/// Container Data Type specialization extension for extraction of values from a query result set.
///
/// This class is intended for PocoData internal use - it is used by StatementImpl
/// to automaticaly create internal BulkExtraction in cases when statement returns data and no external storage
/// was supplied. It is later used by RecordSet to retrieve the fetched data after statement execution.
/// It takes ownership of the Column pointer supplied as constructor argument. Column object, in turn
/// owns the data container pointer.
///
/// InternalBulkExtraction objects can not be copied or assigned.
namespace Data
{
public:
typedef C ValType;
typedef typename C::value_type CValType;
typedef SharedPtr<ValType> ValPtr;
typedef InternalBulkExtraction<ValType> Type;
typedef SharedPtr<Type> Ptr;
InternalBulkExtraction(C& result,
Column<C>* pColumn,
Poco::UInt32 limit,
const Position& pos = Position(0)):
BulkExtraction<C>(result, CValType(), limit, pos),
_pColumn(pColumn)
/// Creates InternalBulkExtraction.
{
}
~InternalBulkExtraction()
/// Destroys InternalBulkExtraction.
{
delete _pColumn;
}
void reset()
{
_pColumn->reset();
}
const CValType& value(int index) const
{
try
{
return BulkExtraction<C>::result().at(index);
}
catch (std::out_of_range& ex)
{
throw RangeException(ex.what());
}
}
bool isNull(std::size_t row) const
{
return BulkExtraction<C>::isNull(row);
}
const Column<C>& column() const
{
return *_pColumn;
}
private:
InternalBulkExtraction();
InternalBulkExtraction(const InternalBulkExtraction&);
InternalBulkExtraction& operator = (const InternalBulkExtraction&);
Column<C>* _pColumn;
};
namespace Keywords {
template <class C>
class BulkExtraction : public AbstractExtraction
/// Specialization for bulk extraction of values from a query result set.
/// Bulk extraction support is provided only for following STL containers:
/// - std::vector
/// - std::deque
/// - std::list
{
public:
typedef C ValType;
typedef typename C::value_type CValType;
typedef SharedPtr<ValType> ValPtr;
typedef BulkExtraction<ValType> Type;
typedef SharedPtr<Type> Ptr;
BulkExtraction(C & result, Poco::UInt32 limit, const Position & pos = Position(0))
: AbstractExtraction(limit, pos.value(), true), _rResult(result), _default()
{
if (static_cast<Poco::UInt32>(result.size()) != limit)
result.resize(limit);
}
BulkExtraction(C & result, const CValType & def, Poco::UInt32 limit, const Position & pos = Position(0))
: AbstractExtraction(limit, pos.value(), true), _rResult(result), _default(def)
{
if (static_cast<Poco::UInt32>(result.size()) != limit)
result.resize(limit);
}
virtual ~BulkExtraction() { }
std::size_t numOfColumnsHandled() const { return TypeHandler<C>::size(); }
std::size_t numOfRowsHandled() const { return _rResult.size(); }
std::size_t numOfRowsAllowed() const { return getLimit(); }
bool isNull(std::size_t row) const
{
try
{
return _nulls.at(row);
}
catch (std::out_of_range & ex)
{
throw RangeException(ex.what());
}
}
std::size_t extract(std::size_t col)
{
AbstractExtractor::Ptr pExt = getExtractor();
TypeHandler<C>::extract(col, _rResult, _default, pExt);
typename C::iterator it = _rResult.begin();
typename C::iterator end = _rResult.end();
for (int row = 0; it != end; ++it, ++row)
{
_nulls.push_back(isValueNull(*it, pExt->isNull(col, row)));
}
return _rResult.size();
}
virtual void reset() { }
AbstractPreparation::Ptr createPreparation(AbstractPreparator::Ptr & pPrep, std::size_t col)
{
Poco::UInt32 limit = getLimit();
if (limit != _rResult.size())
_rResult.resize(limit);
pPrep->setLength(limit);
pPrep->setBulk(true);
return new Preparation<C>(pPrep, col, _rResult);
}
protected:
const C & result() const { return _rResult; }
private:
C & _rResult;
CValType _default;
std::deque<bool> _nulls;
};
template <class C>
class InternalBulkExtraction : public BulkExtraction<C>
/// Container Data Type specialization extension for extraction of values from a query result set.
///
/// This class is intended for PocoData internal use - it is used by StatementImpl
/// to automatically create internal BulkExtraction in cases when statement returns data and no external storage
/// was supplied. It is later used by RecordSet to retrieve the fetched data after statement execution.
/// It takes ownership of the Column pointer supplied as constructor argument. Column object, in turn
/// owns the data container pointer.
///
/// InternalBulkExtraction objects can not be copied or assigned.
{
public:
typedef C ValType;
typedef typename C::value_type CValType;
typedef SharedPtr<ValType> ValPtr;
typedef InternalBulkExtraction<ValType> Type;
typedef SharedPtr<Type> Ptr;
InternalBulkExtraction(C & result, Column<C> * pColumn, Poco::UInt32 limit, const Position & pos = Position(0))
: BulkExtraction<C>(result, CValType(), limit, pos), _pColumn(pColumn)
/// Creates InternalBulkExtraction.
{
}
~InternalBulkExtraction()
/// Destroys InternalBulkExtraction.
{
delete _pColumn;
}
void reset() { _pColumn->reset(); }
const CValType & value(int index) const
{
try
{
return BulkExtraction<C>::result().at(index);
}
catch (std::out_of_range & ex)
{
throw RangeException(ex.what());
}
}
bool isNull(std::size_t row) const { return BulkExtraction<C>::isNull(row); }
const Column<C> & column() const { return *_pColumn; }
private:
InternalBulkExtraction();
InternalBulkExtraction(const InternalBulkExtraction &);
InternalBulkExtraction & operator=(const InternalBulkExtraction &);
Column<C> * _pColumn;
};
namespace Keywords
{
template <typename T>
AbstractExtraction::Ptr into(std::vector<T> & t, const Bulk & bulk, const Position & pos = Position(0))
/// Convenience function to allow for a more compact creation of an extraction object
/// with std::vector bulk extraction support.
{
return new BulkExtraction<std::vector<T>>(t, bulk.size(), pos);
}
template <typename T>
AbstractExtraction::Ptr into(std::vector<T> & t, BulkFnType, const Position & pos = Position(0))
/// Convenience function to allow for a more compact creation of an extraction object
/// with std::vector bulk extraction support.
{
Poco::UInt32 size = static_cast<Poco::UInt32>(t.size());
if (0 == size)
throw InvalidArgumentException("Zero length not allowed.");
return new BulkExtraction<std::vector<T>>(t, size, pos);
}
template <typename T>
AbstractExtraction::Ptr into(std::deque<T> & t, const Bulk & bulk, const Position & pos = Position(0))
/// Convenience function to allow for a more compact creation of an extraction object
/// with std::deque bulk extraction support.
{
return new BulkExtraction<std::deque<T>>(t, bulk.size(), pos);
}
template <typename T>
AbstractExtraction::Ptr into(std::deque<T> & t, BulkFnType, const Position & pos = Position(0))
/// Convenience function to allow for a more compact creation of an extraction object
/// with std::deque bulk extraction support.
{
Poco::UInt32 size = static_cast<Poco::UInt32>(t.size());
if (0 == size)
throw InvalidArgumentException("Zero length not allowed.");
return new BulkExtraction<std::deque<T>>(t, size, pos);
}
template <typename T>
AbstractExtraction::Ptr into(std::list<T> & t, const Bulk & bulk, const Position & pos = Position(0))
/// Convenience function to allow for a more compact creation of an extraction object
/// with std::list bulk extraction support.
{
return new BulkExtraction<std::list<T>>(t, bulk.size(), pos);
}
template <typename T>
AbstractExtraction::Ptr into(std::list<T> & t, BulkFnType, const Position & pos = Position(0))
/// Convenience function to allow for a more compact creation of an extraction object
/// with std::list bulk extraction support.
{
Poco::UInt32 size = static_cast<Poco::UInt32>(t.size());
if (0 == size)
throw InvalidArgumentException("Zero length not allowed.");
return new BulkExtraction<std::list<T>>(t, size, pos);
}
} // namespace Keywords
template <typename T>
AbstractExtraction::Ptr into(std::vector<T>& t, const Bulk& bulk, const Position& pos = Position(0))
/// Convenience function to allow for a more compact creation of an extraction object
/// with std::vector bulk extraction support.
{
return new BulkExtraction<std::vector<T> >(t, bulk.size(), pos);
}
template <typename T>
AbstractExtraction::Ptr into(std::vector<T>& t, BulkFnType, const Position& pos = Position(0))
/// Convenience function to allow for a more compact creation of an extraction object
/// with std::vector bulk extraction support.
{
Poco::UInt32 size = static_cast<Poco::UInt32>(t.size());
if (0 == size) throw InvalidArgumentException("Zero length not allowed.");
return new BulkExtraction<std::vector<T> >(t, size, pos);
}
template <typename T>
AbstractExtraction::Ptr into(std::deque<T>& t, const Bulk& bulk, const Position& pos = Position(0))
/// Convenience function to allow for a more compact creation of an extraction object
/// with std::deque bulk extraction support.
{
return new BulkExtraction<std::deque<T> >(t, bulk.size(), pos);
}
template <typename T>
AbstractExtraction::Ptr into(std::deque<T>& t, BulkFnType, const Position& pos = Position(0))
/// Convenience function to allow for a more compact creation of an extraction object
/// with std::deque bulk extraction support.
{
Poco::UInt32 size = static_cast<Poco::UInt32>(t.size());
if (0 == size) throw InvalidArgumentException("Zero length not allowed.");
return new BulkExtraction<std::deque<T> >(t, size, pos);
}
template <typename T>
AbstractExtraction::Ptr into(std::list<T>& t, const Bulk& bulk, const Position& pos = Position(0))
/// Convenience function to allow for a more compact creation of an extraction object
/// with std::list bulk extraction support.
{
return new BulkExtraction<std::list<T> >(t, bulk.size(), pos);
}
template <typename T>
AbstractExtraction::Ptr into(std::list<T>& t, BulkFnType, const Position& pos = Position(0))
/// Convenience function to allow for a more compact creation of an extraction object
/// with std::list bulk extraction support.
{
Poco::UInt32 size = static_cast<Poco::UInt32>(t.size());
if (0 == size) throw InvalidArgumentException("Zero length not allowed.");
return new BulkExtraction<std::list<T> >(t, size, pos);
}
} // namespace Keywords
} } // namespace Poco::Data
} // namespace Poco::Data
#endif // Data_BulkExtraction_INCLUDED

View File

@ -18,473 +18,465 @@
#define Data_Column_INCLUDED
#include <deque>
#include <list>
#include <vector>
#include "Poco/Data/Data.h"
#include "Poco/Data/MetaColumn.h"
#include "Poco/SharedPtr.h"
#include "Poco/RefCountedObject.h"
#include <vector>
#include <list>
#include <deque>
#include "Poco/SharedPtr.h"
namespace Poco {
namespace Data {
template <class C>
class Column
/// Column class is column data container.
/// Data (a pointer to underlying STL container) is assigned to the class
/// at construction time. Construction with null pointer is not allowed.
/// This class owns the data assigned to it and deletes the storage on destruction.
namespace Poco
{
public:
typedef C Container;
typedef Poco::SharedPtr<C> ContainerPtr;
typedef typename C::const_iterator Iterator;
typedef typename C::const_reverse_iterator RIterator;
typedef typename C::size_type Size;
typedef typename C::value_type Type;
Column(const MetaColumn& metaColumn, Container* pData):
_metaColumn(metaColumn),
_pData(pData)
/// Creates the Column.
{
if (!_pData)
throw NullPointerException("Container pointer must point to valid storage.");
}
Column(const Column& col):
_metaColumn(col._metaColumn),
_pData(col._pData)
/// Creates the Column.
{
}
~Column()
/// Destroys the Column.
{
}
Column& operator = (const Column& col)
/// Assignment operator.
{
Column tmp(col);
swap(tmp);
return *this;
}
void swap(Column& other)
/// Swaps the column with another one.
{
using std::swap;
swap(_metaColumn, other._metaColumn);
swap(_pData, other._pData);
}
Container& data()
/// Returns reference to contained data.
{
return *_pData;
}
const Type& value(std::size_t row) const
/// Returns the field value in specified row.
{
try
{
return _pData->at(row);
}
catch (std::out_of_range& ex)
{
throw RangeException(ex.what());
}
}
const Type& operator [] (std::size_t row) const
/// Returns the field value in specified row.
{
return value(row);
}
Size rowCount() const
/// Returns number of rows.
{
return _pData->size();
}
void reset()
/// Clears and shrinks the storage.
{
Container().swap(*_pData);
}
const std::string& name() const
/// Returns column name.
{
return _metaColumn.name();
}
std::size_t length() const
/// Returns column maximum length.
{
return _metaColumn.length();
}
std::size_t precision() const
/// Returns column precision.
/// Valid for floating point fields only (zero for other data types).
{
return _metaColumn.precision();
}
std::size_t position() const
/// Returns column position.
{
return _metaColumn.position();
}
MetaColumn::ColumnDataType type() const
/// Returns column type.
{
return _metaColumn.type();
}
Iterator begin() const
/// Returns iterator pointing to the beginning of data storage vector.
{
return _pData->begin();
}
Iterator end() const
/// Returns iterator pointing to the end of data storage vector.
{
return _pData->end();
}
private:
Column();
MetaColumn _metaColumn;
ContainerPtr _pData;
};
template <>
class Column<std::vector<bool> >
/// The std::vector<bool> specialization for the Column class.
///
/// This specialization is necessary due to the nature of std::vector<bool>.
/// For details, see the standard library implementation of vector<bool>
/// or
/// S. Meyers: "Effective STL" (Copyright Addison-Wesley 2001),
/// Item 18: "Avoid using vector<bool>."
///
/// The workaround employed here is using deque<bool> as an
/// internal "companion" container kept in sync with the vector<bool>
/// column data.
namespace Data
{
public:
typedef std::vector<bool> Container;
typedef Poco::SharedPtr<Container> ContainerPtr;
typedef Container::const_iterator Iterator;
typedef Container::const_reverse_iterator RIterator;
typedef Container::size_type Size;
Column(const MetaColumn& metaColumn, Container* pData):
_metaColumn(metaColumn),
_pData(pData)
/// Creates the Column.
{
poco_check_ptr (_pData);
_deque.assign(_pData->begin(), _pData->end());
}
Column(const Column& col):
_metaColumn(col._metaColumn),
_pData(col._pData)
/// Creates the Column.
{
_deque.assign(_pData->begin(), _pData->end());
}
~Column()
/// Destroys the Column.
{
}
Column& operator = (const Column& col)
/// Assignment operator.
{
Column tmp(col);
swap(tmp);
return *this;
}
void swap(Column& other)
/// Swaps the column with another one.
{
using std::swap;
swap(_metaColumn, other._metaColumn);
swap(_pData, other._pData);
swap(_deque, other._deque);
}
Container& data()
/// Returns reference to contained data.
{
return *_pData;
}
const bool& value(std::size_t row) const
/// Returns the field value in specified row.
{
if (_deque.size() < _pData->size())
_deque.resize(_pData->size());
try
{
return _deque.at(row) = _pData->at(row);
}
catch (std::out_of_range& ex)
{
throw RangeException(ex.what());
}
}
const bool& operator [] (std::size_t row) const
/// Returns the field value in specified row.
{
return value(row);
}
Size rowCount() const
/// Returns number of rows.
{
return _pData->size();
}
void reset()
/// Clears and shrinks the storage.
{
Container().swap(*_pData);
_deque.clear();
}
const std::string& name() const
/// Returns column name.
{
return _metaColumn.name();
}
std::size_t length() const
/// Returns column maximum length.
{
return _metaColumn.length();
}
std::size_t precision() const
/// Returns column precision.
/// Valid for floating point fields only (zero for other data types).
{
return _metaColumn.precision();
}
std::size_t position() const
/// Returns column position.
{
return _metaColumn.position();
}
MetaColumn::ColumnDataType type() const
/// Returns column type.
{
return _metaColumn.type();
}
Iterator begin() const
/// Returns iterator pointing to the beginning of data storage vector.
{
return _pData->begin();
}
Iterator end() const
/// Returns iterator pointing to the end of data storage vector.
{
return _pData->end();
}
private:
Column();
MetaColumn _metaColumn;
ContainerPtr _pData;
mutable std::deque<bool> _deque;
};
template <class T>
class Column<std::list<T> >
/// Column specialization for std::list
{
public:
typedef std::list<T> Container;
typedef Poco::SharedPtr<Container> ContainerPtr;
typedef typename Container::const_iterator Iterator;
typedef typename Container::const_reverse_iterator RIterator;
typedef typename Container::size_type Size;
template <class C>
class Column
/// Column class is column data container.
/// Data (a pointer to underlying STL container) is assigned to the class
/// at construction time. Construction with null pointer is not allowed.
/// This class owns the data assigned to it and deletes the storage on destruction.
{
public:
typedef C Container;
typedef Poco::SharedPtr<C> ContainerPtr;
typedef typename C::const_iterator Iterator;
typedef typename C::const_reverse_iterator RIterator;
typedef typename C::size_type Size;
typedef typename C::value_type Type;
Column(const MetaColumn& metaColumn, std::list<T>* pData):
_metaColumn(metaColumn),
_pData(pData)
/// Creates the Column.
{
poco_check_ptr (_pData);
}
Column(const MetaColumn & metaColumn, Container * pData) : _metaColumn(metaColumn), _pData(pData)
/// Creates the Column.
{
if (!_pData)
throw NullPointerException("Container pointer must point to valid storage.");
}
Column(const Column& col):
_metaColumn(col._metaColumn),
_pData(col._pData)
/// Creates the Column.
{
}
Column(const Column & col) : _metaColumn(col._metaColumn), _pData(col._pData)
/// Creates the Column.
{
}
~Column()
/// Destroys the Column.
{
}
~Column()
/// Destroys the Column.
{
}
Column& operator = (const Column& col)
/// Assignment operator.
{
Column tmp(col);
swap(tmp);
return *this;
}
Column & operator=(const Column & col)
/// Assignment operator.
{
Column tmp(col);
swap(tmp);
return *this;
}
void swap(Column& other)
/// Swaps the column with another one.
{
using std::swap;
swap(_metaColumn, other._metaColumn);
swap(_pData, other._pData);
}
void swap(Column & other)
/// Swaps the column with another one.
{
using std::swap;
swap(_metaColumn, other._metaColumn);
swap(_pData, other._pData);
}
Container& data()
/// Returns reference to contained data.
{
return *_pData;
}
Container & data()
/// Returns reference to contained data.
{
return *_pData;
}
const T& value(std::size_t row) const
/// Returns the field value in specified row.
/// This is the std::list specialization and std::list
/// is not the optimal solution for cases where random
/// access is needed.
/// However, to allow for compatibility with other
/// containers, this functionality is provided here.
/// To alleviate the problem, an effort is made
/// to start iteration from beginning or end,
/// depending on the position requested.
{
if (row <= (std::size_t) (_pData->size() / 2))
{
Iterator it = _pData->begin();
Iterator end = _pData->end();
for (int i = 0; it != end; ++it, ++i)
if (i == row) return *it;
}
else
{
row = _pData->size() - row;
RIterator it = _pData->rbegin();
RIterator end = _pData->rend();
for (int i = 1; it != end; ++it, ++i)
if (i == row) return *it;
}
const Type & value(std::size_t row) const
/// Returns the field value in specified row.
{
try
{
return _pData->at(row);
}
catch (std::out_of_range & ex)
{
throw RangeException(ex.what());
}
}
throw RangeException("Invalid row number.");
}
const Type & operator[](std::size_t row) const
/// Returns the field value in specified row.
{
return value(row);
}
const T& operator [] (std::size_t row) const
/// Returns the field value in specified row.
{
return value(row);
}
Size rowCount() const
/// Returns number of rows.
{
return _pData->size();
}
Size rowCount() const
/// Returns number of rows.
{
return _pData->size();
}
void reset()
/// Clears and shrinks the storage.
{
Container().swap(*_pData);
}
void reset()
/// Clears the storage.
{
_pData->clear();
}
const std::string & name() const
/// Returns column name.
{
return _metaColumn.name();
}
const std::string& name() const
/// Returns column name.
{
return _metaColumn.name();
}
std::size_t length() const
/// Returns column maximum length.
{
return _metaColumn.length();
}
std::size_t length() const
/// Returns column maximum length.
{
return _metaColumn.length();
}
std::size_t precision() const
/// Returns column precision.
/// Valid for floating point fields only (zero for other data types).
{
return _metaColumn.precision();
}
std::size_t precision() const
/// Returns column precision.
/// Valid for floating point fields only (zero for other data types).
{
return _metaColumn.precision();
}
std::size_t position() const
/// Returns column position.
{
return _metaColumn.position();
}
std::size_t position() const
/// Returns column position.
{
return _metaColumn.position();
}
MetaColumn::ColumnDataType type() const
/// Returns column type.
{
return _metaColumn.type();
}
MetaColumn::ColumnDataType type() const
/// Returns column type.
{
return _metaColumn.type();
}
Iterator begin() const
/// Returns iterator pointing to the beginning of data storage vector.
{
return _pData->begin();
}
Iterator begin() const
/// Returns iterator pointing to the beginning of data storage vector.
{
return _pData->begin();
}
Iterator end() const
/// Returns iterator pointing to the end of data storage vector.
{
return _pData->end();
}
Iterator end() const
/// Returns iterator pointing to the end of data storage vector.
{
return _pData->end();
}
private:
Column();
private:
Column();
MetaColumn _metaColumn;
ContainerPtr _pData;
};
MetaColumn _metaColumn;
ContainerPtr _pData;
};
template <>
class Column<std::vector<bool>>
/// The std::vector<bool> specialization for the Column class.
///
/// This specialization is necessary due to the nature of std::vector<bool>.
/// For details, see the standard library implementation of vector<bool>
/// or
/// S. Meyers: "Effective STL" (Copyright Addison-Wesley 2001),
/// Item 18: "Avoid using vector<bool>."
///
/// The workaround employed here is using deque<bool> as an
/// internal "companion" container kept in sync with the vector<bool>
/// column data.
{
public:
typedef std::vector<bool> Container;
typedef Poco::SharedPtr<Container> ContainerPtr;
typedef Container::const_iterator Iterator;
typedef Container::const_reverse_iterator RIterator;
typedef Container::size_type Size;
Column(const MetaColumn & metaColumn, Container * pData) : _metaColumn(metaColumn), _pData(pData)
/// Creates the Column.
{
poco_check_ptr(_pData);
_deque.assign(_pData->begin(), _pData->end());
}
Column(const Column & col) : _metaColumn(col._metaColumn), _pData(col._pData)
/// Creates the Column.
{
_deque.assign(_pData->begin(), _pData->end());
}
~Column()
/// Destroys the Column.
{
}
Column & operator=(const Column & col)
/// Assignment operator.
{
Column tmp(col);
swap(tmp);
return *this;
}
void swap(Column & other)
/// Swaps the column with another one.
{
using std::swap;
swap(_metaColumn, other._metaColumn);
swap(_pData, other._pData);
swap(_deque, other._deque);
}
Container & data()
/// Returns reference to contained data.
{
return *_pData;
}
const bool & value(std::size_t row) const
/// Returns the field value in specified row.
{
if (_deque.size() < _pData->size())
_deque.resize(_pData->size());
try
{
return _deque.at(row) = _pData->at(row);
}
catch (std::out_of_range & ex)
{
throw RangeException(ex.what());
}
}
const bool & operator[](std::size_t row) const
/// Returns the field value in specified row.
{
return value(row);
}
Size rowCount() const
/// Returns number of rows.
{
return _pData->size();
}
void reset()
/// Clears and shrinks the storage.
{
Container().swap(*_pData);
_deque.clear();
}
const std::string & name() const
/// Returns column name.
{
return _metaColumn.name();
}
std::size_t length() const
/// Returns column maximum length.
{
return _metaColumn.length();
}
std::size_t precision() const
/// Returns column precision.
/// Valid for floating point fields only (zero for other data types).
{
return _metaColumn.precision();
}
std::size_t position() const
/// Returns column position.
{
return _metaColumn.position();
}
MetaColumn::ColumnDataType type() const
/// Returns column type.
{
return _metaColumn.type();
}
Iterator begin() const
/// Returns iterator pointing to the beginning of data storage vector.
{
return _pData->begin();
}
Iterator end() const
/// Returns iterator pointing to the end of data storage vector.
{
return _pData->end();
}
private:
Column();
MetaColumn _metaColumn;
ContainerPtr _pData;
mutable std::deque<bool> _deque;
};
template <class T>
class Column<std::list<T>>
/// Column specialization for std::list
{
public:
typedef std::list<T> Container;
typedef Poco::SharedPtr<Container> ContainerPtr;
typedef typename Container::const_iterator Iterator;
typedef typename Container::const_reverse_iterator RIterator;
typedef typename Container::size_type Size;
Column(const MetaColumn & metaColumn, std::list<T> * pData) : _metaColumn(metaColumn), _pData(pData)
/// Creates the Column.
{
poco_check_ptr(_pData);
}
Column(const Column & col) : _metaColumn(col._metaColumn), _pData(col._pData)
/// Creates the Column.
{
}
~Column()
/// Destroys the Column.
{
}
Column & operator=(const Column & col)
/// Assignment operator.
{
Column tmp(col);
swap(tmp);
return *this;
}
void swap(Column & other)
/// Swaps the column with another one.
{
using std::swap;
swap(_metaColumn, other._metaColumn);
swap(_pData, other._pData);
}
Container & data()
/// Returns reference to contained data.
{
return *_pData;
}
const T & value(std::size_t row) const
/// Returns the field value in specified row.
/// This is the std::list specialization and std::list
/// is not the optimal solution for cases where random
/// access is needed.
/// However, to allow for compatibility with other
/// containers, this functionality is provided here.
/// To alleviate the problem, an effort is made
/// to start iteration from beginning or end,
/// depending on the position requested.
{
if (row <= (std::size_t)(_pData->size() / 2))
{
Iterator it = _pData->begin();
Iterator end = _pData->end();
for (int i = 0; it != end; ++it, ++i)
if (i == row)
return *it;
}
else
{
row = _pData->size() - row;
RIterator it = _pData->rbegin();
RIterator end = _pData->rend();
for (int i = 1; it != end; ++it, ++i)
if (i == row)
return *it;
}
throw RangeException("Invalid row number.");
}
const T & operator[](std::size_t row) const
/// Returns the field value in specified row.
{
return value(row);
}
Size rowCount() const
/// Returns number of rows.
{
return _pData->size();
}
void reset()
/// Clears the storage.
{
_pData->clear();
}
const std::string & name() const
/// Returns column name.
{
return _metaColumn.name();
}
std::size_t length() const
/// Returns column maximum length.
{
return _metaColumn.length();
}
std::size_t precision() const
/// Returns column precision.
/// Valid for floating point fields only (zero for other data types).
{
return _metaColumn.precision();
}
std::size_t position() const
/// Returns column position.
{
return _metaColumn.position();
}
MetaColumn::ColumnDataType type() const
/// Returns column type.
{
return _metaColumn.type();
}
Iterator begin() const
/// Returns iterator pointing to the beginning of data storage vector.
{
return _pData->begin();
}
Iterator end() const
/// Returns iterator pointing to the end of data storage vector.
{
return _pData->end();
}
private:
Column();
MetaColumn _metaColumn;
ContainerPtr _pData;
};
template <typename C>
inline void swap(Column<C> & c1, Column<C> & c2)
{
c1.swap(c2);
}
template <typename C>
inline void swap(Column<C>& c1, Column<C>& c2)
{
c1.swap(c2);
}
} } // namespace Poco::Data
} // namespace Poco::Data
#endif // Data_Column_INCLUDED

View File

@ -18,39 +18,42 @@
#define Data_Connector_INCLUDED
#include "Poco/AutoPtr.h"
#include "Poco/Data/Data.h"
#include "Poco/Data/SessionImpl.h"
#include "Poco/AutoPtr.h"
namespace Poco {
namespace Data {
class Data_API Connector
/// A Connector creates SessionImpl objects.
///
/// Every connector library (like the SQLite or the ODBC connector)
/// provides a subclass of this class, an instance of which is
/// registered with the SessionFactory.
namespace Poco
{
namespace Data
{
public:
Connector();
/// Creates the Connector.
virtual ~Connector();
/// Destroys the Connector.
virtual const std::string& name() const = 0;
/// Returns the name associated with this connector.
virtual Poco::AutoPtr<SessionImpl> createSession(const std::string& connectionString,
std::size_t timeout = SessionImpl::LOGIN_TIMEOUT_DEFAULT) = 0;
/// Create a SessionImpl object and initialize it with the given connectionString.
};
} } // namespace Poco::Data
class Data_API Connector
/// A Connector creates SessionImpl objects.
///
/// Every connector library (like the SQLite or the ODBC connector)
/// provides a subclass of this class, an instance of which is
/// registered with the SessionFactory.
{
public:
Connector();
/// Creates the Connector.
virtual ~Connector();
/// Destroys the Connector.
virtual const std::string & name() const = 0;
/// Returns the name associated with this connector.
virtual Poco::AutoPtr<SessionImpl>
createSession(const std::string & connectionString, std::size_t timeout = SessionImpl::LOGIN_TIMEOUT_DEFAULT) = 0;
/// Create a SessionImpl object and initialize it with the given connectionString.
};
}
} // namespace Poco::Data
#endif // Data_Connector_INCLUDED

View File

@ -19,18 +19,21 @@
#undef max
#include <limits>
#include <cstddef>
#include <limits>
namespace Poco {
namespace Data {
namespace Poco
{
namespace Data
{
static const std::size_t POCO_DATA_INVALID_ROW = std::numeric_limits<std::size_t>::max();
static const std::size_t POCO_DATA_INVALID_ROW = std::numeric_limits<std::size_t>::max();
} } // namespace Poco::Data
}
} // namespace Poco::Data
#endif // Data_Constants_INCLUDED

View File

@ -28,24 +28,24 @@
// from a DLL simpler. All files within this DLL are compiled with the Data_EXPORTS
// symbol defined on the command line. this symbol should not be defined on any project
// that uses this DLL. This way any other project whose source files include this file see
// Data_API functions as being imported from a DLL, wheras this DLL sees symbols
// Data_API functions as being imported from a DLL, whereas this DLL sees symbols
// defined with this macro as being exported.
//
#if defined(_WIN32) && defined(POCO_DLL)
#if defined(Data_EXPORTS)
#define Data_API __declspec(dllexport)
#else
#define Data_API __declspec(dllimport)
#endif
# if defined(Data_EXPORTS)
# define Data_API __declspec(dllexport)
# else
# define Data_API __declspec(dllimport)
# endif
#endif
#if !defined(Data_API)
#if !defined(POCO_NO_GCC_API_ATTRIBUTE) && defined (__GNUC__) && (__GNUC__ >= 4)
#define Data_API __attribute__ ((visibility ("default")))
#else
#define Data_API
#endif
# if !defined(POCO_NO_GCC_API_ATTRIBUTE) && defined(__GNUC__) && (__GNUC__ >= 4)
# define Data_API __attribute__((visibility("default")))
# else
# define Data_API
# endif
#endif
@ -53,9 +53,9 @@
// Automatically link Data library.
//
#if defined(_MSC_VER)
#if !defined(POCO_NO_AUTOMATIC_LIBS) && !defined(Data_EXPORTS)
#pragma comment(lib, "PocoData" POCO_LIB_SUFFIX)
#endif
# if !defined(POCO_NO_AUTOMATIC_LIBS) && !defined(Data_EXPORTS)
# pragma comment(lib, "PocoData" POCO_LIB_SUFFIX)
# endif
#endif

View File

@ -22,29 +22,32 @@
#include "Poco/Exception.h"
namespace Poco {
namespace Data {
namespace Poco
{
namespace Data
{
POCO_DECLARE_EXCEPTION(Data_API, DataException, Poco::IOException)
POCO_DECLARE_EXCEPTION(Data_API, RowDataMissingException, DataException)
POCO_DECLARE_EXCEPTION(Data_API, UnknownDataBaseException, DataException)
POCO_DECLARE_EXCEPTION(Data_API, UnknownTypeException, DataException)
POCO_DECLARE_EXCEPTION(Data_API, ExecutionException, DataException)
POCO_DECLARE_EXCEPTION(Data_API, BindingException, DataException)
POCO_DECLARE_EXCEPTION(Data_API, ExtractException, DataException)
POCO_DECLARE_EXCEPTION(Data_API, LimitException, DataException)
POCO_DECLARE_EXCEPTION(Data_API, NotSupportedException, DataException)
POCO_DECLARE_EXCEPTION(Data_API, SessionUnavailableException, DataException)
POCO_DECLARE_EXCEPTION(Data_API, SessionPoolExhaustedException, DataException)
POCO_DECLARE_EXCEPTION(Data_API, SessionPoolExistsException, DataException)
POCO_DECLARE_EXCEPTION(Data_API, NoDataException, DataException)
POCO_DECLARE_EXCEPTION(Data_API, LengthExceededException, DataException)
POCO_DECLARE_EXCEPTION(Data_API, ConnectionFailedException, DataException)
POCO_DECLARE_EXCEPTION(Data_API, NotConnectedException, DataException)
POCO_DECLARE_EXCEPTION(Data_API, DataException, Poco::IOException)
POCO_DECLARE_EXCEPTION(Data_API, RowDataMissingException, DataException)
POCO_DECLARE_EXCEPTION(Data_API, UnknownDataBaseException, DataException)
POCO_DECLARE_EXCEPTION(Data_API, UnknownTypeException, DataException)
POCO_DECLARE_EXCEPTION(Data_API, ExecutionException, DataException)
POCO_DECLARE_EXCEPTION(Data_API, BindingException, DataException)
POCO_DECLARE_EXCEPTION(Data_API, ExtractException, DataException)
POCO_DECLARE_EXCEPTION(Data_API, LimitException, DataException)
POCO_DECLARE_EXCEPTION(Data_API, NotSupportedException, DataException)
POCO_DECLARE_EXCEPTION(Data_API, SessionUnavailableException, DataException)
POCO_DECLARE_EXCEPTION(Data_API, SessionPoolExhaustedException, DataException)
POCO_DECLARE_EXCEPTION(Data_API, SessionPoolExistsException, DataException)
POCO_DECLARE_EXCEPTION(Data_API, NoDataException, DataException)
POCO_DECLARE_EXCEPTION(Data_API, LengthExceededException, DataException)
POCO_DECLARE_EXCEPTION(Data_API, ConnectionFailedException, DataException)
POCO_DECLARE_EXCEPTION(Data_API, NotConnectedException, DataException)
} } // namespace Poco::Data
}
} // namespace Poco::Data
#endif // Data_DataException_INCLUDED

View File

@ -23,135 +23,137 @@
#include "Poco/Exception.h"
namespace Poco {
namespace Poco
{
class DateTime;
namespace Dynamic {
namespace Dynamic
{
class Var;
class Var;
}
namespace Data {
class Time;
class Data_API Date
/// Date class wraps a DateTime and exposes date related interface.
/// The purpose of this class is binding/extraction support for date fields.
namespace Data
{
public:
Date();
/// Creates the Date
Date(int year, int month, int day);
/// Creates the Date
Date(const DateTime& dt);
/// Creates the Date from DateTime
~Date();
/// Destroys the Date.
int year() const;
/// Returns the year.
int month() const;
/// Returns the month.
int day() const;
/// Returns the day.
void assign(int year, int month, int day);
/// Assigns date.
Date& operator = (const Date& d);
/// Assignment operator for Date.
Date& operator = (const DateTime& dt);
/// Assignment operator for DateTime.
Date& operator = (const Poco::Dynamic::Var& var);
/// Assignment operator for Var.
bool operator == (const Date& date) const;
/// Equality operator.
bool operator != (const Date& date) const;
/// Inequality operator.
bool operator < (const Date& date) const;
/// Less then operator.
bool operator > (const Date& date) const;
/// Greater then operator.
private:
int _year;
int _month;
int _day;
};
//
// inlines
//
inline int Date::year() const
{
return _year;
class Time;
class Data_API Date
/// Date class wraps a DateTime and exposes date related interface.
/// The purpose of this class is binding/extraction support for date fields.
{
public:
Date();
/// Creates the Date
Date(int year, int month, int day);
/// Creates the Date
Date(const DateTime & dt);
/// Creates the Date from DateTime
~Date();
/// Destroys the Date.
int year() const;
/// Returns the year.
int month() const;
/// Returns the month.
int day() const;
/// Returns the day.
void assign(int year, int month, int day);
/// Assigns date.
Date & operator=(const Date & d);
/// Assignment operator for Date.
Date & operator=(const DateTime & dt);
/// Assignment operator for DateTime.
Date & operator=(const Poco::Dynamic::Var & var);
/// Assignment operator for Var.
bool operator==(const Date & date) const;
/// Equality operator.
bool operator!=(const Date & date) const;
/// Inequality operator.
bool operator<(const Date & date) const;
/// Less then operator.
bool operator>(const Date & date) const;
/// Greater then operator.
private:
int _year;
int _month;
int _day;
};
//
// inlines
//
inline int Date::year() const
{
return _year;
}
inline int Date::month() const
{
return _month;
}
inline int Date::day() const
{
return _day;
}
inline Date & Date::operator=(const Date & d)
{
assign(d.year(), d.month(), d.day());
return *this;
}
inline Date & Date::operator=(const DateTime & dt)
{
assign(dt.year(), dt.month(), dt.day());
return *this;
}
inline bool Date::operator==(const Date & date) const
{
return _year == date.year() && _month == date.month() && _day == date.day();
}
inline bool Date::operator!=(const Date & date) const
{
return !(*this == date);
}
inline bool Date::operator>(const Date & date) const
{
return !(*this == date) && !(*this < date);
}
}
inline int Date::month() const
{
return _month;
}
inline int Date::day() const
{
return _day;
}
inline Date& Date::operator = (const Date& d)
{
assign(d.year(), d.month(), d.day());
return *this;
}
inline Date& Date::operator = (const DateTime& dt)
{
assign(dt.year(), dt.month(), dt.day());
return *this;
}
inline bool Date::operator == (const Date& date) const
{
return _year == date.year() &&
_month == date.month() &&
_day == date.day();
}
inline bool Date::operator != (const Date& date) const
{
return !(*this == date);
}
inline bool Date::operator > (const Date& date) const
{
return !(*this == date) && !(*this < date);
}
} } // namespace Poco::Data
} // namespace Poco::Data
//
@ -159,67 +161,51 @@ inline bool Date::operator > (const Date& date) const
//
namespace Poco {
namespace Dynamic {
template <>
class VarHolderImpl<Poco::Data::Date>: public VarHolder
namespace Poco
{
namespace Dynamic
{
public:
VarHolderImpl(const Poco::Data::Date& val): _val(val)
{
}
~VarHolderImpl()
{
}
const std::type_info& type() const
{
return typeid(Poco::Data::Date);
}
void convert(Poco::Timestamp& val) const
{
DateTime dt;
dt.assign(_val.year(), _val.month(), _val.day());
val = dt.timestamp();
}
void convert(Poco::DateTime& val) const
{
val.assign(_val.year(), _val.month(), _val.day());
}
void convert(Poco::LocalDateTime& val) const
{
val.assign(_val.year(), _val.month(), _val.day());
}
void convert(std::string& val) const
{
DateTime dt(_val.year(), _val.month(), _val.day());
val = DateTimeFormatter::format(dt, "%Y/%m/%d");
}
VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
{
return cloneHolder(pVarHolder, _val);
}
const Poco::Data::Date& value() const
{
return _val;
}
private:
VarHolderImpl();
Poco::Data::Date _val;
};
} } // namespace Poco::Dynamic
template <>
class VarHolderImpl<Poco::Data::Date> : public VarHolder
{
public:
VarHolderImpl(const Poco::Data::Date & val) : _val(val) { }
~VarHolderImpl() { }
const std::type_info & type() const { return typeid(Poco::Data::Date); }
void convert(Poco::Timestamp & val) const
{
DateTime dt;
dt.assign(_val.year(), _val.month(), _val.day());
val = dt.timestamp();
}
void convert(Poco::DateTime & val) const { val.assign(_val.year(), _val.month(), _val.day()); }
void convert(Poco::LocalDateTime & val) const { val.assign(_val.year(), _val.month(), _val.day()); }
void convert(std::string & val) const
{
DateTime dt(_val.year(), _val.month(), _val.day());
val = DateTimeFormatter::format(dt, "%Y/%m/%d");
}
VarHolder * clone(Placeholder<VarHolder> * pVarHolder = 0) const { return cloneHolder(pVarHolder, _val); }
const Poco::Data::Date & value() const { return _val; }
private:
VarHolderImpl();
Poco::Data::Date _val;
};
}
} // namespace Poco::Dynamic
#endif // Data_Date_INCLUDED

View File

@ -24,24 +24,32 @@
#include "Poco/Dynamic/Var.h"
namespace Poco {
namespace Data {
namespace Poco
{
namespace Data
{
class Date;
class Time;
class Date;
class Time;
} } // namespace Poco::Data
}
} // namespace Poco::Data
namespace Poco {
namespace Dynamic {
namespace Poco
{
namespace Dynamic
{
template <> Data_API Var::operator Poco::Data::Date () const;
template <> Data_API Var::operator Poco::Data::Time () const;
template <>
Data_API Var::operator Poco::Data::Date() const;
template <>
Data_API Var::operator Poco::Data::Time() const;
} } // namespace Poco::Dynamic
}
} // namespace Poco::Dynamic
#endif // Data_DynamicDateTime_INCLUDED

View File

@ -23,23 +23,32 @@
#include "Poco/Dynamic/Var.h"
namespace Poco {
namespace Data {
namespace Poco
{
namespace Data
{
template <typename T> class LOB;
typedef LOB<unsigned char> BLOB;
typedef LOB<char> CLOB;
template <typename T>
class LOB;
typedef LOB<unsigned char> BLOB;
typedef LOB<char> CLOB;
} } // namespace Poco::Data
}
} // namespace Poco::Data
namespace Poco {
namespace Dynamic {
namespace Poco
{
namespace Dynamic
{
template <> Data_API Var::operator Poco::Data::CLOB () const;
template <> Data_API Var::operator Poco::Data::BLOB () const;
template <>
Data_API Var::operator Poco::Data::CLOB() const;
template <>
Data_API Var::operator Poco::Data::BLOB() const;
} } // namespace Poco::Dynamic
}
} // namespace Poco::Dynamic
#endif // Data_DynamicLOB_INCLUDED

File diff suppressed because it is too large Load Diff

View File

@ -18,203 +18,196 @@
#define Data_LOB_INCLUDED
#include <algorithm>
#include <vector>
#include "Poco/Data/Data.h"
#include "Poco/SharedPtr.h"
#include "Poco/Dynamic/VarHolder.h"
#include "Poco/Exception.h"
#include <vector>
#include <algorithm>
#include "Poco/SharedPtr.h"
namespace Poco {
namespace Data {
template <typename T>
class LOB
/// Representation of a Large OBject.
///
/// A LOB can hold arbitrary data.
/// The maximum size depends on the underlying database.
///
/// The LOBInputStream and LOBOutputStream classes provide
/// a convenient way to access the data in a LOB.
namespace Poco
{
public:
typedef typename std::vector<T>::const_iterator Iterator;
typedef T ValueType;
typedef typename std::vector<T> Container;
typedef Poco::SharedPtr<Container> ContentPtr;
LOB(): _pContent(new std::vector<T>())
/// Creates an empty LOB.
{
}
LOB(const std::vector<T>& content):
_pContent(new std::vector<T>(content))
/// Creates the LOB, content is deep-copied.
{
}
LOB(const T* const pContent, std::size_t size):
_pContent(new std::vector<T>(pContent, pContent + size))
/// Creates the LOB by deep-copying pContent.
{
}
LOB(const std::basic_string<T>& content):
_pContent(new std::vector<T>(content.begin(), content.end()))
/// Creates a LOB from a string.
{
}
LOB(const LOB& other): _pContent(other._pContent)
/// Creates a LOB by copying another one.
{
}
~LOB()
/// Destroys the LOB.
{
}
LOB& operator = (const LOB& other)
/// Assignment operator.
{
LOB tmp(other);
swap(tmp);
return *this;
}
bool operator == (const LOB& other) const
/// Compares for equality LOB by value.
{
return *_pContent == *other._pContent;
}
bool operator != (const LOB& other) const
/// Compares for inequality LOB by value.
{
return *_pContent != *other._pContent;
}
void swap(LOB& other)
/// Swaps the LOB with another one.
{
using std::swap;
swap(_pContent, other._pContent);
}
const std::vector<T>& content() const
/// Returns the content.
{
return *_pContent;
}
const T* rawContent() const
/// Returns the raw content.
///
/// If the LOB is empty, returns NULL.
{
if (_pContent->empty())
return 0;
else
return &(*_pContent)[0];
}
void assignVal(std::size_t count, const T& val)
/// Assigns raw content to internal storage.
{
ContentPtr tmp = new Container(count, val);
_pContent.swap(tmp);
}
void assignRaw(const T* ptr, std::size_t count)
/// Assigns raw content to internal storage.
{
poco_assert_dbg (ptr);
LOB tmp(ptr, count);
swap(tmp);
}
void appendRaw(const T* pChar, std::size_t count)
/// Assigns raw content to internal storage.
{
poco_assert_dbg (pChar);
_pContent->insert(_pContent->end(), pChar, pChar+count);
}
void clear(bool doCompact = false)
/// Clears the content of the blob.
/// If doCompact is true, trims the excess capacity.
{
_pContent->clear();
if (doCompact) compact();
}
void compact()
/// Trims the internal storage excess capacity.
{
std::vector<T>(*_pContent).swap(*_pContent);
}
Iterator begin() const
{
return _pContent->begin();
}
Iterator end() const
{
return _pContent->end();
}
std::size_t size() const
/// Returns the size of the LOB in bytes.
{
return static_cast<std::size_t>(_pContent->size());
}
private:
ContentPtr _pContent;
};
typedef LOB<unsigned char> BLOB;
typedef LOB<char> CLOB;
//
// inlines
//
template <typename T>
inline void swap(LOB<T>& b1, LOB<T>& b2)
namespace Data
{
b1.swap(b2);
template <typename T>
class LOB
/// Representation of a Large OBject.
///
/// A LOB can hold arbitrary data.
/// The maximum size depends on the underlying database.
///
/// The LOBInputStream and LOBOutputStream classes provide
/// a convenient way to access the data in a LOB.
{
public:
typedef typename std::vector<T>::const_iterator Iterator;
typedef T ValueType;
typedef typename std::vector<T> Container;
typedef Poco::SharedPtr<Container> ContentPtr;
LOB() : _pContent(new std::vector<T>())
/// Creates an empty LOB.
{
}
LOB(const std::vector<T> & content) : _pContent(new std::vector<T>(content))
/// Creates the LOB, content is deep-copied.
{
}
LOB(const T * const pContent, std::size_t size) : _pContent(new std::vector<T>(pContent, pContent + size))
/// Creates the LOB by deep-copying pContent.
{
}
LOB(const std::basic_string<T> & content) : _pContent(new std::vector<T>(content.begin(), content.end()))
/// Creates a LOB from a string.
{
}
LOB(const LOB & other) : _pContent(other._pContent)
/// Creates a LOB by copying another one.
{
}
~LOB()
/// Destroys the LOB.
{
}
LOB & operator=(const LOB & other)
/// Assignment operator.
{
LOB tmp(other);
swap(tmp);
return *this;
}
bool operator==(const LOB & other) const
/// Compares for equality LOB by value.
{
return *_pContent == *other._pContent;
}
bool operator!=(const LOB & other) const
/// Compares for inequality LOB by value.
{
return *_pContent != *other._pContent;
}
void swap(LOB & other)
/// Swaps the LOB with another one.
{
using std::swap;
swap(_pContent, other._pContent);
}
const std::vector<T> & content() const
/// Returns the content.
{
return *_pContent;
}
const T * rawContent() const
/// Returns the raw content.
///
/// If the LOB is empty, returns NULL.
{
if (_pContent->empty())
return 0;
else
return &(*_pContent)[0];
}
void assignVal(std::size_t count, const T & val)
/// Assigns raw content to internal storage.
{
ContentPtr tmp = new Container(count, val);
_pContent.swap(tmp);
}
void assignRaw(const T * ptr, std::size_t count)
/// Assigns raw content to internal storage.
{
poco_assert_dbg(ptr);
LOB tmp(ptr, count);
swap(tmp);
}
void appendRaw(const T * pChar, std::size_t count)
/// Assigns raw content to internal storage.
{
poco_assert_dbg(pChar);
_pContent->insert(_pContent->end(), pChar, pChar + count);
}
void clear(bool doCompact = false)
/// Clears the content of the blob.
/// If doCompact is true, trims the excess capacity.
{
_pContent->clear();
if (doCompact)
compact();
}
void compact()
/// Trims the internal storage excess capacity.
{
std::vector<T>(*_pContent).swap(*_pContent);
}
Iterator begin() const { return _pContent->begin(); }
Iterator end() const { return _pContent->end(); }
std::size_t size() const
/// Returns the size of the LOB in bytes.
{
return static_cast<std::size_t>(_pContent->size());
}
private:
ContentPtr _pContent;
};
typedef LOB<unsigned char> BLOB;
typedef LOB<char> CLOB;
//
// inlines
//
template <typename T>
inline void swap(LOB<T> & b1, LOB<T> & b2)
{
b1.swap(b2);
}
}
} } // namespace Poco::Data
} // namespace Poco::Data
namespace std
{
template<>
inline void swap<Poco::Data::BLOB>(Poco::Data::BLOB& b1,
Poco::Data::BLOB& b2)
/// Full template specalization of std:::swap for BLOB
{
b1.swap(b2);
}
template <>
inline void swap<Poco::Data::BLOB>(Poco::Data::BLOB & b1, Poco::Data::BLOB & b2)
/// Full template specalization of std:::swap for BLOB
{
b1.swap(b2);
}
template<>
inline void swap<Poco::Data::CLOB>(Poco::Data::CLOB& c1,
Poco::Data::CLOB& c2)
/// Full template specalization of std:::swap for CLOB
{
c1.swap(c2);
}
template <>
inline void swap<Poco::Data::CLOB>(Poco::Data::CLOB & c1, Poco::Data::CLOB & c2)
/// Full template specalization of std:::swap for CLOB
{
c1.swap(c2);
}
}
@ -223,87 +216,58 @@ namespace std
//
namespace Poco {
namespace Dynamic {
template <>
class VarHolderImpl<Poco::Data::BLOB>: public VarHolder
namespace Poco
{
public:
VarHolderImpl(const Poco::Data::BLOB& val): _val(val)
{
}
~VarHolderImpl()
{
}
const std::type_info& type() const
{
return typeid(Poco::Data::BLOB);
}
void convert(std::string& val) const
{
val.assign(_val.begin(), _val.end());
}
VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
{
return cloneHolder(pVarHolder, _val);
}
const Poco::Data::BLOB& value() const
{
return _val;
}
private:
VarHolderImpl();
Poco::Data::BLOB _val;
};
template <>
class VarHolderImpl<Poco::Data::CLOB>: public VarHolder
namespace Dynamic
{
public:
VarHolderImpl(const Poco::Data::CLOB& val): _val(val)
{
}
~VarHolderImpl()
{
}
const std::type_info& type() const
{
return typeid(Poco::Data::CLOB);
}
void convert(std::string& val) const
{
val.assign(_val.begin(), _val.end());
}
VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
{
return cloneHolder(pVarHolder, _val);
}
const Poco::Data::CLOB& value() const
{
return _val;
}
private:
VarHolderImpl();
Poco::Data::CLOB _val;
};
} } // namespace Poco::Dynamic
template <>
class VarHolderImpl<Poco::Data::BLOB> : public VarHolder
{
public:
VarHolderImpl(const Poco::Data::BLOB & val) : _val(val) { }
~VarHolderImpl() { }
const std::type_info & type() const { return typeid(Poco::Data::BLOB); }
void convert(std::string & val) const { val.assign(_val.begin(), _val.end()); }
VarHolder * clone(Placeholder<VarHolder> * pVarHolder = 0) const { return cloneHolder(pVarHolder, _val); }
const Poco::Data::BLOB & value() const { return _val; }
private:
VarHolderImpl();
Poco::Data::BLOB _val;
};
template <>
class VarHolderImpl<Poco::Data::CLOB> : public VarHolder
{
public:
VarHolderImpl(const Poco::Data::CLOB & val) : _val(val) { }
~VarHolderImpl() { }
const std::type_info & type() const { return typeid(Poco::Data::CLOB); }
void convert(std::string & val) const { val.assign(_val.begin(), _val.end()); }
VarHolder * clone(Placeholder<VarHolder> * pVarHolder = 0) const { return cloneHolder(pVarHolder, _val); }
const Poco::Data::CLOB & value() const { return _val; }
private:
VarHolderImpl();
Poco::Data::CLOB _val;
};
}
} // namespace Poco::Dynamic
#endif // Data_LOB_INCLUDED

View File

@ -18,133 +18,132 @@
#define Data_LOBStream_INCLUDED
#include "Poco/Foundation.h"
#include "Poco/UnbufferedStreamBuf.h"
#include "Poco/Data/LOB.h"
#include <istream>
#include <ostream>
#include "Poco/Data/LOB.h"
#include "Poco/Foundation.h"
#include "Poco/UnbufferedStreamBuf.h"
namespace Poco {
namespace Data {
template <typename T>
class LOBStreamBuf: public BasicUnbufferedStreamBuf<T, std::char_traits<T> >
/// This is the streambuf class used for reading from and writing to a LOB.
namespace Poco
{
public:
LOBStreamBuf(LOB<T>& lob): _lob(lob), _it(_lob.begin())
/// Creates LOBStreamBuf.
{
}
~LOBStreamBuf()
/// Destroys LOBStreamBuf.
{
}
protected:
typedef std::char_traits<T> TraitsType;
typedef BasicUnbufferedStreamBuf<T, TraitsType> BaseType;
typename BaseType::int_type readFromDevice()
{
if (_it != _lob.end())
return BaseType::charToInt(*_it++);
else
return -1;
}
typename BaseType::int_type writeToDevice(T c)
{
_lob.appendRaw(&c, 1);
return 1;
}
private:
LOB<T>& _lob;
typename LOB<T>::Iterator _it;
};
template <typename T>
class LOBIOS: public virtual std::ios
/// The base class for LOBInputStream and
/// LOBOutputStream.
///
/// This class is needed to ensure the correct initialization
/// order of the stream buffer and base classes.
namespace Data
{
public:
LOBIOS(LOB<T>& lob, openmode mode): _buf(lob)
/// Creates the LOBIOS with the given LOB.
{
poco_ios_init(&_buf);
}
~LOBIOS()
/// Destroys the LOBIOS.
{
}
LOBStreamBuf<T>* rdbuf()
/// Returns a pointer to the internal LOBStreamBuf.
{
return &_buf;
}
protected:
LOBStreamBuf<T> _buf;
};
template <typename T>
class LOBOutputStream: public LOBIOS<T>, public std::basic_ostream<T, std::char_traits<T> >
/// An output stream for writing to a LOB.
{
public:
LOBOutputStream(LOB<T>& lob):
LOBIOS<T>(lob, std::ios::out),
std::ostream(LOBIOS<T>::rdbuf())
/// Creates the LOBOutputStream with the given LOB.
{
}
~LOBOutputStream()
/// Destroys the LOBOutputStream.
{
}
};
template <typename T>
class LOBStreamBuf : public BasicUnbufferedStreamBuf<T, std::char_traits<T>>
/// This is the streambuf class used for reading from and writing to a LOB.
{
public:
LOBStreamBuf(LOB<T> & lob) : _lob(lob), _it(_lob.begin())
/// Creates LOBStreamBuf.
{
}
template <typename T>
class LOBInputStream: public LOBIOS<T>, public std::basic_istream<T, std::char_traits<T> >
/// An input stream for reading from a LOB.
{
public:
LOBInputStream(LOB<T>& lob):
LOBIOS<T>(lob, std::ios::in),
std::istream(LOBIOS<T>::rdbuf())
/// Creates the LOBInputStream with the given LOB.
{
}
~LOBStreamBuf()
/// Destroys LOBStreamBuf.
{
}
~LOBInputStream()
/// Destroys the LOBInputStream.
{
}
};
protected:
typedef std::char_traits<T> TraitsType;
typedef BasicUnbufferedStreamBuf<T, TraitsType> BaseType;
typename BaseType::int_type readFromDevice()
{
if (_it != _lob.end())
return BaseType::charToInt(*_it++);
else
return -1;
}
typename BaseType::int_type writeToDevice(T c)
{
_lob.appendRaw(&c, 1);
return 1;
}
private:
LOB<T> & _lob;
typename LOB<T>::Iterator _it;
};
typedef LOBOutputStream<unsigned char> BLOBOutputStream;
typedef LOBOutputStream<char> CLOBOutputStream;
template <typename T>
class LOBIOS : public virtual std::ios
/// The base class for LOBInputStream and
/// LOBOutputStream.
///
/// This class is needed to ensure the correct initialization
/// order of the stream buffer and base classes.
{
public:
LOBIOS(LOB<T> & lob, openmode mode) : _buf(lob)
/// Creates the LOBIOS with the given LOB.
{
poco_ios_init(&_buf);
}
typedef LOBInputStream<unsigned char> BLOBInputStream;
typedef LOBInputStream<char> CLOBInputStream;
~LOBIOS()
/// Destroys the LOBIOS.
{
}
} } // namespace Poco::Data
LOBStreamBuf<T> * rdbuf()
/// Returns a pointer to the internal LOBStreamBuf.
{
return &_buf;
}
protected:
LOBStreamBuf<T> _buf;
};
template <typename T>
class LOBOutputStream : public LOBIOS<T>, public std::basic_ostream<T, std::char_traits<T>>
/// An output stream for writing to a LOB.
{
public:
LOBOutputStream(LOB<T> & lob) : LOBIOS<T>(lob, std::ios::out), std::ostream(LOBIOS<T>::rdbuf())
/// Creates the LOBOutputStream with the given LOB.
{
}
~LOBOutputStream()
/// Destroys the LOBOutputStream.
{
}
};
template <typename T>
class LOBInputStream : public LOBIOS<T>, public std::basic_istream<T, std::char_traits<T>>
/// An input stream for reading from a LOB.
{
public:
LOBInputStream(LOB<T> & lob) : LOBIOS<T>(lob, std::ios::in), std::istream(LOBIOS<T>::rdbuf())
/// Creates the LOBInputStream with the given LOB.
{
}
~LOBInputStream()
/// Destroys the LOBInputStream.
{
}
};
typedef LOBOutputStream<unsigned char> BLOBOutputStream;
typedef LOBOutputStream<char> CLOBOutputStream;
typedef LOBInputStream<unsigned char> BLOBInputStream;
typedef LOBInputStream<char> CLOBInputStream;
}
} // namespace Poco::Data
#endif // Data_LOBStream_INCLUDED

View File

@ -21,93 +21,92 @@
#include "Poco/Data/Data.h"
namespace Poco {
namespace Data {
class Data_API Limit
/// Limit stores information how many rows a query should return.
namespace Poco
{
public:
typedef Poco::UInt32 SizeT;
enum Type
{
LIMIT_UNLIMITED = ~((SizeT) 0)
};
Limit(SizeT value, bool hardLimit = false, bool isLowerLimit = false);
/// Creates the Limit.
///
/// Value contains the upper row hint, if hardLimit is set to true, the limit acts as a hard
/// border, ie. every query must return exactly value rows, returning more than value objects will throw an exception!
/// LowerLimits always act as hard-limits!
///
/// A value of LIMIT_UNLIMITED disables the limit.
~Limit();
/// Destroys the Limit.
SizeT value() const;
/// Returns the value of the limit
bool isHardLimit() const;
/// Returns true if the limit is a hard limit.
bool isLowerLimit() const;
/// Returns true if the limit is a lower limit, otherwise it is an upperLimit
bool operator == (const Limit& other) const;
/// Equality operator.
bool operator != (const Limit& other) const;
/// Inequality operator.
private:
SizeT _value;
bool _hardLimit;
bool _isLowerLimit;
};
//
// inlines
//
inline Poco::UInt32 Limit::value() const
namespace Data
{
return _value;
class Data_API Limit
/// Limit stores information how many rows a query should return.
{
public:
typedef Poco::UInt32 SizeT;
enum Type
{
LIMIT_UNLIMITED = ~((SizeT)0)
};
Limit(SizeT value, bool hardLimit = false, bool isLowerLimit = false);
/// Creates the Limit.
///
/// Value contains the upper row hint, if hardLimit is set to true, the limit acts as a hard
/// border, ie. every query must return exactly value rows, returning more than value objects will throw an exception!
/// LowerLimits always act as hard-limits!
///
/// A value of LIMIT_UNLIMITED disables the limit.
~Limit();
/// Destroys the Limit.
SizeT value() const;
/// Returns the value of the limit
bool isHardLimit() const;
/// Returns true if the limit is a hard limit.
bool isLowerLimit() const;
/// Returns true if the limit is a lower limit, otherwise it is an upperLimit
bool operator==(const Limit & other) const;
/// Equality operator.
bool operator!=(const Limit & other) const;
/// Inequality operator.
private:
SizeT _value;
bool _hardLimit;
bool _isLowerLimit;
};
//
// inlines
//
inline Poco::UInt32 Limit::value() const
{
return _value;
}
inline bool Limit::isHardLimit() const
{
return _hardLimit;
}
inline bool Limit::isLowerLimit() const
{
return _isLowerLimit;
}
inline bool Limit::operator==(const Limit & other) const
{
return other._value == _value && other._hardLimit == _hardLimit && other._isLowerLimit == _isLowerLimit;
}
inline bool Limit::operator!=(const Limit & other) const
{
return other._value != _value || other._hardLimit != _hardLimit || other._isLowerLimit != _isLowerLimit;
}
}
inline bool Limit::isHardLimit() const
{
return _hardLimit;
}
inline bool Limit::isLowerLimit() const
{
return _isLowerLimit;
}
inline bool Limit::operator == (const Limit& other) const
{
return other._value == _value &&
other._hardLimit == _hardLimit &&
other._isLowerLimit == _isLowerLimit;
}
inline bool Limit::operator != (const Limit& other) const
{
return other._value != _value ||
other._hardLimit != _hardLimit ||
other._isLowerLimit != _isLowerLimit;
}
} } // namespace Poco::Data
} // namespace Poco::Data
#endif // Data_Limit_INCLUDED

View File

@ -18,171 +18,175 @@
#define Data_MetaColumn_INCLUDED
#include "Poco/Data/Data.h"
#include <cstddef>
#include "Poco/Data/Data.h"
namespace Poco {
namespace Data {
class Data_API MetaColumn
/// MetaColumn class contains column metadata information.
namespace Poco
{
public:
enum ColumnDataType
{
FDT_BOOL,
FDT_INT8,
FDT_UINT8,
FDT_INT16,
FDT_UINT16,
FDT_INT32,
FDT_UINT32,
FDT_INT64,
FDT_UINT64,
FDT_FLOAT,
FDT_DOUBLE,
FDT_STRING,
FDT_WSTRING,
FDT_BLOB,
FDT_CLOB,
FDT_DATE,
FDT_TIME,
FDT_TIMESTAMP,
FDT_UNKNOWN
};
MetaColumn();
/// Creates the MetaColumn.
explicit MetaColumn(std::size_t position,
const std::string& name = "",
ColumnDataType type = FDT_UNKNOWN,
std::size_t length = 0,
std::size_t precision = 0,
bool nullable = false);
/// Creates the MetaColumn.
virtual ~MetaColumn();
/// Destroys the MetaColumn.
const std::string& name() const;
/// Returns column name.
std::size_t length() const;
/// Returns column maximum length.
std::size_t precision() const;
/// Returns column precision.
/// Valid for floating point fields only
/// (zero for other data types).
std::size_t position() const;
/// Returns column position.
ColumnDataType type() const;
/// Returns column type.
bool isNullable() const;
/// Returns true if column allows null values, false otherwise.
protected:
void setName(const std::string& name);
/// Sets the column name.
void setLength(std::size_t length);
/// Sets the column length.
void setPrecision(std::size_t precision);
/// Sets the column precision.
void setType(ColumnDataType type);
/// Sets the column data type.
void setNullable(bool nullable);
/// Sets the column nullability.
private:
std::string _name;
std::size_t _length;
std::size_t _precision;
std::size_t _position;
ColumnDataType _type;
bool _nullable;
};
///
/// inlines
///
inline const std::string& MetaColumn::name() const
namespace Data
{
return _name;
class Data_API MetaColumn
/// MetaColumn class contains column metadata information.
{
public:
enum ColumnDataType
{
FDT_BOOL,
FDT_INT8,
FDT_UINT8,
FDT_INT16,
FDT_UINT16,
FDT_INT32,
FDT_UINT32,
FDT_INT64,
FDT_UINT64,
FDT_FLOAT,
FDT_DOUBLE,
FDT_STRING,
FDT_WSTRING,
FDT_BLOB,
FDT_CLOB,
FDT_DATE,
FDT_TIME,
FDT_TIMESTAMP,
FDT_UNKNOWN
};
MetaColumn();
/// Creates the MetaColumn.
explicit MetaColumn(
std::size_t position,
const std::string & name = "",
ColumnDataType type = FDT_UNKNOWN,
std::size_t length = 0,
std::size_t precision = 0,
bool nullable = false);
/// Creates the MetaColumn.
virtual ~MetaColumn();
/// Destroys the MetaColumn.
const std::string & name() const;
/// Returns column name.
std::size_t length() const;
/// Returns column maximum length.
std::size_t precision() const;
/// Returns column precision.
/// Valid for floating point fields only
/// (zero for other data types).
std::size_t position() const;
/// Returns column position.
ColumnDataType type() const;
/// Returns column type.
bool isNullable() const;
/// Returns true if column allows null values, false otherwise.
protected:
void setName(const std::string & name);
/// Sets the column name.
void setLength(std::size_t length);
/// Sets the column length.
void setPrecision(std::size_t precision);
/// Sets the column precision.
void setType(ColumnDataType type);
/// Sets the column data type.
void setNullable(bool nullable);
/// Sets the column nullability.
private:
std::string _name;
std::size_t _length;
std::size_t _precision;
std::size_t _position;
ColumnDataType _type;
bool _nullable;
};
///
/// inlines
///
inline const std::string & MetaColumn::name() const
{
return _name;
}
inline std::size_t MetaColumn::length() const
{
return _length;
}
inline std::size_t MetaColumn::precision() const
{
return _precision;
}
inline std::size_t MetaColumn::position() const
{
return _position;
}
inline MetaColumn::ColumnDataType MetaColumn::type() const
{
return _type;
}
inline bool MetaColumn::isNullable() const
{
return _nullable;
}
inline void MetaColumn::setName(const std::string & name)
{
_name = name;
}
inline void MetaColumn::setLength(std::size_t length)
{
_length = length;
}
inline void MetaColumn::setPrecision(std::size_t precision)
{
_precision = precision;
}
inline void MetaColumn::setType(ColumnDataType type)
{
_type = type;
}
inline void MetaColumn::setNullable(bool nullable)
{
_nullable = nullable;
}
}
inline std::size_t MetaColumn::length() const
{
return _length;
}
inline std::size_t MetaColumn::precision() const
{
return _precision;
}
inline std::size_t MetaColumn::position() const
{
return _position;
}
inline MetaColumn::ColumnDataType MetaColumn::type() const
{
return _type;
}
inline bool MetaColumn::isNullable() const
{
return _nullable;
}
inline void MetaColumn::setName(const std::string& name)
{
_name = name;
}
inline void MetaColumn::setLength(std::size_t length)
{
_length = length;
}
inline void MetaColumn::setPrecision(std::size_t precision)
{
_precision = precision;
}
inline void MetaColumn::setType(ColumnDataType type)
{
_type = type;
}
inline void MetaColumn::setNullable(bool nullable)
{
_nullable = nullable;
}
} } // namespace Poco::Data
} // namespace Poco::Data
#endif // Data_MetaColumn_INCLUDED

View File

@ -18,82 +18,85 @@
#define Data_PooledSessionHolder_INCLUDED
#include "Poco/AutoPtr.h"
#include "Poco/Data/Data.h"
#include "Poco/Data/SessionImpl.h"
#include "Poco/AutoPtr.h"
#include "Poco/Timestamp.h"
#include "Poco/Mutex.h"
#include "Poco/Timestamp.h"
namespace Poco {
namespace Data {
class SessionPool;
class Data_API PooledSessionHolder: public Poco::RefCountedObject
/// This class is used by SessionPool to manage SessionImpl objects.
namespace Poco
{
public:
PooledSessionHolder(SessionPool& owner, SessionImpl* pSessionImpl);
/// Creates the PooledSessionHolder.
~PooledSessionHolder();
/// Destroys the PooledSessionHolder.
SessionImpl* session();
/// Returns a pointer to the SessionImpl.
SessionPool& owner();
/// Returns a reference to the SessionHolder's owner.
void access();
/// Updates the last access timestamp.
int idle() const;
/// Returns the number of seconds the session has not been used.
private:
SessionPool& _owner;
Poco::AutoPtr<SessionImpl> _pImpl;
Poco::Timestamp _lastUsed;
mutable Poco::FastMutex _mutex;
};
//
// inlines
//
inline SessionImpl* PooledSessionHolder::session()
namespace Data
{
return _pImpl;
class SessionPool;
class Data_API PooledSessionHolder : public Poco::RefCountedObject
/// This class is used by SessionPool to manage SessionImpl objects.
{
public:
PooledSessionHolder(SessionPool & owner, SessionImpl * pSessionImpl);
/// Creates the PooledSessionHolder.
~PooledSessionHolder();
/// Destroys the PooledSessionHolder.
SessionImpl * session();
/// Returns a pointer to the SessionImpl.
SessionPool & owner();
/// Returns a reference to the SessionHolder's owner.
void access();
/// Updates the last access timestamp.
int idle() const;
/// Returns the number of seconds the session has not been used.
private:
SessionPool & _owner;
Poco::AutoPtr<SessionImpl> _pImpl;
Poco::Timestamp _lastUsed;
mutable Poco::FastMutex _mutex;
};
//
// inlines
//
inline SessionImpl * PooledSessionHolder::session()
{
return _pImpl;
}
inline SessionPool & PooledSessionHolder::owner()
{
return _owner;
}
inline void PooledSessionHolder::access()
{
Poco::FastMutex::ScopedLock lock(_mutex);
_lastUsed.update();
}
inline int PooledSessionHolder::idle() const
{
Poco::FastMutex::ScopedLock lock(_mutex);
return (int)(_lastUsed.elapsed() / Poco::Timestamp::resolution());
}
}
inline SessionPool& PooledSessionHolder::owner()
{
return _owner;
}
inline void PooledSessionHolder::access()
{
Poco::FastMutex::ScopedLock lock(_mutex);
_lastUsed.update();
}
inline int PooledSessionHolder::idle() const
{
Poco::FastMutex::ScopedLock lock(_mutex);
return (int) (_lastUsed.elapsed()/Poco::Timestamp::resolution());
}
} } // namespace Poco::Data
} // namespace Poco::Data
#endif // Data_PooledSessionHolder_INCLUDED

View File

@ -18,80 +18,83 @@
#define Data_PooledSessionImpl_INCLUDED
#include "Poco/Data/Data.h"
#include "Poco/Data/SessionImpl.h"
#include "Poco/Data/PooledSessionHolder.h"
#include "Poco/AutoPtr.h"
#include "Poco/Data/Data.h"
#include "Poco/Data/PooledSessionHolder.h"
#include "Poco/Data/SessionImpl.h"
namespace Poco {
namespace Data {
class SessionPool;
class Data_API PooledSessionImpl: public SessionImpl
/// PooledSessionImpl is a decorator created by
/// SessionPool that adds session pool
/// management to SessionImpl objects.
namespace Poco
{
public:
PooledSessionImpl(PooledSessionHolder* pHolder);
/// Creates the PooledSessionImpl.
~PooledSessionImpl();
/// Destroys the PooledSessionImpl.
// SessionImpl
StatementImpl* createStatementImpl();
void begin();
void commit();
void rollback();
void open(const std::string& connect = "");
void close();
bool isConnected();
void setConnectionTimeout(std::size_t timeout);
std::size_t getConnectionTimeout();
bool canTransact();
bool isTransaction();
void setTransactionIsolation(Poco::UInt32);
Poco::UInt32 getTransactionIsolation();
bool hasTransactionIsolation(Poco::UInt32);
bool isTransactionIsolation(Poco::UInt32);
const std::string& connectorName() const;
void setFeature(const std::string& name, bool state);
bool getFeature(const std::string& name);
void setProperty(const std::string& name, const Poco::Any& value);
Poco::Any getProperty(const std::string& name);
protected:
SessionImpl* access() const;
/// Updates the last access timestamp,
/// verifies validity of the session
/// and returns the session if it is valid.
///
/// Throws an SessionUnavailableException if the
/// session is no longer valid.
SessionImpl* impl() const;
/// Returns a pointer to the SessionImpl.
private:
mutable Poco::AutoPtr<PooledSessionHolder> _pHolder;
};
//
// inlines
//
inline SessionImpl* PooledSessionImpl::impl() const
namespace Data
{
return _pHolder->session();
class SessionPool;
class Data_API PooledSessionImpl : public SessionImpl
/// PooledSessionImpl is a decorator created by
/// SessionPool that adds session pool
/// management to SessionImpl objects.
{
public:
PooledSessionImpl(PooledSessionHolder * pHolder);
/// Creates the PooledSessionImpl.
~PooledSessionImpl();
/// Destroys the PooledSessionImpl.
// SessionImpl
StatementImpl * createStatementImpl();
void begin();
void commit();
void rollback();
void open(const std::string & connect = "");
void close();
bool isConnected();
void setConnectionTimeout(std::size_t timeout);
std::size_t getConnectionTimeout();
bool canTransact();
bool isTransaction();
void setTransactionIsolation(Poco::UInt32);
Poco::UInt32 getTransactionIsolation();
bool hasTransactionIsolation(Poco::UInt32);
bool isTransactionIsolation(Poco::UInt32);
const std::string & connectorName() const;
void setFeature(const std::string & name, bool state);
bool getFeature(const std::string & name);
void setProperty(const std::string & name, const Poco::Any & value);
Poco::Any getProperty(const std::string & name);
protected:
SessionImpl * access() const;
/// Updates the last access timestamp,
/// verifies validity of the session
/// and returns the session if it is valid.
///
/// Throws an SessionUnavailableException if the
/// session is no longer valid.
SessionImpl * impl() const;
/// Returns a pointer to the SessionImpl.
private:
mutable Poco::AutoPtr<PooledSessionHolder> _pHolder;
};
//
// inlines
//
inline SessionImpl * PooledSessionImpl::impl() const
{
return _pHolder->session();
}
}
} } // namespace Poco::Data
} // namespace Poco::Data
#endif // Data_PooledSessionImpl_INCLUDED

View File

@ -21,55 +21,59 @@
#include "Poco/Data/Limit.h"
namespace Poco {
namespace Data {
class Data_API Position
/// Utility class wrapping unsigned integer. Used to
/// indicate the recordset position in batch SQL statements.
namespace Poco
{
public:
Position(Poco::UInt32 value);
/// Creates the Position.
~Position();
/// Destroys the Position.
Poco::UInt32 value() const;
/// Returns the position value.
private:
Position();
Poco::UInt32 _value;
};
///
/// inlines
///
inline Poco::UInt32 Position::value() const
{
return _value;
}
namespace Keywords {
template <typename T>
inline Position from(const T& value)
/// Convenience function for creation of position.
namespace Data
{
return Position(value);
class Data_API Position
/// Utility class wrapping unsigned integer. Used to
/// indicate the recordset position in batch SQL statements.
{
public:
Position(Poco::UInt32 value);
/// Creates the Position.
~Position();
/// Destroys the Position.
Poco::UInt32 value() const;
/// Returns the position value.
private:
Position();
Poco::UInt32 _value;
};
///
/// inlines
///
inline Poco::UInt32 Position::value() const
{
return _value;
}
namespace Keywords
{
template <typename T>
inline Position from(const T & value)
/// Convenience function for creation of position.
{
return Position(value);
}
} // namespace Keywords
}
} // namespace Keywords
} } // namespace Poco::Data
} // namespace Poco::Data
#endif // Data_Position_INCLUDED

View File

@ -18,144 +18,139 @@
#define Data_Preparation_INCLUDED
#include "Poco/Data/Data.h"
#include "Poco/Data/AbstractPreparation.h"
#include "Poco/Data/TypeHandler.h"
#include <cstddef>
#include <vector>
#include "Poco/Data/AbstractPreparation.h"
#include "Poco/Data/Data.h"
#include "Poco/Data/TypeHandler.h"
namespace Poco {
namespace Data {
template<typename T>
class Preparation: public AbstractPreparation
/// Class for calling the appropriate AbstractPreparator method.
namespace Poco
{
public:
Preparation(AbstractPreparator::Ptr& pPreparator, std::size_t pos, T& val):
AbstractPreparation(pPreparator),
_pos(pos),
_val(val)
/// Creates the Preparation.
{
}
~Preparation()
/// Destroys the Preparation.
{
}
void prepare()
/// Prepares data.
{
TypeHandler<T>::prepare(_pos, _val, preparation());
}
private:
std::size_t _pos;
T& _val;
};
template<typename T>
class Preparation<std::vector<T> >: public AbstractPreparation
/// Preparation specialization for std::vector.
/// This specialization is needed for bulk operations to enforce
/// the whole vector preparation, rather than only individual contained values.
namespace Data
{
public:
Preparation(AbstractPreparator::Ptr pPreparator, std::size_t pos, std::vector<T>& val = std::vector<T>()):
AbstractPreparation(pPreparator),
_pos(pos),
_val(val)
/// Creates the Preparation.
{
}
~Preparation()
/// Destroys the Preparation.
{
}
void prepare()
/// Prepares data.
{
TypeHandler<std::vector<T> >::prepare(_pos, _val, preparation());
}
private:
std::size_t _pos;
std::vector<T>& _val;
};
template<typename T>
class Preparation<std::deque<T> >: public AbstractPreparation
/// Preparation specialization for std::deque.
/// This specialization is needed for bulk operations to enforce
/// the whole deque preparation, rather than only individual contained values.
{
public:
Preparation(AbstractPreparator::Ptr pPreparator, std::size_t pos, std::deque<T>& val = std::deque<T>()):
AbstractPreparation(pPreparator),
_pos(pos),
_val(val)
/// Creates the Preparation.
{
}
template <typename T>
class Preparation : public AbstractPreparation
/// Class for calling the appropriate AbstractPreparator method.
{
public:
Preparation(AbstractPreparator::Ptr & pPreparator, std::size_t pos, T & val)
: AbstractPreparation(pPreparator), _pos(pos), _val(val)
/// Creates the Preparation.
{
}
~Preparation()
/// Destroys the Preparation.
{
}
~Preparation()
/// Destroys the Preparation.
{
}
void prepare()
/// Prepares data.
{
TypeHandler<std::deque<T> >::prepare(_pos, _val, preparation());
}
void prepare()
/// Prepares data.
{
TypeHandler<T>::prepare(_pos, _val, preparation());
}
private:
std::size_t _pos;
std::deque<T>& _val;
};
private:
std::size_t _pos;
T & _val;
};
template<typename T>
class Preparation<std::list<T> >: public AbstractPreparation
/// Preparation specialization for std::list.
/// This specialization is needed for bulk operations to enforce
/// the whole list preparation, rather than only individual contained values.
{
public:
Preparation(AbstractPreparator::Ptr pPreparator, std::size_t pos, std::list<T>& val = std::list<T>()):
AbstractPreparation(pPreparator),
_pos(pos),
_val(val)
/// Creates the Preparation.
{
}
template <typename T>
class Preparation<std::vector<T>> : public AbstractPreparation
/// Preparation specialization for std::vector.
/// This specialization is needed for bulk operations to enforce
/// the whole vector preparation, rather than only individual contained values.
{
public:
Preparation(AbstractPreparator::Ptr pPreparator, std::size_t pos, std::vector<T> & val = std::vector<T>())
: AbstractPreparation(pPreparator), _pos(pos), _val(val)
/// Creates the Preparation.
{
}
~Preparation()
/// Destroys the Preparation.
{
}
~Preparation()
/// Destroys the Preparation.
{
}
void prepare()
/// Prepares data.
{
TypeHandler<std::list<T> >::prepare(_pos, _val, preparation());
}
void prepare()
/// Prepares data.
{
TypeHandler<std::vector<T>>::prepare(_pos, _val, preparation());
}
private:
std::size_t _pos;
std::list<T>& _val;
};
private:
std::size_t _pos;
std::vector<T> & _val;
};
} } // namespace Poco::Data
template <typename T>
class Preparation<std::deque<T>> : public AbstractPreparation
/// Preparation specialization for std::deque.
/// This specialization is needed for bulk operations to enforce
/// the whole deque preparation, rather than only individual contained values.
{
public:
Preparation(AbstractPreparator::Ptr pPreparator, std::size_t pos, std::deque<T> & val = std::deque<T>())
: AbstractPreparation(pPreparator), _pos(pos), _val(val)
/// Creates the Preparation.
{
}
~Preparation()
/// Destroys the Preparation.
{
}
void prepare()
/// Prepares data.
{
TypeHandler<std::deque<T>>::prepare(_pos, _val, preparation());
}
private:
std::size_t _pos;
std::deque<T> & _val;
};
template <typename T>
class Preparation<std::list<T>> : public AbstractPreparation
/// Preparation specialization for std::list.
/// This specialization is needed for bulk operations to enforce
/// the whole list preparation, rather than only individual contained values.
{
public:
Preparation(AbstractPreparator::Ptr pPreparator, std::size_t pos, std::list<T> & val = std::list<T>())
: AbstractPreparation(pPreparator), _pos(pos), _val(val)
/// Creates the Preparation.
{
}
~Preparation()
/// Destroys the Preparation.
{
}
void prepare()
/// Prepares data.
{
TypeHandler<std::list<T>>::prepare(_pos, _val, preparation());
}
private:
std::size_t _pos;
std::list<T> & _val;
};
}
} // namespace Poco::Data
#endif // Data_Preparation_INCLUDED

View File

@ -22,83 +22,87 @@
#include "Poco/Data/Limit.h"
namespace Poco {
namespace Data {
class Data_API Range
/// Range stores information how many rows a query should return.
namespace Poco
{
public:
Range(Limit::SizeT lowValue, Limit::SizeT upValue, bool hardLimit);
/// Creates the Range. lowValue must be smaller equal than upValue
~Range();
/// Destroys the Limit.
const Limit& lower() const;
/// Returns the lower limit
const Limit& upper() const;
/// Returns the upper limit
private:
Limit _lower;
Limit _upper;
};
//
// inlines
//
inline const Limit& Range::lower() const
namespace Data
{
return _lower;
class Data_API Range
/// Range stores information how many rows a query should return.
{
public:
Range(Limit::SizeT lowValue, Limit::SizeT upValue, bool hardLimit);
/// Creates the Range. lowValue must be smaller equal than upValue
~Range();
/// Destroys the Limit.
const Limit & lower() const;
/// Returns the lower limit
const Limit & upper() const;
/// Returns the upper limit
private:
Limit _lower;
Limit _upper;
};
//
// inlines
//
inline const Limit & Range::lower() const
{
return _lower;
}
inline const Limit & Range::upper() const
{
return _upper;
}
namespace Keywords
{
template <typename T>
Limit limit(T lim, bool hard = false)
/// Creates an upperLimit
{
return Limit(static_cast<Limit::SizeT>(lim), hard, false);
}
template <typename T>
Limit upperLimit(T lim, bool hard = false)
{
return limit(lim, hard);
}
template <typename T>
Limit lowerLimit(T lim)
{
return Limit(static_cast<Limit::SizeT>(lim), true, true);
}
template <typename T>
Range range(T low, T upp, bool hard = false)
{
return Range(static_cast<Limit::SizeT>(low), static_cast<Limit::SizeT>(upp), hard);
}
} // namespace Keywords
}
inline const Limit& Range::upper() const
{
return _upper;
}
namespace Keywords {
template <typename T>
Limit limit(T lim, bool hard = false)
/// Creates an upperLimit
{
return Limit(static_cast<Limit::SizeT>(lim), hard, false);
}
template <typename T>
Limit upperLimit(T lim, bool hard = false)
{
return limit(lim, hard);
}
template <typename T>
Limit lowerLimit(T lim)
{
return Limit(static_cast<Limit::SizeT>(lim), true, true);
}
template <typename T>
Range range(T low, T upp, bool hard = false)
{
return Range(static_cast<Limit::SizeT>(low), static_cast<Limit::SizeT>(upp), hard);
}
} // namespace Keywords
} } // namespace Poco::Data
} // namespace Poco::Data
#endif // Data_Range_INCLUDED

File diff suppressed because it is too large Load Diff

View File

@ -18,295 +18,297 @@
#define Data_Row_INCLUDED
#include <ostream>
#include <string>
#include <vector>
#include "Poco/Data/Data.h"
#include "Poco/Data/RowFormatter.h"
#include "Poco/Dynamic/Var.h"
#include "Poco/Tuple.h"
#include "Poco/SharedPtr.h"
#include <vector>
#include <string>
#include <ostream>
#include "Poco/Tuple.h"
namespace Poco {
namespace Data {
class RecordSet;
class Data_API Row
/// Row class provides a data type for RecordSet iteration purposes.
/// Dereferencing a RowIterator returns Row.
/// Rows are sortable. The sortability is maintained at all times (i.e. there
/// is always at least one column specified as a sorting criteria) .
/// The default and minimal sorting criteria is the first field (position 0).
/// The default sorting criteria can be replaced with any other field by
/// calling replaceSortField() member function.
/// Additional fields can be added to sorting criteria, in which case the
/// field precedence corresponds to addition order (i.e. later added fields
/// have lower sorting precedence).
/// These features make Row suitable for use with standard sorted
/// containers and algorithms. The main constraint is that all the rows from
/// a set that is being sorted must have the same sorting criteria (i.e., the same
/// set of fields must be in sorting criteria in the same order). Since rows don't
/// know about each other, it is the programmer's responsibility to ensure this
/// constraint is satisfied.
/// Field names are a shared pointer to a vector of strings. For efficiency sake,
/// a constructor taking a shared pointer to names vector argument is provided.
/// The stream operator is provided for Row data type as a free-standing function.
namespace Poco
{
public:
typedef RowFormatter::NameVec NameVec;
typedef RowFormatter::NameVecPtr NameVecPtr;
typedef RowFormatter::ValueVec ValueVec;
enum ComparisonType
{
COMPARE_AS_EMPTY,
COMPARE_AS_INTEGER,
COMPARE_AS_FLOAT,
COMPARE_AS_STRING
};
typedef Tuple<std::size_t, ComparisonType> SortTuple;
typedef std::vector<SortTuple> SortMap;
/// The type for map holding fields used for sorting criteria.
/// Fields are added sequentially and have precedence that
/// corresponds to field adding sequence order (rather than field's
/// position in the row).
/// This requirement rules out use of std::map due to its sorted nature.
typedef SharedPtr<SortMap> SortMapPtr;
Row();
/// Creates the Row.
Row(NameVecPtr pNames,
const RowFormatter::Ptr& pFormatter = 0);
/// Creates the Row.
Row(NameVecPtr pNames,
const SortMapPtr& pSortMap,
const RowFormatter::Ptr& pFormatter = 0);
/// Creates the Row.
~Row();
/// Destroys the Row.
Poco::Dynamic::Var& get(std::size_t col);
/// Returns the reference to data value at column location.
Poco::Dynamic::Var& operator [] (std::size_t col);
/// Returns the reference to data value at column location.
Poco::Dynamic::Var& operator [] (const std::string& name);
/// Returns the reference to data value at named column location.
template <typename T>
void append(const std::string& name, const T& val)
/// Appends the value to the row.
{
if (!_pNames) _pNames = new NameVec;
_values.push_back(val);
_pNames->push_back(name);
if (1 == _values.size()) addSortField(0);
}
template <typename T>
void set(std::size_t pos, const T& val)
/// Assigns the value to the row.
{
try
{
_values.at(pos) = val;
}
catch (std::out_of_range&)
{
throw RangeException("Invalid column number.");
}
}
template <typename T>
void set(const std::string& name, const T& val)
/// Assigns the value to the row.
{
NameVec::iterator it = _pNames->begin();
NameVec::iterator end = _pNames->end();
for (int i = 0; it != end; ++it, ++i)
{
if (*it == name)
return set(i, val);
}
std::ostringstream os;
os << "Column with name " << name << " not found.";
throw NotFoundException(os.str());
}
std::size_t fieldCount() const;
/// Returns the number of fields in this row.
void reset();
/// Resets the row by clearing all field names and values.
void separator(const std::string& sep);
/// Sets the separator.
void addSortField(std::size_t pos);
/// Adds the field used for sorting.
void addSortField(const std::string& name);
/// Adds the field used for sorting.
void removeSortField(std::size_t pos);
/// Removes the field used for sorting.
void removeSortField(const std::string& name);
/// Removes the field used for sorting.
void replaceSortField(std::size_t oldPos, std::size_t newPos);
/// Replaces the field used for sorting.
void replaceSortField(const std::string& oldName, const std::string& newName);
/// Replaces the field used for sorting.
void resetSort();
/// Resets the sorting criteria to field 0 only.
const std::string& namesToString() const;
/// Converts the column names to string.
void formatNames() const;
/// Fomats the column names.
const std::string& valuesToString() const;
/// Converts the row values to string and returns the formated string.
void formatValues() const;
/// Fomats the row values.
bool operator == (const Row& other) const;
/// Equality operator.
bool operator != (const Row& other) const;
/// Inequality operator.
bool operator < (const Row& other) const;
/// Less-than operator.
const NameVecPtr names() const;
/// Returns the shared pointer to names vector.
const ValueVec& values() const;
/// Returns the const reference to values vector.
void setFormatter(const RowFormatter::Ptr& pFormatter = 0);
/// Sets the formatter for this row and takes the
/// shared ownership of it.
const RowFormatter& getFormatter() const;
/// Returns the reference to the formatter.
void setSortMap(const SortMapPtr& pSortMap = 0);
/// Adds the sorting fields entry and takes the
/// shared ownership of it.
const SortMapPtr& getSortMap() const;
/// Returns the reference to the sorting fields.
private:
void init(const SortMapPtr& pSortMap, const RowFormatter::Ptr& pFormatter);
ValueVec& values();
/// Returns the reference to values vector.
std::size_t getPosition(const std::string& name);
bool isEqualSize(const Row& other) const;
bool isEqualType(const Row& other) const;
NameVecPtr _pNames;
ValueVec _values;
SortMapPtr _pSortMap;
mutable RowFormatter::Ptr _pFormatter;
mutable std::string _nameStr;
mutable std::string _valueStr;
};
Data_API std::ostream& operator << (std::ostream &os, const Row& row);
///
/// inlines
///
inline std::size_t Row::fieldCount() const
namespace Data
{
return static_cast<std::size_t>(_values.size());
class RecordSet;
class Data_API Row
/// Row class provides a data type for RecordSet iteration purposes.
/// Dereferencing a RowIterator returns Row.
/// Rows are sortable. The sortability is maintained at all times (i.e. there
/// is always at least one column specified as a sorting criteria) .
/// The default and minimal sorting criteria is the first field (position 0).
/// The default sorting criteria can be replaced with any other field by
/// calling replaceSortField() member function.
/// Additional fields can be added to sorting criteria, in which case the
/// field precedence corresponds to addition order (i.e. later added fields
/// have lower sorting precedence).
/// These features make Row suitable for use with standard sorted
/// containers and algorithms. The main constraint is that all the rows from
/// a set that is being sorted must have the same sorting criteria (i.e., the same
/// set of fields must be in sorting criteria in the same order). Since rows don't
/// know about each other, it is the programmer's responsibility to ensure this
/// constraint is satisfied.
/// Field names are a shared pointer to a vector of strings. For efficiency sake,
/// a constructor taking a shared pointer to names vector argument is provided.
/// The stream operator is provided for Row data type as a free-standing function.
{
public:
typedef RowFormatter::NameVec NameVec;
typedef RowFormatter::NameVecPtr NameVecPtr;
typedef RowFormatter::ValueVec ValueVec;
enum ComparisonType
{
COMPARE_AS_EMPTY,
COMPARE_AS_INTEGER,
COMPARE_AS_FLOAT,
COMPARE_AS_STRING
};
typedef Tuple<std::size_t, ComparisonType> SortTuple;
typedef std::vector<SortTuple> SortMap;
/// The type for map holding fields used for sorting criteria.
/// Fields are added sequentially and have precedence that
/// corresponds to field adding sequence order (rather than field's
/// position in the row).
/// This requirement rules out use of std::map due to its sorted nature.
typedef SharedPtr<SortMap> SortMapPtr;
Row();
/// Creates the Row.
Row(NameVecPtr pNames, const RowFormatter::Ptr & pFormatter = 0);
/// Creates the Row.
Row(NameVecPtr pNames, const SortMapPtr & pSortMap, const RowFormatter::Ptr & pFormatter = 0);
/// Creates the Row.
~Row();
/// Destroys the Row.
Poco::Dynamic::Var & get(std::size_t col);
/// Returns the reference to data value at column location.
Poco::Dynamic::Var & operator[](std::size_t col);
/// Returns the reference to data value at column location.
Poco::Dynamic::Var & operator[](const std::string & name);
/// Returns the reference to data value at named column location.
template <typename T>
void append(const std::string & name, const T & val)
/// Appends the value to the row.
{
if (!_pNames)
_pNames = new NameVec;
_values.push_back(val);
_pNames->push_back(name);
if (1 == _values.size())
addSortField(0);
}
template <typename T>
void set(std::size_t pos, const T & val)
/// Assigns the value to the row.
{
try
{
_values.at(pos) = val;
}
catch (std::out_of_range &)
{
throw RangeException("Invalid column number.");
}
}
template <typename T>
void set(const std::string & name, const T & val)
/// Assigns the value to the row.
{
NameVec::iterator it = _pNames->begin();
NameVec::iterator end = _pNames->end();
for (int i = 0; it != end; ++it, ++i)
{
if (*it == name)
return set(i, val);
}
std::ostringstream os;
os << "Column with name " << name << " not found.";
throw NotFoundException(os.str());
}
std::size_t fieldCount() const;
/// Returns the number of fields in this row.
void reset();
/// Resets the row by clearing all field names and values.
void separator(const std::string & sep);
/// Sets the separator.
void addSortField(std::size_t pos);
/// Adds the field used for sorting.
void addSortField(const std::string & name);
/// Adds the field used for sorting.
void removeSortField(std::size_t pos);
/// Removes the field used for sorting.
void removeSortField(const std::string & name);
/// Removes the field used for sorting.
void replaceSortField(std::size_t oldPos, std::size_t newPos);
/// Replaces the field used for sorting.
void replaceSortField(const std::string & oldName, const std::string & newName);
/// Replaces the field used for sorting.
void resetSort();
/// Resets the sorting criteria to field 0 only.
const std::string & namesToString() const;
/// Converts the column names to string.
void formatNames() const;
/// Formats the column names.
const std::string & valuesToString() const;
/// Converts the row values to string and returns the formatted string.
void formatValues() const;
/// Formats the row values.
bool operator==(const Row & other) const;
/// Equality operator.
bool operator!=(const Row & other) const;
/// Inequality operator.
bool operator<(const Row & other) const;
/// Less-than operator.
const NameVecPtr names() const;
/// Returns the shared pointer to names vector.
const ValueVec & values() const;
/// Returns the const reference to values vector.
void setFormatter(const RowFormatter::Ptr & pFormatter = 0);
/// Sets the formatter for this row and takes the
/// shared ownership of it.
const RowFormatter & getFormatter() const;
/// Returns the reference to the formatter.
void setSortMap(const SortMapPtr & pSortMap = 0);
/// Adds the sorting fields entry and takes the
/// shared ownership of it.
const SortMapPtr & getSortMap() const;
/// Returns the reference to the sorting fields.
private:
void init(const SortMapPtr & pSortMap, const RowFormatter::Ptr & pFormatter);
ValueVec & values();
/// Returns the reference to values vector.
std::size_t getPosition(const std::string & name);
bool isEqualSize(const Row & other) const;
bool isEqualType(const Row & other) const;
NameVecPtr _pNames;
ValueVec _values;
SortMapPtr _pSortMap;
mutable RowFormatter::Ptr _pFormatter;
mutable std::string _nameStr;
mutable std::string _valueStr;
};
Data_API std::ostream & operator<<(std::ostream & os, const Row & row);
///
/// inlines
///
inline std::size_t Row::fieldCount() const
{
return static_cast<std::size_t>(_values.size());
}
inline void Row::reset()
{
_pNames->clear();
_values.clear();
}
inline const Row::NameVecPtr Row::names() const
{
return _pNames;
}
inline const Row::ValueVec & Row::values() const
{
return _values;
}
inline Row::ValueVec & Row::values()
{
return _values;
}
inline Poco::Dynamic::Var & Row::operator[](std::size_t col)
{
return get(col);
}
inline Poco::Dynamic::Var & Row::operator[](const std::string & name)
{
return get(getPosition(name));
}
inline const RowFormatter & Row::getFormatter() const
{
return *_pFormatter;
}
inline const Row::SortMapPtr & Row::getSortMap() const
{
return _pSortMap;
}
inline const std::string & Row::valuesToString() const
{
return _pFormatter->formatValues(values(), _valueStr);
}
inline void Row::formatValues() const
{
return _pFormatter->formatValues(values());
}
}
inline void Row::reset()
{
_pNames->clear();
_values.clear();
}
inline const Row::NameVecPtr Row::names() const
{
return _pNames;
}
inline const Row::ValueVec& Row::values() const
{
return _values;
}
inline Row::ValueVec& Row::values()
{
return _values;
}
inline Poco::Dynamic::Var& Row::operator [] (std::size_t col)
{
return get(col);
}
inline Poco::Dynamic::Var& Row::operator [] (const std::string& name)
{
return get(getPosition(name));
}
inline const RowFormatter& Row::getFormatter() const
{
return *_pFormatter;
}
inline const Row::SortMapPtr& Row::getSortMap() const
{
return _pSortMap;
}
inline const std::string& Row::valuesToString() const
{
return _pFormatter->formatValues(values(), _valueStr);
}
inline void Row::formatValues() const
{
return _pFormatter->formatValues(values());
}
} } // namespace Poco::Data
} // namespace Poco::Data
#endif // Data_Row_INCLUDED

View File

@ -18,259 +18,258 @@
#define Data_RowFilter_INCLUDED
#include <list>
#include <map>
#include <utility>
#include "Poco/AutoPtr.h"
#include "Poco/Data/Data.h"
#include "Poco/Dynamic/Var.h"
#include "Poco/Tuple.h"
#include "Poco/String.h"
#include "Poco/RefCountedObject.h"
#include "Poco/AutoPtr.h"
#include <map>
#include <list>
#include <utility>
#include "Poco/String.h"
#include "Poco/Tuple.h"
namespace Poco {
namespace Data {
class RecordSet;
class Data_API RowFilter: public RefCountedObject
/// RowFilter class provides row filtering functionality.
/// A filter contains a set of criteria (field name, value and
/// logical operation) for row filtering.
/// Additionally, a row filter contains a map of pointers to other
/// filters with related logical operations between filters.
/// RowFilter is typically added to recordset in order to filter
/// its content. Since the recordset own iteration is dependent upon
/// filtering, whenever the filtering criteria is changed,
/// the filter automatically notifies all associated recordsets
/// by rewinding them to the first position.
namespace Poco
{
public:
enum Comparison
{
VALUE_LESS_THAN,
VALUE_LESS_THAN_OR_EQUAL,
VALUE_EQUAL,
VALUE_GREATER_THAN,
VALUE_GREATER_THAN_OR_EQUAL,
VALUE_NOT_EQUAL,
VALUE_IS_NULL
};
enum LogicOperator
{
OP_AND,
OP_OR,
OP_NOT
};
typedef bool (*CompT)(const Poco::Dynamic::Var&, const Poco::Dynamic::Var&);
typedef AutoPtr<RowFilter> Ptr;
typedef std::map<std::string, Comparison> Comparisons;
typedef Tuple<Poco::Dynamic::Var, Comparison, LogicOperator> ComparisonEntry;
typedef std::multimap<std::string, ComparisonEntry> ComparisonMap;
typedef std::map<AutoPtr<RowFilter>, LogicOperator> FilterMap;
RowFilter(RecordSet* pRecordSet);
/// Creates the top-level RowFilter and associates it with the recordset.
RowFilter(Ptr pParent, LogicOperator op = OP_OR);
/// Creates child RowFilter and associates it with the parent filter.
~RowFilter();
/// Destroys the RowFilter.
void addFilter(Ptr pFilter, LogicOperator comparison);
/// Appends another filter to this one.
void removeFilter(Ptr pFilter);
/// Removes filter from this filter.
bool has(Ptr pFilter) const;
/// Returns true if this filter is parent of pFilter;
template <typename T>
void add(const std::string& name, Comparison comparison, const T& value, LogicOperator op = OP_OR)
/// Adds value to the filter.
{
rewindRecordSet();
_comparisonMap.insert(ComparisonMap::value_type(toUpper(name),
ComparisonEntry(value, comparison, op)));
}
template <typename T>
void add(const std::string& name, const std::string& comp, const T& value, LogicOperator op = OP_OR)
/// Adds value to the filter.
{
add(name, getComparison(comp), value, op);
}
template <typename T>
void addAnd(const std::string& name, const std::string& comp, const T& value)
/// Adds logically AND-ed value to the filter.
{
add(name, getComparison(comp), value, OP_AND);
}
template <typename T>
void addOr(const std::string& name, const std::string& comp, const T& value)
/// Adds logically OR-ed value to the filter.
{
add(name, getComparison(comp), value, OP_OR);
}
int remove(const std::string& name);
/// Removes named comparisons from the filter.
/// All comparisons with specified name are removed.
/// Returns the number of comparisons removed.
void toggleNot();
/// Togless the NOT operator for this filter;
bool isNot() const;
/// Returns true if filter is NOT-ed, false otherwise.
bool isEmpty() const;
/// Returns true if there is not filtering criteria specified.
bool isAllowed(std::size_t row) const;
/// Returns true if name and value are allowed.
bool exists(const std::string& name) const;
/// Returns true if name is known to this row filter.
private:
RowFilter();
RowFilter(const RowFilter&);
RowFilter& operator=(const RowFilter&);
void init();
static bool equal(const Poco::Dynamic::Var& p1, const Poco::Dynamic::Var& p2);
static bool notEqual(const Poco::Dynamic::Var& p1, const Poco::Dynamic::Var& p2);
static bool less(const Poco::Dynamic::Var& p1, const Poco::Dynamic::Var& p2);
static bool greater(const Poco::Dynamic::Var& p1, const Poco::Dynamic::Var& p2);
static bool lessOrEqual(const Poco::Dynamic::Var& p1, const Poco::Dynamic::Var& p2);
static bool greaterOrEqual(const Poco::Dynamic::Var& p1, const Poco::Dynamic::Var& p2);
static bool logicalAnd(const Poco::Dynamic::Var& p1, const Poco::Dynamic::Var& p2);
static bool logicalOr(const Poco::Dynamic::Var& p1, const Poco::Dynamic::Var& p2);
static bool isNull(const Poco::Dynamic::Var& p1, const Poco::Dynamic::Var&);
static void doCompare(Poco::Dynamic::Var& ret,
Poco::Dynamic::Var& val,
CompT comp,
const ComparisonEntry& ce);
RecordSet& recordSet() const;
Comparison getComparison(const std::string& comp) const;
void rewindRecordSet();
Comparisons _comparisons;
ComparisonMap _comparisonMap;
mutable RecordSet* _pRecordSet;
Ptr _pParent;
FilterMap _filterMap;
bool _not;
friend class RecordSet;
};
///
/// inlines
///
inline bool RowFilter::has(Ptr pFilter) const
namespace Data
{
return _filterMap.find(pFilter) != _filterMap.end();
class RecordSet;
class Data_API RowFilter : public RefCountedObject
/// RowFilter class provides row filtering functionality.
/// A filter contains a set of criteria (field name, value and
/// logical operation) for row filtering.
/// Additionally, a row filter contains a map of pointers to other
/// filters with related logical operations between filters.
/// RowFilter is typically added to recordset in order to filter
/// its content. Since the recordset own iteration is dependent upon
/// filtering, whenever the filtering criteria is changed,
/// the filter automatically notifies all associated recordsets
/// by rewinding them to the first position.
{
public:
enum Comparison
{
VALUE_LESS_THAN,
VALUE_LESS_THAN_OR_EQUAL,
VALUE_EQUAL,
VALUE_GREATER_THAN,
VALUE_GREATER_THAN_OR_EQUAL,
VALUE_NOT_EQUAL,
VALUE_IS_NULL
};
enum LogicOperator
{
OP_AND,
OP_OR,
OP_NOT
};
typedef bool (*CompT)(const Poco::Dynamic::Var &, const Poco::Dynamic::Var &);
typedef AutoPtr<RowFilter> Ptr;
typedef std::map<std::string, Comparison> Comparisons;
typedef Tuple<Poco::Dynamic::Var, Comparison, LogicOperator> ComparisonEntry;
typedef std::multimap<std::string, ComparisonEntry> ComparisonMap;
typedef std::map<AutoPtr<RowFilter>, LogicOperator> FilterMap;
RowFilter(RecordSet * pRecordSet);
/// Creates the top-level RowFilter and associates it with the recordset.
RowFilter(Ptr pParent, LogicOperator op = OP_OR);
/// Creates child RowFilter and associates it with the parent filter.
~RowFilter();
/// Destroys the RowFilter.
void addFilter(Ptr pFilter, LogicOperator comparison);
/// Appends another filter to this one.
void removeFilter(Ptr pFilter);
/// Removes filter from this filter.
bool has(Ptr pFilter) const;
/// Returns true if this filter is parent of pFilter;
template <typename T>
void add(const std::string & name, Comparison comparison, const T & value, LogicOperator op = OP_OR)
/// Adds value to the filter.
{
rewindRecordSet();
_comparisonMap.insert(ComparisonMap::value_type(toUpper(name), ComparisonEntry(value, comparison, op)));
}
template <typename T>
void add(const std::string & name, const std::string & comp, const T & value, LogicOperator op = OP_OR)
/// Adds value to the filter.
{
add(name, getComparison(comp), value, op);
}
template <typename T>
void addAnd(const std::string & name, const std::string & comp, const T & value)
/// Adds logically AND-ed value to the filter.
{
add(name, getComparison(comp), value, OP_AND);
}
template <typename T>
void addOr(const std::string & name, const std::string & comp, const T & value)
/// Adds logically OR-ed value to the filter.
{
add(name, getComparison(comp), value, OP_OR);
}
int remove(const std::string & name);
/// Removes named comparisons from the filter.
/// All comparisons with specified name are removed.
/// Returns the number of comparisons removed.
void toggleNot();
/// Togless the NOT operator for this filter;
bool isNot() const;
/// Returns true if filter is NOT-ed, false otherwise.
bool isEmpty() const;
/// Returns true if there is not filtering criteria specified.
bool isAllowed(std::size_t row) const;
/// Returns true if name and value are allowed.
bool exists(const std::string & name) const;
/// Returns true if name is known to this row filter.
private:
RowFilter();
RowFilter(const RowFilter &);
RowFilter & operator=(const RowFilter &);
void init();
static bool equal(const Poco::Dynamic::Var & p1, const Poco::Dynamic::Var & p2);
static bool notEqual(const Poco::Dynamic::Var & p1, const Poco::Dynamic::Var & p2);
static bool less(const Poco::Dynamic::Var & p1, const Poco::Dynamic::Var & p2);
static bool greater(const Poco::Dynamic::Var & p1, const Poco::Dynamic::Var & p2);
static bool lessOrEqual(const Poco::Dynamic::Var & p1, const Poco::Dynamic::Var & p2);
static bool greaterOrEqual(const Poco::Dynamic::Var & p1, const Poco::Dynamic::Var & p2);
static bool logicalAnd(const Poco::Dynamic::Var & p1, const Poco::Dynamic::Var & p2);
static bool logicalOr(const Poco::Dynamic::Var & p1, const Poco::Dynamic::Var & p2);
static bool isNull(const Poco::Dynamic::Var & p1, const Poco::Dynamic::Var &);
static void doCompare(Poco::Dynamic::Var & ret, Poco::Dynamic::Var & val, CompT comp, const ComparisonEntry & ce);
RecordSet & recordSet() const;
Comparison getComparison(const std::string & comp) const;
void rewindRecordSet();
Comparisons _comparisons;
ComparisonMap _comparisonMap;
mutable RecordSet * _pRecordSet;
Ptr _pParent;
FilterMap _filterMap;
bool _not;
friend class RecordSet;
};
///
/// inlines
///
inline bool RowFilter::has(Ptr pFilter) const
{
return _filterMap.find(pFilter) != _filterMap.end();
}
inline bool RowFilter::isEmpty() const
{
return _comparisonMap.size() == 0;
}
inline bool RowFilter::exists(const std::string & name) const
{
return _comparisonMap.find(name) != _comparisonMap.end();
}
inline void RowFilter::toggleNot()
{
_not = !_not;
}
inline bool RowFilter::isNot() const
{
return _not;
}
inline bool RowFilter::equal(const Poco::Dynamic::Var & p1, const Poco::Dynamic::Var & p2)
{
return p1 == p2;
}
inline bool RowFilter::notEqual(const Poco::Dynamic::Var & p1, const Poco::Dynamic::Var & p2)
{
return p1 != p2;
}
inline bool RowFilter::less(const Poco::Dynamic::Var & p1, const Poco::Dynamic::Var & p2)
{
return p1 < p2;
}
inline bool RowFilter::greater(const Poco::Dynamic::Var & p1, const Poco::Dynamic::Var & p2)
{
return p1 > p2;
}
inline bool RowFilter::lessOrEqual(const Poco::Dynamic::Var & p1, const Poco::Dynamic::Var & p2)
{
return p1 <= p2;
}
inline bool RowFilter::greaterOrEqual(const Poco::Dynamic::Var & p1, const Poco::Dynamic::Var & p2)
{
return p1 >= p2;
}
inline bool RowFilter::logicalAnd(const Poco::Dynamic::Var & p1, const Poco::Dynamic::Var & p2)
{
return p1 && p2;
}
inline bool RowFilter::logicalOr(const Poco::Dynamic::Var & p1, const Poco::Dynamic::Var & p2)
{
return p1 || p2;
}
inline bool RowFilter::isNull(const Poco::Dynamic::Var & p1, const Poco::Dynamic::Var &)
{
return p1.isEmpty();
}
}
inline bool RowFilter::isEmpty() const
{
return _comparisonMap.size() == 0;
}
inline bool RowFilter::exists(const std::string& name) const
{
return _comparisonMap.find(name) != _comparisonMap.end();
}
inline void RowFilter::toggleNot()
{
_not = !_not;
}
inline bool RowFilter::isNot() const
{
return _not;
}
inline bool RowFilter::equal(const Poco::Dynamic::Var& p1, const Poco::Dynamic::Var& p2)
{
return p1 == p2;
}
inline bool RowFilter::notEqual(const Poco::Dynamic::Var& p1, const Poco::Dynamic::Var& p2)
{
return p1 != p2;
}
inline bool RowFilter::less(const Poco::Dynamic::Var& p1, const Poco::Dynamic::Var& p2)
{
return p1 < p2;
}
inline bool RowFilter::greater(const Poco::Dynamic::Var& p1, const Poco::Dynamic::Var& p2)
{
return p1 > p2;
}
inline bool RowFilter::lessOrEqual(const Poco::Dynamic::Var& p1, const Poco::Dynamic::Var& p2)
{
return p1 <= p2;
}
inline bool RowFilter::greaterOrEqual(const Poco::Dynamic::Var& p1, const Poco::Dynamic::Var& p2)
{
return p1 >= p2;
}
inline bool RowFilter::logicalAnd(const Poco::Dynamic::Var& p1, const Poco::Dynamic::Var& p2)
{
return p1 && p2;
}
inline bool RowFilter::logicalOr(const Poco::Dynamic::Var& p1, const Poco::Dynamic::Var& p2)
{
return p1 || p2;
}
inline bool RowFilter::isNull(const Poco::Dynamic::Var& p1, const Poco::Dynamic::Var&)
{
return p1.isEmpty();
}
} } // namespace Poco::Data
} // namespace Poco::Data
#endif // Data_RowFilter_INCLUDED

View File

@ -18,214 +18,214 @@
#define Data_RowFormatter_INCLUDED
#include "Poco/Data/Data.h"
#include "Poco/SharedPtr.h"
#include "Poco/RefCountedObject.h"
#include "Poco/Dynamic/Var.h"
#include <sstream>
#include <vector>
#include "Poco/Data/Data.h"
#include "Poco/Dynamic/Var.h"
#include "Poco/RefCountedObject.h"
#include "Poco/SharedPtr.h"
namespace Poco {
namespace Data {
class Data_API RowFormatter
/// Row formatter is an abstract class providing definition for row formatting functionality.
/// For custom formatting strategies, inherit from this class and override formatNames()
/// and formatValues() member functions.
///
/// Row formatter can be either passed to the RecordSet at construction time,
/// like in the following example:
///
/// RecordSet rs(session. "SELECT * FROM Table", new MyRowFormater);
///
/// or it can be supplied to the statement as in the following example:
///
/// MyRowFormatter rf
/// session << "SELECT * FROM Table", format(rf);
///
/// If no formatter is externally supplied to the statement, the SimpleRowFormatter is used.
/// Statement always has the ownership of the row formatter and shares
/// it with rows through RecordSet.
///
/// To accomodate for various formatting needs, a formatter can operate in two modes:
///
/// - progressive: formatted individual row strings are gemerated and returned from each
/// call to formatValues;
/// std::string& formatNames(const NameVecPtr, std::string&) and
/// std::string& formatValues(const ValueVec&, std::string&) member calls should be
/// used in this case; this is the default mode
///
/// - bulk: formatted resulting string is accumulated internally and obtained at
/// the end of iteration via toString() member function;
/// void formatNames(const NameVecPtr) and
/// void formatValues(const ValueVec&) member calls should be used in this case
///
/// When formatter is used in conjunction with Row/RecordSet, the formatting members corresponding
/// to the formater mode are expected to be implemented. If a call is propagated to this parent
/// class, the functions do nothing or silently return empty string respectively.
///
namespace Poco
{
public:
typedef SharedPtr<RowFormatter> Ptr;
typedef std::vector<std::string> NameVec;
typedef SharedPtr<std::vector<std::string> > NameVecPtr;
typedef std::vector<Poco::Dynamic::Var> ValueVec;
static const int INVALID_ROW_COUNT = -1;
enum Mode
{
FORMAT_PROGRESSIVE,
FORMAT_BULK
};
RowFormatter(const std::string& prefix = "",
const std::string& postfix = "",
Mode mode = FORMAT_PROGRESSIVE);
/// Creates the RowFormatter and sets the prefix and postfix to specified values.
virtual ~RowFormatter();
/// Destroys the RowFormatter.
virtual std::string& formatNames(const NameVecPtr pNames, std::string& formattedNames);
/// Should be implemented to format the row fields names and return the formatted string.
/// The default implementation clears the names string and returns it.
virtual void formatNames(const NameVecPtr pNames);
/// Should be implemented to format the row fields names.
/// The default implementation does nothing.
virtual std::string& formatValues(const ValueVec& vals, std::string& formattedValues);
/// Should be implemented to format the row fields values and return the formatted string.
/// The default implementation clears the values string and returns it.
virtual void formatValues(const ValueVec& vals);
/// Should be implemented to format the row fields values.
/// The default implementation does nothing.
virtual const std::string& toString();
/// Throws NotImplementedException. Formatters operating in bulk mode should
/// implement this member function to return valid pointer to the formatted result.
virtual int rowCount() const;
/// Returns INVALID_ROW_COUNT. Must be implemented by inheriting classes
/// which maintain count of processed rows.
int getTotalRowCount() const;
/// Returns zero. Must be implemented by inheriting classes.
/// Typically, total row count shall be set up front through
/// setTotalRowCount() call.
void setTotalRowCount(int count);
/// Sets total row count.
virtual const std::string& prefix() const;
/// Returns prefix string;
virtual const std::string& postfix() const;
/// Returns postfix string;
void reset();
/// Resets the formatter by setting prefix and postfix
/// to empty strings and row count to INVALID_ROW_COUNT.
Mode getMode() const;
/// Returns the formater mode.
void setMode(Mode mode);
/// Sets the fromatter mode.
protected:
void setPrefix(const std::string& prefix);
/// Sets the prefix for the formatter.
void setPostfix(const std::string& postfix);
/// Sets the postfix for the formatter
private:
mutable std::string _prefix;
mutable std::string _postfix;
Mode _mode;
int _totalRowCount;
};
///
/// inlines
///
inline int RowFormatter::rowCount() const
namespace Data
{
return INVALID_ROW_COUNT;
class Data_API RowFormatter
/// Row formatter is an abstract class providing definition for row formatting functionality.
/// For custom formatting strategies, inherit from this class and override formatNames()
/// and formatValues() member functions.
///
/// Row formatter can be either passed to the RecordSet at construction time,
/// like in the following example:
///
/// RecordSet rs(session. "SELECT * FROM Table", new MyRowFormater);
///
/// or it can be supplied to the statement as in the following example:
///
/// MyRowFormatter rf
/// session << "SELECT * FROM Table", format(rf);
///
/// If no formatter is externally supplied to the statement, the SimpleRowFormatter is used.
/// Statement always has the ownership of the row formatter and shares
/// it with rows through RecordSet.
///
/// To accommodate for various formatting needs, a formatter can operate in two modes:
///
/// - progressive: formatted individual row strings are gemerated and returned from each
/// call to formatValues;
/// std::string& formatNames(const NameVecPtr, std::string&) and
/// std::string& formatValues(const ValueVec&, std::string&) member calls should be
/// used in this case; this is the default mode
///
/// - bulk: formatted resulting string is accumulated internally and obtained at
/// the end of iteration via toString() member function;
/// void formatNames(const NameVecPtr) and
/// void formatValues(const ValueVec&) member calls should be used in this case
///
/// When formatter is used in conjunction with Row/RecordSet, the formatting members corresponding
/// to the formatter mode are expected to be implemented. If a call is propagated to this parent
/// class, the functions do nothing or silently return empty string respectively.
///
{
public:
typedef SharedPtr<RowFormatter> Ptr;
typedef std::vector<std::string> NameVec;
typedef SharedPtr<std::vector<std::string>> NameVecPtr;
typedef std::vector<Poco::Dynamic::Var> ValueVec;
static const int INVALID_ROW_COUNT = -1;
enum Mode
{
FORMAT_PROGRESSIVE,
FORMAT_BULK
};
RowFormatter(const std::string & prefix = "", const std::string & postfix = "", Mode mode = FORMAT_PROGRESSIVE);
/// Creates the RowFormatter and sets the prefix and postfix to specified values.
virtual ~RowFormatter();
/// Destroys the RowFormatter.
virtual std::string & formatNames(const NameVecPtr pNames, std::string & formattedNames);
/// Should be implemented to format the row fields names and return the formatted string.
/// The default implementation clears the names string and returns it.
virtual void formatNames(const NameVecPtr pNames);
/// Should be implemented to format the row fields names.
/// The default implementation does nothing.
virtual std::string & formatValues(const ValueVec & vals, std::string & formattedValues);
/// Should be implemented to format the row fields values and return the formatted string.
/// The default implementation clears the values string and returns it.
virtual void formatValues(const ValueVec & vals);
/// Should be implemented to format the row fields values.
/// The default implementation does nothing.
virtual const std::string & toString();
/// Throws NotImplementedException. Formatters operating in bulk mode should
/// implement this member function to return valid pointer to the formatted result.
virtual int rowCount() const;
/// Returns INVALID_ROW_COUNT. Must be implemented by inheriting classes
/// which maintain count of processed rows.
int getTotalRowCount() const;
/// Returns zero. Must be implemented by inheriting classes.
/// Typically, total row count shall be set up front through
/// setTotalRowCount() call.
void setTotalRowCount(int count);
/// Sets total row count.
virtual const std::string & prefix() const;
/// Returns prefix string;
virtual const std::string & postfix() const;
/// Returns postfix string;
void reset();
/// Resets the formatter by setting prefix and postfix
/// to empty strings and row count to INVALID_ROW_COUNT.
Mode getMode() const;
/// Returns the formatter mo
void setMode(Mode mode);
/// Sets the fromatter mode.
protected:
void setPrefix(const std::string & prefix);
/// Sets the prefix for the formatter.
void setPostfix(const std::string & postfix);
/// Sets the postfix for the formatter
private:
mutable std::string _prefix;
mutable std::string _postfix;
Mode _mode;
int _totalRowCount;
};
///
/// inlines
///
inline int RowFormatter::rowCount() const
{
return INVALID_ROW_COUNT;
}
inline int RowFormatter::getTotalRowCount() const
{
return _totalRowCount;
}
inline void RowFormatter::setTotalRowCount(int count)
{
_totalRowCount = count;
}
inline void RowFormatter::setPrefix(const std::string & prefix)
{
_prefix = prefix;
}
inline void RowFormatter::setPostfix(const std::string & postfix)
{
_postfix = postfix;
}
inline const std::string & RowFormatter::prefix() const
{
return _prefix;
}
inline const std::string & RowFormatter::postfix() const
{
return _postfix;
}
inline RowFormatter::Mode RowFormatter::getMode() const
{
return _mode;
}
inline void RowFormatter::setMode(Mode mode)
{
_mode = mode;
}
namespace Keywords
{
template <typename T>
inline RowFormatter::Ptr format(const T & formatter)
/// Utility function used to pass formatter to the statement.
{
return new T(formatter);
}
} // namespace Keywords
}
inline int RowFormatter::getTotalRowCount() const
{
return _totalRowCount;
}
inline void RowFormatter::setTotalRowCount(int count)
{
_totalRowCount = count;
}
inline void RowFormatter::setPrefix(const std::string& prefix)
{
_prefix = prefix;
}
inline void RowFormatter::setPostfix(const std::string& postfix)
{
_postfix = postfix;
}
inline const std::string& RowFormatter::prefix() const
{
return _prefix;
}
inline const std::string& RowFormatter::postfix() const
{
return _postfix;
}
inline RowFormatter::Mode RowFormatter::getMode() const
{
return _mode;
}
inline void RowFormatter::setMode(Mode mode)
{
_mode = mode;
}
namespace Keywords {
template <typename T>
inline RowFormatter::Ptr format(const T& formatter)
/// Utility function used to pass formatter to the statement.
{
return new T(formatter);
}
} // namespace Keywords
} } // namespace Poco::Data
} // namespace Poco::Data
#endif // Data_RowFormatter_INCLUDED

View File

@ -18,132 +18,134 @@
#define Data_RowIterator_INCLUDED
#include <algorithm>
#include <iterator>
#include "Poco/Data/Data.h"
#include "Poco/Data/Row.h"
#include "Poco/Dynamic/Var.h"
#include <iterator>
#include <algorithm>
namespace Poco {
namespace Data {
class RecordSet;
class Data_API RowIterator
/// RowIterator class.
namespace Poco
{
public:
typedef std::bidirectional_iterator_tag iterator_category;
typedef Row value_type;
typedef std::ptrdiff_t difference_type;
typedef Row* pointer;
typedef Row& reference;
static const std::size_t POSITION_END;
/// End position indicator.
RowIterator(RecordSet* pRecordSet, bool positionEnd);
/// Creates the RowIterator and positions it at the end of
/// the recordset if positionEnd is true. Otherwise, it is
/// positioned at the beginning.
RowIterator(const RowIterator& other);
/// Creates a copy of other RowIterator.
~RowIterator();
/// Destroys the RowIterator.
RowIterator& operator = (const RowIterator& other);
/// Assigns the other RowIterator.
bool operator == (const RowIterator& other) const;
/// Equality operator.
bool operator != (const RowIterator& other) const;
/// Inequality operator.
Row& operator * () const;
/// Returns reference to the current row.
Row* operator -> () const;
/// Returns pointer to the current row.
const RowIterator& operator ++ () const;
/// Advances by one position and returns current position.
RowIterator operator ++ (int) const;
/// Advances by one position and returns copy of the iterator with
/// previous current position.
const RowIterator& operator -- () const;
/// Goes back by one position and returns copy of the iterator with
/// previous current position.
RowIterator operator -- (int) const;
/// Goes back by one position and returns previous current position.
RowIterator operator + (std::size_t diff) const;
/// Returns a copy the RowIterator advanced by diff positions.
RowIterator operator - (std::size_t diff) const;
/// Returns a copy the RowIterator backed by diff positions.
/// Throws RangeException if diff is larger than current position.
void swap(RowIterator& other);
/// Swaps the RowIterator with another one.
private:
RowIterator();
void increment() const;
/// Increments the iterator position by one.
/// Throws RangeException if position is out of range.
void decrement() const;
/// Decrements the iterator position by one.
/// Throws RangeException if position is out of range.
void setPosition(std::size_t pos) const;
/// Sets the iterator position.
/// Throws RangeException if position is out of range.
RecordSet* _pRecordSet;
mutable std::size_t _position;
};
///
/// inlines
///
inline bool RowIterator::operator == (const RowIterator& other) const
namespace Data
{
return _pRecordSet == other._pRecordSet && _position == other._position;
class RecordSet;
class Data_API RowIterator
/// RowIterator class.
{
public:
typedef std::bidirectional_iterator_tag iterator_category;
typedef Row value_type;
typedef std::ptrdiff_t difference_type;
typedef Row * pointer;
typedef Row & reference;
static const std::size_t POSITION_END;
/// End position indicator.
RowIterator(RecordSet * pRecordSet, bool positionEnd);
/// Creates the RowIterator and positions it at the end of
/// the recordset if positionEnd is true. Otherwise, it is
/// positioned at the beginning.
RowIterator(const RowIterator & other);
/// Creates a copy of other RowIterator.
~RowIterator();
/// Destroys the RowIterator.
RowIterator & operator=(const RowIterator & other);
/// Assigns the other RowIterator.
bool operator==(const RowIterator & other) const;
/// Equality operator.
bool operator!=(const RowIterator & other) const;
/// Inequality operator.
Row & operator*() const;
/// Returns reference to the current row.
Row * operator->() const;
/// Returns pointer to the current row.
const RowIterator & operator++() const;
/// Advances by one position and returns current position.
RowIterator operator++(int) const;
/// Advances by one position and returns copy of the iterator with
/// previous current position.
const RowIterator & operator--() const;
/// Goes back by one position and returns copy of the iterator with
/// previous current position.
RowIterator operator--(int) const;
/// Goes back by one position and returns previous current position.
RowIterator operator+(std::size_t diff) const;
/// Returns a copy the RowIterator advanced by diff positions.
RowIterator operator-(std::size_t diff) const;
/// Returns a copy the RowIterator backed by diff positions.
/// Throws RangeException if diff is larger than current position.
void swap(RowIterator & other);
/// Swaps the RowIterator with another one.
private:
RowIterator();
void increment() const;
/// Increments the iterator position by one.
/// Throws RangeException if position is out of range.
void decrement() const;
/// Decrements the iterator position by one.
/// Throws RangeException if position is out of range.
void setPosition(std::size_t pos) const;
/// Sets the iterator position.
/// Throws RangeException if position is out of range.
RecordSet * _pRecordSet;
mutable std::size_t _position;
};
///
/// inlines
///
inline bool RowIterator::operator==(const RowIterator & other) const
{
return _pRecordSet == other._pRecordSet && _position == other._position;
}
inline bool RowIterator::operator!=(const RowIterator & other) const
{
return _pRecordSet != other._pRecordSet || _position != other._position;
}
}
inline bool RowIterator::operator != (const RowIterator& other) const
{
return _pRecordSet != other._pRecordSet || _position != other._position;
}
} } // namespace Poco::Data
} // namespace Poco::Data
namespace std
{
template<>
inline void swap<Poco::Data::RowIterator>(Poco::Data::RowIterator& s1,
Poco::Data::RowIterator& s2)
/// Full template specalization of std:::swap for RowIterator
{
s1.swap(s2);
}
template <>
inline void swap<Poco::Data::RowIterator>(Poco::Data::RowIterator & s1, Poco::Data::RowIterator & s2)
/// Full template specalization of std:::swap for RowIterator
{
s1.swap(s2);
}
}

View File

@ -18,200 +18,199 @@
#define Data_SQLChannel_INCLUDED
#include "Poco/Data/Data.h"
#include "Poco/AutoPtr.h"
#include "Poco/Channel.h"
#include "Poco/Data/ArchiveStrategy.h"
#include "Poco/Data/Connector.h"
#include "Poco/Data/Data.h"
#include "Poco/Data/Session.h"
#include "Poco/Data/Statement.h"
#include "Poco/Data/ArchiveStrategy.h"
#include "Poco/Channel.h"
#include "Poco/Message.h"
#include "Poco/AutoPtr.h"
#include "Poco/String.h"
namespace Poco {
namespace Data {
class Data_API SQLChannel: public Poco::Channel
/// This Channel implements logging to a SQL database.
/// The channel is dependent on the schema. The DDL for
/// table creation (subject to target DDL dialect dependent
/// modifications) is:
///
/// "CREATE TABLE T_POCO_LOG (Source VARCHAR,
/// Name VARCHAR,
/// ProcessId INTEGER,
/// Thread VARCHAR,
/// ThreadId INTEGER,
/// Priority INTEGER,
/// Text VARCHAR,
/// DateTime DATE)"
///
/// The table name is configurable through "table" property.
/// Other than DateTime filed name used for optiona time-based archiving purposes, currently the
/// field names are not mandated. However, it is recomended to use names as specified above.
///
/// To provide as non-intrusive operation as possbile, the log entries are cached and
/// inserted into the target database asynchronously by default . The blocking, however, will occur
/// before the next entry insertion with default timeout of 1 second. The default settings can be
/// overriden (see async, timeout and throw properties for details).
/// If throw property is false, insertion timeouts are ignored, otherwise a TimeoutException is thrown.
/// To force insertion of every entry, set timeout to 0. This setting, however, introduces
/// a risk of long blocking periods in case of remote server communication delays.
namespace Poco
{
public:
SQLChannel();
/// Creates SQLChannel.
SQLChannel(const std::string& connector,
const std::string& connect,
const std::string& name = "-");
/// Creates a SQLChannel with the given connector, connect string, timeout, table and name.
/// The connector must be already registered.
void open();
/// Opens the SQLChannel.
void close();
/// Closes the SQLChannel.
void log(const Message& msg);
/// Sends the message's text to the syslog service.
void setProperty(const std::string& name, const std::string& value);
/// Sets the property with the given value.
///
/// The following properties are supported:
/// * name: The name used to identify the source of log messages.
/// Defaults to "-".
///
/// * target: The target data storage type ("SQLite", "ODBC", ...).
///
/// * connector: The target data storage connector name.
///
/// * connect: The target data storage connection string.
///
/// * table: Destination log table name. Defaults to "T_POCO_LOG".
/// Table must exist in the target database.
///
/// * keep: Max row age for the log table. To disable archiving,
/// set this property to empty string or "forever".
///
/// * archive: Archive table name. Defaults to "T_POCO_LOG_ARCHIVE".
/// Table must exist in the target database. To disable archiving,
/// set this property to empty string.
///
/// * async: Indicates asynchronous execution. When excuting asynchronously,
/// messages are sent to the target using asyncronous execution.
/// However, prior to the next message being processed and sent to
/// the target, the previous operation must have been either completed
/// or timed out (see timeout and throw properties for details on
/// how abnormal conditos are handled).
///
/// * timeout: Timeout (ms) to wait for previous log operation completion.
/// Values "0" and "" mean no timeout. Only valid when logging
/// is asynchronous, otherwise ignored.
///
/// * throw: Boolean value indicating whether to throw in case of timeout.
/// Setting this property to false may result in log entries being lost.
/// True values are (case insensitive) "true", "t", "yes", "y".
/// Anything else yields false.
std::string getProperty(const std::string& name) const;
/// Returns the value of the property with the given name.
std::size_t wait();
/// Waits for the completion of the previous operation and returns
/// the result. If chanel is in synchronous mode, returns 0 immediately.
static void registerChannel();
/// Registers the channel with the global LoggingFactory.
static const std::string PROP_CONNECT;
static const std::string PROP_CONNECTOR;
static const std::string PROP_NAME;
static const std::string PROP_TABLE;
static const std::string PROP_ARCHIVE_TABLE;
static const std::string PROP_MAX_AGE;
static const std::string PROP_ASYNC;
static const std::string PROP_TIMEOUT;
static const std::string PROP_THROW;
protected:
~SQLChannel();
private:
typedef Poco::SharedPtr<Session> SessionPtr;
typedef Poco::SharedPtr<Statement> StatementPtr;
typedef Poco::Message::Priority Priority;
typedef Poco::SharedPtr<ArchiveStrategy> StrategyPtr;
void initLogStatement();
/// Initiallizes the log statement.
void initArchiveStatements();
/// Initiallizes the archive statement.
void logAsync(const Message& msg);
/// Waits for previous operation completion and
/// calls logSync(). If the previous operation times out,
/// and _throw is true, TimeoutException is thrown, oterwise
/// the timeout is ignored and log entry is lost.
void logSync(const Message& msg);
/// Inserts the message in the target database.
bool isTrue(const std::string& value) const;
/// Returns true is value is "true", "t", "yes" or "y".
/// Case insensitive.
std::string _connector;
std::string _connect;
SessionPtr _pSession;
StatementPtr _pLogStatement;
std::string _name;
std::string _table;
int _timeout;
bool _throw;
bool _async;
// members for log entry cache (needed for async mode)
std::string _source;
long _pid;
std::string _thread;
long _tid;
int _priority;
std::string _text;
DateTime _dateTime;
StrategyPtr _pArchiveStrategy;
};
//
// inlines
//
inline std::size_t SQLChannel::wait()
namespace Data
{
if (_async && _pLogStatement)
return _pLogStatement->wait(_timeout);
return 0;
class Data_API SQLChannel : public Poco::Channel
/// This Channel implements logging to a SQL database.
/// The channel is dependent on the schema. The DDL for
/// table creation (subject to target DDL dialect dependent
/// modifications) is:
///
/// "CREATE TABLE T_POCO_LOG (Source VARCHAR,
/// Name VARCHAR,
/// ProcessId INTEGER,
/// Thread VARCHAR,
/// ThreadId INTEGER,
/// Priority INTEGER,
/// Text VARCHAR,
/// DateTime DATE)"
///
/// The table name is configurable through "table" property.
/// Other than DateTime filed name used for optiona time-based archiving purposes, currently the
/// field names are not mandated. However, it is recommended to use names as specified above.
///
/// To provide as non-intrusive operation as possible, the log entries are cached and
/// inserted into the target database asynchronously by default . The blocking, however, will occur
/// before the next entry insertion with default timeout of 1 second. The default settings can be
/// overridden (see async, timeout and throw properties for details).
/// If throw property is false, insertion timeouts are ignored, otherwise a TimeoutException is thrown.
/// To force insertion of every entry, set timeout to 0. This setting, however, introduces
/// a risk of long blocking periods in case of remote server communication delays.
{
public:
SQLChannel();
/// Creates SQLChannel.
SQLChannel(const std::string & connector, const std::string & connect, const std::string & name = "-");
/// Creates a SQLChannel with the given connector, connect string, timeout, table and name.
/// The connector must be already registered.
void open();
/// Opens the SQLChannel.
void close();
/// Closes the SQLChannel.
void log(const Message & msg);
/// Sends the message's text to the syslog service.
void setProperty(const std::string & name, const std::string & value);
/// Sets the property with the given value.
///
/// The following properties are supported:
/// * name: The name used to identify the source of log messages.
/// Defaults to "-".
///
/// * target: The target data storage type ("SQLite", "ODBC", ...).
///
/// * connector: The target data storage connector name.
///
/// * connect: The target data storage connection string.
///
/// * table: Destination log table name. Defaults to "T_POCO_LOG".
/// Table must exist in the target database.
///
/// * keep: Max row age for the log table. To disable archiving,
/// set this property to empty string or "forever".
///
/// * archive: Archive table name. Defaults to "T_POCO_LOG_ARCHIVE".
/// Table must exist in the target database. To disable archiving,
/// set this property to empty string.
///
/// * async: Indicates asynchronous execution. When executing asynchronously,
/// messages are sent to the target using asynchronous execution.
/// However, prior to the next message being processed and sent to
/// the target, the previous operation must have been either completed
/// or timed out (see timeout and throw properties for details on
/// how abnormal conditos are handled).
///
/// * timeout: Timeout (ms) to wait for previous log operation completion.
/// Values "0" and "" mean no timeout. Only valid when logging
/// is asynchronous, otherwise ignored.
///
/// * throw: Boolean value indicating whether to throw in case of timeout.
/// Setting this property to false may result in log entries being lost.
/// True values are (case insensitive) "true", "t", "yes", "y".
/// Anything else yields false.
std::string getProperty(const std::string & name) const;
/// Returns the value of the property with the given name.
std::size_t wait();
/// Waits for the completion of the previous operation and returns
/// the result. If channel is in synchronous mode, returns 0 immediately.
static void registerChannel();
/// Registers the channel with the global LoggingFactory.
static const std::string PROP_CONNECT;
static const std::string PROP_CONNECTOR;
static const std::string PROP_NAME;
static const std::string PROP_TABLE;
static const std::string PROP_ARCHIVE_TABLE;
static const std::string PROP_MAX_AGE;
static const std::string PROP_ASYNC;
static const std::string PROP_TIMEOUT;
static const std::string PROP_THROW;
protected:
~SQLChannel();
private:
typedef Poco::SharedPtr<Session> SessionPtr;
typedef Poco::SharedPtr<Statement> StatementPtr;
typedef Poco::Message::Priority Priority;
typedef Poco::SharedPtr<ArchiveStrategy> StrategyPtr;
void initLogStatement();
/// Initiallizes the log statement.
void initArchiveStatements();
/// Initiallizes the archive statement.
void logAsync(const Message & msg);
/// Waits for previous operation completion and
/// calls logSync(). If the previous operation times out,
/// and _throw is true, TimeoutException is thrown, otherwise
/// the timeout is ignored and log entry is lost.
void logSync(const Message & msg);
/// Inserts the message in the target database.
bool isTrue(const std::string & value) const;
/// Returns true is value is "true", "t", "yes" or "y".
/// Case insensitive.
std::string _connector;
std::string _connect;
SessionPtr _pSession;
StatementPtr _pLogStatement;
std::string _name;
std::string _table;
int _timeout;
bool _throw;
bool _async;
// members for log entry cache (needed for async mode)
std::string _source;
long _pid;
std::string _thread;
long _tid;
int _priority;
std::string _text;
DateTime _dateTime;
StrategyPtr _pArchiveStrategy;
};
//
// inlines
//
inline std::size_t SQLChannel::wait()
{
if (_async && _pLogStatement)
return _pLogStatement->wait(_timeout);
return 0;
}
inline bool SQLChannel::isTrue(const std::string & value) const
{
return (
(0 == icompare(value, "true")) || (0 == icompare(value, "t")) || (0 == icompare(value, "yes")) || (0 == icompare(value, "y")));
}
}
inline bool SQLChannel::isTrue(const std::string& value) const
{
return ((0 == icompare(value, "true")) ||
(0 == icompare(value, "t")) ||
(0 == icompare(value, "yes")) ||
(0 == icompare(value, "y")));
}
} } // namespace Poco::Data
} // namespace Poco::Data
#endif // Data_SQLChannel_INCLUDED

View File

@ -18,476 +18,473 @@
#define Data_Session_INCLUDED
#include <algorithm>
#include "Poco/Any.h"
#include "Poco/AutoPtr.h"
#include "Poco/Data/Binding.h"
#include "Poco/Data/Data.h"
#include "Poco/Data/SessionImpl.h"
#include "Poco/Data/Statement.h"
#include "Poco/Data/StatementCreator.h"
#include "Poco/Data/Binding.h"
#include "Poco/AutoPtr.h"
#include "Poco/Any.h"
#include <algorithm>
namespace Poco {
namespace Data {
class StatementImpl;
class Data_API Session
/// A Session holds a connection to a Database and creates Statement objects.
///
/// Sessions are always created via the SessionFactory:
///
/// Session ses(SessionFactory::instance().create(connectorKey, connectionString));
///
/// where the first param presents the type of session one wants to create (e.g., for SQLite one would choose "SQLite",
/// for ODBC the key is "ODBC") and the second param is the connection string that the session implementation
/// requires to connect to the database. The format of the connection string is specific to the actual connector.
///
/// A simpler form to create the session is to pass the connector key and connection string directly to
/// the Session constructor.
///
/// A concrete example to open an SQLite database stored in the file "dummy.db" would be
///
/// Session ses("SQLite", "dummy.db");
///
/// Via a Session one can create two different types of statements. First, statements that should only be executed once and immediately, and
/// second, statements that should be executed multiple times, using a separate execute() call.
/// The simple one is immediate execution:
///
/// ses << "CREATE TABLE Dummy (data INTEGER(10))", now;
///
/// The now at the end of the statement is required, otherwise the statement
/// would not be executed.
///
/// If one wants to reuse a Statement (and avoid the overhead of repeatedly parsing an SQL statement)
/// one uses an explicit Statement object and its execute() method:
///
/// int i = 0;
/// Statement stmt = (ses << "INSERT INTO Dummy VALUES(:data)", use(i));
///
/// for (i = 0; i < 100; ++i)
/// {
/// stmt.execute();
/// }
///
/// The above example assigns the variable i to the ":data" placeholder in the SQL query. The query is parsed and compiled exactly
/// once, but executed 100 times. At the end the values 0 to 99 will be present in the Table "DUMMY".
///
/// A faster implementaton of the above code will simply create a vector of int
/// and use the vector as parameter to the use clause (you could also use set or multiset instead):
///
/// std::vector<int> data;
/// for (int i = 0; i < 100; ++i)
/// {
/// data.push_back(i);
/// }
/// ses << "INSERT INTO Dummy VALUES(:data)", use(data);
///
/// NEVER try to bind to an empty collection. This will give a BindingException at run-time!
///
/// Retrieving data from a database works similar, you could use simple data types, vectors, sets or multiset as your targets:
///
/// std::set<int> retData;
/// ses << "SELECT * FROM Dummy", into(retData));
///
/// Due to the blocking nature of the above call it is possible to partition the data retrieval into chunks by setting a limit to
/// the maximum number of rows retrieved from the database:
///
/// std::set<int> retData;
/// Statement stmt = (ses << "SELECT * FROM Dummy", into(retData), limit(50));
/// while (!stmt.done())
/// {
/// stmt.execute();
/// }
///
/// The "into" keyword is used to inform the statement where output results should be placed. The limit value ensures
/// that during each run at most 50 rows are retrieved. Assuming Dummy contains 100 rows, retData will contain 50
/// elements after the first run and 100 after the second run, i.e.
/// the collection is not cleared between consecutive runs. After the second execute stmt.done() will return true.
///
/// A prepared Statement will behave exactly the same but a further call to execute() will simply reset the Statement,
/// execute it again and append more data to the result set.
///
/// Note that it is possible to append several "bind" or "into" clauses to the statement. Theoretically, one could also have several
/// limit clauses but only the last one that was added will be effective.
/// Also several preconditions must be met concerning binds and intos.
/// Take the following example:
///
/// ses << "CREATE TABLE Person (LastName VARCHAR(30), FirstName VARCHAR, Age INTEGER(3))";
/// std::vector<std::string> nameVec; // [...] add some elements
/// std::vector<int> ageVec; // [...] add some elements
/// ses << "INSERT INTO Person (LastName, Age) VALUES(:ln, :age)", use(nameVec), use(ageVec);
///
/// The size of all use parameters MUST be the same, otherwise an exception is thrown. Furthermore,
/// the amount of use clauses must match the number of wildcards in the query (to be more precise:
/// each binding has a numberOfColumnsHandled() value which defaults to 1. The sum of all these values
/// must match the wildcard count in the query.
/// However, this is only important if you have written your own TypeHandler specializations.
/// If you plan to map complex object types to tables see the TypeHandler documentation.
/// For now, we simply assume we have written one TypeHandler for Person objects. Instead of having n different vectors,
/// we have one collection:
///
/// std::vector<Person> people; // [...] add some elements
/// ses << "INSERT INTO Person (LastName, FirstName, Age) VALUES(:ln, :fn, :age)", use(people);
///
/// which will insert all Person objects from the people vector to the database (and again, you can use set, multiset too,
/// even map and multimap if Person provides an operator() which returns the key for the map).
/// The same works for a SELECT statement with "into" clauses:
///
/// std::vector<Person> people;
/// ses << "SELECT * FROM PERSON", into(people);
///
/// Mixing constants or variables with manipulators is allowed provided there are corresponding placeholders for the constants provided in
/// the SQL string, such as in following example:
///
/// std::vector<Person> people;
/// ses << "SELECT * FROM %s", into(people), "PERSON";
///
/// Formatting only kicks in if there are values to be injected into the SQL string, otherwise it is skipped.
/// If the formatting will occur and the percent sign is part of the query itself, it can be passed to the query by entering it twice (%%).
/// However, if no formatting is used, one percent sign is sufficient as the string will be passed unaltered.
/// For complete list of supported data types with their respective specifications, see the documentation for format in Foundation.
namespace Poco
{
public:
static const std::size_t LOGIN_TIMEOUT_DEFAULT = SessionImpl::LOGIN_TIMEOUT_DEFAULT;
static const Poco::UInt32 TRANSACTION_READ_UNCOMMITTED = 0x00000001L;
static const Poco::UInt32 TRANSACTION_READ_COMMITTED = 0x00000002L;
static const Poco::UInt32 TRANSACTION_REPEATABLE_READ = 0x00000004L;
static const Poco::UInt32 TRANSACTION_SERIALIZABLE = 0x00000008L;
Session(Poco::AutoPtr<SessionImpl> ptrImpl);
/// Creates the Session.
Session(const std::string& connector,
const std::string& connectionString,
std::size_t timeout = LOGIN_TIMEOUT_DEFAULT);
/// Creates a new session, using the given connector (which must have
/// been registered), and connectionString.
Session(const std::string& connection,
std::size_t timeout = LOGIN_TIMEOUT_DEFAULT);
/// Creates a new session, using the given connection (must be in
/// "connection:///connectionString" format).
Session(const Session&);
/// Creates a session by copying another one.
Session& operator = (const Session&);
/// Assignment operator.
~Session();
/// Destroys the Session.
void swap(Session& other);
/// Swaps the session with another one.
template <typename T>
Statement operator << (const T& t)
/// Creates a Statement with the given data as SQLContent
{
return _statementCreator << t;
}
StatementImpl* createStatementImpl();
/// Creates a StatementImpl.
void open(const std::string& connect = "");
/// Opens the session using the supplied string.
/// Can also be used with default empty string to
/// reconnect a disconnected session.
/// If the connection is not established,
/// a ConnectionFailedException is thrown.
/// Zero timout means indefinite
void close();
/// Closes the session.
bool isConnected();
/// Returns true iff session is connected, false otherwise.
void reconnect();
/// Closes the session and opens it.
void setLoginTimeout(std::size_t timeout);
/// Sets the session login timeout value.
std::size_t getLoginTimeout() const;
/// Returns the session login timeout value.
void setConnectionTimeout(std::size_t timeout);
/// Sets the session connection timeout value.
std::size_t getConnectionTimeout();
/// Returns the session connection timeout value.
void begin();
/// Starts a transaction.
void commit();
/// Commits and ends a transaction.
void rollback();
/// Rolls back and ends a transaction.
bool canTransact();
/// Returns true if session has transaction capabilities.
bool isTransaction();
/// Returns true iff a transaction is in progress, false otherwise.
void setTransactionIsolation(Poco::UInt32);
/// Sets the transaction isolation level.
Poco::UInt32 getTransactionIsolation();
/// Returns the transaction isolation level.
bool hasTransactionIsolation(Poco::UInt32 ti);
/// Returns true iff the transaction isolation level corresponding
/// to the supplied bitmask is supported.
bool isTransactionIsolation(Poco::UInt32 ti);
/// Returns true iff the transaction isolation level corresponds
/// to the supplied bitmask.
std::string connector() const;
/// Returns the connector name for this session.
std::string uri() const;
/// Returns the URI for this session.
static std::string uri(const std::string& connector,
const std::string& connectionString);
/// Utility function that teturns the URI formatted from supplied
/// arguments as "connector:///connectionString".
void setFeature(const std::string& name, bool state);
/// Set the state of a feature.
///
/// Features are a generic extension mechanism for session implementations.
/// and are defined by the underlying SessionImpl instance.
///
/// Throws a NotSupportedException if the requested feature is
/// not supported by the underlying implementation.
bool getFeature(const std::string& name) const;
/// Look up the state of a feature.
///
/// Features are a generic extension mechanism for session implementations.
/// and are defined by the underlying SessionImpl instance.
///
/// Throws a NotSupportedException if the requested feature is
/// not supported by the underlying implementation.
void setProperty(const std::string& name, const Poco::Any& value);
/// Set the value of a property.
///
/// Properties are a generic extension mechanism for session implementations.
/// and are defined by the underlying SessionImpl instance.
///
/// Throws a NotSupportedException if the requested property is
/// not supported by the underlying implementation.
Poco::Any getProperty(const std::string& name) const;
/// Look up the value of a property.
///
/// Properties are a generic extension mechanism for session implementations.
/// and are defined by the underlying SessionImpl instance.
///
/// Throws a NotSupportedException if the requested property is
/// not supported by the underlying implementation.
SessionImpl* impl();
/// Returns a pointer to the underlying SessionImpl.
private:
Session();
Poco::AutoPtr<SessionImpl> _pImpl;
StatementCreator _statementCreator;
};
//
// inlines
//
inline StatementImpl* Session::createStatementImpl()
namespace Data
{
return _pImpl->createStatementImpl();
class StatementImpl;
class Data_API Session
/// A Session holds a connection to a Database and creates Statement objects.
///
/// Sessions are always created via the SessionFactory:
///
/// Session ses(SessionFactory::instance().create(connectorKey, connectionString));
///
/// where the first param presents the type of session one wants to create (e.g., for SQLite one would choose "SQLite",
/// for ODBC the key is "ODBC") and the second param is the connection string that the session implementation
/// requires to connect to the database. The format of the connection string is specific to the actual connector.
///
/// A simpler form to create the session is to pass the connector key and connection string directly to
/// the Session constructor.
///
/// A concrete example to open an SQLite database stored in the file "dummy.db" would be
///
/// Session ses("SQLite", "dummy.db");
///
/// Via a Session one can create two different types of statements. First, statements that should only be executed once and immediately, and
/// second, statements that should be executed multiple times, using a separate execute() call.
/// The simple one is immediate execution:
///
/// ses << "CREATE TABLE Dummy (data INTEGER(10))", now;
///
/// The now at the end of the statement is required, otherwise the statement
/// would not be executed.
///
/// If one wants to reuse a Statement (and avoid the overhead of repeatedly parsing an SQL statement)
/// one uses an explicit Statement object and its execute() method:
///
/// int i = 0;
/// Statement stmt = (ses << "INSERT INTO Dummy VALUES(:data)", use(i));
///
/// for (i = 0; i < 100; ++i)
/// {
/// stmt.execute();
/// }
///
/// The above example assigns the variable i to the ":data" placeholder in the SQL query. The query is parsed and compiled exactly
/// once, but executed 100 times. At the end the values 0 to 99 will be present in the Table "DUMMY".
///
/// A faster implementation of the above code will simply create a vector of int
/// and use the vector as parameter to the use clause (you could also use set or multiset instead):
///
/// std::vector<int> data;
/// for (int i = 0; i < 100; ++i)
/// {
/// data.push_back(i);
/// }
/// ses << "INSERT INTO Dummy VALUES(:data)", use(data);
///
/// NEVER try to bind to an empty collection. This will give a BindingException at run-time!
///
/// Retrieving data from a database works similar, you could use simple data types, vectors, sets or multiset as your targets:
///
/// std::set<int> retData;
/// ses << "SELECT * FROM Dummy", into(retData));
///
/// Due to the blocking nature of the above call it is possible to partition the data retrieval into chunks by setting a limit to
/// the maximum number of rows retrieved from the database:
///
/// std::set<int> retData;
/// Statement stmt = (ses << "SELECT * FROM Dummy", into(retData), limit(50));
/// while (!stmt.done())
/// {
/// stmt.execute();
/// }
///
/// The "into" keyword is used to inform the statement where output results should be placed. The limit value ensures
/// that during each run at most 50 rows are retrieved. Assuming Dummy contains 100 rows, retData will contain 50
/// elements after the first run and 100 after the second run, i.e.
/// the collection is not cleared between consecutive runs. After the second execute stmt.done() will return true.
///
/// A prepared Statement will behave exactly the same but a further call to execute() will simply reset the Statement,
/// execute it again and append more data to the result set.
///
/// Note that it is possible to append several "bind" or "into" clauses to the statement. Theoretically, one could also have several
/// limit clauses but only the last one that was added will be effective.
/// Also several preconditions must be met concerning binds and intos.
/// Take the following example:
///
/// ses << "CREATE TABLE Person (LastName VARCHAR(30), FirstName VARCHAR, Age INTEGER(3))";
/// std::vector<std::string> nameVec; // [...] add some elements
/// std::vector<int> ageVec; // [...] add some elements
/// ses << "INSERT INTO Person (LastName, Age) VALUES(:ln, :age)", use(nameVec), use(ageVec);
///
/// The size of all use parameters MUST be the same, otherwise an exception is thrown. Furthermore,
/// the amount of use clauses must match the number of wildcards in the query (to be more precise:
/// each binding has a numberOfColumnsHandled() value which defaults to 1. The sum of all these values
/// must match the wildcard count in the query.
/// However, this is only important if you have written your own TypeHandler specializations.
/// If you plan to map complex object types to tables see the TypeHandler documentation.
/// For now, we simply assume we have written one TypeHandler for Person objects. Instead of having n different vectors,
/// we have one collection:
///
/// std::vector<Person> people; // [...] add some elements
/// ses << "INSERT INTO Person (LastName, FirstName, Age) VALUES(:ln, :fn, :age)", use(people);
///
/// which will insert all Person objects from the people vector to the database (and again, you can use set, multiset too,
/// even map and multimap if Person provides an operator() which returns the key for the map).
/// The same works for a SELECT statement with "into" clauses:
///
/// std::vector<Person> people;
/// ses << "SELECT * FROM PERSON", into(people);
///
/// Mixing constants or variables with manipulators is allowed provided there are corresponding placeholders for the constants provided in
/// the SQL string, such as in following example:
///
/// std::vector<Person> people;
/// ses << "SELECT * FROM %s", into(people), "PERSON";
///
/// Formatting only kicks in if there are values to be injected into the SQL string, otherwise it is skipped.
/// If the formatting will occur and the percent sign is part of the query itself, it can be passed to the query by entering it twice (%%).
/// However, if no formatting is used, one percent sign is sufficient as the string will be passed unaltered.
/// For complete list of supported data types with their respective specifications, see the documentation for format in Foundation.
{
public:
static const std::size_t LOGIN_TIMEOUT_DEFAULT = SessionImpl::LOGIN_TIMEOUT_DEFAULT;
static const Poco::UInt32 TRANSACTION_READ_UNCOMMITTED = 0x00000001L;
static const Poco::UInt32 TRANSACTION_READ_COMMITTED = 0x00000002L;
static const Poco::UInt32 TRANSACTION_REPEATABLE_READ = 0x00000004L;
static const Poco::UInt32 TRANSACTION_SERIALIZABLE = 0x00000008L;
Session(Poco::AutoPtr<SessionImpl> ptrImpl);
/// Creates the Session.
Session(const std::string & connector, const std::string & connectionString, std::size_t timeout = LOGIN_TIMEOUT_DEFAULT);
/// Creates a new session, using the given connector (which must have
/// been registered), and connectionString.
Session(const std::string & connection, std::size_t timeout = LOGIN_TIMEOUT_DEFAULT);
/// Creates a new session, using the given connection (must be in
/// "connection:///connectionString" format).
Session(const Session &);
/// Creates a session by copying another one.
Session & operator=(const Session &);
/// Assignment operator.
~Session();
/// Destroys the Session.
void swap(Session & other);
/// Swaps the session with another one.
template <typename T>
Statement operator<<(const T & t)
/// Creates a Statement with the given data as SQLContent
{
return _statementCreator << t;
}
StatementImpl * createStatementImpl();
/// Creates a StatementImpl.
void open(const std::string & connect = "");
/// Opens the session using the supplied string.
/// Can also be used with default empty string to
/// reconnect a disconnected session.
/// If the connection is not established,
/// a ConnectionFailedException is thrown.
/// Zero timeout means indefinite
void close();
/// Closes the session.
bool isConnected();
/// Returns true iff session is connected, false otherwise.
void reconnect();
/// Closes the session and opens it.
void setLoginTimeout(std::size_t timeout);
/// Sets the session login timeout value.
std::size_t getLoginTimeout() const;
/// Returns the session login timeout value.
void setConnectionTimeout(std::size_t timeout);
/// Sets the session connection timeout value.
std::size_t getConnectionTimeout();
/// Returns the session connection timeout value.
void begin();
/// Starts a transaction.
void commit();
/// Commits and ends a transaction.
void rollback();
/// Rolls back and ends a transaction.
bool canTransact();
/// Returns true if session has transaction capabilities.
bool isTransaction();
/// Returns true iff a transaction is in progress, false otherwise.
void setTransactionIsolation(Poco::UInt32);
/// Sets the transaction isolation level.
Poco::UInt32 getTransactionIsolation();
/// Returns the transaction isolation level.
bool hasTransactionIsolation(Poco::UInt32 ti);
/// Returns true iff the transaction isolation level corresponding
/// to the supplied bitmask is supported.
bool isTransactionIsolation(Poco::UInt32 ti);
/// Returns true iff the transaction isolation level corresponds
/// to the supplied bitmask.
std::string connector() const;
/// Returns the connector name for this session.
std::string uri() const;
/// Returns the URI for this session.
static std::string uri(const std::string & connector, const std::string & connectionString);
/// Utility function that teturns the URI formatted from supplied
/// arguments as "connector:///connectionString".
void setFeature(const std::string & name, bool state);
/// Set the state of a feature.
///
/// Features are a generic extension mechanism for session implementations.
/// and are defined by the underlying SessionImpl instance.
///
/// Throws a NotSupportedException if the requested feature is
/// not supported by the underlying implementation.
bool getFeature(const std::string & name) const;
/// Look up the state of a feature.
///
/// Features are a generic extension mechanism for session implementations.
/// and are defined by the underlying SessionImpl instance.
///
/// Throws a NotSupportedException if the requested feature is
/// not supported by the underlying implementation.
void setProperty(const std::string & name, const Poco::Any & value);
/// Set the value of a property.
///
/// Properties are a generic extension mechanism for session implementations.
/// and are defined by the underlying SessionImpl instance.
///
/// Throws a NotSupportedException if the requested property is
/// not supported by the underlying implementation.
Poco::Any getProperty(const std::string & name) const;
/// Look up the value of a property.
///
/// Properties are a generic extension mechanism for session implementations.
/// and are defined by the underlying SessionImpl instance.
///
/// Throws a NotSupportedException if the requested property is
/// not supported by the underlying implementation.
SessionImpl * impl();
/// Returns a pointer to the underlying SessionImpl.
private:
Session();
Poco::AutoPtr<SessionImpl> _pImpl;
StatementCreator _statementCreator;
};
//
// inlines
//
inline StatementImpl * Session::createStatementImpl()
{
return _pImpl->createStatementImpl();
}
inline void Session::open(const std::string & connect)
{
_pImpl->open(connect);
}
inline void Session::close()
{
_pImpl->close();
}
inline bool Session::isConnected()
{
return _pImpl->isConnected();
}
inline void Session::reconnect()
{
_pImpl->reconnect();
}
inline void Session::setLoginTimeout(std::size_t timeout)
{
_pImpl->setLoginTimeout(timeout);
}
inline std::size_t Session::getLoginTimeout() const
{
return _pImpl->getLoginTimeout();
}
inline void Session::setConnectionTimeout(std::size_t timeout)
{
_pImpl->setConnectionTimeout(timeout);
}
inline std::size_t Session::getConnectionTimeout()
{
return _pImpl->getConnectionTimeout();
}
inline void Session::begin()
{
return _pImpl->begin();
}
inline void Session::commit()
{
return _pImpl->commit();
}
inline void Session::rollback()
{
return _pImpl->rollback();
}
inline bool Session::canTransact()
{
return _pImpl->canTransact();
}
inline bool Session::isTransaction()
{
return _pImpl->isTransaction();
}
inline void Session::setTransactionIsolation(Poco::UInt32 ti)
{
_pImpl->setTransactionIsolation(ti);
}
inline Poco::UInt32 Session::getTransactionIsolation()
{
return _pImpl->getTransactionIsolation();
}
inline bool Session::hasTransactionIsolation(Poco::UInt32 ti)
{
return _pImpl->hasTransactionIsolation(ti);
}
inline bool Session::isTransactionIsolation(Poco::UInt32 ti)
{
return _pImpl->isTransactionIsolation(ti);
}
inline std::string Session::connector() const
{
return _pImpl->connectorName();
}
inline std::string Session::uri(const std::string & connector, const std::string & connectionString)
{
return SessionImpl::uri(connector, connectionString);
}
inline std::string Session::uri() const
{
return _pImpl->uri();
}
inline void Session::setFeature(const std::string & name, bool state)
{
_pImpl->setFeature(name, state);
}
inline bool Session::getFeature(const std::string & name) const
{
return const_cast<SessionImpl *>(_pImpl.get())->getFeature(name);
}
inline void Session::setProperty(const std::string & name, const Poco::Any & value)
{
_pImpl->setProperty(name, value);
}
inline Poco::Any Session::getProperty(const std::string & name) const
{
return const_cast<SessionImpl *>(_pImpl.get())->getProperty(name);
}
inline SessionImpl * Session::impl()
{
return _pImpl;
}
inline void swap(Session & s1, Session & s2)
{
s1.swap(s2);
}
}
inline void Session::open(const std::string& connect)
{
_pImpl->open(connect);
}
inline void Session::close()
{
_pImpl->close();
}
inline bool Session::isConnected()
{
return _pImpl->isConnected();
}
inline void Session::reconnect()
{
_pImpl->reconnect();
}
inline void Session::setLoginTimeout(std::size_t timeout)
{
_pImpl->setLoginTimeout(timeout);
}
inline std::size_t Session::getLoginTimeout() const
{
return _pImpl->getLoginTimeout();
}
inline void Session::setConnectionTimeout(std::size_t timeout)
{
_pImpl->setConnectionTimeout(timeout);
}
inline std::size_t Session::getConnectionTimeout()
{
return _pImpl->getConnectionTimeout();
}
inline void Session::begin()
{
return _pImpl->begin();
}
inline void Session::commit()
{
return _pImpl->commit();
}
inline void Session::rollback()
{
return _pImpl->rollback();
}
inline bool Session::canTransact()
{
return _pImpl->canTransact();
}
inline bool Session::isTransaction()
{
return _pImpl->isTransaction();
}
inline void Session::setTransactionIsolation(Poco::UInt32 ti)
{
_pImpl->setTransactionIsolation(ti);
}
inline Poco::UInt32 Session::getTransactionIsolation()
{
return _pImpl->getTransactionIsolation();
}
inline bool Session::hasTransactionIsolation(Poco::UInt32 ti)
{
return _pImpl->hasTransactionIsolation(ti);
}
inline bool Session::isTransactionIsolation(Poco::UInt32 ti)
{
return _pImpl->isTransactionIsolation(ti);
}
inline std::string Session::connector() const
{
return _pImpl->connectorName();
}
inline std::string Session::uri(const std::string& connector,
const std::string& connectionString)
{
return SessionImpl::uri(connector, connectionString);
}
inline std::string Session::uri() const
{
return _pImpl->uri();
}
inline void Session::setFeature(const std::string& name, bool state)
{
_pImpl->setFeature(name, state);
}
inline bool Session::getFeature(const std::string& name) const
{
return const_cast<SessionImpl*>(_pImpl.get())->getFeature(name);
}
inline void Session::setProperty(const std::string& name, const Poco::Any& value)
{
_pImpl->setProperty(name, value);
}
inline Poco::Any Session::getProperty(const std::string& name) const
{
return const_cast<SessionImpl*>(_pImpl.get())->getProperty(name);
}
inline SessionImpl* Session::impl()
{
return _pImpl;
}
inline void swap(Session& s1, Session& s2)
{
s1.swap(s2);
}
} } // namespace Poco::Data
} // namespace Poco::Data
namespace std
{
template<>
inline void swap<Poco::Data::Session>(Poco::Data::Session& s1,
Poco::Data::Session& s2)
/// Full template specalization of std:::swap for Session
{
s1.swap(s2);
}
template <>
inline void swap<Poco::Data::Session>(Poco::Data::Session & s1, Poco::Data::Session & s2)
/// Full template specalization of std:::swap for Session
{
s1.swap(s2);
}
}

View File

@ -18,82 +18,81 @@
#define Data_SessionFactory_INCLUDED
#include "Poco/Data/Data.h"
#include <map>
#include "Poco/Data/Connector.h"
#include "Poco/Data/Data.h"
#include "Poco/Data/Session.h"
#include "Poco/Mutex.h"
#include "Poco/SharedPtr.h"
#include "Poco/String.h"
#include <map>
namespace Poco {
namespace Data {
class Data_API SessionFactory
/// A SessionFactory is a singleton class that stores Connectors and allows to
/// create Sessions of the required type:
///
/// Session ses(SessionFactory::instance().create(connector, connectionString));
///
/// where the first param presents the type of session one wants to create (e.g. for SQLite one would choose "SQLite")
/// and the second param is the connection string that the connector requires to connect to the database.
///
/// A concrete example to open an SQLite database stored in the file "dummy.db" would be
///
/// Session ses(SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
///
/// An even simpler way to create a session is to use the two argument constructor of Session, which
/// automatically invokes the SessionFactory:
///
/// Session ses("SQLite", "dummy.db");
namespace Poco
{
namespace Data
{
public:
static SessionFactory& instance();
/// returns the static instance of the singleton.
void add(Connector* pIn);
/// Registers a Connector under its key at the factory. If a registration for that
/// key is already active, the first registration will be kept, only its reference count will be increased.
/// Always takes ownership of parameter pIn.
void remove(const std::string& key);
/// Lowers the reference count for the Connector registered under that key. If the count reaches zero,
/// the object is removed.
Session create(const std::string& key,
const std::string& connectionString,
std::size_t timeout = Session::LOGIN_TIMEOUT_DEFAULT);
/// Creates a Session for the given key with the connectionString. Throws an Poco:Data::UnknownDataBaseException
/// if no Connector is registered for that key.
Session create(const std::string& uri,
std::size_t timeout = Session::LOGIN_TIMEOUT_DEFAULT);
/// Creates a Session for the given URI (must be in key:///connectionString format).
/// Throws a Poco:Data::UnknownDataBaseException if no Connector is registered for the key.
private:
SessionFactory();
~SessionFactory();
SessionFactory(const SessionFactory&);
SessionFactory& operator = (const SessionFactory&);
struct SessionInfo
{
int cnt;
Poco::SharedPtr<Connector> ptrSI;
SessionInfo(Connector* pSI);
};
typedef std::map<std::string, SessionInfo, Poco::CILess> Connectors;
Connectors _connectors;
Poco::FastMutex _mutex;
};
} } // namespace Poco::Data
class Data_API SessionFactory
/// A SessionFactory is a singleton class that stores Connectors and allows to
/// create Sessions of the required type:
///
/// Session ses(SessionFactory::instance().create(connector, connectionString));
///
/// where the first param presents the type of session one wants to create (e.g. for SQLite one would choose "SQLite")
/// and the second param is the connection string that the connector requires to connect to the database.
///
/// A concrete example to open an SQLite database stored in the file "dummy.db" would be
///
/// Session ses(SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
///
/// An even simpler way to create a session is to use the two argument constructor of Session, which
/// automatically invokes the SessionFactory:
///
/// Session ses("SQLite", "dummy.db");
{
public:
static SessionFactory & instance();
/// returns the static instance of the singleton.
void add(Connector * pIn);
/// Registers a Connector under its key at the factory. If a registration for that
/// key is already active, the first registration will be kept, only its reference count will be increased.
/// Always takes ownership of parameter pIn.
void remove(const std::string & key);
/// Lowers the reference count for the Connector registered under that key. If the count reaches zero,
/// the object is removed.
Session create(const std::string & key, const std::string & connectionString, std::size_t timeout = Session::LOGIN_TIMEOUT_DEFAULT);
/// Creates a Session for the given key with the connectionString. Throws an Poco:Data::UnknownDataBaseException
/// if no Connector is registered for that key.
Session create(const std::string & uri, std::size_t timeout = Session::LOGIN_TIMEOUT_DEFAULT);
/// Creates a Session for the given URI (must be in key:///connectionString format).
/// Throws a Poco:Data::UnknownDataBaseException if no Connector is registered for the key.
private:
SessionFactory();
~SessionFactory();
SessionFactory(const SessionFactory &);
SessionFactory & operator=(const SessionFactory &);
struct SessionInfo
{
int cnt;
Poco::SharedPtr<Connector> ptrSI;
SessionInfo(Connector * pSI);
};
typedef std::map<std::string, SessionInfo, Poco::CILess> Connectors;
Connectors _connectors;
Poco::FastMutex _mutex;
};
}
} // namespace Poco::Data
#endif // Data_SessionFactory_INCLUDED

View File

@ -18,204 +18,205 @@
#define Data_SessionImpl_INCLUDED
#include "Poco/Any.h"
#include "Poco/Data/Data.h"
#include "Poco/Format.h"
#include "Poco/RefCountedObject.h"
#include "Poco/String.h"
#include "Poco/Format.h"
#include "Poco/Any.h"
namespace Poco {
namespace Data {
class StatementImpl;
class Data_API SessionImpl: public Poco::RefCountedObject
/// Interface for Session functionality that subclasses must extend.
/// SessionImpl objects are noncopyable.
namespace Poco
{
public:
static const std::size_t LOGIN_TIMEOUT_INFINITE = 0;
/// Infinite connection/login timeout.
static const std::size_t LOGIN_TIMEOUT_DEFAULT = 60;
/// Default connection/login timeout in seconds.
static const std::size_t CONNECTION_TIMEOUT_INFINITE = 0;
/// Infinite connection/login timeout.
static const std::size_t CONNECTION_TIMEOUT_DEFAULT = CONNECTION_TIMEOUT_INFINITE;
/// Default connection/login timeout in seconds.
SessionImpl(const std::string& connectionString,
std::size_t timeout = LOGIN_TIMEOUT_DEFAULT);
/// Creates the SessionImpl.
virtual ~SessionImpl();
/// Destroys the SessionImpl.
virtual StatementImpl* createStatementImpl() = 0;
/// Creates a StatementImpl.
virtual void open(const std::string& connectionString = "") = 0;
/// Opens the session using the supplied string.
/// Can also be used with default empty string to reconnect
/// a disconnected session.
/// If the connection is not established within requested timeout
/// (specified in seconds), a ConnectionFailedException is thrown.
/// Zero timout means indefinite
virtual void close() = 0;
/// Closes the connection.
virtual bool isConnected() = 0;
/// Returns true if session is connected, false otherwise.
void setLoginTimeout(std::size_t timeout);
/// Sets the session login timeout value.
std::size_t getLoginTimeout() const;
/// Returns the session login timeout value.
virtual void setConnectionTimeout(std::size_t timeout) = 0;
/// Sets the session connection timeout value.
virtual std::size_t getConnectionTimeout() = 0;
/// Returns the session connection timeout value.
void reconnect();
/// Closes the connection and opens it again.
virtual void begin() = 0;
/// Starts a transaction.
virtual void commit() = 0;
/// Commits and ends a transaction.
virtual void rollback() = 0;
/// Aborts a transaction.
virtual bool canTransact() = 0;
/// Returns true if session has transaction capabilities.
virtual bool isTransaction() = 0;
/// Returns true iff a transaction is a transaction is in progress, false otherwise.
virtual void setTransactionIsolation(Poco::UInt32) = 0;
/// Sets the transaction isolation level.
virtual Poco::UInt32 getTransactionIsolation() = 0;
/// Returns the transaction isolation level.
virtual bool hasTransactionIsolation(Poco::UInt32) = 0;
/// Returns true iff the transaction isolation level corresponding
/// to the supplied bitmask is supported.
virtual bool isTransactionIsolation(Poco::UInt32) = 0;
/// Returns true iff the transaction isolation level corresponds
/// to the supplied bitmask.
virtual const std::string& connectorName() const = 0;
/// Returns the name of the connector.
const std::string& connectionString() const;
/// Returns the connection string.
static std::string uri(const std::string& connector, const std::string& connectionString);
/// Returns formatted URI.
std::string uri() const;
/// Returns the URI for this session.
virtual void setFeature(const std::string& name, bool state) = 0;
/// Set the state of a feature.
///
/// Features are a generic extension mechanism for session implementations.
/// and are defined by the underlying SessionImpl instance.
///
/// Throws a NotSupportedException if the requested feature is
/// not supported by the underlying implementation.
virtual bool getFeature(const std::string& name) = 0;
/// Look up the state of a feature.
///
/// Features are a generic extension mechanism for session implementations.
/// and are defined by the underlying SessionImpl instance.
///
/// Throws a NotSupportedException if the requested feature is
/// not supported by the underlying implementation.
virtual void setProperty(const std::string& name, const Poco::Any& value) = 0;
/// Set the value of a property.
///
/// Properties are a generic extension mechanism for session implementations.
/// and are defined by the underlying SessionImpl instance.
///
/// Throws a NotSupportedException if the requested property is
/// not supported by the underlying implementation.
virtual Poco::Any getProperty(const std::string& name) = 0;
/// Look up the value of a property.
///
/// Properties are a generic extension mechanism for session implementations.
/// and are defined by the underlying SessionImpl instance.
///
/// Throws a NotSupportedException if the requested property is
/// not supported by the underlying implementation.
protected:
void setConnectionString(const std::string& connectionString);
/// Sets the connection string. Should only be called on
/// disconnetced sessions. Throws InvalidAccessException when called on
/// a connected session.
private:
SessionImpl();
SessionImpl(const SessionImpl&);
SessionImpl& operator = (const SessionImpl&);
std::string _connectionString;
std::size_t _loginTimeout;
};
//
// inlines
//
inline const std::string& SessionImpl::connectionString() const
namespace Data
{
return _connectionString;
class StatementImpl;
class Data_API SessionImpl : public Poco::RefCountedObject
/// Interface for Session functionality that subclasses must extend.
/// SessionImpl objects are noncopyable.
{
public:
static const std::size_t LOGIN_TIMEOUT_INFINITE = 0;
/// Infinite connection/login timeout.
static const std::size_t LOGIN_TIMEOUT_DEFAULT = 60;
/// Default connection/login timeout in seconds.
static const std::size_t CONNECTION_TIMEOUT_INFINITE = 0;
/// Infinite connection/login timeout.
static const std::size_t CONNECTION_TIMEOUT_DEFAULT = CONNECTION_TIMEOUT_INFINITE;
/// Default connection/login timeout in seconds.
SessionImpl(const std::string & connectionString, std::size_t timeout = LOGIN_TIMEOUT_DEFAULT);
/// Creates the SessionImpl.
virtual ~SessionImpl();
/// Destroys the SessionImpl.
virtual StatementImpl * createStatementImpl() = 0;
/// Creates a StatementImpl.
virtual void open(const std::string & connectionString = "") = 0;
/// Opens the session using the supplied string.
/// Can also be used with default empty string to reconnect
/// a disconnected session.
/// If the connection is not established within requested timeout
/// (specified in seconds), a ConnectionFailedException is thrown.
/// Zero timeout means indefinite
virtual void close() = 0;
/// Closes the connection.
virtual bool isConnected() = 0;
/// Returns true if session is connected, false otherwise.
void setLoginTimeout(std::size_t timeout);
/// Sets the session login timeout value.
std::size_t getLoginTimeout() const;
/// Returns the session login timeout value.
virtual void setConnectionTimeout(std::size_t timeout) = 0;
/// Sets the session connection timeout value.
virtual std::size_t getConnectionTimeout() = 0;
/// Returns the session connection timeout value.
void reconnect();
/// Closes the connection and opens it again.
virtual void begin() = 0;
/// Starts a transaction.
virtual void commit() = 0;
/// Commits and ends a transaction.
virtual void rollback() = 0;
/// Aborts a transaction.
virtual bool canTransact() = 0;
/// Returns true if session has transaction capabilities.
virtual bool isTransaction() = 0;
/// Returns true iff a transaction is a transaction is in progress, false otherwise.
virtual void setTransactionIsolation(Poco::UInt32) = 0;
/// Sets the transaction isolation level.
virtual Poco::UInt32 getTransactionIsolation() = 0;
/// Returns the transaction isolation level.
virtual bool hasTransactionIsolation(Poco::UInt32) = 0;
/// Returns true iff the transaction isolation level corresponding
/// to the supplied bitmask is supported.
virtual bool isTransactionIsolation(Poco::UInt32) = 0;
/// Returns true iff the transaction isolation level corresponds
/// to the supplied bitmask.
virtual const std::string & connectorName() const = 0;
/// Returns the name of the connector.
const std::string & connectionString() const;
/// Returns the connection string.
static std::string uri(const std::string & connector, const std::string & connectionString);
/// Returns formatted URI.
std::string uri() const;
/// Returns the URI for this session.
virtual void setFeature(const std::string & name, bool state) = 0;
/// Set the state of a feature.
///
/// Features are a generic extension mechanism for session implementations.
/// and are defined by the underlying SessionImpl instance.
///
/// Throws a NotSupportedException if the requested feature is
/// not supported by the underlying implementation.
virtual bool getFeature(const std::string & name) = 0;
/// Look up the state of a feature.
///
/// Features are a generic extension mechanism for session implementations.
/// and are defined by the underlying SessionImpl instance.
///
/// Throws a NotSupportedException if the requested feature is
/// not supported by the underlying implementation.
virtual void setProperty(const std::string & name, const Poco::Any & value) = 0;
/// Set the value of a property.
///
/// Properties are a generic extension mechanism for session implementations.
/// and are defined by the underlying SessionImpl instance.
///
/// Throws a NotSupportedException if the requested property is
/// not supported by the underlying implementation.
virtual Poco::Any getProperty(const std::string & name) = 0;
/// Look up the value of a property.
///
/// Properties are a generic extension mechanism for session implementations.
/// and are defined by the underlying SessionImpl instance.
///
/// Throws a NotSupportedException if the requested property is
/// not supported by the underlying implementation.
protected:
void setConnectionString(const std::string & connectionString);
/// Sets the connection string. Should only be called on
/// disconnetced sessions. Throws InvalidAccessException when called on
/// a connected session.
private:
SessionImpl();
SessionImpl(const SessionImpl &);
SessionImpl & operator=(const SessionImpl &);
std::string _connectionString;
std::size_t _loginTimeout;
};
//
// inlines
//
inline const std::string & SessionImpl::connectionString() const
{
return _connectionString;
}
inline void SessionImpl::setLoginTimeout(std::size_t timeout)
{
_loginTimeout = timeout;
}
inline std::size_t SessionImpl::getLoginTimeout() const
{
return _loginTimeout;
}
inline std::string SessionImpl::uri(const std::string & connector, const std::string & connectionString)
{
return format("%s:///%s", connector, connectionString);
}
inline std::string SessionImpl::uri() const
{
return uri(connectorName(), connectionString());
}
}
inline void SessionImpl::setLoginTimeout(std::size_t timeout)
{
_loginTimeout = timeout;
}
inline std::size_t SessionImpl::getLoginTimeout() const
{
return _loginTimeout;
}
inline std::string SessionImpl::uri(const std::string& connector,
const std::string& connectionString)
{
return format("%s:///%s", connector, connectionString);
}
inline std::string SessionImpl::uri() const
{
return uri(connectorName(), connectionString());
}
} } // namespace Poco::Data
} // namespace Poco::Data
#endif // Data_SessionImpl_INCLUDED

View File

@ -18,216 +18,216 @@
#define Data_SessionPool_INCLUDED
#include <list>
#include "Poco/Any.h"
#include "Poco/Data/Data.h"
#include "Poco/Data/PooledSessionHolder.h"
#include "Poco/Data/PooledSessionImpl.h"
#include "Poco/Data/Session.h"
#include "Poco/HashMap.h"
#include "Poco/Any.h"
#include "Poco/Timer.h"
#include "Poco/Mutex.h"
#include <list>
#include "Poco/Timer.h"
namespace Poco {
namespace Data {
class Data_API SessionPool: public RefCountedObject
/// This class implements session pooling for POCO Data.
///
/// Creating a connection to a database is often a time consuming
/// operation. Therefore it makes sense to reuse a session object
/// once it is no longer needed.
///
/// A SessionPool manages a collection of SessionImpl objects
/// (decorated with a PooledSessionImpl).
///
/// When a SessionImpl object is requested, the SessionPool first
/// looks in its set of already initialized SessionImpl for an
/// available object. If one is found, it is returned to the
/// client and marked as "in-use". If no SessionImpl is available,
/// the SessionPool attempts to create a new one for the client.
/// To avoid excessive creation of SessionImpl objects, a limit
/// can be set on the maximum number of objects.
/// Sessions found not to be connected to the database are purged
/// from the pool whenever one of the following events occurs:
///
/// - JanitorTimer event
/// - get() request
/// - putBack() request
///
/// Not connected idle sessions can not exist.
///
/// Usage example:
///
/// SessionPool pool("ODBC", "...");
/// ...
/// Session sess(pool.get());
/// ...
namespace Poco
{
public:
SessionPool(const std::string& connector,
const std::string& connectionString,
int minSessions = 1,
int maxSessions = 32,
int idleTime = 60);
/// Creates the SessionPool for sessions with the given connector
/// and connectionString.
///
/// The pool allows for at most maxSessions sessions to be created.
/// If a session has been idle for more than idleTime seconds, and more than
/// minSessions sessions are in the pool, the session is automatically destroyed.
~SessionPool();
/// Destroys the SessionPool.
Session get();
/// Returns a Session.
///
/// If there are unused sessions available, one of the
/// unused sessions is recycled. Otherwise, a new session
/// is created.
///
/// If the maximum number of sessions for this pool has
/// already been created, a SessionPoolExhaustedException
/// is thrown.
template <typename T>
Session get(const std::string& name, const T& value)
/// Returns a Session with requested property set.
/// The property can be different from the default pool
/// value, in which case it is reset back to the pool
/// value when the session is reclaimed by the pool.
{
Session s = get();
_addPropertyMap.insert(AddPropertyMap::value_type(s.impl(),
std::make_pair(name, s.getProperty(name))));
s.setProperty(name, value);
return s;
}
Session get(const std::string& name, bool value);
/// Returns a Session with requested feature set.
/// The feature can be different from the default pool
/// value, in which case it is reset back to the pool
/// value when the session is reclaimed by the pool.
int capacity() const;
/// Returns the maximum number of sessions the SessionPool will manage.
int used() const;
/// Returns the number of sessions currently in use.
int idle() const;
/// Returns the number of idle sessions.
int dead();
/// Returns the number of not connected active sessions.
int allocated() const;
/// Returns the number of allocated sessions.
int available() const;
/// Returns the number of available (idle + remaining capacity) sessions.
std::string name() const;
/// Returns the name for this pool.
static std::string name(const std::string& connector,
const std::string& connectionString);
/// Returns the name formatted from supplied arguments as "connector:///connectionString".
void setFeature(const std::string& name, bool state);
/// Sets feature for all the sessions.
bool getFeature(const std::string& name);
/// Returns the requested feature.
void setProperty(const std::string& name, const Poco::Any& value);
/// Sets property for all sessions.
Poco::Any getProperty(const std::string& name);
/// Returns the requested property.
void shutdown();
/// Shuts down the session pool.
bool isActive() const;
/// Returns true if session pool is active (not shut down).
protected:
virtual void customizeSession(Session& session);
/// Can be overridden by subclass to perform custom initialization
/// of a newly created database session.
///
/// The default implementation does nothing.
typedef Poco::AutoPtr<PooledSessionHolder> PooledSessionHolderPtr;
typedef Poco::AutoPtr<PooledSessionImpl> PooledSessionImplPtr;
typedef std::list<PooledSessionHolderPtr> SessionList;
typedef Poco::HashMap<std::string, bool> FeatureMap;
typedef Poco::HashMap<std::string, Poco::Any> PropertyMap;
void purgeDeadSessions();
int deadImpl(SessionList& rSessions);
void applySettings(SessionImpl* pImpl);
void putBack(PooledSessionHolderPtr pHolder);
void onJanitorTimer(Poco::Timer&);
private:
typedef std::pair<std::string, Poco::Any> PropertyPair;
typedef std::pair<std::string, bool> FeaturePair;
typedef std::map<SessionImpl*, PropertyPair> AddPropertyMap;
typedef std::map<SessionImpl*, FeaturePair> AddFeatureMap;
SessionPool(const SessionPool&);
SessionPool& operator = (const SessionPool&);
void closeAll(SessionList& sessionList);
std::string _connector;
std::string _connectionString;
int _minSessions;
int _maxSessions;
int _idleTime;
int _nSessions;
SessionList _idleSessions;
SessionList _activeSessions;
Poco::Timer _janitorTimer;
FeatureMap _featureMap;
PropertyMap _propertyMap;
bool _shutdown;
AddPropertyMap _addPropertyMap;
AddFeatureMap _addFeatureMap;
mutable
Poco::Mutex _mutex;
friend class PooledSessionImpl;
};
inline std::string SessionPool::name(const std::string& connector,
const std::string& connectionString)
namespace Data
{
return Session::uri(connector, connectionString);
class Data_API SessionPool : public RefCountedObject
/// This class implements session pooling for POCO Data.
///
/// Creating a connection to a database is often a time consuming
/// operation. Therefore it makes sense to reuse a session object
/// once it is no longer needed.
///
/// A SessionPool manages a collection of SessionImpl objects
/// (decorated with a PooledSessionImpl).
///
/// When a SessionImpl object is requested, the SessionPool first
/// looks in its set of already initialized SessionImpl for an
/// available object. If one is found, it is returned to the
/// client and marked as "in-use". If no SessionImpl is available,
/// the SessionPool attempts to create a new one for the client.
/// To avoid excessive creation of SessionImpl objects, a limit
/// can be set on the maximum number of objects.
/// Sessions found not to be connected to the database are purged
/// from the pool whenever one of the following events occurs:
///
/// - JanitorTimer event
/// - get() request
/// - putBack() request
///
/// Not connected idle sessions can not exist.
///
/// Usage example:
///
/// SessionPool pool("ODBC", "...");
/// ...
/// Session sess(pool.get());
/// ...
{
public:
SessionPool(
const std::string & connector,
const std::string & connectionString,
int minSessions = 1,
int maxSessions = 32,
int idleTime = 60);
/// Creates the SessionPool for sessions with the given connector
/// and connectionString.
///
/// The pool allows for at most maxSessions sessions to be created.
/// If a session has been idle for more than idleTime seconds, and more than
/// minSessions sessions are in the pool, the session is automatically destroyed.
~SessionPool();
/// Destroys the SessionPool.
Session get();
/// Returns a Session.
///
/// If there are unused sessions available, one of the
/// unused sessions is recycled. Otherwise, a new session
/// is created.
///
/// If the maximum number of sessions for this pool has
/// already been created, a SessionPoolExhaustedException
/// is thrown.
template <typename T>
Session get(const std::string & name, const T & value)
/// Returns a Session with requested property set.
/// The property can be different from the default pool
/// value, in which case it is reset back to the pool
/// value when the session is reclaimed by the pool.
{
Session s = get();
_addPropertyMap.insert(AddPropertyMap::value_type(s.impl(), std::make_pair(name, s.getProperty(name))));
s.setProperty(name, value);
return s;
}
Session get(const std::string & name, bool value);
/// Returns a Session with requested feature set.
/// The feature can be different from the default pool
/// value, in which case it is reset back to the pool
/// value when the session is reclaimed by the pool.
int capacity() const;
/// Returns the maximum number of sessions the SessionPool will manage.
int used() const;
/// Returns the number of sessions currently in use.
int idle() const;
/// Returns the number of idle sessions.
int dead();
/// Returns the number of not connected active sessions.
int allocated() const;
/// Returns the number of allocated sessions.
int available() const;
/// Returns the number of available (idle + remaining capacity) sessions.
std::string name() const;
/// Returns the name for this pool.
static std::string name(const std::string & connector, const std::string & connectionString);
/// Returns the name formatted from supplied arguments as "connector:///connectionString".
void setFeature(const std::string & name, bool state);
/// Sets feature for all the sessions.
bool getFeature(const std::string & name);
/// Returns the requested feature.
void setProperty(const std::string & name, const Poco::Any & value);
/// Sets property for all sessions.
Poco::Any getProperty(const std::string & name);
/// Returns the requested property.
void shutdown();
/// Shuts down the session pool.
bool isActive() const;
/// Returns true if session pool is active (not shut down).
protected:
virtual void customizeSession(Session & session);
/// Can be overridden by subclass to perform custom initialization
/// of a newly created database session.
///
/// The default implementation does nothing.
typedef Poco::AutoPtr<PooledSessionHolder> PooledSessionHolderPtr;
typedef Poco::AutoPtr<PooledSessionImpl> PooledSessionImplPtr;
typedef std::list<PooledSessionHolderPtr> SessionList;
typedef Poco::HashMap<std::string, bool> FeatureMap;
typedef Poco::HashMap<std::string, Poco::Any> PropertyMap;
void purgeDeadSessions();
int deadImpl(SessionList & rSessions);
void applySettings(SessionImpl * pImpl);
void putBack(PooledSessionHolderPtr pHolder);
void onJanitorTimer(Poco::Timer &);
private:
typedef std::pair<std::string, Poco::Any> PropertyPair;
typedef std::pair<std::string, bool> FeaturePair;
typedef std::map<SessionImpl *, PropertyPair> AddPropertyMap;
typedef std::map<SessionImpl *, FeaturePair> AddFeatureMap;
SessionPool(const SessionPool &);
SessionPool & operator=(const SessionPool &);
void closeAll(SessionList & sessionList);
std::string _connector;
std::string _connectionString;
int _minSessions;
int _maxSessions;
int _idleTime;
int _nSessions;
SessionList _idleSessions;
SessionList _activeSessions;
Poco::Timer _janitorTimer;
FeatureMap _featureMap;
PropertyMap _propertyMap;
bool _shutdown;
AddPropertyMap _addPropertyMap;
AddFeatureMap _addFeatureMap;
mutable Poco::Mutex _mutex;
friend class PooledSessionImpl;
};
inline std::string SessionPool::name(const std::string & connector, const std::string & connectionString)
{
return Session::uri(connector, connectionString);
}
inline std::string SessionPool::name() const
{
return name(_connector, _connectionString);
}
inline bool SessionPool::isActive() const
{
return !_shutdown;
}
}
inline std::string SessionPool::name() const
{
return name(_connector, _connectionString);
}
inline bool SessionPool::isActive() const
{
return !_shutdown;
}
} } // namespace Poco::Data
} // namespace Poco::Data
#endif // Data_SessionPool_INCLUDED

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