diff --git a/Data/MySQL/Makefile b/Data/MySQL/Makefile
new file mode 100644
index 000000000..b50e5d111
--- /dev/null
+++ b/Data/MySQL/Makefile
@@ -0,0 +1,23 @@
+#
+# Makefile
+#
+# $Id: //poco/1.3/Data/MySQL/Makefile#3 $
+#
+# Makefile for Poco MySQL
+#
+
+include $(POCO_BASE)/build/rules/global
+
+SYSLIBS += -L/usr/local/lib/mysql
+INCLUDE += -I/usr/local/include/mysql/
+SYSFLAGS += -DTHREADSAFE -DNO_TCL
+
+objects = Binder Extractor SessionImpl Connector \
+ MySQLStatementImpl ResultMetadata MySQLException \
+ SessionHandle StatementExecutor
+
+target = PocoMySQL
+target_version = $(LIBVERSION)
+target_libs = PocoData PocoFoundation
+
+include $(POCO_BASE)/build/rules/lib
diff --git a/Data/MySQL/MySQL_VS80.sln b/Data/MySQL/MySQL_VS80.sln
new file mode 100644
index 000000000..528a7f3d4
--- /dev/null
+++ b/Data/MySQL/MySQL_VS80.sln
@@ -0,0 +1,29 @@
+
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestSuite", "testsuite\TestSuite_VS80.vcproj", "{1B30A91B-375F-11DB-837B-00123FC423B5}"
+ ProjectSection(ProjectDependencies) = postProject
+ {73E19FDE-1570-488C-B3DB-72A60FADD408} = {73E19FDE-1570-488C-B3DB-72A60FADD408}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MySQL", "MySQL_VS80.vcproj", "{73E19FDE-1570-488C-B3DB-72A60FADD408}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ debug_shared|Win32 = debug_shared|Win32
+ release_shared|Win32 = release_shared|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {1B30A91B-375F-11DB-837B-00123FC423B5}.debug_shared|Win32.ActiveCfg = debug_shared|Win32
+ {1B30A91B-375F-11DB-837B-00123FC423B5}.debug_shared|Win32.Build.0 = debug_shared|Win32
+ {1B30A91B-375F-11DB-837B-00123FC423B5}.release_shared|Win32.ActiveCfg = release_shared|Win32
+ {1B30A91B-375F-11DB-837B-00123FC423B5}.release_shared|Win32.Build.0 = release_shared|Win32
+ {73E19FDE-1570-488C-B3DB-72A60FADD408}.debug_shared|Win32.ActiveCfg = debug_shared|Win32
+ {73E19FDE-1570-488C-B3DB-72A60FADD408}.debug_shared|Win32.Build.0 = debug_shared|Win32
+ {73E19FDE-1570-488C-B3DB-72A60FADD408}.release_shared|Win32.ActiveCfg = release_shared|Win32
+ {73E19FDE-1570-488C-B3DB-72A60FADD408}.release_shared|Win32.Build.0 = release_shared|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/Data/MySQL/MySQL_VS80.vcproj b/Data/MySQL/MySQL_VS80.vcproj
new file mode 100644
index 000000000..5adcde9db
--- /dev/null
+++ b/Data/MySQL/MySQL_VS80.vcproj
@@ -0,0 +1,279 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Data/MySQL/include/Poco/Data/MySQL/Binder.h b/Data/MySQL/include/Poco/Data/MySQL/Binder.h
new file mode 100644
index 000000000..2a5b742ae
--- /dev/null
+++ b/Data/MySQL/include/Poco/Data/MySQL/Binder.h
@@ -0,0 +1,133 @@
+//
+// Binder.h
+//
+// $Id: //poco/1.3/Data/MySQL/include/Poco/Data/MySQL/Binder.h#1 $
+//
+// Library: Data
+// Package: MySQL
+// Module: Binder
+//
+// Definition of the Binder class.
+//
+// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// Permission is hereby granted, free of charge, to any person or organization
+// obtaining a copy of the software and accompanying documentation covered by
+// this license (the "Software") to use, reproduce, display, distribute,
+// execute, and transmit the Software, and to prepare derivative works of the
+// Software, and to permit third-parties to whom the Software is furnished to
+// do so, all subject to the following:
+//
+// The copyright notices in the Software and this entire statement, including
+// the above license grant, this restriction and the following disclaimer,
+// must be included in all copies of the Software, in whole or in part, and
+// all derivative works of the Software, unless such copies or derivative
+// works are solely in the form of machine-executable object code generated by
+// a source language processor.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+
+
+#ifndef Data_MySQL_Binder_INCLUDED
+#define Data_MySQL_Binder_INCLUDED
+
+#include "Poco/Data/MySQL/MySQL.h"
+#include "Poco/Data/AbstractBinder.h"
+#include "Poco/Data/BLOB.h"
+#include "Poco/Data/MySQL/MySQLException.h"
+#include
+
+namespace Poco {
+namespace Data {
+namespace MySQL {
+
+
+class MySQL_API Binder: public Poco::Data::AbstractBinder
+ /// Binds placeholders in the sql query to the provided values. Performs data types mapping.
+{
+public:
+
+ Binder();
+ /// Creates the Binder.
+
+ virtual ~Binder();
+ /// Destroys the Binder.
+
+ virtual void bind(std::size_t pos, const Poco::Int8& val);
+ /// Binds an Int8.
+
+ virtual void bind(std::size_t pos, const Poco::UInt8& val);
+ /// Binds an UInt8.
+
+ virtual void bind(std::size_t pos, const Poco::Int16& val);
+ /// Binds an Int16.
+
+ virtual void bind(std::size_t pos, const Poco::UInt16& val);
+ /// Binds an UInt16.
+
+ virtual void bind(std::size_t pos, const Poco::Int32& val);
+ /// Binds an Int32.
+
+ virtual void bind(std::size_t pos, const Poco::UInt32& val);
+ /// Binds an UInt32.
+
+ virtual void bind(std::size_t pos, const Poco::Int64& val);
+ /// Binds an Int64.
+
+ virtual void bind(std::size_t pos, const Poco::UInt64& val);
+ /// Binds an UInt64.
+
+ virtual void bind(std::size_t pos, const bool& val);
+ /// Binds a boolean.
+
+ virtual void bind(std::size_t pos, const float& val);
+ /// Binds a float.
+
+ virtual void bind(std::size_t pos, const double& val);
+ /// Binds a double.
+
+ virtual void bind(std::size_t pos, const char& val);
+ /// Binds a single character.
+
+ virtual void bind(std::size_t pos, const std::string& val);
+ /// Binds a string.
+
+ virtual void bind(std::size_t pos, const Poco::Data::BLOB& val);
+ /// Binds a BLOB.
+
+ size_t size() const;
+ /// Return count of binded parameters
+
+ MYSQL_BIND* getBindArray() const;
+ /// Return array
+
+private:
+
+ virtual void bind(std::size_t, const char* const&)
+ /// Binds a const char ptr.
+ /// This is a private no-op in this implementation
+ /// due to security risk.
+ {
+ }
+
+ void realBind(std::size_t pos, enum_field_types type, const void* buffer, int length);
+ /// Common bind implementation
+
+private:
+
+ std::vector _bindArray;
+};
+
+
+} } } // namespace Poco::Data::MySQL
+
+
+#endif // Data_MySQL_Binder_INCLUDED
diff --git a/Data/MySQL/include/Poco/Data/MySQL/Connector.h b/Data/MySQL/include/Poco/Data/MySQL/Connector.h
new file mode 100644
index 000000000..397336f2c
--- /dev/null
+++ b/Data/MySQL/include/Poco/Data/MySQL/Connector.h
@@ -0,0 +1,76 @@
+//
+// Connector.h
+//
+// $Id: //poco/1.3/Data/MySQL/include/Poco/Data/MySQL/Connector.h#1 $
+//
+// Library: Data
+// Package: MySQL
+// Module: Connector
+//
+// Definition of the Connector class.
+//
+// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// Permission is hereby granted, free of charge, to any person or organization
+// obtaining a copy of the software and accompanying documentation covered by
+// this license (the "Software") to use, reproduce, display, distribute,
+// execute, and transmit the Software, and to prepare derivative works of the
+// Software, and to permit third-parties to whom the Software is furnished to
+// do so, all subject to the following:
+//
+// The copyright notices in the Software and this entire statement, including
+// the above license grant, this restriction and the following disclaimer,
+// must be included in all copies of the Software, in whole or in part, and
+// all derivative works of the Software, unless such copies or derivative
+// works are solely in the form of machine-executable object code generated by
+// a source language processor.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+
+
+#ifndef Data_MySQL_Connector_INCLUDED
+#define Data_MySQL_Connector_INCLUDED
+
+#include "MySQL.h"
+#include "Poco/Data/Connector.h"
+
+namespace Poco {
+namespace Data {
+namespace MySQL {
+
+class MySQL_API Connector: public Poco::Data::Connector
+ /// Connector instantiates MySQL SessionImpl objects.
+{
+public:
+
+ static std::string KEY;
+
+ Connector();
+ /// Creates the Connector.
+
+ virtual ~Connector();
+ /// Destroys the Connector.
+
+ virtual Poco::AutoPtr createSession(const std::string& connectionString);
+ /// Creates a MySQL 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
+};
+
+
+} } } // namespace Poco::Data::MySQL
+
+
+#endif // Data_MySQL_Connector_INCLUDED
diff --git a/Data/MySQL/include/Poco/Data/MySQL/Extractor.h b/Data/MySQL/include/Poco/Data/MySQL/Extractor.h
new file mode 100644
index 000000000..0e5eb068b
--- /dev/null
+++ b/Data/MySQL/include/Poco/Data/MySQL/Extractor.h
@@ -0,0 +1,124 @@
+//
+// Extractor.h
+//
+// $Id: //poco/1.3/Data/MySQL/include/Poco/Data/MySQL/Extractor.h#1 $
+//
+// Library: Data
+// Package: MySQL
+// Module: Extractor
+//
+// Definition of the Extractor class.
+//
+// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// Permission is hereby granted, free of charge, to any person or organization
+// obtaining a copy of the software and accompanying documentation covered by
+// this license (the "Software") to use, reproduce, display, distribute,
+// execute, and transmit the Software, and to prepare derivative works of the
+// Software, and to permit third-parties to whom the Software is furnished to
+// do so, all subject to the following:
+//
+// The copyright notices in the Software and this entire statement, including
+// the above license grant, this restriction and the following disclaimer,
+// must be included in all copies of the Software, in whole or in part, and
+// all derivative works of the Software, unless such copies or derivative
+// works are solely in the form of machine-executable object code generated by
+// a source language processor.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+
+
+#ifndef Data_MySQL_Extractor_INCLUDED
+#define Data_MySQL_Extractor_INCLUDED
+
+
+#include "Poco/Data/MySQL/MySQL.h"
+#include "Poco/Data/MySQL/StatementExecutor.h"
+#include "Poco/Data/MySQL/ResultMetadata.h"
+#include "Poco/Data/AbstractExtractor.h"
+#include "Poco/Data/BLOB.h"
+
+
+namespace Poco {
+namespace Data {
+namespace MySQL {
+
+
+class MySQL_API Extractor: public Poco::Data::AbstractExtractor
+ /// Extracts and converts data values from the result row returned by MySQL.
+ /// If NULL is received, the incoming val value is not changed and false is returned
+{
+public:
+ Extractor(StatementExecutor& st, ResultMetadata& md);
+ /// Creates the Extractor.
+
+ virtual ~Extractor();
+ /// Destroys the Extractor.
+
+ virtual bool extract(std::size_t pos, Poco::Int8& val);
+ /// Extracts an Int8.
+
+ virtual bool extract(std::size_t pos, Poco::UInt8& val);
+ /// Extracts an UInt8.
+
+ virtual bool extract(std::size_t pos, Poco::Int16& val);
+ /// Extracts an Int16.
+
+ virtual bool extract(std::size_t pos, Poco::UInt16& val);
+ /// Extracts an UInt16.
+
+ virtual bool extract(std::size_t pos, Poco::Int32& val);
+ /// Extracts an Int32.
+
+ virtual bool extract(std::size_t pos, Poco::UInt32& val);
+ /// Extracts an UInt32.
+
+ virtual bool extract(std::size_t pos, Poco::Int64& val);
+ /// Extracts an Int64.
+
+ virtual bool extract(std::size_t pos, Poco::UInt64& val);
+ /// Extracts an UInt64.
+
+ virtual bool extract(std::size_t pos, bool& val);
+ /// Extracts a boolean.
+
+ virtual bool extract(std::size_t pos, float& val);
+ /// Extracts a float.
+
+ virtual bool extract(std::size_t pos, double& val);
+ /// Extracts a double.
+
+ virtual bool extract(std::size_t pos, char& val);
+ /// Extracts a single character.
+
+ virtual bool extract(std::size_t pos, std::string& val);
+ /// Extracts a string.
+
+ virtual bool extract(std::size_t pos, Poco::Data::BLOB& val);
+ /// Extracts a BLOB.
+
+private:
+
+ bool realExtractFixed(std::size_t pos, enum_field_types type, void* buffer, size_t length = 0);
+
+ // Prevent VC8 warning "operator= could not be generated"
+ Extractor& operator=(const Extractor&);
+
+private:
+
+ StatementExecutor& _stmt;
+ ResultMetadata& _metadata;
+};
+
+} } } // namespace Poco::Data::MySQL
+
+
+#endif // Data_MySQL_Extractor_INCLUDED
diff --git a/Data/MySQL/include/Poco/Data/MySQL/MySQL.h b/Data/MySQL/include/Poco/Data/MySQL/MySQL.h
new file mode 100644
index 000000000..cf57af789
--- /dev/null
+++ b/Data/MySQL/include/Poco/Data/MySQL/MySQL.h
@@ -0,0 +1,90 @@
+//
+// MySQL.h
+//
+// $Id: //poco/1.3/Data/MySQL/include/Poco/Data/MySQL/MySQL.h#1 $
+//
+// Library: Data
+// Package: MySQL
+// Module: MySQL
+//
+// Basic definitions for the MySQL library.
+//
+// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// Permission is hereby granted, free of charge, to any person or organization
+// obtaining a copy of the software and accompanying documentation covered by
+// this license (the "Software") to use, reproduce, display, distribute,
+// execute, and transmit the Software, and to prepare derivative works of the
+// Software, and to permit third-parties to whom the Software is furnished to
+// do so, all subject to the following:
+//
+// The copyright notices in the Software and this entire statement, including
+// the above license grant, this restriction and the following disclaimer,
+// must be included in all copies of the Software, in whole or in part, and
+// all derivative works of the Software, unless such copies or derivative
+// works are solely in the form of machine-executable object code generated by
+// a source language processor.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+
+
+#ifndef MySQL_MySQL_INCLUDED
+#define MySQL_MySQL_INCLUDED
+
+
+#include "Poco/Foundation.h"
+
+
+//
+// The following block is the standard way of creating macros which make exporting
+// 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
+// defined with this macro as being exported.
+//
+#if defined(_WIN32) && defined(POCO_DLL)
+ #if defined(MYSQL_EXPORTS)
+ #define MySQL_API __declspec(dllexport)
+ #else
+ #define MySQL_API __declspec(dllimport)
+ #endif
+#endif
+
+
+#if !defined(MySQL_API)
+ #define MySQL_API
+#endif
+
+
+//
+// Automatically link Data library.
+//
+#if defined(_MSC_VER)
+ #if !defined(POCO_NO_AUTOMATIC_LIBS) && !defined(MYSQL_EXPORTS)
+ #if defined(POCO_DLL)
+ #if defined(_DEBUG)
+ #pragma comment(lib, "PocoMySQLd.lib")
+ #else
+ #pragma comment(lib, "PocoMySQL.lib")
+ #endif
+ #else
+ #if defined(_DEBUG)
+ #pragma comment(lib, "PocoMySQLmtd.lib")
+ #else
+ #pragma comment(lib, "PocoMySQLmt.lib")
+ #endif
+ #endif
+ #endif
+#endif
+
+
+#endif // MySQL_MySQL_INCLUDED
diff --git a/Data/MySQL/include/Poco/Data/MySQL/MySQLException.h b/Data/MySQL/include/Poco/Data/MySQL/MySQLException.h
new file mode 100644
index 000000000..8cb5b7dfd
--- /dev/null
+++ b/Data/MySQL/include/Poco/Data/MySQL/MySQLException.h
@@ -0,0 +1,165 @@
+//
+// MySQLException.h
+//
+// $Id: //poco/1.3/Data/MySQL/include/Poco/Data/MySQL/MySQLException.h#1 $
+//
+// Library: Data
+// Package: MySQL
+// Module: MySQLException
+//
+// Definition of the MySQLException class.
+//
+// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// Permission is hereby granted, free of charge, to any person or organization
+// obtaining a copy of the software and accompanying documentation covered by
+// this license (the "Software") to use, reproduce, display, distribute,
+// execute, and transmit the Software, and to prepare derivative works of the
+// Software, and to permit third-parties to whom the Software is furnished to
+// do so, all subject to the following:
+//
+// The copyright notices in the Software and this entire statement, including
+// the above license grant, this restriction and the following disclaimer,
+// must be included in all copies of the Software, in whole or in part, and
+// all derivative works of the Software, unless such copies or derivative
+// works are solely in the form of machine-executable object code generated by
+// a source language processor.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+
+
+#ifndef Data_MySQL_MySQLException_INCLUDED
+#define Data_MySQL_MySQLException_INCLUDED
+
+#include "Poco/Data/MySQL/MySQL.h"
+#include "Poco/Data/DataException.h"
+#include
+#include
+
+
+typedef struct st_mysql MYSQL;
+typedef struct st_mysql_stmt MYSQL_STMT;
+
+
+namespace Poco {
+namespace Data {
+namespace MySQL {
+
+// End-user include this file and use in code ConnectionException/StatementException
+// So it need not know
+
+class MySQL_API MySQLException: public Poco::Data::DataException
+ /// Base class for all MySQL exceptions
+{
+public:
+
+ MySQLException(const std::string& msg);
+ /// Creates MySQLException.
+
+ MySQLException(const MySQLException& exc);
+ /// Creates MySQLException.
+
+ ~MySQLException() throw();
+ /// Destroys MySQLexception.
+
+ MySQLException& operator=(const MySQLException& exc);
+ /// Assignment operator.
+
+ const char* name() const throw();
+ /// Returns exception name.
+
+ const char* className() const throw();
+ /// Returns the name of the exception class.
+
+ Poco::Exception* clone() const;
+ /// Creates an exact copy of the exception.
+ ///
+ /// The copy can later be thrown again by
+ /// invoking rethrow() on it.
+
+ void rethrow() const;
+ /// (Re)Throws the exception.
+ ///
+ /// This is useful for temporarily storing a
+ /// copy of an exception (see clone()), then
+ /// throwing it again.
+};
+
+
+class ConnectionException : public MySQLException
+ /// ConnectionException
+{
+public:
+
+ ConnectionException(const std::string& msg);
+ /// Creates ConnectionException.
+
+ ConnectionException(const std::string& text, MYSQL* h);
+ /// Destroys ConnectionException.
+
+private:
+
+ static std::string compose(const std::string& text, MYSQL* h);
+
+};
+
+
+class StatementException : public MySQLException
+ /// StatementException
+{
+public:
+
+ StatementException(const std::string& msg);
+ /// Creates StatementException.
+
+ StatementException(const std::string& text, MYSQL_STMT* h, const std::string& stmt = "");
+ /// Destroys StatementException.
+
+private:
+
+ static std::string compose(const std::string& text, MYSQL_STMT* h, const std::string& stmt);
+};
+
+
+//
+// inlines
+//
+
+inline MySQLException& MySQLException::operator=(const MySQLException& exc)
+{
+ Poco::Data::DataException::operator=(exc);
+ return *this;
+}
+
+inline const char* MySQLException::name() const throw()
+{
+ return "MySQL";
+}
+
+inline const char* MySQLException::className() const throw()
+{
+ return typeid(*this).name();
+}
+
+inline Poco::Exception* MySQLException::clone() const
+{
+ return new MySQLException(*this);
+}
+
+inline void MySQLException::rethrow() const
+{
+ throw *this;
+}
+
+
+} } } // namespace Poco::Data::MySQL
+
+#endif //Data_MySQL_MySQLException_INCLUDED
diff --git a/Data/MySQL/include/Poco/Data/MySQL/MySQLStatementImpl.h b/Data/MySQL/include/Poco/Data/MySQL/MySQLStatementImpl.h
new file mode 100644
index 000000000..b1eb9be49
--- /dev/null
+++ b/Data/MySQL/include/Poco/Data/MySQL/MySQLStatementImpl.h
@@ -0,0 +1,118 @@
+//
+// MySQLstatementImpl.h
+//
+// $Id: //poco/1.3/Data/MySQL/include/Poco/Data/MySQL/MySQLStatementImpl.h#1 $
+//
+// Library: Data
+// Package: MySQL
+// Module: MySQLstatementImpl
+//
+// Definition of the MySQLStatementImpl class.
+//
+// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// Permission is hereby granted, free of charge, to any person or organization
+// obtaining a copy of the software and accompanying documentation covered by
+// this license (the "Software") to use, reproduce, display, distribute,
+// execute, and transmit the Software, and to prepare derivative works of the
+// Software, and to permit third-parties to whom the Software is furnished to
+// do so, all subject to the following:
+//
+// The copyright notices in the Software and this entire statement, including
+// the above license grant, this restriction and the following disclaimer,
+// must be included in all copies of the Software, in whole or in part, and
+// all derivative works of the Software, unless such copies or derivative
+// works are solely in the form of machine-executable object code generated by
+// a source language processor.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+
+
+#ifndef Data_MySQL_MySQLStatementImpl_INCLUDED
+#define Data_MySQL_MySQLStatementImpl_INCLUDED
+
+#include "Poco/Data/MySQL/MySQL.h"
+#include "Poco/Data/MySQL/SessionImpl.h"
+#include "Poco/Data/MySQL/Binder.h"
+#include "Poco/Data/MySQL/Extractor.h"
+#include "Poco/Data/MySQL/StatementExecutor.h"
+#include "Poco/Data/MySQL/ResultMetadata.h"
+#include "Poco/Data/StatementImpl.h"
+#include "Poco/SharedPtr.h"
+#include "Poco/Format.h"
+
+
+namespace Poco {
+namespace Data {
+namespace MySQL {
+
+
+class MySQL_API MySQLStatementImpl: public Poco::Data::StatementImpl
+ /// Implements statement functionality needed for MySQL
+{
+public:
+
+ MySQLStatementImpl(SessionHandle& h);
+ /// Creates the MySQLStatementImpl.
+
+ ~MySQLStatementImpl();
+ /// Destroys the MySQLStatementImpl.
+
+protected:
+
+ virtual Poco::UInt32 columnsReturned() const;
+ /// Returns number of columns returned by query.
+
+ virtual const MetaColumn& metaColumn(Poco::UInt32 pos) const;
+ /// Returns column meta data.
+
+ virtual bool hasNext();
+ /// Returns true if a call to next() will return data.
+
+ virtual void next();
+ /// Retrieves the next row from the resultset.
+ /// Will throw, if the resultset is empty.
+
+ virtual bool canBind() const;
+ /// Returns true if a valid statement is set and we can bind.
+
+ virtual void compileImpl();
+ /// Compiles the statement, doesn't bind yet
+
+ virtual void bindImpl();
+ /// Binds parameters
+
+ virtual AbstractExtractor& extractor();
+ /// Returns the concrete extractor used by the statement.
+
+ virtual AbstractBinder& binder();
+ /// Returns the concrete binder used by the statement.
+
+private:
+ enum
+ {
+ NEXT_DONTKNOW,
+ NEXT_TRUE,
+ NEXT_FALSE
+ };
+
+ StatementExecutor _stmt;
+ ResultMetadata _metadata;
+ Binder _binder;
+ Extractor _extractor;
+ int _hasNext;
+};
+
+
+} } } // namespace Poco::Data::MySQL
+
+
+#endif // Data_MySQL_MySQLStatementImpl_INCLUDED
diff --git a/Data/MySQL/include/Poco/Data/MySQL/ResultMetadata.h b/Data/MySQL/include/Poco/Data/MySQL/ResultMetadata.h
new file mode 100644
index 000000000..46299fbaf
--- /dev/null
+++ b/Data/MySQL/include/Poco/Data/MySQL/ResultMetadata.h
@@ -0,0 +1,86 @@
+//
+// ResultMetadata.h
+//
+// $Id: //poco/1.3/Data/MySQL/include/Poco/Data/MySQL/ResultMetadata.h#1 $
+//
+// Library: Data
+// Package: MySQL
+// Module: ResultMetadata
+//
+// Definition of the ResultMetadata class.
+//
+// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// Permission is hereby granted, free of charge, to any person or organization
+// obtaining a copy of the software and accompanying documentation covered by
+// this license (the "Software") to use, reproduce, display, distribute,
+// execute, and transmit the Software, and to prepare derivative works of the
+// Software, and to permit third-parties to whom the Software is furnished to
+// do so, all subject to the following:
+//
+// The copyright notices in the Software and this entire statement, including
+// the above license grant, this restriction and the following disclaimer,
+// must be included in all copies of the Software, in whole or in part, and
+// all derivative works of the Software, unless such copies or derivative
+// works are solely in the form of machine-executable object code generated by
+// a source language processor.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+
+
+#ifndef Data_MySQL_ResultMetadata_INCLUDED
+#define Data_MySQL_ResultMetadata_INCLUDED
+
+#include
+#include
+#include "Poco/Data/MetaColumn.h"
+
+namespace Poco {
+namespace Data {
+namespace MySQL {
+
+class ResultMetadata
+ /// MySQL result metadata
+{
+public:
+
+ void reset();
+ /// Resets the metadata.
+
+ void init(MYSQL_STMT* stmt);
+ /// Initializes the metadata.
+
+ Poco::UInt32 columnsReturned() const;
+ /// Returns the number of columns in resultset.
+
+ const MetaColumn& metaColumn(Poco::UInt32 pos) const;
+ /// Returns the reference to the specified metacolumn.
+
+ MYSQL_BIND* row();
+ ///
+
+ size_t length(size_t pos);
+ ///
+
+ const char* rawData(size_t pos);
+ ///
+
+private:
+
+ std::vector _columns;
+ std::vector _row;
+ std::vector _buffer;
+ std::vector _lengths;
+};
+
+}}}
+
+#endif //Data_MySQL_ResultMetadata_INCLUDED
diff --git a/Data/MySQL/include/Poco/Data/MySQL/SessionHandle.h b/Data/MySQL/include/Poco/Data/MySQL/SessionHandle.h
new file mode 100644
index 000000000..b3f48636b
--- /dev/null
+++ b/Data/MySQL/include/Poco/Data/MySQL/SessionHandle.h
@@ -0,0 +1,95 @@
+//
+// SesssionHandle.h
+//
+// $Id: //poco/1.3/Data/MySQL/include/Poco/Data/MySQL/SessionHandle.h#1 $
+//
+// Library: Data
+// Package: MySQL
+// Module: SessionHandle
+//
+// Definition of the SessionHandle class.
+//
+// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// Permission is hereby granted, free of charge, to any person or organization
+// obtaining a copy of the software and accompanying documentation covered by
+// this license (the "Software") to use, reproduce, display, distribute,
+// execute, and transmit the Software, and to prepare derivative works of the
+// Software, and to permit third-parties to whom the Software is furnished to
+// do so, all subject to the following:
+//
+// The copyright notices in the Software and this entire statement, including
+// the above license grant, this restriction and the following disclaimer,
+// must be included in all copies of the Software, in whole or in part, and
+// all derivative works of the Software, unless such copies or derivative
+// works are solely in the form of machine-executable object code generated by
+// a source language processor.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+
+
+#ifndef Data_MySQL_SessionHandle_INCLUDED
+#define Data_MySQL_SessionHandle_INCLUDED
+
+#include
+#include "Poco/Data/MySQL/MySQLException.h"
+
+#include
+
+namespace Poco {
+namespace Data {
+namespace MySQL {
+
+class SessionHandle
+ /// MySQL session handle
+{
+public:
+
+ explicit SessionHandle(MYSQL* mysql);
+
+ ~SessionHandle();
+
+ void options(mysql_option opt);
+
+ void options(mysql_option opt, bool b);
+
+ void connect(const char* host, const char* user, const char* password, const char* db, unsigned int port);
+
+ void close();
+
+ void query(const char* str);
+
+ operator MYSQL* ();
+
+private:
+
+ SessionHandle(const SessionHandle&);
+ SessionHandle& operator=(const SessionHandle&);
+
+private:
+
+ MYSQL* h;
+};
+
+
+//
+// inlines
+//
+
+inline SessionHandle::operator MYSQL* ()
+{
+ return h;
+}
+
+
+}}}
+
+#endif // Data_MySQL_SessionHandle_INCLUDED
diff --git a/Data/MySQL/include/Poco/Data/MySQL/SessionImpl.h b/Data/MySQL/include/Poco/Data/MySQL/SessionImpl.h
new file mode 100644
index 000000000..459ee9c4f
--- /dev/null
+++ b/Data/MySQL/include/Poco/Data/MySQL/SessionImpl.h
@@ -0,0 +1,127 @@
+//
+// SessionImpl.h
+//
+// $Id: //poco/1.3/Data/MySQL/include/Poco/Data/MySQL/SessionImpl.h#1 $
+//
+// Library: Data
+// Package: MySQL
+// Module: SessionImpl
+//
+// Definition of the SessionImpl class.
+//
+// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// Permission is hereby granted, free of charge, to any person or organization
+// obtaining a copy of the software and accompanying documentation covered by
+// this license (the "Software") to use, reproduce, display, distribute,
+// execute, and transmit the Software, and to prepare derivative works of the
+// Software, and to permit third-parties to whom the Software is furnished to
+// do so, all subject to the following:
+//
+// The copyright notices in the Software and this entire statement, including
+// the above license grant, this restriction and the following disclaimer,
+// must be included in all copies of the Software, in whole or in part, and
+// all derivative works of the Software, unless such copies or derivative
+// works are solely in the form of machine-executable object code generated by
+// a source language processor.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+
+
+#ifndef Data_MySQL_SessionImpl_INCLUDED
+#define Data_MySQL_SessionImpl_INCLUDED
+
+
+#include "Poco/Data/MySQL/MySQL.h"
+#include "Poco/Data/AbstractSessionImpl.h"
+#include "Poco/Data/MySQL/SessionHandle.h"
+
+
+namespace Poco {
+namespace Data {
+namespace MySQL {
+
+
+class MySQL_API SessionImpl: public Poco::Data::AbstractSessionImpl
+ /// Implements SessionImpl interface
+{
+public:
+
+ SessionImpl(const std::string& connectionString);
+ /// Creates the SessionImpl. Opens a connection to the database
+ ///
+ /// Connection string format:
+ /// == | ';'
+ /// == '='
+ /// == 'host' | 'port' | 'user' | 'password' | 'db' } 'compress' | 'auto-reconnect'
+ /// == [~;]*
+ ///
+ /// for compress and auto-reconnect correct values are true/false
+ /// for port - numeric in decimal notation
+ ///
+
+ ~SessionImpl();
+ /// Destroys the SessionImpl.
+
+ virtual Poco::Data::StatementImpl* createStatementImpl();
+ /// Returns an MySQL StatementImpl
+
+ virtual void begin();
+ /// Starts a transaction
+
+ virtual void commit();
+ /// Commits and ends a transaction
+
+ virtual void rollback();
+ /// Aborts a transaction
+
+ virtual void close();
+ /// Closes the connection
+
+ virtual bool isConnected();
+ /// Returns true iff session is connected.
+
+ virtual bool isTransaction();
+ /// Returns true iff a transaction is in progress.
+
+ void setInsertId(const std::string&, const Poco::Any&);
+ /// Try to set insert id - do nothing.
+
+ Poco::Any getInsertId(const std::string&);
+ /// Get insert id
+
+private:
+
+ SessionHandle _mysql;
+ bool _connected;
+ int _inTransaction;
+};
+
+
+//
+// inlines
+//
+
+inline void SessionImpl::setInsertId(const std::string&, const Poco::Any&)
+{
+}
+
+
+inline Poco::Any SessionImpl::getInsertId(const std::string&)
+{
+ return Poco::Any(Poco::UInt64(mysql_insert_id(_mysql)));
+}
+
+
+} } } // namespace Poco::Data::MySQL
+
+
+#endif // Data_MySQL_SessionImpl_INCLUDED
diff --git a/Data/MySQL/include/Poco/Data/MySQL/StatementExecutor.h b/Data/MySQL/include/Poco/Data/MySQL/StatementExecutor.h
new file mode 100644
index 000000000..923224c59
--- /dev/null
+++ b/Data/MySQL/include/Poco/Data/MySQL/StatementExecutor.h
@@ -0,0 +1,118 @@
+//
+// StatementExecutor.h
+//
+// $Id: //poco/1.3/Data/MySQL/include/Poco/Data/MySQL/StatementExecutor.h#1 $
+//
+// Library: Data
+// Package: MySQL
+// Module: StatementExecutor
+//
+// Definition of the StatementExecutor class.
+//
+// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// Permission is hereby granted, free of charge, to any person or organization
+// obtaining a copy of the software and accompanying documentation covered by
+// this license (the "Software") to use, reproduce, display, distribute,
+// execute, and transmit the Software, and to prepare derivative works of the
+// Software, and to permit third-parties to whom the Software is furnished to
+// do so, all subject to the following:
+//
+// The copyright notices in the Software and this entire statement, including
+// the above license grant, this restriction and the following disclaimer,
+// must be included in all copies of the Software, in whole or in part, and
+// all derivative works of the Software, unless such copies or derivative
+// works are solely in the form of machine-executable object code generated by
+// a source language processor.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+
+
+#ifndef Data_MySQL_StatementHandle_INCLUDED
+#define Data_MySQL_StatementHandle_INCLUDED
+
+#include
+#include "Poco/Data/MySQL/MySQLException.h"
+
+#include
+
+namespace Poco {
+namespace Data {
+namespace MySQL {
+
+class StatementExecutor
+ /// MySQL statement executor.
+{
+public:
+ enum State
+ {
+ STMT_INITED,
+ STMT_COMPILED,
+ STMT_EXECUTED
+ };
+
+ explicit StatementExecutor(MYSQL* mysql);
+ /// Creates the StatementExecutor.
+
+ ~StatementExecutor();
+ /// Destroys the StatementExecutor.
+
+ int state() const;
+ /// Returns the current state.
+
+ void prepare(const std::string& query);
+ /// Prepares the statement for execution.
+
+ void bindParams(MYSQL_BIND* params, size_t count);
+ /// Binds the params.
+
+ void bindResult(MYSQL_BIND* result);
+ /// Binds result.
+
+ void execute();
+ /// Executes the statement.
+
+ bool fetch();
+ /// Fetches the data.
+
+ bool fetchColumn(size_t n, MYSQL_BIND *bind);
+ /// Fetches the column.
+
+ operator MYSQL_STMT* ();
+ /// Cast operator to native handle type.
+
+private:
+
+ StatementExecutor(const StatementExecutor&);
+ StatementExecutor& operator=(const StatementExecutor&);
+
+private:
+
+ MYSQL_STMT* h;
+ int _state;
+ std::string _query;
+};
+
+
+//
+// inlines
+//
+
+inline StatementExecutor::operator MYSQL_STMT* ()
+{
+ return h;
+}
+
+
+}}}
+
+
+#endif // Data_MySQL_StatementHandle_INCLUDED
diff --git a/Data/MySQL/src/Binder.cpp b/Data/MySQL/src/Binder.cpp
new file mode 100644
index 000000000..da991773d
--- /dev/null
+++ b/Data/MySQL/src/Binder.cpp
@@ -0,0 +1,181 @@
+//
+// MySQLException.cpp
+//
+// $Id: //poco/1.3/Data/MySQL/src/Binder.cpp#1 $
+//
+// Library: Data
+// Package: MySQL
+// Module: Binder
+//
+// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// Permission is hereby granted, free of charge, to any person or organization
+// obtaining a copy of the software and accompanying documentation covered by
+// this license (the "Software") to use, reproduce, display, distribute,
+// execute, and transmit the Software, and to prepare derivative works of the
+// Software, and to permit third-parties to whom the Software is furnished to
+// do so, all subject to the following:
+//
+// The copyright notices in the Software and this entire statement, including
+// the above license grant, this restriction and the following disclaimer,
+// must be included in all copies of the Software, in whole or in part, and
+// all derivative works of the Software, unless such copies or derivative
+// works are solely in the form of machine-executable object code generated by
+// a source language processor.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+
+
+#include "Poco/Data/MySQL/Binder.h"
+
+
+namespace Poco {
+namespace Data {
+namespace MySQL {
+
+
+Binder::Binder()
+{
+}
+
+
+Binder::~Binder()
+{
+}
+
+
+void Binder::bind(std::size_t pos, const Poco::Int8& val)
+{
+ realBind(pos, MYSQL_TYPE_TINY, &val, 0);
+}
+
+
+void Binder::bind(std::size_t pos, const Poco::UInt8& val)
+{
+ realBind(pos, MYSQL_TYPE_TINY, &val, 0);
+}
+
+
+void Binder::bind(std::size_t pos, const Poco::Int16& val)
+{
+ realBind(pos, MYSQL_TYPE_SHORT, &val, 0);
+}
+
+
+void Binder::bind(std::size_t pos, const Poco::UInt16& val)
+{
+ realBind(pos, MYSQL_TYPE_SHORT, &val, 0);
+}
+
+
+void Binder::bind(std::size_t pos, const Poco::Int32& val)
+{
+ realBind(pos, MYSQL_TYPE_LONG, &val, 0);
+}
+
+
+void Binder::bind(std::size_t pos, const Poco::UInt32& val)
+{
+ realBind(pos, MYSQL_TYPE_LONG, &val, 0);
+}
+
+
+void Binder::bind(std::size_t pos, const Poco::Int64& val)
+{
+ realBind(pos, MYSQL_TYPE_LONGLONG, &val, 0);
+}
+
+
+void Binder::bind(std::size_t pos, const Poco::UInt64& val)
+{
+ realBind(pos, MYSQL_TYPE_LONGLONG, &val, 0);
+}
+
+
+void Binder::bind(std::size_t pos, const bool& val)
+{
+ realBind(pos, MYSQL_TYPE_TINY, &val, 0);
+}
+
+
+void Binder::bind(std::size_t pos, const float& val)
+{
+ realBind(pos, MYSQL_TYPE_FLOAT, &val, 0);
+}
+
+
+void Binder::bind(std::size_t pos, const double& val)
+{
+ realBind(pos, MYSQL_TYPE_DOUBLE, &val, 0);
+}
+
+
+void Binder::bind(std::size_t pos, const char& val)
+{
+ realBind(pos, MYSQL_TYPE_TINY, &val, 0);
+}
+
+
+void Binder::bind(std::size_t pos, const std::string& val)
+{
+ realBind(pos, MYSQL_TYPE_STRING, val.c_str(), static_cast(val.length()));
+}
+
+
+void Binder::bind(std::size_t pos, const Poco::Data::BLOB& val)
+{
+ realBind(pos, MYSQL_TYPE_STRING, val.rawContent(), static_cast(val.size()));
+}
+
+
+size_t Binder::size() const
+{
+ return _bindArray.size();
+}
+
+
+MYSQL_BIND* Binder::getBindArray() const
+{
+ if (_bindArray.size() == 0)
+ {
+ return 0;
+ }
+
+ return const_cast(&_bindArray[0]);
+}
+
+
+void Binder::realBind(std::size_t pos, enum_field_types type, const void* buffer, int length)
+{
+ if (pos > 1024)
+ {
+ throw StatementException("too many bind parameters");
+ }
+
+ if (pos >= _bindArray.size())
+ {
+ size_t s = _bindArray.size();
+ _bindArray.resize(pos + 1);
+
+ memset(&_bindArray[s], 0, sizeof(MYSQL_BIND) * (_bindArray.size() - s));
+ }
+
+ MYSQL_BIND b = {0};
+
+ b.buffer_type = type;
+ b.buffer = const_cast(buffer);
+ b.buffer_length = length;
+
+ _bindArray[pos] = b;
+}
+
+
+} } } // namespace Poco::Data::MySQL
diff --git a/Data/MySQL/src/Connector.cpp b/Data/MySQL/src/Connector.cpp
new file mode 100644
index 000000000..f515813fc
--- /dev/null
+++ b/Data/MySQL/src/Connector.cpp
@@ -0,0 +1,88 @@
+//
+// MySQLException.cpp
+//
+// $Id: //poco/1.3/Data/MySQL/src/Connector.cpp#1 $
+//
+// Library: Data
+// Package: MySQL
+// Module: Connector
+//
+// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// Permission is hereby granted, free of charge, to any person or organization
+// obtaining a copy of the software and accompanying documentation covered by
+// this license (the "Software") to use, reproduce, display, distribute,
+// execute, and transmit the Software, and to prepare derivative works of the
+// Software, and to permit third-parties to whom the Software is furnished to
+// do so, all subject to the following:
+//
+// The copyright notices in the Software and this entire statement, including
+// the above license grant, this restriction and the following disclaimer,
+// must be included in all copies of the Software, in whole or in part, and
+// all derivative works of the Software, unless such copies or derivative
+// works are solely in the form of machine-executable object code generated by
+// a source language processor.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+
+
+#include "Poco/Data/MySQL/Connector.h"
+#include "Poco/Data/MySQL/SessionImpl.h"
+#include "Poco/Data/SessionFactory.h"
+#include "Poco/Exception.h"
+
+#include
+
+
+namespace Poco {
+namespace Data {
+namespace MySQL {
+
+
+std::string Connector::KEY("MySQL");
+
+
+Connector::Connector()
+{
+}
+
+
+Connector::~Connector()
+{
+}
+
+
+Poco::AutoPtr Connector::createSession(const std::string& connectionString)
+{
+ return Poco::AutoPtr(new SessionImpl(connectionString));
+}
+
+
+void Connector::registerConnector()
+{
+ if (mysql_library_init(0, 0, 0) != 0)
+ {
+ throw Exception("mysql_library_init error");
+ }
+
+ Poco::Data::SessionFactory::instance().add(KEY, new Connector());
+}
+
+
+void Connector::unregisterConnector()
+{
+ Poco::Data::SessionFactory::instance().remove(KEY);
+ mysql_library_end();
+}
+
+
+} } } // namespace Poco::Data::MySQL
+
diff --git a/Data/MySQL/src/Extractor.cpp b/Data/MySQL/src/Extractor.cpp
new file mode 100644
index 000000000..e7fb6b062
--- /dev/null
+++ b/Data/MySQL/src/Extractor.cpp
@@ -0,0 +1,173 @@
+//
+// MySQLException.cpp
+//
+// $Id: //poco/1.3/Data/MySQL/src/Extractor.cpp#1 $
+//
+// Library: Data
+// Package: MySQL
+// Module: Extractor
+//
+// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// Permission is hereby granted, free of charge, to any person or organization
+// obtaining a copy of the software and accompanying documentation covered by
+// this license (the "Software") to use, reproduce, display, distribute,
+// execute, and transmit the Software, and to prepare derivative works of the
+// Software, and to permit third-parties to whom the Software is furnished to
+// do so, all subject to the following:
+//
+// The copyright notices in the Software and this entire statement, including
+// the above license grant, this restriction and the following disclaimer,
+// must be included in all copies of the Software, in whole or in part, and
+// all derivative works of the Software, unless such copies or derivative
+// works are solely in the form of machine-executable object code generated by
+// a source language processor.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+
+
+#include "Poco/Data/MySQL/Extractor.h"
+
+
+namespace Poco {
+namespace Data {
+namespace MySQL {
+
+
+Extractor::Extractor(StatementExecutor& st, ResultMetadata& md): _stmt(st), _metadata(md)
+{
+}
+
+
+Extractor::~Extractor()
+{
+}
+
+
+bool Extractor::extract(std::size_t pos, Poco::Int8& val)
+{
+ return realExtractFixed(pos, MYSQL_TYPE_TINY, &val);
+}
+
+
+bool Extractor::extract(std::size_t pos, Poco::UInt8& val)
+{
+ return realExtractFixed(pos, MYSQL_TYPE_TINY, &val);
+}
+
+
+bool Extractor::extract(std::size_t pos, Poco::Int16& val)
+{
+ return realExtractFixed(pos, MYSQL_TYPE_SHORT, &val);
+}
+
+
+bool Extractor::extract(std::size_t pos, Poco::UInt16& val)
+{
+ return realExtractFixed(pos, MYSQL_TYPE_SHORT, &val);
+}
+
+
+bool Extractor::extract(std::size_t pos, Poco::Int32& val)
+{
+ return realExtractFixed(pos, MYSQL_TYPE_LONG, &val);
+}
+
+
+bool Extractor::extract(std::size_t pos, Poco::UInt32& val)
+{
+ return realExtractFixed(pos, MYSQL_TYPE_LONG, &val);
+}
+
+
+bool Extractor::extract(std::size_t pos, Poco::Int64& val)
+{
+ return realExtractFixed(pos, MYSQL_TYPE_LONGLONG, &val);
+}
+
+
+bool Extractor::extract(std::size_t pos, Poco::UInt64& val)
+{
+ return realExtractFixed(pos, MYSQL_TYPE_LONGLONG, &val);
+}
+
+
+bool Extractor::extract(std::size_t pos, bool& val)
+{
+ return realExtractFixed(pos, MYSQL_TYPE_TINY, &val);
+}
+
+
+bool Extractor::extract(std::size_t pos, float& val)
+{
+ return realExtractFixed(pos, MYSQL_TYPE_FLOAT, &val);
+}
+
+
+bool Extractor::extract(std::size_t pos, double& val)
+{
+ return realExtractFixed(pos, MYSQL_TYPE_DOUBLE, &val);
+}
+
+
+bool Extractor::extract(std::size_t pos, char& val)
+{
+ return realExtractFixed(pos, MYSQL_TYPE_TINY, &val);
+}
+
+
+bool Extractor::extract(std::size_t pos, std::string& val)
+{
+ if (_metadata.columnsReturned() <= pos)
+ {
+ return false;
+ }
+
+ if (_metadata.metaColumn(static_cast(pos)).type() != Poco::Data::MetaColumn::FDT_STRING)
+ {
+ return false;
+ }
+
+ val.assign(_metadata.rawData(pos), _metadata.length(pos));
+ return true;
+}
+
+
+bool Extractor::extract(std::size_t pos, Poco::Data::BLOB& val)
+{
+ if (_metadata.columnsReturned() <= pos)
+ {
+ return false;
+ }
+
+ if (_metadata.metaColumn(static_cast(pos)).type() != Poco::Data::MetaColumn::FDT_BLOB)
+ {
+ return false;
+ }
+
+ val.assignRaw(_metadata.rawData(pos), _metadata.length(pos));
+ return true;
+}
+
+
+bool Extractor::realExtractFixed(std::size_t pos, enum_field_types type, void* buffer, size_t length)
+{
+ MYSQL_BIND bind = {0};
+
+ bind.buffer_type = type;
+ bind.buffer = buffer;
+ bind.buffer_length = static_cast(length);
+
+ return _stmt.fetchColumn(pos, &bind);
+}
+
+
+} } } // namespace Poco::Data::MySQL
diff --git a/Data/MySQL/src/MySQLException.cpp b/Data/MySQL/src/MySQLException.cpp
new file mode 100644
index 000000000..5e679db44
--- /dev/null
+++ b/Data/MySQL/src/MySQLException.cpp
@@ -0,0 +1,129 @@
+//
+// MySQLException.cpp
+//
+// $Id: //poco/1.3/Data/MySQL/src/MySQLException.cpp#1 $
+//
+// Library: Data
+// Package: MySQL
+// Module: MySQLException
+//
+// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// Permission is hereby granted, free of charge, to any person or organization
+// obtaining a copy of the software and accompanying documentation covered by
+// this license (the "Software") to use, reproduce, display, distribute,
+// execute, and transmit the Software, and to prepare derivative works of the
+// Software, and to permit third-parties to whom the Software is furnished to
+// do so, all subject to the following:
+//
+// The copyright notices in the Software and this entire statement, including
+// the above license grant, this restriction and the following disclaimer,
+// must be included in all copies of the Software, in whole or in part, and
+// all derivative works of the Software, unless such copies or derivative
+// works are solely in the form of machine-executable object code generated by
+// a source language processor.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+
+
+#include "Poco/Data/MySQL/MySQLException.h"
+#include
+
+
+namespace Poco {
+namespace Data {
+namespace MySQL {
+
+
+MySQLException::MySQLException(const std::string& msg) : Poco::Data::DataException(std::string("[MySQL]: ") + msg)
+{
+}
+
+
+MySQLException::MySQLException(const MySQLException& exc) : Poco::Data::DataException(exc)
+{
+}
+
+
+MySQLException::~MySQLException() throw()
+{
+}
+
+
+ConnectionException::ConnectionException(const std::string& msg) : MySQLException(msg)
+{
+}
+
+
+ConnectionException::ConnectionException(const std::string& text, MYSQL* h) : MySQLException(compose(text, h))
+{
+}
+
+
+StatementException::StatementException(const std::string& msg) : MySQLException(msg)
+{
+}
+
+
+StatementException::StatementException(const std::string& text, MYSQL_STMT* h, const std::string& stmt) : MySQLException(compose(text, h, stmt))
+{
+}
+
+
+std::string ConnectionException::compose(const std::string& text, MYSQL* h)
+{
+ std::string str;
+ str += "[Comment]: ";
+ str += text;
+ str += "\t[mysql_error]: ";
+ str += mysql_error(h);
+
+ str += "\t[mysql_errno]: ";
+ char buff[30];
+ sprintf(buff, "%d", mysql_errno(h));
+ str += buff;
+
+ str += "\t[mysql_sqlstate]: ";
+ str += mysql_sqlstate(h);
+ return str;
+}
+
+std::string StatementException::compose(const std::string& text, MYSQL_STMT* h, const std::string& stmt)
+{
+ std::string str;
+ str += "[Comment]: ";
+ str += text;
+
+ if (h != 0)
+ {
+ str += "\t[mysql_stmt_error]: ";
+ str += mysql_stmt_error(h);
+
+ str += "\t[mysql_stmt_errno]: ";
+ char buff[30];
+ sprintf(buff, "%d", mysql_stmt_errno(h));
+ str += buff;
+
+ str += "\t[mysql_stmt_sqlstate]: ";
+ str += mysql_stmt_sqlstate(h);
+ }
+
+ if (stmt.length() > 0)
+ {
+ str += "\t[statemnt]: ";
+ str += stmt;
+ }
+
+ return str;
+}
+
+
+} } } // namespace Poco::Data::MySQL
diff --git a/Data/MySQL/src/MySQLStatementImpl.cpp b/Data/MySQL/src/MySQLStatementImpl.cpp
new file mode 100644
index 000000000..4f51ef6b3
--- /dev/null
+++ b/Data/MySQL/src/MySQLStatementImpl.cpp
@@ -0,0 +1,175 @@
+//
+// MySQLException.cpp
+//
+// $Id: //poco/1.3/Data/MySQL/src/MySQLStatementImpl.cpp#1 $
+//
+// Library: Data
+// Package: MySQL
+// Module: MySQLStatementImpl
+//
+// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// Permission is hereby granted, free of charge, to any person or organization
+// obtaining a copy of the software and accompanying documentation covered by
+// this license (the "Software") to use, reproduce, display, distribute,
+// execute, and transmit the Software, and to prepare derivative works of the
+// Software, and to permit third-parties to whom the Software is furnished to
+// do so, all subject to the following:
+//
+// The copyright notices in the Software and this entire statement, including
+// the above license grant, this restriction and the following disclaimer,
+// must be included in all copies of the Software, in whole or in part, and
+// all derivative works of the Software, unless such copies or derivative
+// works are solely in the form of machine-executable object code generated by
+// a source language processor.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+
+
+#include "Poco/Data/MySQL/MySQLStatementImpl.h"
+
+
+namespace Poco {
+namespace Data {
+namespace MySQL {
+
+
+MySQLStatementImpl::MySQLStatementImpl(SessionHandle& h):
+ _stmt(h),
+ _extractor(_stmt, _metadata),
+ _hasNext(NEXT_DONTKNOW)
+{
+}
+
+
+MySQLStatementImpl::~MySQLStatementImpl()
+{
+}
+
+
+Poco::UInt32 MySQLStatementImpl::columnsReturned() const
+{
+ return _metadata.columnsReturned();
+}
+
+
+const MetaColumn& MySQLStatementImpl::metaColumn(Poco::UInt32 pos) const
+{
+ return _metadata.metaColumn(pos);
+}
+
+
+bool MySQLStatementImpl::hasNext()
+{
+ if (_hasNext == NEXT_DONTKNOW)
+ {
+ if (_metadata.columnsReturned() == 0)
+ {
+ return false;
+ }
+
+ if (_stmt.fetch())
+ {
+ _hasNext = NEXT_TRUE;
+ return true;
+ }
+
+ _hasNext = NEXT_FALSE;
+ return false;
+ }
+ else if (_hasNext == NEXT_TRUE)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+
+void MySQLStatementImpl::next()
+{
+ if (!hasNext())
+ throw StatementException("No data received");
+
+ Poco::Data::AbstractExtractionVec::iterator it = extractions().begin();
+ Poco::Data::AbstractExtractionVec::iterator itEnd = extractions().end();
+ std::size_t pos = 0;
+
+ for (; it != itEnd; ++it)
+ {
+ (*it)->extract(pos);
+ pos += (*it)->numOfColumnsHandled();
+ }
+
+ _hasNext = NEXT_DONTKNOW;
+}
+
+
+bool MySQLStatementImpl::canBind() const
+{
+ bool ret = false;
+
+ if ((_stmt.state() >= StatementExecutor::STMT_COMPILED) && !bindings().empty())
+ ret = (*bindings().begin())->canBind();
+
+ return ret;
+}
+
+
+void MySQLStatementImpl::compileImpl()
+{
+ _metadata.reset();
+ _stmt.prepare(toString());
+ _metadata.init(_stmt);
+
+ if (_metadata.columnsReturned() > 0)
+ {
+ _stmt.bindResult(_metadata.row());
+ }
+}
+
+
+void MySQLStatementImpl::bindImpl()
+{
+ {
+ Poco::Data::AbstractBindingVec& binds = bindings();
+ size_t pos = 0;
+ Poco::Data::AbstractBindingVec::iterator it = binds.begin();
+ Poco::Data::AbstractBindingVec::iterator itEnd = binds.end();
+
+ for (; it != itEnd && (*it)->canBind(); ++it)
+ {
+ (*it)->bind(pos);
+ pos += (*it)->numOfColumnsHandled();
+ }
+ }
+
+ _stmt.bindParams(_binder.getBindArray(), _binder.size());
+
+ _stmt.execute();
+
+ _hasNext = NEXT_DONTKNOW;
+}
+
+
+AbstractExtractor& MySQLStatementImpl::extractor()
+{
+ return _extractor;
+}
+
+
+AbstractBinder& MySQLStatementImpl::binder()
+{
+ return _binder;
+}
+
+
+} } } // namespace Poco::Data::MySQL
diff --git a/Data/MySQL/src/ResultMetadata.cpp b/Data/MySQL/src/ResultMetadata.cpp
new file mode 100644
index 000000000..33cd3ad8f
--- /dev/null
+++ b/Data/MySQL/src/ResultMetadata.cpp
@@ -0,0 +1,259 @@
+//
+// MySQLException.cpp
+//
+// $Id: //poco/1.3/Data/MySQL/src/ResultMetadata.cpp#1 $
+//
+// Library: Data
+// Package: MySQL
+// Module: ResultMetadata
+//
+// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// Permission is hereby granted, free of charge, to any person or organization
+// obtaining a copy of the software and accompanying documentation covered by
+// this license (the "Software") to use, reproduce, display, distribute,
+// execute, and transmit the Software, and to prepare derivative works of the
+// Software, and to permit third-parties to whom the Software is furnished to
+// do so, all subject to the following:
+//
+// The copyright notices in the Software and this entire statement, including
+// the above license grant, this restriction and the following disclaimer,
+// must be included in all copies of the Software, in whole or in part, and
+// all derivative works of the Software, unless such copies or derivative
+// works are solely in the form of machine-executable object code generated by
+// a source language processor.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+
+
+#include "Poco/Data/MySQL/ResultMetadata.h"
+#include "Poco/Data/MySQL/MySQLException.h"
+
+namespace
+{
+ class ResultMetadataHandle
+ /// Simple exception-safe wrapper
+ {
+ public:
+
+ explicit ResultMetadataHandle(MYSQL_STMT* stmt)
+ {
+ h = mysql_stmt_result_metadata(stmt);
+ }
+
+ ~ResultMetadataHandle()
+ {
+ if (h)
+ {
+ mysql_free_result(h);
+ }
+ }
+
+ operator MYSQL_RES* ()
+ {
+ return h;
+ }
+
+ private:
+
+ MYSQL_RES* h;
+ };
+
+ size_t fieldSize(const MYSQL_FIELD& field)
+ /// Convert field MySQL-type and field MySQL-length to actual field length
+ {
+ switch (field.type)
+ {
+ case MYSQL_TYPE_TINY: return sizeof(char);
+ case MYSQL_TYPE_SHORT: return sizeof(short);
+ case MYSQL_TYPE_LONG: return sizeof(Poco::Int32);
+ case MYSQL_TYPE_FLOAT: return sizeof(float);
+ case MYSQL_TYPE_DOUBLE: return sizeof(double);
+ case MYSQL_TYPE_LONGLONG: return sizeof(Poco::Int64);
+
+ case MYSQL_TYPE_DECIMAL:
+ case MYSQL_TYPE_NEWDECIMAL:
+ case MYSQL_TYPE_STRING:
+ case MYSQL_TYPE_VAR_STRING:
+ case MYSQL_TYPE_TINY_BLOB:
+ case MYSQL_TYPE_MEDIUM_BLOB:
+ case MYSQL_TYPE_LONG_BLOB:
+ case MYSQL_TYPE_BLOB:
+ case MYSQL_TYPE_NULL:
+ case MYSQL_TYPE_TIMESTAMP:
+ case MYSQL_TYPE_INT24:
+ case MYSQL_TYPE_DATE:
+ case MYSQL_TYPE_TIME:
+ case MYSQL_TYPE_DATETIME:
+ case MYSQL_TYPE_YEAR:
+ case MYSQL_TYPE_NEWDATE:
+ case MYSQL_TYPE_VARCHAR:
+ case MYSQL_TYPE_BIT:
+ case MYSQL_TYPE_ENUM:
+ case MYSQL_TYPE_SET:
+ case MYSQL_TYPE_GEOMETRY:
+ default:
+ return field.length;
+ }
+
+ throw Poco::Data::MySQL::StatementException("unknown field type");
+ }
+
+ Poco::Data::MetaColumn::ColumnDataType fieldType(const MYSQL_FIELD& field)
+ /// Convert field MySQL-type to Poco-type
+ {
+ bool unsig = ((field.flags & UNSIGNED_FLAG) == UNSIGNED_FLAG);
+
+ switch (field.type)
+ {
+ case MYSQL_TYPE_TINY:
+ if (unsig) return Poco::Data::MetaColumn::FDT_UINT8;
+ return Poco::Data::MetaColumn::FDT_INT8;
+
+ case MYSQL_TYPE_SHORT:
+ if (unsig) return Poco::Data::MetaColumn::FDT_UINT16;
+ return Poco::Data::MetaColumn::FDT_INT16;
+
+ case MYSQL_TYPE_LONG:
+ if (unsig) return Poco::Data::MetaColumn::FDT_UINT32;
+ return Poco::Data::MetaColumn::FDT_INT32;
+
+ case MYSQL_TYPE_FLOAT:
+ return Poco::Data::MetaColumn::FDT_FLOAT;
+
+ case MYSQL_TYPE_DOUBLE:
+ return Poco::Data::MetaColumn::FDT_DOUBLE;
+
+ case MYSQL_TYPE_LONGLONG:
+ if (unsig) return Poco::Data::MetaColumn::FDT_UINT64;
+ return Poco::Data::MetaColumn::FDT_INT64;
+
+ case MYSQL_TYPE_STRING:
+ case MYSQL_TYPE_VAR_STRING:
+ return Poco::Data::MetaColumn::FDT_STRING;
+
+ case MYSQL_TYPE_TINY_BLOB:
+ case MYSQL_TYPE_MEDIUM_BLOB:
+ case MYSQL_TYPE_LONG_BLOB:
+ case MYSQL_TYPE_BLOB:
+ return Poco::Data::MetaColumn::FDT_BLOB;
+
+ case MYSQL_TYPE_DECIMAL:
+ case MYSQL_TYPE_NEWDECIMAL:
+ case MYSQL_TYPE_NULL:
+ case MYSQL_TYPE_TIMESTAMP:
+ case MYSQL_TYPE_INT24:
+ case MYSQL_TYPE_DATE:
+ case MYSQL_TYPE_TIME:
+ case MYSQL_TYPE_DATETIME:
+ case MYSQL_TYPE_YEAR:
+ case MYSQL_TYPE_NEWDATE:
+ case MYSQL_TYPE_VARCHAR:
+ case MYSQL_TYPE_BIT:
+ case MYSQL_TYPE_ENUM:
+ case MYSQL_TYPE_SET:
+ case MYSQL_TYPE_GEOMETRY:
+ default:
+ return Poco::Data::MetaColumn::FDT_UNKNOWN;
+ }
+ }
+}
+
+
+namespace Poco {
+namespace Data {
+namespace MySQL {
+
+void ResultMetadata::reset()
+{
+ _columns.resize(0);
+ _row.resize(0);
+ _buffer.resize(0);
+ _lengths.resize(0);
+}
+
+void ResultMetadata::init(MYSQL_STMT* stmt)
+{
+ ResultMetadataHandle h(stmt);
+
+ if (!h)
+ {
+ // all right, it is normal
+ // querys such an "INSERT INTO" just does not have result at all
+ reset();
+ return;
+ }
+
+ size_t count = mysql_num_fields(h);
+ MYSQL_FIELD* fields = mysql_fetch_fields(h);
+
+ size_t commonSize = 0;
+ _columns.reserve(count);
+
+ {for (size_t i = 0; i < count; i++)
+ {
+ _columns.push_back(MetaColumn(
+ i, // position
+ fields[i].name, // name
+ fieldType(fields[i]), // type
+ fieldSize(fields[i]), // length
+ 0, // TODO: precision (Now I dont know how to get it)
+ !IS_NOT_NULL(fields[i].flags) // nullable
+ ));
+
+ commonSize += _columns[i].length();
+ }}
+
+ _buffer.resize(commonSize);
+ _row.resize(count);
+ _lengths.resize(count);
+
+ size_t offset = 0;
+
+ {for (size_t i = 0; i < count; i++)
+ {
+ memset(&_row[i], 0, sizeof(MYSQL_BIND));
+
+ _row[i].buffer_type = fields[i].type;
+ _row[i].buffer_length = static_cast(_columns[i].length());
+ _row[i].buffer = &_buffer[0] + offset;
+ _row[i].length = &_lengths[i];
+
+ offset += _row[i].buffer_length;
+ }}
+}
+
+Poco::UInt32 ResultMetadata::columnsReturned() const
+{
+ return static_cast(_columns.size());
+}
+
+const MetaColumn& ResultMetadata::metaColumn(Poco::UInt32 pos) const
+{
+ return _columns[pos];
+}
+
+MYSQL_BIND* ResultMetadata::row()
+{
+ return &_row[0];
+}
+
+size_t ResultMetadata::length(size_t pos)
+{
+ return _lengths[pos];
+}
+
+const char* ResultMetadata::rawData(size_t pos)
+{
+ return reinterpret_cast(_row[pos].buffer);
+}
+
+}}}
diff --git a/Data/MySQL/src/SessionHandle.cpp b/Data/MySQL/src/SessionHandle.cpp
new file mode 100644
index 000000000..d6778e42c
--- /dev/null
+++ b/Data/MySQL/src/SessionHandle.cpp
@@ -0,0 +1,119 @@
+//
+// SesssionHandle.cpp
+//
+// $Id: //poco/1.3/Data/MySQL/src/SessionHandle.cpp#1 $
+//
+// Library: Data
+// Package: MySQL
+// Module: SessionHandle
+//
+// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// Permission is hereby granted, free of charge, to any person or organization
+// obtaining a copy of the software and accompanying documentation covered by
+// this license (the "Software") to use, reproduce, display, distribute,
+// execute, and transmit the Software, and to prepare derivative works of the
+// Software, and to permit third-parties to whom the Software is furnished to
+// do so, all subject to the following:
+//
+// The copyright notices in the Software and this entire statement, including
+// the above license grant, this restriction and the following disclaimer,
+// must be included in all copies of the Software, in whole or in part, and
+// all derivative works of the Software, unless such copies or derivative
+// works are solely in the form of machine-executable object code generated by
+// a source language processor.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+
+
+#include "Poco/Data/MySQL/SessionHandle.h"
+
+
+namespace Poco {
+namespace Data {
+namespace MySQL {
+
+
+SessionHandle::SessionHandle(MYSQL* mysql)
+{
+ h = mysql_init(mysql);
+
+ if (!h)
+ {
+ throw ConnectionException("mysql_init error");
+ }
+}
+
+
+SessionHandle::~SessionHandle()
+{
+ close();
+}
+
+
+void SessionHandle::options(mysql_option opt)
+{
+ int res = mysql_options(h, opt, 0);
+
+ if (res != 0)
+ {
+ throw ConnectionException("mysql_options error", h);
+ }
+}
+
+
+void SessionHandle::options(mysql_option opt, bool b)
+{
+ my_bool tmp = b;
+ int res = mysql_options(h, opt, &tmp);
+
+ if (res != 0)
+ {
+ throw ConnectionException("mysql_options error", h);
+ }
+}
+
+
+void SessionHandle::connect(const char* host, const char* user, const char* password, const char* db, unsigned int port)
+{
+ if (!mysql_real_connect(h, host, user, password, db, port, 0, 0))
+ {
+ throw ConnectionException("create session: mysql_real_connect error", h);
+ }
+}
+
+
+void SessionHandle::close()
+{
+ if (h)
+ {
+ mysql_close(h);
+ h = 0;
+ }
+}
+
+
+void SessionHandle::query(const char* str)
+{
+ int res = mysql_real_query(h, str, static_cast(strlen(str)));
+
+ if (res != 0)
+ {
+ std::string msg;
+ msg += "mysql_real_query('";
+ msg += str;
+ msg += "') error";
+ throw ConnectionException(msg, h);
+ }
+}
+
+
+}}} // Poco::Data::MySQL
diff --git a/Data/MySQL/src/SessionImpl.cpp b/Data/MySQL/src/SessionImpl.cpp
new file mode 100644
index 000000000..ece215895
--- /dev/null
+++ b/Data/MySQL/src/SessionImpl.cpp
@@ -0,0 +1,232 @@
+//
+// MySQLException.cpp
+//
+// $Id: //poco/1.3/Data/MySQL/src/SessionImpl.cpp#1 $
+//
+// Library: Data
+// Package: MySQL
+// Module: SessionImpl
+//
+// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// Permission is hereby granted, free of charge, to any person or organization
+// obtaining a copy of the software and accompanying documentation covered by
+// this license (the "Software") to use, reproduce, display, distribute,
+// execute, and transmit the Software, and to prepare derivative works of the
+// Software, and to permit third-parties to whom the Software is furnished to
+// do so, all subject to the following:
+//
+// The copyright notices in the Software and this entire statement, including
+// the above license grant, this restriction and the following disclaimer,
+// must be included in all copies of the Software, in whole or in part, and
+// all derivative works of the Software, unless such copies or derivative
+// works are solely in the form of machine-executable object code generated by
+// a source language processor.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+
+
+#include "Poco/Data/MySQL/SessionImpl.h"
+#include "Poco/Data/MySQL/MySQLStatementImpl.h"
+
+
+namespace
+{
+ std::string copyStripped(std::string::const_iterator from, std::string::const_iterator to)
+ {
+ // skip leading spaces
+ while ((from != to) && isspace(*from)) from++;
+ // skip trailing spaces
+ while ((from != to) && isspace(*(to - 1))) to--;
+
+ return std::string(from, to);
+ }
+}
+
+
+namespace Poco {
+namespace Data {
+namespace MySQL {
+
+
+SessionImpl::SessionImpl(const std::string& connectionString) : _mysql(0), _connected(false), _inTransaction(0)
+{
+ addProperty("insertId",
+ &SessionImpl::setInsertId,
+ &SessionImpl::getInsertId);
+
+ std::map options;
+
+ // Default values
+ options["host"] = "localhost";
+ options["port"] = "3306";
+ options["user"] = "";
+ options["password"] = "";
+ options["db"] = "";
+ options["compress"] = "";
+ options["auto-reconnect"] = "";
+
+ //
+ // Parse string
+ //
+
+ for (std::string::const_iterator start = connectionString.begin();;)
+ {
+ // find next ';'
+ std::string::const_iterator finish = std::find(start, connectionString.end(), ';');
+
+ // find '='
+ std::string::const_iterator middle = std::find(start, finish, '=');
+
+ if (middle == finish)
+ {
+ throw MySQLException("create session: bad connection string format, can not find '='");
+ }
+
+ // Parse name and value, skip all spaces
+ options[copyStripped(start, middle)] = copyStripped(middle + 1, finish);
+
+ if (finish == connectionString.end())
+ {
+ // end of parse
+ break;
+ }
+
+ // move start position after ';'
+ start = finish + 1;
+ }
+
+ //
+ // Checking
+ //
+
+ if (options["user"] == "")
+ {
+ throw MySQLException("create session: specify user name");
+ }
+
+ if (options["db"] == "")
+ {
+ throw MySQLException("create session: specify database");
+ }
+
+ if (atoi(options["port"].c_str()) == 0)
+ {
+ throw MySQLException("create session: specify correct port (numeric in decimal notation)");
+ }
+
+ //
+ // Options
+ //
+
+ if (options["compress"] == "true")
+ {
+ _mysql.options(MYSQL_OPT_COMPRESS);
+ }
+ else if (options["compress"] == "false")
+ {
+ // do nothing
+ }
+ else if (options["compress"] != "")
+ {
+ throw MySQLException("create session: specify correct compress option (true or false) or skip it");
+ }
+
+ if (options["auto-reconnect"] == "true")
+ {
+ _mysql.options(MYSQL_OPT_RECONNECT, true);
+ }
+ else if (options["auto-reconnect"] == "false")
+ {
+ _mysql.options(MYSQL_OPT_RECONNECT, false);
+ }
+ else if (options["auto-reconnect"] != "")
+ {
+ throw MySQLException("create session: specify correct auto-reconnect option (true or false) or skip it");
+ }
+
+ //
+ // Real connect
+ //
+
+ _mysql.connect(
+ options["host"].c_str(),
+ options["user"].c_str(),
+ options["password"].c_str(),
+ options["db"].c_str(),
+ atoi(options["port"].c_str()));
+
+ _connected = true;
+}
+
+
+SessionImpl::~SessionImpl()
+{
+ close();
+}
+
+
+Poco::Data::StatementImpl* SessionImpl::createStatementImpl()
+{
+ return new MySQLStatementImpl(_mysql);
+}
+
+
+void SessionImpl::begin()
+{
+ _mysql.query("START TRANSACTION");
+ _inTransaction++;
+}
+
+
+void SessionImpl::commit()
+{
+ _mysql.query("COMMIT");
+ _inTransaction--;
+
+ // ?
+ // mysql_commit(fMysql);
+}
+
+
+void SessionImpl::rollback()
+{
+ _mysql.query("ROLLBACK");
+ _inTransaction--;
+
+ // ?
+ // mysql_commit(fMysql);
+}
+
+
+void SessionImpl::close()
+{
+ if (_connected)
+ {
+ _mysql.close();
+ _connected = false;
+ }
+}
+
+
+bool SessionImpl::isConnected()
+{
+ return _connected;
+}
+
+
+bool SessionImpl::isTransaction()
+{
+ return (_inTransaction > 0);
+}
+
+
+}}}
diff --git a/Data/MySQL/src/StatementExecutor.cpp b/Data/MySQL/src/StatementExecutor.cpp
new file mode 100644
index 000000000..9a13b2887
--- /dev/null
+++ b/Data/MySQL/src/StatementExecutor.cpp
@@ -0,0 +1,195 @@
+//
+// StatementExecutor.cpp
+//
+// $Id: //poco/1.3/Data/MySQL/src/StatementExecutor.cpp#1 $
+//
+// Library: Data
+// Package: MySQL
+// Module: StatementExecutor
+//
+// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// Permission is hereby granted, free of charge, to any person or organization
+// obtaining a copy of the software and accompanying documentation covered by
+// this license (the "Software") to use, reproduce, display, distribute,
+// execute, and transmit the Software, and to prepare derivative works of the
+// Software, and to permit third-parties to whom the Software is furnished to
+// do so, all subject to the following:
+//
+// The copyright notices in the Software and this entire statement, including
+// the above license grant, this restriction and the following disclaimer,
+// must be included in all copies of the Software, in whole or in part, and
+// all derivative works of the Software, unless such copies or derivative
+// works are solely in the form of machine-executable object code generated by
+// a source language processor.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+
+
+#include
+#include "Poco/Data/MySQL/StatementExecutor.h"
+
+
+namespace Poco {
+namespace Data {
+namespace MySQL {
+
+
+StatementExecutor::StatementExecutor(MYSQL* mysql)
+{
+ h = mysql_stmt_init(mysql);
+
+ if (!h)
+ {
+ throw StatementException("mysql_stmt_init error");
+ }
+
+ _state = STMT_INITED;
+}
+
+
+StatementExecutor::~StatementExecutor()
+{
+ mysql_stmt_close(h);
+}
+
+
+int StatementExecutor::state() const
+{
+ return _state;
+}
+
+
+void StatementExecutor::prepare(const std::string& query)
+{
+ if (_state >= STMT_COMPILED)
+ {
+ throw StatementException("Satement is already compiled");
+ }
+
+ // compile
+ int res = mysql_stmt_prepare(h, query.c_str(), static_cast(query.length()));
+
+ if (res != 0)
+ {
+ throw StatementException("mysql_stmt_prepare error", h, query);
+ }
+
+ _query = query;
+ _state = STMT_COMPILED;
+}
+
+
+void StatementExecutor::bindParams(MYSQL_BIND* params, size_t count)
+{
+ if (_state < STMT_COMPILED)
+ {
+ throw StatementException("Satement is not compiled yet");
+ }
+
+ if (count != mysql_stmt_param_count(h))
+ {
+ throw StatementException("wrong bind parameters count", 0, _query);
+ }
+
+ if (count == 0)
+ {
+ return;
+ }
+
+ int res = mysql_stmt_bind_param(h, params);
+
+ if (res != 0)
+ {
+ throw StatementException("mysql_stmt_bind_param() error ", h, _query);
+ }
+}
+
+
+void StatementExecutor::bindResult(MYSQL_BIND* result)
+{
+ if (_state < STMT_COMPILED)
+ {
+ throw StatementException("Satement is not compiled yet");
+ }
+
+ int res = mysql_stmt_bind_result(h, result);
+
+ if (res != 0)
+ {
+ throw StatementException("mysql_stmt_bind_result error ", h, _query);
+ }
+}
+
+
+void StatementExecutor::execute()
+{
+ if (_state < STMT_COMPILED)
+ {
+ throw StatementException("Satement is not compiled yet");
+ }
+
+ int res = mysql_stmt_execute(h);
+
+ if (res != 0)
+ {
+ throw StatementException("mysql_stmt_execute error", h, _query);
+ }
+
+ _state = STMT_EXECUTED;
+}
+
+
+bool StatementExecutor::fetch()
+{
+ if (_state < STMT_EXECUTED)
+ {
+ throw StatementException("Satement is not executed yet");
+ }
+
+ int res = mysql_stmt_fetch(h);
+
+ if ((res != 0) && (res != MYSQL_NO_DATA))
+ {
+ throw StatementException("mysql_stmt_fetch error", h, _query);
+ }
+
+ return (res == 0);
+}
+
+
+bool StatementExecutor::fetchColumn(size_t n, MYSQL_BIND *bind)
+{
+ if (_state < STMT_EXECUTED)
+ {
+ throw StatementException("Satement is not executed yet");
+ }
+
+ int res = mysql_stmt_fetch_column(h, bind, static_cast(n), 0);
+
+ if ((res != 0) && (res != MYSQL_NO_DATA))
+ {
+ std::string msg;
+ msg += "mysql_stmt_fetch_column(";
+
+ char buff[30];
+ sprintf(buff, "%d", n);
+ msg += buff;
+
+ msg += ") error";
+ throw StatementException(msg, h, _query);
+ }
+
+ return (res == 0);
+}
+
+
+}}}
diff --git a/Data/MySQL/testsuite/Makefile b/Data/MySQL/testsuite/Makefile
new file mode 100644
index 000000000..e6e16465a
--- /dev/null
+++ b/Data/MySQL/testsuite/Makefile
@@ -0,0 +1,21 @@
+#
+# Makefile
+#
+# $Id: //poco/1.3/Data/MySQL/testsuite/Makefile#1 $
+#
+# Makefile for Poco MySQL testsuite
+#
+
+include $(POCO_BASE)/build/rules/global
+
+INCLUDE += -I./../include -I/usr/local/include/mysql
+SYSLIBS += -L/usr/local/lib/mysql -lmysqlclient -lz
+
+objects = MySQLTestSuite Driver \
+ MySQLTest SQLExecutor
+
+target = testrunner
+target_version = 1
+target_libs = PocoMySQL PocoData PocoFoundation CppUnit
+
+include $(POCO_BASE)/build/rules/exec
diff --git a/Data/MySQL/testsuite/TestSuite_VS80.vcproj b/Data/MySQL/testsuite/TestSuite_VS80.vcproj
new file mode 100644
index 000000000..bd99269b6
--- /dev/null
+++ b/Data/MySQL/testsuite/TestSuite_VS80.vcproj
@@ -0,0 +1,259 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Data/MySQL/testsuite/src/Driver.cpp b/Data/MySQL/testsuite/src/Driver.cpp
new file mode 100644
index 000000000..c96881a73
--- /dev/null
+++ b/Data/MySQL/testsuite/src/Driver.cpp
@@ -0,0 +1,39 @@
+//
+// Driver.cpp
+//
+// $Id: //poco/1.3/Data/ODBC/testsuite/src/Driver.cpp#2 $
+//
+// Console-based test driver for Poco SQLite.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// Permission is hereby granted, free of charge, to any person or organization
+// obtaining a copy of the software and accompanying documentation covered by
+// this license (the "Software") to use, reproduce, display, distribute,
+// execute, and transmit the Software, and to prepare derivative works of the
+// Software, and to permit third-parties to whom the Software is furnished to
+// do so, all subject to the following:
+//
+// The copyright notices in the Software and this entire statement, including
+// the above license grant, this restriction and the following disclaimer,
+// must be included in all copies of the Software, in whole or in part, and
+// all derivative works of the Software, unless such copies or derivative
+// works are solely in the form of machine-executable object code generated by
+// a source language processor.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+
+
+#include "CppUnit/TestRunner.h"
+#include "MySQLTestSuite.h"
+
+
+CppUnitMain(MySQLTestSuite)
diff --git a/Data/MySQL/testsuite/src/MySQLTest.cpp b/Data/MySQL/testsuite/src/MySQLTest.cpp
new file mode 100644
index 000000000..b7a08b7d0
--- /dev/null
+++ b/Data/MySQL/testsuite/src/MySQLTest.cpp
@@ -0,0 +1,627 @@
+//
+// MySQLTest.cpp
+//
+// $Id: //poco/1.3/Data/MySQL/testsuite/src/MySQLTest.cpp#4 $
+//
+// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// Permission is hereby granted, free of charge, to any person or organization
+// obtaining a copy of the software and accompanying documentation covered by
+// this license (the "Software") to use, reproduce, display, distribute,
+// execute, and transmit the Software, and to prepare derivative works of the
+// Software, and to permit third-parties to whom the Software is furnished to
+// do so, all subject to the following:
+//
+// The copyright notices in the Software and this entire statement, including
+// the above license grant, this restriction and the following disclaimer,
+// must be included in all copies of the Software, in whole or in part, and
+// all derivative works of the Software, unless such copies or derivative
+// works are solely in the form of machine-executable object code generated by
+// a source language processor.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+
+
+#include "MySQLTest.h"
+#include "CppUnit/TestCaller.h"
+#include "CppUnit/TestSuite.h"
+#include "Poco/String.h"
+#include "Poco/Format.h"
+#include "Poco/Exception.h"
+#include "Poco/Data/Common.h"
+#include "Poco/Data/BLOB.h"
+#include "Poco/Data/StatementImpl.h"
+#include "Poco/Data/MySQL/Connector.h"
+#include "Poco/Data/MySQL/MySQLException.h"
+#include
+
+using namespace Poco::Data;
+using Poco::Data::MySQL::ConnectionException;
+using Poco::Data::MySQL::StatementException;
+using Poco::format;
+using Poco::NotFoundException;
+
+Poco::SharedPtr MySQLTest::_pSession = 0;
+Poco::SharedPtr MySQLTest::_pExecutor = 0;
+
+// Parameters for barebone-test
+#define MYSQL_USER "root"
+#define MYSQL_PWD ""
+#define MYSQL_HOST "localhost"
+#define MYSQL_PORT 3306
+#define MYSQL_DB "test"
+
+// Connection string to POCO
+std::string MySQLTest::_dbConnString = "user=root;password=;db=test;compress=true;auto-reconnect=true";
+
+
+MySQLTest::MySQLTest(const std::string& name):
+ CppUnit::TestCase(name)
+{
+ static bool beenHere = false;
+ MySQL::Connector::registerConnector();
+
+ if (!beenHere)
+ {
+ try
+ {
+ _pSession = new Session(SessionFactory::instance().create(MySQL::Connector::KEY, _dbConnString));
+ }catch (ConnectionException& ex)
+ {
+ std::cout << "!!! WARNING: Connection failed. MySQL tests will fail !!!" << std::endl;
+ std::cout << ex.displayText() << std::endl;
+ }
+
+ if (_pSession && _pSession->isConnected())
+ std::cout << "*** Connected to " << '(' << _dbConnString << ')' << std::endl;
+ if (!_pExecutor) _pExecutor = new SQLExecutor("MySQL SQL Executor", _pSession);
+ }
+
+ beenHere = true;
+}
+
+
+MySQLTest::~MySQLTest()
+{
+ MySQL::Connector::unregisterConnector();
+}
+
+
+void MySQLTest::testBareboneMySQL()
+{
+ if (!_pSession) fail ("Test not available.");
+
+ std::string tableCreateString = "CREATE TABLE Test "
+ "(First VARCHAR(30),"
+ "Second VARCHAR(30),"
+ "Third VARBINARY(30),"
+ "Fourth INTEGER,"
+ "Fifth FLOAT)";
+
+ _pExecutor->bareboneMySQLTest(MYSQL_HOST, MYSQL_USER, MYSQL_PWD, MYSQL_DB, MYSQL_PORT, tableCreateString.c_str());
+}
+
+
+void MySQLTest::testSimpleAccess()
+{
+ if (!_pSession) fail ("Test not available.");
+
+ recreatePersonTable();
+ _pExecutor->simpleAccess();
+}
+
+
+void MySQLTest::testComplexType()
+{
+ if (!_pSession) fail ("Test not available.");
+
+ recreatePersonTable();
+ _pExecutor->complexType();
+}
+
+
+void MySQLTest::testSimpleAccessVector()
+{
+ if (!_pSession) fail ("Test not available.");
+
+ recreatePersonTable();
+ _pExecutor->simpleAccessVector();
+}
+
+
+void MySQLTest::testComplexTypeVector()
+{
+ if (!_pSession) fail ("Test not available.");
+
+ recreatePersonTable();
+ _pExecutor->complexTypeVector();
+}
+
+
+void MySQLTest::testInsertVector()
+{
+ if (!_pSession) fail ("Test not available.");
+
+ recreateStringsTable();
+ _pExecutor->insertVector();
+}
+
+
+void MySQLTest::testInsertEmptyVector()
+{
+ if (!_pSession) fail ("Test not available.");
+
+ recreateStringsTable();
+ _pExecutor->insertEmptyVector();
+}
+
+
+void MySQLTest::testInsertSingleBulk()
+{
+ if (!_pSession) fail ("Test not available.");
+
+ recreateIntsTable();
+ _pExecutor->insertSingleBulk();
+}
+
+
+void MySQLTest::testInsertSingleBulkVec()
+{
+ if (!_pSession) fail ("Test not available.");
+
+ recreateIntsTable();
+ _pExecutor->insertSingleBulkVec();
+}
+
+
+void MySQLTest::testLimit()
+{
+ if (!_pSession) fail ("Test not available.");
+
+ recreateIntsTable();
+ _pExecutor->limits();
+}
+
+
+void MySQLTest::testLimitZero()
+{
+ if (!_pSession) fail ("Test not available.");
+
+ recreateIntsTable();
+ _pExecutor->limitZero();
+}
+
+
+void MySQLTest::testLimitOnce()
+{
+ if (!_pSession) fail ("Test not available.");
+
+ recreateIntsTable();
+ _pExecutor->limitOnce();
+
+}
+
+
+void MySQLTest::testLimitPrepare()
+{
+ if (!_pSession) fail ("Test not available.");
+
+ recreateIntsTable();
+ _pExecutor->limitPrepare();
+}
+
+
+
+void MySQLTest::testPrepare()
+{
+ if (!_pSession) fail ("Test not available.");
+
+ recreateIntsTable();
+ _pExecutor->prepare();
+}
+
+
+void MySQLTest::testSetSimple()
+{
+ if (!_pSession) fail ("Test not available.");
+
+ recreatePersonTable();
+ _pExecutor->setSimple();
+}
+
+
+void MySQLTest::testSetComplex()
+{
+ if (!_pSession) fail ("Test not available.");
+
+ recreatePersonTable();
+ _pExecutor->setComplex();
+}
+
+
+void MySQLTest::testSetComplexUnique()
+{
+ if (!_pSession) fail ("Test not available.");
+
+ recreatePersonTable();
+ _pExecutor->setComplexUnique();
+}
+
+void MySQLTest::testMultiSetSimple()
+{
+ if (!_pSession) fail ("Test not available.");
+
+ recreatePersonTable();
+ _pExecutor->multiSetSimple();
+}
+
+
+void MySQLTest::testMultiSetComplex()
+{
+ if (!_pSession) fail ("Test not available.");
+
+ recreatePersonTable();
+ _pExecutor->multiSetComplex();
+}
+
+
+void MySQLTest::testMapComplex()
+{
+ if (!_pSession) fail ("Test not available.");
+
+ recreatePersonTable();
+ _pExecutor->mapComplex();
+}
+
+
+void MySQLTest::testMapComplexUnique()
+{
+ if (!_pSession) fail ("Test not available.");
+
+ recreatePersonTable();
+ _pExecutor->mapComplexUnique();
+}
+
+
+void MySQLTest::testMultiMapComplex()
+{
+ if (!_pSession) fail ("Test not available.");
+
+ recreatePersonTable();
+ _pExecutor->multiMapComplex();
+}
+
+
+void MySQLTest::testSelectIntoSingle()
+{
+ if (!_pSession) fail ("Test not available.");
+
+ recreatePersonTable();
+ _pExecutor->selectIntoSingle();
+}
+
+
+void MySQLTest::testSelectIntoSingleStep()
+{
+ if (!_pSession) fail ("Test not available.");
+
+ recreatePersonTable();
+ _pExecutor->selectIntoSingleStep();
+}
+
+
+void MySQLTest::testSelectIntoSingleFail()
+{
+ if (!_pSession) fail ("Test not available.");
+
+ recreatePersonTable();
+ _pExecutor->selectIntoSingleFail();
+}
+
+
+void MySQLTest::testLowerLimitOk()
+{
+ if (!_pSession) fail ("Test not available.");
+
+ recreatePersonTable();
+ _pExecutor->lowerLimitOk();
+}
+
+
+void MySQLTest::testSingleSelect()
+{
+ if (!_pSession) fail ("Test not available.");
+
+ recreatePersonTable();
+ _pExecutor->singleSelect();
+}
+
+
+void MySQLTest::testLowerLimitFail()
+{
+ if (!_pSession) fail ("Test not available.");
+
+ recreatePersonTable();
+ _pExecutor->lowerLimitFail();
+}
+
+
+void MySQLTest::testCombinedLimits()
+{
+ if (!_pSession) fail ("Test not available.");
+
+ recreatePersonTable();
+ _pExecutor->combinedLimits();
+}
+
+
+
+void MySQLTest::testRange()
+{
+ if (!_pSession) fail ("Test not available.");
+
+ recreatePersonTable();
+ _pExecutor->ranges();
+}
+
+
+void MySQLTest::testCombinedIllegalLimits()
+{
+ if (!_pSession) fail ("Test not available.");
+
+ recreatePersonTable();
+ _pExecutor->combinedIllegalLimits();
+}
+
+
+
+void MySQLTest::testIllegalRange()
+{
+ if (!_pSession) fail ("Test not available.");
+
+ recreatePersonTable();
+ _pExecutor->illegalRange();
+}
+
+
+void MySQLTest::testEmptyDB()
+{
+ if (!_pSession) fail ("Test not available.");
+
+ recreatePersonTable();
+ _pExecutor->emptyDB();
+}
+
+
+void MySQLTest::testBLOB()
+{
+ if (!_pSession) fail ("Test not available.");
+
+ const std::size_t maxFldSize = 65534;
+ _pSession->setProperty("maxFieldSize", Poco::Any(maxFldSize-1));
+ recreatePersonBLOBTable();
+
+ try
+ {
+ _pExecutor->blob(maxFldSize);
+ fail ("must fail");
+ }
+ catch (DataException&)
+ {
+ _pSession->setProperty("maxFieldSize", Poco::Any(maxFldSize));
+ }
+
+ recreatePersonBLOBTable();
+ _pExecutor->blob(maxFldSize);
+
+ recreatePersonBLOBTable();
+
+ try
+ {
+ _pExecutor->blob(maxFldSize+1);
+ fail ("must fail");
+ }
+ catch (DataException&) { }
+}
+
+
+void MySQLTest::testBLOBStmt()
+{
+ if (!_pSession) fail ("Test not available.");
+
+ recreatePersonBLOBTable();
+ _pExecutor->blobStmt();
+}
+
+
+void MySQLTest::testFloat()
+{
+ if (!_pSession) fail ("Test not available.");
+
+ recreateFloatsTable();
+ _pExecutor->floats();
+}
+
+
+void MySQLTest::testDouble()
+{
+ if (!_pSession) fail ("Test not available.");
+
+ recreateFloatsTable();
+ _pExecutor->doubles();
+}
+
+
+void MySQLTest::testTuple()
+{
+ if (!_pSession) fail ("Test not available.");
+
+ recreateTuplesTable();
+ _pExecutor->tuples();
+}
+
+
+void MySQLTest::testTupleVector()
+{
+ if (!_pSession) fail ("Test not available.");
+
+ recreateTuplesTable();
+ _pExecutor->tupleVector();
+}
+
+
+void MySQLTest::testInternalExtraction()
+{
+ if (!_pSession) fail ("Test not available.");
+
+ recreateVectorsTable();
+ _pExecutor->internalExtraction();
+}
+
+
+void MySQLTest::dropTable(const std::string& tableName)
+{
+ try
+ {
+ *_pSession << format("DROP TABLE %s", tableName), now;
+ }
+ catch (StatementException& )
+ {
+ //throw;
+ }
+}
+
+
+void MySQLTest::recreatePersonTable()
+{
+ dropTable("Person");
+ try { *_pSession << "CREATE TABLE Person (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), Age INTEGER)", now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail ("recreatePersonTable()"); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail ("recreatePersonTable()"); }
+}
+
+
+void MySQLTest::recreatePersonBLOBTable()
+{
+ dropTable("Person");
+ try { *_pSession << "CREATE TABLE Person (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), Image BLOB)", now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail ("recreatePersonBLOBTable()"); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail ("recreatePersonBLOBTable()"); }
+}
+
+
+void MySQLTest::recreateIntsTable()
+{
+ dropTable("Strings");
+ try { *_pSession << "CREATE TABLE Strings (str INTEGER)", now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail ("recreateIntsTable()"); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail ("recreateIntsTable()"); }
+}
+
+
+void MySQLTest::recreateStringsTable()
+{
+ dropTable("Strings");
+ try { *_pSession << "CREATE TABLE Strings (str VARCHAR(30))", now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail ("recreateStringsTable()"); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail ("recreateStringsTable()"); }
+}
+
+
+void MySQLTest::recreateFloatsTable()
+{
+ dropTable("Strings");
+ try { *_pSession << "CREATE TABLE Strings (str FLOAT)", now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail ("recreateFloatsTable()"); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail ("recreateFloatsTable()"); }
+}
+
+
+void MySQLTest::recreateTuplesTable()
+{
+ dropTable("Tuples");
+ try { *_pSession << "CREATE TABLE Tuples "
+ "(i0 INTEGER, i1 INTEGER, i2 INTEGER, i3 INTEGER, i4 INTEGER, i5 INTEGER, i6 INTEGER, "
+ "i7 INTEGER, i8 INTEGER, i9 INTEGER, i10 INTEGER, i11 INTEGER, i12 INTEGER, i13 INTEGER,"
+ "i14 INTEGER, i15 INTEGER, i16 INTEGER, i17 INTEGER, i18 INTEGER, i19 INTEGER)", now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail ("recreateTuplesTable()"); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail ("recreateTuplesTable()"); }
+}
+
+
+void MySQLTest::recreateVectorsTable()
+{
+ dropTable("Vectors");
+ try { *_pSession << "CREATE TABLE Vectors (i0 INTEGER, flt0 FLOAT, str0 VARCHAR(30))", now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail ("recreateVectorsTable()"); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail ("recreateVectorsTable()"); }
+}
+
+
+void MySQLTest::setUp()
+{
+}
+
+
+void MySQLTest::tearDown()
+{
+ dropTable("Person");
+ dropTable("Strings");
+}
+
+
+CppUnit::Test* MySQLTest::suite()
+{
+ CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("MySQLTest");
+
+ CppUnit_addTest(pSuite, MySQLTest, testBareboneMySQL);
+ CppUnit_addTest(pSuite, MySQLTest, testSimpleAccess);
+ CppUnit_addTest(pSuite, MySQLTest, testComplexType);
+ CppUnit_addTest(pSuite, MySQLTest, testSimpleAccessVector);
+ CppUnit_addTest(pSuite, MySQLTest, testComplexTypeVector);
+ CppUnit_addTest(pSuite, MySQLTest, testInsertVector);
+ CppUnit_addTest(pSuite, MySQLTest, testInsertEmptyVector);
+ CppUnit_addTest(pSuite, MySQLTest, testInsertSingleBulk);
+ CppUnit_addTest(pSuite, MySQLTest, testInsertSingleBulkVec);
+ CppUnit_addTest(pSuite, MySQLTest, testLimit);
+ CppUnit_addTest(pSuite, MySQLTest, testLimitOnce);
+ CppUnit_addTest(pSuite, MySQLTest, testLimitPrepare);
+ CppUnit_addTest(pSuite, MySQLTest, testLimitZero);
+ CppUnit_addTest(pSuite, MySQLTest, testPrepare);
+ CppUnit_addTest(pSuite, MySQLTest, testSetSimple);
+ CppUnit_addTest(pSuite, MySQLTest, testSetComplex);
+ CppUnit_addTest(pSuite, MySQLTest, testSetComplexUnique);
+ CppUnit_addTest(pSuite, MySQLTest, testMultiSetSimple);
+ CppUnit_addTest(pSuite, MySQLTest, testMultiSetComplex);
+ CppUnit_addTest(pSuite, MySQLTest, testMapComplex);
+ CppUnit_addTest(pSuite, MySQLTest, testMapComplexUnique);
+ CppUnit_addTest(pSuite, MySQLTest, testMultiMapComplex);
+ CppUnit_addTest(pSuite, MySQLTest, testSelectIntoSingle);
+ CppUnit_addTest(pSuite, MySQLTest, testSelectIntoSingleStep);
+ CppUnit_addTest(pSuite, MySQLTest, testSelectIntoSingleFail);
+ CppUnit_addTest(pSuite, MySQLTest, testLowerLimitOk);
+ CppUnit_addTest(pSuite, MySQLTest, testLowerLimitFail);
+ CppUnit_addTest(pSuite, MySQLTest, testCombinedLimits);
+ CppUnit_addTest(pSuite, MySQLTest, testCombinedIllegalLimits);
+ CppUnit_addTest(pSuite, MySQLTest, testRange);
+ CppUnit_addTest(pSuite, MySQLTest, testIllegalRange);
+ CppUnit_addTest(pSuite, MySQLTest, testSingleSelect);
+ CppUnit_addTest(pSuite, MySQLTest, testEmptyDB);
+ //CppUnit_addTest(pSuite, MySQLTest, testBLOB);
+ CppUnit_addTest(pSuite, MySQLTest, testBLOBStmt);
+ CppUnit_addTest(pSuite, MySQLTest, testFloat);
+ CppUnit_addTest(pSuite, MySQLTest, testDouble);
+ CppUnit_addTest(pSuite, MySQLTest, testTuple);
+ CppUnit_addTest(pSuite, MySQLTest, testTupleVector);
+ CppUnit_addTest(pSuite, MySQLTest, testInternalExtraction);
+
+ return pSuite;
+}
diff --git a/Data/MySQL/testsuite/src/MySQLTest.h b/Data/MySQL/testsuite/src/MySQLTest.h
new file mode 100644
index 000000000..bc0949b12
--- /dev/null
+++ b/Data/MySQL/testsuite/src/MySQLTest.h
@@ -0,0 +1,132 @@
+//
+// ODBCMySQLTest.h
+//
+// $Id: //poco/1.3/Data/MySQL/testsuite/src/ODBCMySQLTest.h#2 $
+//
+// Definition of the MySQLTest class.
+//
+// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// Permission is hereby granted, free of charge, to any person or organization
+// obtaining a copy of the software and accompanying documentation covered by
+// this license (the "Software") to use, reproduce, display, distribute,
+// execute, and transmit the Software, and to prepare derivative works of the
+// Software, and to permit third-parties to whom the Software is furnished to
+// do so, all subject to the following:
+//
+// The copyright notices in the Software and this entire statement, including
+// the above license grant, this restriction and the following disclaimer,
+// must be included in all copies of the Software, in whole or in part, and
+// all derivative works of the Software, unless such copies or derivative
+// works are solely in the form of machine-executable object code generated by
+// a source language processor.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+
+
+#ifndef MySQLTest_INCLUDED
+#define MySQLTest_INCLUDED
+
+
+#include "Poco/Data/MySQL/MySQL.h"
+#include "Poco/Data/Session.h"
+#include "Poco/SharedPtr.h"
+#include "CppUnit/TestCase.h"
+#include "SQLExecutor.h"
+
+
+class MySQLTest: public CppUnit::TestCase
+ /// MySQL test class
+ /// Tested:
+ ///
+ /// Driver | DB | OS
+ /// ----------------+---------------------------+------------------------------------------
+ /// 03.51.12.00 | MySQL 5.0.27-community-nt | MS Windows XP Professional x64 v.2003/SP1
+ ///
+
+{
+public:
+ MySQLTest(const std::string& name);
+ ~MySQLTest();
+
+ void testBareboneMySQL();
+
+ void testSimpleAccess();
+ void testComplexType();
+ void testSimpleAccessVector();
+ void testComplexTypeVector();
+ void testInsertVector();
+ void testInsertEmptyVector();
+
+ void testInsertSingleBulk();
+ void testInsertSingleBulkVec();
+
+ void testLimit();
+ void testLimitOnce();
+ void testLimitPrepare();
+ void testLimitZero();
+ void testPrepare();
+
+ void testSetSimple();
+ void testSetComplex();
+ void testSetComplexUnique();
+ void testMultiSetSimple();
+ void testMultiSetComplex();
+ void testMapComplex();
+ void testMapComplexUnique();
+ void testMultiMapComplex();
+ void testSelectIntoSingle();
+ void testSelectIntoSingleStep();
+ void testSelectIntoSingleFail();
+ void testLowerLimitOk();
+ void testLowerLimitFail();
+ void testCombinedLimits();
+ void testCombinedIllegalLimits();
+ void testRange();
+ void testIllegalRange();
+ void testSingleSelect();
+ void testEmptyDB();
+
+ void testBLOB();
+ void testBLOBStmt();
+
+ void testFloat();
+ void testDouble();
+
+ void testTuple();
+ void testTupleVector();
+
+ void testInternalExtraction();
+
+ void setUp();
+ void tearDown();
+
+ static CppUnit::Test* suite();
+
+private:
+
+ void dropTable(const std::string& tableName);
+ void recreatePersonTable();
+ void recreatePersonBLOBTable();
+ void recreateStringsTable();
+ void recreateIntsTable();
+ void recreateFloatsTable();
+ void recreateTuplesTable();
+ void recreateVectorsTable();
+
+ static std::string _dbConnString;
+ static Poco::SharedPtr _pSession;
+ static Poco::SharedPtr _pExecutor;
+ static const bool bindValues[8];
+};
+
+
+#endif // MySQLTest_INCLUDED
diff --git a/Data/MySQL/testsuite/src/MySQLTestSuite.cpp b/Data/MySQL/testsuite/src/MySQLTestSuite.cpp
new file mode 100644
index 000000000..f21dfd658
--- /dev/null
+++ b/Data/MySQL/testsuite/src/MySQLTestSuite.cpp
@@ -0,0 +1,41 @@
+//
+// ODBCTestSuite.cpp
+//
+// $Id: //poco/1.3/Data/ODBC/testsuite/src/ODBCTestSuite.cpp#2 $
+//
+// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// Permission is hereby granted, free of charge, to any person or organization
+// obtaining a copy of the software and accompanying documentation covered by
+// this license (the "Software") to use, reproduce, display, distribute,
+// execute, and transmit the Software, and to prepare derivative works of the
+// Software, and to permit third-parties to whom the Software is furnished to
+// do so, all subject to the following:
+//
+// The copyright notices in the Software and this entire statement, including
+// the above license grant, this restriction and the following disclaimer,
+// must be included in all copies of the Software, in whole or in part, and
+// all derivative works of the Software, unless such copies or derivative
+// works are solely in the form of machine-executable object code generated by
+// a source language processor.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+
+
+#include "MySQLTestSuite.h"
+#include "MySQLTest.h"
+
+CppUnit::Test* MySQLTestSuite::suite()
+{
+ CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("MySQLTestSuite");
+ pSuite->addTest(MySQLTest::suite());
+ return pSuite;
+}
diff --git a/Data/MySQL/testsuite/src/MySQLTestSuite.h b/Data/MySQL/testsuite/src/MySQLTestSuite.h
new file mode 100644
index 000000000..2676006d9
--- /dev/null
+++ b/Data/MySQL/testsuite/src/MySQLTestSuite.h
@@ -0,0 +1,49 @@
+//
+// ODBCTestSuite.h
+//
+// $Id: //poco/1.3/Data/ODBC/testsuite/src/ODBCTestSuite.h#2 $
+//
+// Definition of the ODBCTestSuite class.
+//
+// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// Permission is hereby granted, free of charge, to any person or organization
+// obtaining a copy of the software and accompanying documentation covered by
+// this license (the "Software") to use, reproduce, display, distribute,
+// execute, and transmit the Software, and to prepare derivative works of the
+// Software, and to permit third-parties to whom the Software is furnished to
+// do so, all subject to the following:
+//
+// The copyright notices in the Software and this entire statement, including
+// the above license grant, this restriction and the following disclaimer,
+// must be included in all copies of the Software, in whole or in part, and
+// all derivative works of the Software, unless such copies or derivative
+// works are solely in the form of machine-executable object code generated by
+// a source language processor.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+
+
+#ifndef MySQLTestSuite_INCLUDED
+#define MySQLTestSuite_INCLUDED
+
+
+#include "CppUnit/TestSuite.h"
+
+
+class MySQLTestSuite
+{
+public:
+ static CppUnit::Test* suite();
+};
+
+
+#endif // MySQLTestSuite_INCLUDED
diff --git a/Data/MySQL/testsuite/src/SQLExecutor.cpp b/Data/MySQL/testsuite/src/SQLExecutor.cpp
new file mode 100644
index 000000000..b3119e855
--- /dev/null
+++ b/Data/MySQL/testsuite/src/SQLExecutor.cpp
@@ -0,0 +1,1481 @@
+//
+// SQLExecutor.cpp
+//
+// $Id: //poco/Main/DataConnectors/ODBC/testsuite/src/SQLExecutor.cpp#14 $
+//
+// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// Permission is hereby granted, free of charge, to any person or organization
+// obtaining a copy of the software and accompanying documentation covered by
+// this license (the "Software") to use, reproduce, display, distribute,
+// execute, and transmit the Software, and to prepare derivative works of the
+// Software, and to permit third-parties to whom the Software is furnished to
+// do so, all subject to the following:
+//
+// The copyright notices in the Software and this entire statement, including
+// the above license grant, this restriction and the following disclaimer,
+// must be included in all copies of the Software, in whole or in part, and
+// all derivative works of the Software, unless such copies or derivative
+// works are solely in the form of machine-executable object code generated by
+// a source language processor.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+
+
+#include "CppUnit/TestCase.h"
+#include "SQLExecutor.h"
+#include "Poco/String.h"
+#include "Poco/Format.h"
+#include "Poco/Tuple.h"
+#include "Poco/Any.h"
+#include "Poco/Exception.h"
+#include "Poco/Data/Common.h"
+#include "Poco/Data/BLOB.h"
+#include "Poco/Data/StatementImpl.h"
+#include "Poco/Data/RecordSet.h"
+#include "Poco/Data/MySQL/Connector.h"
+#include "Poco/Data/MySQL/MySQLException.h"
+
+#ifdef _WIN32
+#include
+#endif
+
+#include
+#include
+
+
+using namespace Poco::Data;
+using Poco::Data::MySQL::ConnectionException;
+using Poco::Data::MySQL::StatementException;
+using Poco::format;
+using Poco::Tuple;
+using Poco::Any;
+using Poco::AnyCast;
+using Poco::NotFoundException;
+using Poco::InvalidAccessException;
+using Poco::BadCastException;
+using Poco::RangeException;
+
+
+struct Person
+{
+ std::string lastName;
+ std::string firstName;
+ std::string address;
+ int age;
+ Person(){age = 0;}
+ Person(const std::string& ln, const std::string& fn, const std::string& adr, int a):lastName(ln), firstName(fn), address(adr), age(a)
+ {
+ }
+ bool operator==(const Person& other) const
+ {
+ return lastName == other.lastName && firstName == other.firstName && address == other.address && age == other.age;
+ }
+
+ bool operator < (const Person& p) const
+ {
+ if (age < p.age)
+ return true;
+ if (lastName < p.lastName)
+ return true;
+ if (firstName < p.firstName)
+ return true;
+ return (address < p.address);
+ }
+
+ const std::string& operator () () const
+ /// This method is required so we can extract data to a map!
+ {
+ // we choose the lastName as examplary key
+ return lastName;
+ }
+};
+
+
+namespace Poco {
+namespace Data {
+
+
+template <>
+class TypeHandler
+{
+public:
+ static void bind(std::size_t pos, const Person& obj, AbstractBinder* pBinder)
+ {
+ // the table is defined as Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3))
+ poco_assert_dbg (pBinder != 0);
+ pBinder->bind(pos++, obj.lastName);
+ pBinder->bind(pos++, obj.firstName);
+ pBinder->bind(pos++, obj.address);
+ pBinder->bind(pos++, obj.age);
+ }
+
+ static void prepare(std::size_t pos, const Person& obj, AbstractPreparation* pPrepare)
+ {
+ // the table is defined as Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3))
+ poco_assert_dbg (pPrepare != 0);
+ pPrepare->prepare(pos++, obj.lastName);
+ pPrepare->prepare(pos++, obj.firstName);
+ pPrepare->prepare(pos++, obj.address);
+ pPrepare->prepare(pos++, obj.age);
+ }
+
+ static std::size_t size()
+ {
+ return 4;
+ }
+
+ static void extract(std::size_t pos, Person& obj, const Person& defVal, AbstractExtractor* pExt)
+ {
+ poco_assert_dbg (pExt != 0);
+ if (!pExt->extract(pos++, obj.lastName))
+ obj.lastName = defVal.lastName;
+ if (!pExt->extract(pos++, obj.firstName))
+ obj.firstName = defVal.firstName;
+ if (!pExt->extract(pos++, obj.address))
+ obj.address = defVal.address;
+ if (!pExt->extract(pos++, obj.age))
+ obj.age = defVal.age;
+ }
+
+private:
+ TypeHandler();
+ ~TypeHandler();
+ TypeHandler(const TypeHandler&);
+ TypeHandler& operator=(const TypeHandler&);
+};
+
+
+} } // namespace Poco::Data
+
+
+SQLExecutor::SQLExecutor(const std::string& name, Poco::Data::Session* pSession):
+ CppUnit::TestCase(name),
+ _pSession(pSession)
+{
+}
+
+
+SQLExecutor::~SQLExecutor()
+{
+}
+
+
+void SQLExecutor::bareboneMySQLTest(const char* host, const char* user, const char* pwd, const char* db, int port, const char* tableCreateString)
+{
+ int rc;
+ MYSQL* hsession = mysql_init(0);
+ assert (hsession != 0);
+
+ MYSQL* tmp = mysql_real_connect(hsession, host, user, pwd, db, port, 0, 0);
+ assert(tmp == hsession);
+
+ MYSQL_STMT* hstmt = mysql_stmt_init(hsession);
+ assert(hstmt != 0);
+
+ std::string sql = "DROP TABLE Test";
+ mysql_real_query(hsession, sql.c_str(), static_cast(sql.length()));
+
+ sql = tableCreateString;
+ rc = mysql_stmt_prepare(hstmt, sql.c_str(), static_cast(sql.length()));
+ assert(rc == 0);
+
+ rc = mysql_stmt_execute(hstmt);
+ assert(rc == 0);
+
+ sql = "INSERT INTO Test VALUES (?,?,?,?,?)";
+ rc = mysql_stmt_prepare(hstmt, sql.c_str(), static_cast(sql.length()));
+ assert(rc == 0);
+
+ std::string str[3] = { "111", "222", "333" };
+ int fourth = 4;
+ float fifth = 1.5;
+
+ MYSQL_BIND bind_param[5] = {{0}};
+
+ bind_param[0].buffer = const_cast(str[0].c_str());
+ bind_param[0].buffer_length = static_cast(str[0].length());
+ bind_param[0].buffer_type = MYSQL_TYPE_STRING;
+
+ bind_param[1].buffer = const_cast(str[1].c_str());
+ bind_param[1].buffer_length = static_cast(str[1].length());
+ bind_param[1].buffer_type = MYSQL_TYPE_STRING;
+
+ bind_param[2].buffer = const_cast(str[2].c_str());
+ bind_param[2].buffer_length = static_cast(str[2].length());
+ bind_param[2].buffer_type = MYSQL_TYPE_STRING;
+
+ bind_param[3].buffer = &fourth;
+ bind_param[3].buffer_type = MYSQL_TYPE_LONG;
+
+ bind_param[4].buffer = &fifth;
+ bind_param[4].buffer_type = MYSQL_TYPE_FLOAT;
+
+ rc = mysql_stmt_bind_param(hstmt, bind_param);
+ assert (rc == 0);
+
+ rc = mysql_stmt_execute(hstmt);
+ assert (rc == 0);
+
+ sql = "SELECT * FROM Test";
+ rc = mysql_stmt_prepare(hstmt, sql.c_str(), static_cast(sql.length()));
+ assert (rc == 0);
+
+ char chr[3][5] = {{ 0 }};
+ unsigned long lengths[5] = { 0 };
+ fourth = 0;
+ fifth = 0.0f;
+
+ MYSQL_BIND bind_result[5] = {{0}};
+
+ bind_result[0].buffer = chr[0];
+ bind_result[0].buffer_length = sizeof(chr[0]);
+ bind_result[0].buffer_type = MYSQL_TYPE_STRING;
+ bind_result[0].length = &lengths[0];
+
+ bind_result[1].buffer = chr[1];
+ bind_result[1].buffer_length = sizeof(chr[1]);
+ bind_result[1].buffer_type = MYSQL_TYPE_STRING;
+ bind_result[1].length = &lengths[1];
+
+ bind_result[2].buffer = chr[2];
+ bind_result[2].buffer_length = sizeof(chr[2]);
+ bind_result[2].buffer_type = MYSQL_TYPE_STRING;
+ bind_result[2].length = &lengths[2];
+
+ bind_result[3].buffer = &fourth;
+ bind_result[3].buffer_type = MYSQL_TYPE_LONG;
+ bind_result[3].length = &lengths[3];
+
+ bind_result[4].buffer = &fifth;
+ bind_result[4].buffer_type = MYSQL_TYPE_FLOAT;
+ bind_result[4].length = &lengths[4];
+
+ rc = mysql_stmt_bind_result(hstmt, bind_result);
+ assert (rc == 0);
+
+ rc = mysql_stmt_execute(hstmt);
+ assert (rc == 0);
+ rc = mysql_stmt_fetch(hstmt);
+ assert (rc == 0);
+
+ assert (0 == strncmp("111", chr[0], 3));
+ assert (0 == strncmp("222", chr[1], 3));
+ assert (0 == strncmp("333", chr[2], 3));
+ assert (4 == fourth);
+ assert (1.5 == fifth);
+
+ rc = mysql_stmt_close(hstmt);
+ assert(rc == 0);
+
+ sql = "DROP TABLE Test";
+ rc = mysql_real_query(hsession, sql.c_str(), static_cast(sql.length()));
+ assert(rc == 0);
+
+ mysql_close(hsession);
+}
+
+
+void SQLExecutor::simpleAccess()
+{
+ std::string funct = "simpleAccess()";
+ std::string lastName = "lastName";
+ std::string firstName("firstName");
+ std::string address("Address");
+ int age = 133132;
+ int count = 0;
+ std::string result;
+
+ count = 0;
+ try
+ {
+ Statement stmt(*_pSession);
+ stmt << "INSERT INTO Person VALUES (?,?,?,?)", use(lastName), use(firstName), use(address), use(age);//, now;
+ stmt.execute();
+ }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+
+ try { *_pSession << "SELECT COUNT(*) FROM Person", into(count), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+
+ assert (count == 1);
+
+ try { *_pSession << "SELECT LastName FROM Person", into(result), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ assert (lastName == result);
+
+ try { *_pSession << "SELECT Age FROM Person", into(count), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ assert (count == age);
+}
+
+
+void SQLExecutor::complexType()
+{
+ std::string funct = "complexType()";
+ Person p1("LN1", "FN1", "ADDR1", 1);
+ Person p2("LN2", "FN2", "ADDR2", 2);
+
+ try { *_pSession << "INSERT INTO Person VALUES (?,?,?,?)", use(p1), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+
+ try { *_pSession << "INSERT INTO Person VALUES (?,?,?,?)", use(p2), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+
+ int count = 0;
+ try { *_pSession << "SELECT COUNT(*) FROM Person", into(count), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ assert (count == 2);
+
+ Person c1;
+ Person c2;
+ try { *_pSession << "SELECT * FROM Person WHERE LastName = 'LN1'", into(c1), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ assert (c1 == p1);
+}
+
+
+void SQLExecutor::simpleAccessVector()
+{
+ std::string funct = "simpleAccessVector()";
+ std::vector lastNames;
+ std::vector firstNames;
+ std::vector addresses;
+ std::vector ages;
+ std::string tableName("Person");
+ lastNames.push_back("LN1");
+ lastNames.push_back("LN2");
+ firstNames.push_back("FN1");
+ firstNames.push_back("FN2");
+ addresses.push_back("ADDR1");
+ addresses.push_back("ADDR2");
+ ages.push_back(1);
+ ages.push_back(2);
+ int count = 0;
+ std::string result;
+
+ try { *_pSession << "INSERT INTO Person VALUES (?,?,?,?)", use(lastNames), use(firstNames), use(addresses), use(ages), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+
+ try { *_pSession << "SELECT COUNT(*) FROM Person", into(count), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ assert (count == 2);
+
+ std::vector lastNamesR;
+ std::vector firstNamesR;
+ std::vector addressesR;
+ std::vector agesR;
+ try { *_pSession << "SELECT * FROM Person", into(lastNamesR), into(firstNamesR), into(addressesR), into(agesR), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ assert (ages == agesR);
+ assert (lastNames == lastNamesR);
+ assert (firstNames == firstNamesR);
+ assert (addresses == addressesR);
+}
+
+
+void SQLExecutor::complexTypeVector()
+{
+ std::string funct = "complexTypeVector()";
+ std::vector people;
+ people.push_back(Person("LN1", "FN1", "ADDR1", 1));
+ people.push_back(Person("LN2", "FN2", "ADDR2", 2));
+
+ try { *_pSession << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+
+ int count = 0;
+ try { *_pSession << "SELECT COUNT(*) FROM Person", into(count), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ assert (count == 2);
+
+ std::vector result;
+ try { *_pSession << "SELECT * FROM Person", into(result), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ assert (result == people);
+}
+
+
+void SQLExecutor::insertVector()
+{
+ std::string funct = "insertVector()";
+ std::vector str;
+ str.push_back("s1");
+ str.push_back("s2");
+ str.push_back("s3");
+ str.push_back("s3");
+ int count = 100;
+
+ {
+ Statement stmt((*_pSession << "INSERT INTO Strings VALUES (?)", use(str)));
+ try { *_pSession << "SELECT COUNT(*) FROM Strings", into(count), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ assert (count == 0);
+
+ try { stmt.execute(); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+
+ try { *_pSession << "SELECT COUNT(*) FROM Strings", into(count), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ assert (count == 4);
+ }
+ count = 0;
+ try { *_pSession << "SELECT COUNT(*) FROM Strings", into(count), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ assert (count == 4);
+}
+
+
+void SQLExecutor::insertEmptyVector()
+{
+ std::string funct = "insertEmptyVector()";
+ std::vector str;
+
+ try
+ {
+ *_pSession << "INSERT INTO Strings VALUES (?)", use(str), now;
+ fail("empty collections should not work");
+ }
+ catch (Poco::Exception&)
+ {
+ }
+}
+
+
+void SQLExecutor::insertSingleBulk()
+{
+ std::string funct = "insertSingleBulk()";
+ int x = 0;
+ Statement stmt((*_pSession << "INSERT INTO Strings VALUES (?)", use(x)));
+
+ for (x = 0; x < 100; ++x)
+ {
+ int i = stmt.execute();
+ assert (i == 0);
+ }
+
+ int count = 0;
+ try { *_pSession << "SELECT COUNT(*) FROM Strings", into(count), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ assert (count == 100);
+
+ try { *_pSession << "SELECT SUM(str) FROM Strings", into(count), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ assert (count == ((0+99)*100/2));
+}
+
+
+void SQLExecutor::floats()
+{
+ std::string funct = "floats()";
+ float data = 1.5f;
+ float ret = 0.0f;
+
+ try { *_pSession << "INSERT INTO Strings VALUES (?)", use(data), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+
+ int count = 0;
+ try { *_pSession << "SELECT COUNT(*) FROM Strings", into(count), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ assert (count == 1);
+
+ try { *_pSession << "SELECT str FROM Strings", into(ret), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ assert (ret == data);
+}
+
+
+void SQLExecutor::doubles()
+{
+ std::string funct = "floats()";
+ double data = 1.5;
+ double ret = 0.0;
+
+ try { *_pSession << "INSERT INTO Strings VALUES (?)", use(data), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+
+ int count = 0;
+ try { *_pSession << "SELECT COUNT(*) FROM Strings", into(count), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ assert (count == 1);
+
+ try { *_pSession << "SELECT str FROM Strings", into(ret), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ assert (ret == data);
+}
+
+
+void SQLExecutor::insertSingleBulkVec()
+{
+ std::string funct = "insertSingleBulkVec()";
+ std::vector data;
+
+ for (int x = 0; x < 100; ++x)
+ data.push_back(x);
+
+ Statement stmt((*_pSession << "INSERT INTO Strings VALUES (?)", use(data)));
+ stmt.execute();
+
+ int count = 0;
+ try { *_pSession << "SELECT COUNT(*) FROM Strings", into(count), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+
+ assert (count == 100);
+ try { *_pSession << "SELECT SUM(str) FROM Strings", into(count), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ assert (count == ((0+99)*100/2));
+}
+
+
+void SQLExecutor::limits()
+{
+ std::string funct = "limit()";
+ std::vector data;
+ for (int x = 0; x < 100; ++x)
+ {
+ data.push_back(x);
+ }
+
+ try { *_pSession << "INSERT INTO Strings VALUES (?)", use(data), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+
+ std::vector retData;
+ try { *_pSession << "SELECT * FROM Strings", into(retData), limit(50), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ assert (retData.size() == 50);
+ for (int x = 0; x < 50; ++x)
+ {
+ assert(data[x] == retData[x]);
+ }
+}
+
+
+void SQLExecutor::limitZero()
+{
+ std::string funct = "limitZero()";
+ std::vector data;
+ for (int x = 0; x < 100; ++x)
+ {
+ data.push_back(x);
+ }
+
+ try { *_pSession << "INSERT INTO Strings VALUES (?)", use(data), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+
+ std::vector retData;
+ try { *_pSession << "SELECT * FROM Strings", into(retData), limit(0), now; }// stupid test, but at least we shouldn't crash
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ assert (retData.size() == 0);
+}
+
+
+void SQLExecutor::limitOnce()
+{
+ std::string funct = "limitOnce()";
+ std::vector data;
+ for (int x = 0; x < 101; ++x)
+ {
+ data.push_back(x);
+ }
+
+ try { *_pSession << "INSERT INTO Strings VALUES (?)", use(data), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+
+ std::vector retData;
+ Statement stmt = (*_pSession << "SELECT * FROM Strings", into(retData), limit(50), now);
+ assert (!stmt.done());
+ assert (retData.size() == 50);
+ stmt.execute();
+ assert (!stmt.done());
+ assert (retData.size() == 100);
+ stmt.execute();
+ assert (stmt.done());
+ assert (retData.size() == 101);
+
+ for (int x = 0; x < 101; ++x)
+ {
+ assert(data[x] == retData[x]);
+ }
+}
+
+
+void SQLExecutor::limitPrepare()
+{
+ std::string funct = "limitPrepare()";
+ std::vector data;
+ for (int x = 0; x < 100; ++x)
+ {
+ data.push_back(x);
+ }
+
+ try { *_pSession << "INSERT INTO Strings VALUES (?)", use(data), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+
+ std::vector retData;
+ Statement stmt = (*_pSession << "SELECT * FROM Strings", into(retData), limit(50));
+ assert (retData.size() == 0);
+ assert (!stmt.done());
+
+ try { stmt.execute(); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ assert (!stmt.done());
+ assert (retData.size() == 50);
+
+ try { stmt.execute(); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ assert (stmt.done());
+ assert (retData.size() == 100);
+
+ try { stmt.execute(); }// will restart execution!
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ assert (!stmt.done());
+ assert (retData.size() == 150);
+ for (int x = 0; x < 150; ++x)
+ {
+ assert(data[x%100] == retData[x]);
+ }
+}
+
+
+
+void SQLExecutor::prepare()
+{
+ std::string funct = "prepare()";
+ std::vector data;
+ for (int x = 0; x < 100; x += 2)
+ {
+ data.push_back(x);
+ }
+
+ {
+ Statement stmt((*_pSession << "INSERT INTO Strings VALUES (?)", use(data)));
+ }
+ // stmt should not have been executed when destroyed
+ int count = 100;
+ try { *_pSession << "SELECT COUNT(*) FROM Strings", into(count), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ assert (count == 0);
+}
+
+
+void SQLExecutor::setSimple()
+{
+ std::string funct = "setSimple()";
+ std::set lastNames;
+ std::set firstNames;
+ std::set addresses;
+ std::set ages;
+ std::string tableName("Person");
+ lastNames.insert("LN1");
+ lastNames.insert("LN2");
+ firstNames.insert("FN1");
+ firstNames.insert("FN2");
+ addresses.insert("ADDR1");
+ addresses.insert("ADDR2");
+ ages.insert(1);
+ ages.insert(2);
+ int count = 0;
+ std::string result;
+
+ try { *_pSession << "INSERT INTO Person VALUES (?,?,?,?)", use(lastNames), use(firstNames), use(addresses), use(ages), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ try { *_pSession << "SELECT COUNT(*) FROM Person", into(count), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ assert (count == 2);
+
+ std::set lastNamesR;
+ std::set firstNamesR;
+ std::set addressesR;
+ std::set agesR;
+ try { *_pSession << "SELECT * FROM Person", into(lastNamesR), into(firstNamesR), into(addressesR), into(agesR), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ assert (ages == agesR);
+ assert (lastNames == lastNamesR);
+ assert (firstNames == firstNamesR);
+ assert (addresses == addressesR);
+}
+
+
+void SQLExecutor::setComplex()
+{
+ std::string funct = "setComplex()";
+ std::set people;
+ people.insert(Person("LN1", "FN1", "ADDR1", 1));
+ people.insert(Person("LN2", "FN2", "ADDR2", 2));
+
+ try { *_pSession << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ int count = 0;
+ try { *_pSession << "SELECT COUNT(*) FROM Person", into(count), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ assert (count == 2);
+
+ std::set result;
+ try { *_pSession << "SELECT * FROM Person", into(result), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ assert (result == people);
+}
+
+
+void SQLExecutor::setComplexUnique()
+{
+ std::string funct = "setComplexUnique()";
+ std::vector people;
+ Person p1("LN1", "FN1", "ADDR1", 1);
+ people.push_back(p1);
+ people.push_back(p1);
+ people.push_back(p1);
+ people.push_back(p1);
+ Person p2("LN2", "FN2", "ADDR2", 2);
+ people.push_back(p2);
+
+ try { *_pSession << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ int count = 0;
+ try { *_pSession << "SELECT COUNT(*) FROM Person", into(count), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ assert (count == 5);
+
+ std::set result;
+ try { *_pSession << "SELECT * FROM Person", into(result), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ assert (result.size() == 2);
+ assert (*result.begin() == p1);
+ assert (*++result.begin() == p2);
+}
+
+void SQLExecutor::multiSetSimple()
+{
+ std::string funct = "multiSetSimple()";
+ std::multiset lastNames;
+ std::multiset firstNames;
+ std::multiset addresses;
+ std::multiset ages;
+ std::string tableName("Person");
+ lastNames.insert("LN1");
+ lastNames.insert("LN2");
+ firstNames.insert("FN1");
+ firstNames.insert("FN2");
+ addresses.insert("ADDR1");
+ addresses.insert("ADDR2");
+ ages.insert(1);
+ ages.insert(2);
+ int count = 0;
+ std::string result;
+
+ try { *_pSession << "INSERT INTO Person VALUES (?,?,?,?)", use(lastNames), use(firstNames), use(addresses), use(ages), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ try { *_pSession << "SELECT COUNT(*) FROM Person", into(count), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ assert (count == 2);
+
+ std::multiset lastNamesR;
+ std::multiset firstNamesR;
+ std::multiset addressesR;
+ std::multiset agesR;
+ try { *_pSession << "SELECT * FROM Person", into(lastNamesR), into(firstNamesR), into(addressesR), into(agesR), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ assert (ages.size() == agesR.size());
+ assert (lastNames.size() == lastNamesR.size());
+ assert (firstNames.size() == firstNamesR.size());
+ assert (addresses.size() == addressesR.size());
+}
+
+
+void SQLExecutor::multiSetComplex()
+{
+ std::string funct = "multiSetComplex()";
+ std::multiset people;
+ Person p1("LN1", "FN1", "ADDR1", 1);
+ people.insert(p1);
+ people.insert(p1);
+ people.insert(p1);
+ people.insert(p1);
+ Person p2("LN2", "FN2", "ADDR2", 2);
+ people.insert(p2);
+
+ try { *_pSession << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ int count = 0;
+ try { *_pSession << "SELECT COUNT(*) FROM Person", into(count), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ assert (count == 5);
+
+ std::multiset result;
+ try { *_pSession << "SELECT * FROM Person", into(result), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ assert (result.size() == people.size());
+}
+
+
+void SQLExecutor::mapComplex()
+{
+ std::string funct = "mapComplex()";
+ std::map people;
+ Person p1("LN1", "FN1", "ADDR1", 1);
+ Person p2("LN2", "FN2", "ADDR2", 2);
+ people.insert(std::make_pair("LN1", p1));
+ people.insert(std::make_pair("LN2", p2));
+
+ try { *_pSession << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ int count = 0;
+ try { *_pSession << "SELECT COUNT(*) FROM Person", into(count), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ assert (count == 2);
+
+ std::map result;
+ try { *_pSession << "SELECT * FROM Person", into(result), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ assert (result == people);
+}
+
+
+void SQLExecutor::mapComplexUnique()
+{
+ std::string funct = "mapComplexUnique()";
+ std::multimap people;
+ Person p1("LN1", "FN1", "ADDR1", 1);
+ Person p2("LN2", "FN2", "ADDR2", 2);
+ people.insert(std::make_pair("LN1", p1));
+ people.insert(std::make_pair("LN1", p1));
+ people.insert(std::make_pair("LN1", p1));
+ people.insert(std::make_pair("LN1", p1));
+ people.insert(std::make_pair("LN2", p2));
+
+ try { *_pSession << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ int count = 0;
+ try { *_pSession << "SELECT COUNT(*) FROM Person", into(count), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ assert (count == 5);
+
+ std::map result;
+ try { *_pSession << "SELECT * FROM Person", into(result), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ assert (result.size() == 2);
+}
+
+
+void SQLExecutor::multiMapComplex()
+{
+ std::string funct = "multiMapComplex()";
+ std::multimap people;
+ Person p1("LN1", "FN1", "ADDR1", 1);
+ Person p2("LN2", "FN2", "ADDR2", 2);
+ people.insert(std::make_pair("LN1", p1));
+ people.insert(std::make_pair("LN1", p1));
+ people.insert(std::make_pair("LN1", p1));
+ people.insert(std::make_pair("LN1", p1));
+ people.insert(std::make_pair("LN2", p2));
+
+ try { *_pSession << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ int count = 0;
+ try { *_pSession << "SELECT COUNT(*) FROM Person", into(count), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ assert (count == 5);
+
+ std::multimap result;
+ try { *_pSession << "SELECT * FROM Person", into(result), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ assert (result.size() == people.size());
+}
+
+
+void SQLExecutor::selectIntoSingle()
+{
+ std::string funct = "selectIntoSingle()";
+ std::multimap people;
+ Person p1("LN1", "FN1", "ADDR1", 1);
+ Person p2("LN2", "FN2", "ADDR2", 2);
+ people.insert(std::make_pair("LN1", p1));
+ people.insert(std::make_pair("LN1", p2));
+
+ try { *_pSession << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ int count = 0;
+ try { *_pSession << "SELECT COUNT(*) FROM Person", into(count), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ assert (count == 2);
+ Person result;
+ try { *_pSession << "SELECT * FROM Person", into(result), limit(1), now; }// will return 1 object into one single result
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ assert (result == p1);
+}
+
+
+void SQLExecutor::selectIntoSingleStep()
+{
+ std::string funct = "selectIntoSingleStep()";
+ std::multimap people;
+ Person p1("LN1", "FN1", "ADDR1", 1);
+ Person p2("LN2", "FN2", "ADDR2", 2);
+ people.insert(std::make_pair("LN1", p1));
+ people.insert(std::make_pair("LN1", p2));
+
+ try { *_pSession << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+
+ int count = 0;
+ try { *_pSession << "SELECT COUNT(*) FROM Person", into(count), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ assert (count == 2);
+ Person result;
+ Statement stmt = (*_pSession << "SELECT * FROM Person", into(result), limit(1));
+ stmt.execute();
+ assert (result == p1);
+ assert (!stmt.done());
+ stmt.execute();
+ assert (result == p2);
+ assert (stmt.done());
+}
+
+
+void SQLExecutor::selectIntoSingleFail()
+{
+ std::string funct = "selectIntoSingleFail()";
+ std::multimap people;
+ Person p1("LN1", "FN1", "ADDR1", 1);
+ Person p2("LN2", "FN2", "ADDR2", 2);
+ people.insert(std::make_pair("LN1", p1));
+ people.insert(std::make_pair("LN1", p2));
+
+ try { *_pSession << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ int count = 0;
+ try { *_pSession << "SELECT COUNT(*) FROM Person", into(count), limit(2, true), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ assert (count == 2);
+ Person result;
+ try
+ {
+ *_pSession << "SELECT * FROM Person", into(result), limit(1, true), now; // will fail now
+ fail("hardLimit is set: must fail");
+ }
+ catch(Poco::Data::LimitException&)
+ {
+ }
+}
+
+
+void SQLExecutor::lowerLimitOk()
+{
+ std::string funct = "lowerLimitOk()";
+ std::multimap people;
+ Person p1("LN1", "FN1", "ADDR1", 1);
+ Person p2("LN2", "FN2", "ADDR2", 2);
+ people.insert(std::make_pair("LN1", p1));
+ people.insert(std::make_pair("LN1", p2));
+
+ try { *_pSession << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+
+ int count = 0;
+ try { *_pSession << "SELECT COUNT(*) FROM Person", into(count), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ assert (count == 2);
+ Person result;
+ try
+ {
+ *_pSession << "SELECT * FROM Person", into(result), lowerLimit(2), now; // will return 2 objects into one single result but only room for one!
+ fail("Not enough space for results");
+ }
+ catch(Poco::Exception&)
+ {
+ }
+}
+
+
+void SQLExecutor::singleSelect()
+{
+ std::string funct = "singleSelect()";
+ std::multimap people;
+ Person p1("LN1", "FN1", "ADDR1", 1);
+ Person p2("LN2", "FN2", "ADDR2", 2);
+ people.insert(std::make_pair("LN1", p1));
+ people.insert(std::make_pair("LN1", p2));
+
+ try { *_pSession << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+
+ int count = 0;
+ try { *_pSession << "SELECT COUNT(*) FROM Person", into(count), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ assert (count == 2);
+ Person result;
+ Statement stmt = (*_pSession << "SELECT * FROM Person", into(result), limit(1));
+ stmt.execute();
+ assert (result == p1);
+ assert (!stmt.done());
+ stmt.execute();
+ assert (result == p2);
+ assert (stmt.done());
+}
+
+
+void SQLExecutor::lowerLimitFail()
+{
+ std::string funct = "lowerLimitFail()";
+ std::multimap people;
+ Person p1("LN1", "FN1", "ADDR1", 1);
+ Person p2("LN2", "FN2", "ADDR2", 2);
+ people.insert(std::make_pair("LN1", p1));
+ people.insert(std::make_pair("LN1", p2));
+
+ try { *_pSession << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ int count = 0;
+ try { *_pSession << "SELECT COUNT(*) FROM Person", into(count), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ assert (count == 2);
+ Person result;
+ try
+ {
+ *_pSession << "SELECT * FROM Person", into(result), lowerLimit(3), now; // will fail
+ fail("should fail. not enough data");
+ }
+ catch(Poco::Exception&)
+ {
+ }
+}
+
+
+void SQLExecutor::combinedLimits()
+{
+ std::string funct = "combinedLimits()";
+ std::multimap people;
+ Person p1("LN1", "FN1", "ADDR1", 1);
+ Person p2("LN2", "FN2", "ADDR2", 2);
+ people.insert(std::make_pair("LN1", p1));
+ people.insert(std::make_pair("LN1", p2));
+
+ try { *_pSession << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ int count = 0;
+ try { *_pSession << "SELECT COUNT(*) FROM Person", into(count), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ assert (count == 2);
+ std::vector result;
+ try { *_pSession << "SELECT * FROM Person", into(result), lowerLimit(2), upperLimit(2), now; }// will return 2 objects
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ assert (result.size() == 2);
+ assert (result[0] == p1);
+ assert (result[1] == p2);
+}
+
+
+
+void SQLExecutor::ranges()
+{
+ std::string funct = "range()";
+ std::multimap people;
+ Person p1("LN1", "FN1", "ADDR1", 1);
+ Person p2("LN2", "FN2", "ADDR2", 2);
+ people.insert(std::make_pair("LN1", p1));
+ people.insert(std::make_pair("LN1", p2));
+
+ try { *_pSession << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ int count = 0;
+ try { *_pSession << "SELECT COUNT(*) FROM Person", into(count), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ assert (count == 2);
+ std::vector result;
+ try { *_pSession << "SELECT * FROM Person", into(result), range(2, 2), now; }// will return 2 objects
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ assert (result.size() == 2);
+ assert (result[0] == p1);
+ assert (result[1] == p2);
+}
+
+
+void SQLExecutor::combinedIllegalLimits()
+{
+ std::string funct = "combinedIllegalLimits()";
+ std::multimap people;
+ Person p1("LN1", "FN1", "ADDR1", 1);
+ Person p2("LN2", "FN2", "ADDR2", 2);
+ people.insert(std::make_pair("LN1", p1));
+ people.insert(std::make_pair("LN1", p2));
+
+ try { *_pSession << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ int count = 0;
+ try { *_pSession << "SELECT COUNT(*) FROM Person", into(count), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ assert (count == 2);
+ Person result;
+ try
+ {
+ *_pSession << "SELECT * FROM Person", into(result), lowerLimit(3), upperLimit(2), now;
+ fail("lower > upper is not allowed");
+ }
+ catch(LimitException&)
+ {
+ }
+}
+
+
+void SQLExecutor::illegalRange()
+{
+ std::string funct = "illegalRange()";
+ std::multimap people;
+ Person p1("LN1", "FN1", "ADDR1", 1);
+ Person p2("LN2", "FN2", "ADDR2", 2);
+ people.insert(std::make_pair("LN1", p1));
+ people.insert(std::make_pair("LN1", p2));
+
+ try { *_pSession << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ int count = 0;
+ try { *_pSession << "SELECT COUNT(*) FROM Person", into(count), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ assert (count == 2);
+ Person result;
+ try
+ {
+ *_pSession << "SELECT * FROM Person", into(result), range(3, 2), now;
+ fail("lower > upper is not allowed");
+ }
+ catch(LimitException&)
+ {
+ }
+}
+
+
+void SQLExecutor::emptyDB()
+{
+ std::string funct = "emptyDB()";
+ int count = 0;
+ try { *_pSession << "SELECT COUNT(*) FROM Person", into(count), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ assert (count == 0);
+
+ Person result;
+ Statement stmt = (*_pSession << "SELECT * FROM Person", into(result), limit(1));
+ stmt.execute();
+ assert (result.firstName.empty());
+ assert (stmt.done());
+}
+
+
+void SQLExecutor::blob(int bigSize)
+{
+ std::string funct = "blob()";
+ std::string lastName("lastname");
+ std::string firstName("firstname");
+ std::string address("Address");
+
+ Poco::Data::BLOB img("0123456789", 10);
+ int count = 0;
+ try { *_pSession << "INSERT INTO Person VALUES (?,?,?,?)", use(lastName), use(firstName), use(address), use(img), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ try { *_pSession << "SELECT COUNT(*) FROM Person", into(count), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ assert (count == 1);
+
+ Poco::Data::BLOB res;
+ assert (res.size() == 0);
+ try { *_pSession << "SELECT Image FROM Person", into(res), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ assert (res == img);
+
+ Poco::Data::BLOB big;
+ std::vector v(bigSize, 'x');
+ big.assignRaw(&v[0], v.size());
+
+ assert (big.size() == bigSize);
+
+ try { *_pSession << "DELETE FROM Person", now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+
+ try { *_pSession << "INSERT INTO Person VALUES(?,?,?,?)", use(lastName), use(firstName), use(address), use(big), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+
+ try { *_pSession << "SELECT Image FROM Person", into(res), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ assert (res == big);
+}
+
+void SQLExecutor::blobStmt()
+{
+ std::string funct = "blobStmt()";
+ std::string lastName("lastname");
+ std::string firstName("firstname");
+ std::string address("Address");
+ Poco::Data::BLOB blob("0123456789", 10);
+
+ int count = 0;
+ Statement ins = (*_pSession << "INSERT INTO Person VALUES (?,?,?,?)", use(lastName), use(firstName), use(address), use(blob));
+ ins.execute();
+ try { *_pSession << "SELECT COUNT(*) FROM Person", into(count), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ assert (count == 1);
+
+ Poco::Data::BLOB res;
+ poco_assert (res.size() == 0);
+ Statement stmt = (*_pSession << "SELECT Image FROM Person", into(res));
+ try { stmt.execute(); }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ poco_assert (res == blob);
+}
+
+void SQLExecutor::tuples()
+{
+ typedef Tuple TupleType;
+ std::string funct = "tuples()";
+ TupleType t(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19);
+
+ try { *_pSession << "INSERT INTO Tuples VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", use(t), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+
+ TupleType ret(-10,-11,-12,-13,-14,-15,-16,-17,-18,-19);
+ assert (ret != t);
+ try { *_pSession << "SELECT * FROM Tuples", into(ret), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ assert (ret == t);
+}
+
+void SQLExecutor::tupleVector()
+{
+ typedef Tuple TupleType;
+ std::string funct = "tupleVector()";
+ TupleType t(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19);
+ Tuple
+ t10(10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29);
+ TupleType t100(100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119);
+ std::vector v;
+ v.push_back(t);
+ v.push_back(t10);
+ v.push_back(t100);
+
+ try { *_pSession << "INSERT INTO Tuples VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", use(v), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+
+ int count = 0;
+ try { *_pSession << "SELECT COUNT(*) FROM Tuples", into(count), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ assert (v.size() == count);
+
+ std::vector > ret;
+ try { *_pSession << "SELECT * FROM Tuples", into(ret), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+ assert (ret == v);
+}
+
+
+void SQLExecutor::internalExtraction()
+{
+ std::string funct = "internalExtraction()";
+ std::vector > v;
+ v.push_back(Tuple(1, 1.5f, "3"));
+ v.push_back(Tuple(2, 2.5f, "4"));
+ v.push_back(Tuple(3, 3.5f, "5"));
+ v.push_back(Tuple(4, 4.5f, "6"));
+
+ try { *_pSession << "INSERT INTO Vectors VALUES (?,?,?)", use(v), now; }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+
+ try
+ {
+ Statement stmt = (*_pSession << "SELECT * FROM Vectors", now);
+ RecordSet rset(stmt);
+
+ assert (3 == rset.columnCount());
+ assert (4 == rset.rowCount());
+
+ int curVal = 3;
+ do
+ {
+ assert (rset["str0"] == curVal);
+ ++curVal;
+ } while (rset.moveNext());
+
+ rset.moveFirst();
+ assert (rset["str0"] == "3");
+ rset.moveLast();
+ assert (rset["str0"] == "6");
+
+ RecordSet rset2(rset);
+ assert (3 == rset2.columnCount());
+ assert (4 == rset2.rowCount());
+
+ int i = rset.value(0,0);
+ assert (1 == i);
+
+ std::string s = rset.value(0,0);
+ assert ("1" == s);
+
+ int a = rset.value(0,2);
+ assert (3 == a);
+
+ try
+ {
+ double d = rset.value(1,1);
+ assert (2.5 == d);
+ }
+ catch (BadCastException&)
+ {
+ float f = rset.value(1,1);
+ assert (2.5 == f);
+ }
+
+ s = rset.value(2,2);
+ assert ("5" == s);
+ i = rset.value("str0", 2);
+ assert (5 == i);
+
+ const Column& col = rset.column(0);
+ Column::Iterator it = col.begin();
+ Column::Iterator end = col.end();
+ for (int i = 1; it != end; ++it, ++i)
+ assert (*it == i);
+
+ rset = (*_pSession << "SELECT COUNT(*) AS cnt FROM Vectors", now);
+
+ //various results for COUNT(*) are received from different drivers
+ try
+ {
+ //this is what most drivers will return
+ int i = rset.value(0,0);
+ assert (4 == i);
+ }
+ catch(BadCastException&)
+ {
+ try
+ {
+ //this is for Oracle
+ double i = rset.value(0,0);
+ assert (4 == int(i));
+ }
+ catch(BadCastException&)
+ {
+ //this is for PostgreSQL
+ Poco::Int64 big = rset.value(0,0);
+ assert (4 == big);
+ }
+ }
+
+ s = rset.value("cnt", 0).convert();
+ assert ("4" == s);
+
+ try { const Column& col1 = rset.column(100); fail ("must fail"); }
+ catch (RangeException&) { }
+
+ try { rset.value(0,0); fail ("must fail"); }
+ catch (BadCastException&) { }
+
+ stmt = (*_pSession << "DELETE FROM Vectors", now);
+ rset = stmt;
+
+ try { const Column& col1 = rset.column(0); fail ("must fail"); }
+ catch (RangeException&) { }
+ }
+ catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
+ catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
+}
diff --git a/Data/MySQL/testsuite/src/SQLExecutor.h b/Data/MySQL/testsuite/src/SQLExecutor.h
new file mode 100644
index 000000000..8a20af20a
--- /dev/null
+++ b/Data/MySQL/testsuite/src/SQLExecutor.h
@@ -0,0 +1,117 @@
+//
+// SQLExecutor.h
+//
+// $Id: //poco/1.3/Data/MySQL/testsuite/src/SQLExecutor.h#2 $
+//
+// Definition of the SQLExecutor class.
+//
+// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// Permission is hereby granted, free of charge, to any person or organization
+// obtaining a copy of the software and accompanying documentation covered by
+// this license (the "Software") to use, reproduce, display, distribute,
+// execute, and transmit the Software, and to prepare derivative works of the
+// Software, and to permit third-parties to whom the Software is furnished to
+// do so, all subject to the following:
+//
+// The copyright notices in the Software and this entire statement, including
+// the above license grant, this restriction and the following disclaimer,
+// must be included in all copies of the Software, in whole or in part, and
+// all derivative works of the Software, unless such copies or derivative
+// works are solely in the form of machine-executable object code generated by
+// a source language processor.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+
+
+#ifndef SQLExecutor_INCLUDED
+#define SQLExecutor_INCLUDED
+
+
+#include "Poco/Data/MySQL/MySQL.h"
+#include "Poco/Data/Session.h"
+
+class SQLExecutor: public CppUnit::TestCase
+{
+public:
+ enum DataBinding
+ {
+ PB_IMMEDIATE,
+ PB_AT_EXEC
+ };
+
+ enum DataExtraction
+ {
+ DE_MANUAL,
+ DE_BOUND
+ };
+
+ SQLExecutor(const std::string& name, Poco::Data::Session* _pSession);
+ ~SQLExecutor();
+
+ void bareboneMySQLTest(const char* host, const char* user, const char* pwd, const char* db, int port, const char* tableCreateString);
+ /// This function uses "bare bone" MySQL API calls (i.e. calls are not
+ /// "wrapped" in PocoData framework structures).
+ /// The purpose of the function is to verify that driver behaves
+ /// correctly. If this test passes, subsequent tests failures are likely ours.
+
+ void simpleAccess();
+ void complexType();
+ void simpleAccessVector();
+ void complexTypeVector();
+ void insertVector();
+ void insertEmptyVector();
+
+ void insertSingleBulk();
+ void insertSingleBulkVec();
+
+ void limits();
+ void limitOnce();
+ void limitPrepare();
+ void limitZero();
+ void prepare();
+
+ void setSimple();
+ void setComplex();
+ void setComplexUnique();
+ void multiSetSimple();
+ void multiSetComplex();
+ void mapComplex();
+ void mapComplexUnique();
+ void multiMapComplex();
+ void selectIntoSingle();
+ void selectIntoSingleStep();
+ void selectIntoSingleFail();
+ void lowerLimitOk();
+ void lowerLimitFail();
+ void combinedLimits();
+ void combinedIllegalLimits();
+ void ranges();
+ void illegalRange();
+ void singleSelect();
+ void emptyDB();
+
+ void blob(int bigSize = 1024);
+ void blobStmt();
+
+ void floats();
+ void doubles();
+ void tuples();
+ void tupleVector();
+
+ void internalExtraction();
+
+private:
+ Poco::Data::Session* _pSession;
+};
+
+
+#endif // SQLExecutor_INCLUDED
diff --git a/Data/MySQL/testsuite/src/WinDriver.cpp b/Data/MySQL/testsuite/src/WinDriver.cpp
new file mode 100644
index 000000000..0512574af
--- /dev/null
+++ b/Data/MySQL/testsuite/src/WinDriver.cpp
@@ -0,0 +1,50 @@
+//
+// WinDriver.cpp
+//
+// $Id: //poco/1.3/Data/MySQL/testsuite/src/WinDriver.cpp#2 $
+//
+// Windows test driver for Poco MySQL.
+//
+// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// Permission is hereby granted, free of charge, to any person or organization
+// obtaining a copy of the software and accompanying documentation covered by
+// this license (the "Software") to use, reproduce, display, distribute,
+// execute, and transmit the Software, and to prepare derivative works of the
+// Software, and to permit third-parties to whom the Software is furnished to
+// do so, all subject to the following:
+//
+// The copyright notices in the Software and this entire statement, including
+// the above license grant, this restriction and the following disclaimer,
+// must be included in all copies of the Software, in whole or in part, and
+// all derivative works of the Software, unless such copies or derivative
+// works are solely in the form of machine-executable object code generated by
+// a source language processor.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+
+
+#include "WinTestRunner/WinTestRunner.h"
+#include "MySQLTestSuite.h"
+
+
+class TestDriver: public CppUnit::WinTestRunnerApp
+{
+ void TestMain()
+ {
+ CppUnit::WinTestRunner runner;
+ runner.addTest(MySQLTestSuite::suite());
+ runner.run();
+ }
+};
+
+
+TestDriver theDriver;
diff --git a/Foundation/include/Poco/DynamicAnyHolder.h b/Foundation/include/Poco/DynamicAnyHolder.h
index 802a5f606..0b04eaf7e 100644
--- a/Foundation/include/Poco/DynamicAnyHolder.h
+++ b/Foundation/include/Poco/DynamicAnyHolder.h
@@ -106,8 +106,8 @@ protected:
poco_static_assert (std::numeric_limits::is_signed);
poco_static_assert (std::numeric_limits::is_signed);
- checkUpperLimit(from, to);
- checkLowerLimit(from, to);
+ checkUpperLimit(from);
+ checkLowerLimit(from);
to = static_cast(from);
}
@@ -124,7 +124,7 @@ protected:
poco_static_assert (!std::numeric_limits::is_signed);
poco_static_assert (!std::numeric_limits::is_signed);
- checkUpperLimit(from, to);
+ checkUpperLimit(from);
to = static_cast(from);
}
@@ -142,7 +142,7 @@ protected:
if (from < 0)
throw RangeException("Value too small.");
- checkUpperLimit(from, to);
+ checkUpperLimit(from);
to = static_cast(from);
}
@@ -158,20 +158,20 @@ protected:
poco_static_assert (!std::numeric_limits::is_signed);
poco_static_assert (std::numeric_limits::is_signed);
- checkUpperLimit(from, to);
+ checkUpperLimit(from);
to = static_cast(from);
}
private:
template
- void checkUpperLimit(const F& from, T& to) const
+ void checkUpperLimit(const F& from) const
{
if (from > std::numeric_limits::max())
throw RangeException("Value too large.");
}
template
- void checkLowerLimit(const F& from, T& to) const
+ void checkLowerLimit(const F& from) const
{
if (from < std::numeric_limits::min())
throw RangeException("Value too small.");