Sergey Kholodilov 17 anni fa
parent
commit
33efbefa71
32 ha cambiato i file con 7420 aggiunte e 0 eliminazioni
  1. 23 0
      Data/MySQL/Makefile
  2. 36 0
      Data/MySQL/MySQL_VS80.sln
  3. 279 0
      Data/MySQL/MySQL_VS80.vcproj
  4. 263 0
      Data/MySQL/include/Poco/Data/MySQL/Binder.h
  5. 79 0
      Data/MySQL/include/Poco/Data/MySQL/Connector.h
  6. 336 0
      Data/MySQL/include/Poco/Data/MySQL/Extractor.h
  7. 90 0
      Data/MySQL/include/Poco/Data/MySQL/MySQL.h
  8. 178 0
      Data/MySQL/include/Poco/Data/MySQL/MySQLException.h
  9. 125 0
      Data/MySQL/include/Poco/Data/MySQL/MySQLStatementImpl.h
  10. 89 0
      Data/MySQL/include/Poco/Data/MySQL/ResultMetadata.h
  11. 108 0
      Data/MySQL/include/Poco/Data/MySQL/SessionHandle.h
  12. 135 0
      Data/MySQL/include/Poco/Data/MySQL/SessionImpl.h
  13. 118 0
      Data/MySQL/include/Poco/Data/MySQL/StatementExecutor.h
  14. 623 0
      Data/MySQL/src/Binder.cpp
  15. 92 0
      Data/MySQL/src/Connector.cpp
  16. 622 0
      Data/MySQL/src/Extractor.cpp
  17. 160 0
      Data/MySQL/src/MySQLException.cpp
  18. 200 0
      Data/MySQL/src/MySQLStatementImpl.cpp
  19. 243 0
      Data/MySQL/src/ResultMetadata.cpp
  20. 135 0
      Data/MySQL/src/SessionHandle.cpp
  21. 226 0
      Data/MySQL/src/SessionImpl.cpp
  22. 197 0
      Data/MySQL/src/StatementExecutor.cpp
  23. 21 0
      Data/MySQL/testsuite/Makefile
  24. 259 0
      Data/MySQL/testsuite/TestSuite_VS80.vcproj
  25. 39 0
      Data/MySQL/testsuite/src/Driver.cpp
  26. 816 0
      Data/MySQL/testsuite/src/MySQLTest.cpp
  27. 141 0
      Data/MySQL/testsuite/src/MySQLTest.h
  28. 48 0
      Data/MySQL/testsuite/src/MySQLTestSuite.cpp
  29. 51 0
      Data/MySQL/testsuite/src/MySQLTestSuite.h
  30. 1520 0
      Data/MySQL/testsuite/src/SQLExecutor.cpp
  31. 118 0
      Data/MySQL/testsuite/src/SQLExecutor.h
  32. 50 0
      Data/MySQL/testsuite/src/WinDriver.cpp

+ 23 - 0
Data/MySQL/Makefile

@@ -0,0 +1,23 @@
+#
+# Makefile
+#
+# $Id: //poco/1.4/Data/MySQL/Makefile#1 $
+#
+# 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

+ 36 - 0
Data/MySQL/MySQL_VS80.sln

@@ -0,0 +1,36 @@
+
+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}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MySQL", "MySQL_VS80.vcproj", "{D9C692A6-D089-4269-B444-C445ED192F0D}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		debug_shared|Win32 = debug_shared|Win32
+		debug_static|Win32 = debug_static|Win32
+		release_shared|Win32 = release_shared|Win32
+		release_static|Win32 = release_static|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}.debug_static|Win32.ActiveCfg = debug_shared|Win32
+		{1B30A91B-375F-11DB-837B-00123FC423B5}.debug_static|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
+		{1B30A91B-375F-11DB-837B-00123FC423B5}.release_static|Win32.ActiveCfg = release_shared|Win32
+		{1B30A91B-375F-11DB-837B-00123FC423B5}.release_static|Win32.Build.0 = release_shared|Win32
+		{D9C692A6-D089-4269-B444-C445ED192F0D}.debug_shared|Win32.ActiveCfg = debug_shared|Win32
+		{D9C692A6-D089-4269-B444-C445ED192F0D}.debug_shared|Win32.Build.0 = debug_shared|Win32
+		{D9C692A6-D089-4269-B444-C445ED192F0D}.debug_static|Win32.ActiveCfg = debug_shared|Win32
+		{D9C692A6-D089-4269-B444-C445ED192F0D}.debug_static|Win32.Build.0 = debug_shared|Win32
+		{D9C692A6-D089-4269-B444-C445ED192F0D}.release_shared|Win32.ActiveCfg = release_shared|Win32
+		{D9C692A6-D089-4269-B444-C445ED192F0D}.release_shared|Win32.Build.0 = release_shared|Win32
+		{D9C692A6-D089-4269-B444-C445ED192F0D}.release_static|Win32.ActiveCfg = release_shared|Win32
+		{D9C692A6-D089-4269-B444-C445ED192F0D}.release_static|Win32.Build.0 = release_shared|Win32
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal

+ 279 - 0
Data/MySQL/MySQL_VS80.vcproj

@@ -0,0 +1,279 @@
+<?xml version="1.0" encoding="windows-1251"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8,00"
+	Name="MySQL"
+	ProjectGUID="{D9C692A6-D089-4269-B444-C445ED192F0D}"
+	RootNamespace="MySQL"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="debug_shared|Win32"
+			OutputDirectory="obj\$(ConfigurationName)"
+			IntermediateDirectory="obj\$(ConfigurationName)"
+			ConfigurationType="2"
+			CharacterSet="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories=".\include;.\src;..\..\Foundation\include;..\..\Data\include"
+				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;MYSQL_EXPORTS;POCO_DLL;NO_TCL;THREADSAFE;__LCC__"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="libmysql.lib"
+				OutputFile="../../bin/PocoMySQLd.dll"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../../lib"
+				GenerateDebugInformation="true"
+				SubSystem="2"
+				ImportLibrary="../../lib/PocoMySQLd.lib"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="release_shared|Win32"
+			OutputDirectory="obj\$(ConfigurationName)"
+			IntermediateDirectory="obj\$(ConfigurationName)"
+			ConfigurationType="2"
+			CharacterSet="1"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalIncludeDirectories=".\include;.\src;..\..\Foundation\include;..\..\Data\include"
+				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;MYSQL_EXPORTS;POCO_DLL;NO_TCL;THREADSAFE;__LCC__"
+				RuntimeLibrary="2"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="libmysql.lib"
+				OutputFile="../../bin/PocoMySQL.dll"
+				LinkIncremental="1"
+				AdditionalLibraryDirectories="../../lib"
+				GenerateDebugInformation="true"
+				SubSystem="2"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				ImportLibrary="../../lib/PocoMySQL.lib"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+			>
+			<File
+				RelativePath=".\src\Binder.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\src\Connector.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\src\Extractor.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\src\MySQLException.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\src\MySQLStatementImpl.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\src\ResultMetadata.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\src\SessionHandle.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\src\SessionImpl.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\src\StatementExecutor.cpp"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+			>
+			<File
+				RelativePath=".\include\Poco\Data\MySQL\Binder.h"
+				>
+			</File>
+			<File
+				RelativePath=".\include\Poco\Data\MySQL\Connector.h"
+				>
+			</File>
+			<File
+				RelativePath=".\include\Poco\Data\MySQL\Extractor.h"
+				>
+			</File>
+			<File
+				RelativePath=".\include\Poco\Data\MySQL\MySQL.h"
+				>
+			</File>
+			<File
+				RelativePath=".\include\Poco\Data\MySQL\MySQLException.h"
+				>
+			</File>
+			<File
+				RelativePath=".\include\Poco\Data\MySQL\MySQLStatementImpl.h"
+				>
+			</File>
+			<File
+				RelativePath=".\include\Poco\Data\MySQL\ResultMetadata.h"
+				>
+			</File>
+			<File
+				RelativePath=".\include\Poco\Data\MySQL\SessionHandle.h"
+				>
+			</File>
+			<File
+				RelativePath=".\include\Poco\Data\MySQL\SessionImpl.h"
+				>
+			</File>
+			<File
+				RelativePath=".\include\Poco\Data\MySQL\StatementExecutor.h"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Resource Files"
+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+			>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>

+ 263 - 0
Data/MySQL/include/Poco/Data/MySQL/Binder.h

@@ -0,0 +1,263 @@
+//
+// Binder.h
+//
+// $Id: //poco/1.4/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 <mysql.h>
+
+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, Direction dir);
+		/// Binds an Int8.
+
+	virtual void bind(std::size_t pos, const Poco::UInt8& val, Direction dir);
+		/// Binds an UInt8.
+		
+	virtual void bind(std::size_t pos, const Poco::Int16& val, Direction dir);
+		/// Binds an Int16.
+		
+	virtual void bind(std::size_t pos, const Poco::UInt16& val, Direction dir);
+		/// Binds an UInt16.
+		
+	virtual void bind(std::size_t pos, const Poco::Int32& val, Direction dir);
+		/// Binds an Int32.
+		
+	virtual void bind(std::size_t pos, const Poco::UInt32& val, Direction dir);
+		/// Binds an UInt32.
+		
+	virtual void bind(std::size_t pos, const Poco::Int64& val, Direction dir);
+		/// Binds an Int64.
+		
+	virtual void bind(std::size_t pos, const Poco::UInt64& val, Direction dir);
+		/// Binds an UInt64.
+
+#ifndef POCO_LONG_IS_64_BIT
+	virtual void bind(std::size_t pos, const long& val, Direction dir = PD_IN);
+		/// Binds a long.
+#endif
+		
+	virtual void bind(std::size_t pos, const bool& val, Direction dir);
+		/// Binds a boolean.
+		
+	virtual void bind(std::size_t pos, const float& val, Direction dir);
+		/// Binds a float.
+		
+	virtual void bind(std::size_t pos, const double& val, Direction dir);
+		/// Binds a double.
+		
+	virtual void bind(std::size_t pos, const char& val, Direction dir);
+		/// Binds a single character.
+
+	virtual void bind(std::size_t pos, const std::string& val, Direction dir);
+		/// Binds a string.
+		
+	virtual void bind(std::size_t pos, const Poco::Data::BLOB& val, Direction dir);
+		/// Binds a BLOB.
+
+	virtual void bind(std::size_t pos, const DateTime& val, Direction dir);
+		/// Binds a DateTime.
+
+	virtual void bind(std::size_t pos, const Date& val, Direction dir);
+		/// Binds a Date.
+
+	virtual void bind(std::size_t pos, const Time& val, Direction dir);
+		/// Binds a Time.
+
+	virtual void bind(std::size_t pos, const NullData& val, Direction dir);
+		/// Binds a null.
+
+
+	virtual void bind(std::size_t pos, const std::vector<Poco::Int8>& val, Direction dir = PD_IN); 
+
+	virtual void bind(std::size_t pos, const std::deque<Poco::Int8>& val, Direction dir = PD_IN);
+
+	virtual void bind(std::size_t pos, const std::list<Poco::Int8>& val, Direction dir = PD_IN);
+
+	virtual void bind(std::size_t pos, const std::vector<Poco::UInt8>& val, Direction dir = PD_IN);
+
+	virtual void bind(std::size_t pos, const std::deque<Poco::UInt8>& val, Direction dir = PD_IN);
+
+	virtual void bind(std::size_t pos, const std::list<Poco::UInt8>& val, Direction dir = PD_IN);
+
+	virtual void bind(std::size_t pos, const std::vector<Poco::Int16>& val, Direction dir = PD_IN);
+
+	virtual void bind(std::size_t pos, const std::deque<Poco::Int16>& val, Direction dir = PD_IN);
+
+	virtual void bind(std::size_t pos, const std::list<Poco::Int16>& val, Direction dir = PD_IN);
+
+	virtual void bind(std::size_t pos, const std::vector<Poco::UInt16>& val, Direction dir = PD_IN);
+
+	virtual void bind(std::size_t pos, const std::deque<Poco::UInt16>& val, Direction dir = PD_IN);
+
+	virtual void bind(std::size_t pos, const std::list<Poco::UInt16>& val, Direction dir = PD_IN);
+
+	virtual void bind(std::size_t pos, const std::vector<Poco::Int32>& val, Direction dir = PD_IN);
+
+	virtual void bind(std::size_t pos, const std::deque<Poco::Int32>& val, Direction dir = PD_IN);
+	
+	virtual void bind(std::size_t pos, const std::list<Poco::Int32>& val, Direction dir = PD_IN); 
+	
+	virtual void bind(std::size_t pos, const std::vector<Poco::UInt32>& val, Direction dir = PD_IN); 
+	
+	virtual void bind(std::size_t pos, const std::deque<Poco::UInt32>& val, Direction dir = PD_IN);
+	
+	virtual void bind(std::size_t pos, const std::list<Poco::UInt32>& val, Direction dir = PD_IN); 
+	
+	virtual void bind(std::size_t pos, const std::vector<Poco::Int64>& val, Direction dir = PD_IN); 
+	
+	virtual void bind(std::size_t pos, const std::deque<Poco::Int64>& val, Direction dir = PD_IN);
+	
+	virtual void bind(std::size_t pos, const std::list<Poco::Int64>& val, Direction dir = PD_IN); 
+	
+	virtual void bind(std::size_t pos, const std::vector<Poco::UInt64>& val, Direction dir = PD_IN); 
+	
+	virtual void bind(std::size_t pos, const std::deque<Poco::UInt64>& val, Direction dir = PD_IN);
+	
+	virtual void bind(std::size_t pos, const std::list<Poco::UInt64>& val, Direction dir = PD_IN); 
+	
+	virtual void bind(std::size_t pos, const std::vector<bool>& val, Direction dir = PD_IN);
+
+	virtual void bind(std::size_t pos, const std::deque<bool>& val, Direction dir = PD_IN);
+
+	virtual void bind(std::size_t pos, const std::list<bool>& val, Direction dir = PD_IN);
+
+	virtual void bind(std::size_t pos, const std::vector<float>& val, Direction dir = PD_IN);
+
+	virtual void bind(std::size_t pos, const std::deque<float>& val, Direction dir = PD_IN);
+
+	virtual void bind(std::size_t pos, const std::list<float>& val, Direction dir = PD_IN);
+
+	virtual void bind(std::size_t pos, const std::vector<double>& val, Direction dir = PD_IN);
+
+	virtual void bind(std::size_t pos, const std::deque<double>& val, Direction dir = PD_IN);
+
+	virtual void bind(std::size_t pos, const std::list<double>& val, Direction dir = PD_IN);
+
+	virtual void bind(std::size_t pos, const std::vector<char>& val, Direction dir = PD_IN);
+
+	virtual void bind(std::size_t pos, const std::deque<char>& val, Direction dir = PD_IN);
+
+	virtual void bind(std::size_t pos, const std::list<char>& val, Direction dir = PD_IN);
+
+	virtual void bind(std::size_t pos, const std::vector<BLOB>& val, Direction dir = PD_IN);
+
+	virtual void bind(std::size_t pos, const std::deque<BLOB>& val, Direction dir = PD_IN);
+
+	virtual void bind(std::size_t pos, const std::list<BLOB>& val, Direction dir = PD_IN);
+
+	virtual void bind(std::size_t pos, const std::vector<DateTime>& val, Direction dir = PD_IN);
+
+	virtual void bind(std::size_t pos, const std::deque<DateTime>& val, Direction dir = PD_IN);
+
+	virtual void bind(std::size_t pos, const std::list<DateTime>& val, Direction dir = PD_IN);
+
+	virtual void bind(std::size_t pos, const std::vector<Date>& val, Direction dir = PD_IN);
+
+	virtual void bind(std::size_t pos, const std::deque<Date>& val, Direction dir = PD_IN);
+
+	virtual void bind(std::size_t pos, const std::list<Date>& val, Direction dir = PD_IN);
+
+	virtual void bind(std::size_t pos, const std::vector<Time>& val, Direction dir = PD_IN);
+
+	virtual void bind(std::size_t pos, const std::deque<Time>& val, Direction dir = PD_IN);
+
+	virtual void bind(std::size_t pos, const std::list<Time>& val, Direction dir = PD_IN);
+
+	virtual void bind(std::size_t pos, const std::vector<NullData>& val, Direction dir = PD_IN);
+
+	virtual void bind(std::size_t pos, const std::deque<NullData>& val, Direction dir = PD_IN);
+
+	virtual void bind(std::size_t pos, const std::list<NullData>& val, Direction dir = PD_IN);
+
+	virtual void bind(std::size_t pos, const std::vector<std::string>& val, Direction dir = PD_IN);
+
+	virtual void bind(std::size_t pos, const std::deque<std::string>& val, Direction dir = PD_IN);
+
+	virtual void bind(std::size_t pos, const std::list<std::string>& val, Direction dir = PD_IN);
+
+	size_t size() const;
+		/// Return count of binded parameters
+
+	MYSQL_BIND* getBindArray() const;
+		/// Return array
+
+    //void updateDates();
+        /// Update linked times
+
+private:
+
+	virtual void bind(std::size_t, const char* const&, Direction)
+		/// 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<MYSQL_BIND> _bindArray;
+    std::vector<MYSQL_TIME> _dates;
+};
+
+
+} } } // namespace Poco::Data::MySQL
+
+
+#endif // Data_MySQL_Binder_INCLUDED

+ 79 - 0
Data/MySQL/include/Poco/Data/MySQL/Connector.h

@@ -0,0 +1,79 @@
+//
+// Connector.h
+//
+// $Id: //poco/1.4/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 const std::string& name() const;
+		/// Returns the name associated with this connector.
+
+	virtual Poco::AutoPtr<Poco::Data::SessionImpl> 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

+ 336 - 0
Data/MySQL/include/Poco/Data/MySQL/Extractor.h

@@ -0,0 +1,336 @@
+//
+// Extractor.h
+//
+// $Id: //poco/1.4/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.
+		
+#ifndef POCO_LONG_IS_64_BIT
+	virtual bool extract(std::size_t pos, long& val);
+		/// Extracts a long. Returns false if null was received.
+#endif
+
+	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.
+
+	virtual bool extract(std::size_t pos, DateTime& val);
+		/// Extracts a DateTime. Returns false if null was received.
+
+	virtual bool extract(std::size_t pos, Date& val);
+		/// Extracts a Date. Returns false if null was received.
+
+	virtual bool extract(std::size_t pos, Time& val);
+		/// Extracts a Time. Returns false if null was received.
+
+	virtual bool extract(std::size_t pos, Any& val);
+		/// Extracts an Any. Returns false if null was received.
+
+	virtual bool extract(std::size_t pos, DynamicAny& val);
+		/// Extracts a DynamicAny. Returns false if null was received.
+
+	virtual bool isNull(std::size_t col, std::size_t row);
+		/// Returns true if the value at [col,row] position is null.
+
+	virtual void reset();
+		/// Resets any information internally cached by the extractor.
+
+        ////////////
+	// Not implemented extract functions
+	////////////
+	
+	virtual bool extract(std::size_t pos, std::vector<Poco::Int8>& val);
+		/// Extracts an Int8 vector.
+
+	virtual bool extract(std::size_t pos, std::deque<Poco::Int8>& val);
+		/// Extracts an Int8 deque.
+
+	virtual bool extract(std::size_t pos, std::list<Poco::Int8>& val);
+		/// Extracts an Int8 list.
+
+	virtual bool extract(std::size_t pos, std::vector<Poco::UInt8>& val);
+		/// Extracts an UInt8 vector.
+
+	virtual bool extract(std::size_t pos, std::deque<Poco::UInt8>& val);
+		/// Extracts an UInt8 deque.
+
+	virtual bool extract(std::size_t pos, std::list<Poco::UInt8>& val);
+		/// Extracts an UInt8 list.
+
+	virtual bool extract(std::size_t pos, std::vector<Poco::Int16>& val);
+		/// Extracts an Int16 vector.
+
+	virtual bool extract(std::size_t pos, std::deque<Poco::Int16>& val);
+		/// Extracts an Int16 deque.
+
+	virtual bool extract(std::size_t pos, std::list<Poco::Int16>& val);
+		/// Extracts an Int16 list.
+
+	virtual bool extract(std::size_t pos, std::vector<Poco::UInt16>& val);
+		/// Extracts an UInt16 vector.
+
+	virtual bool extract(std::size_t pos, std::deque<Poco::UInt16>& val);
+		/// Extracts an UInt16 deque.
+
+	virtual bool extract(std::size_t pos, std::list<Poco::UInt16>& val);
+		/// Extracts an UInt16 list.
+
+	virtual bool extract(std::size_t pos, std::vector<Poco::Int32>& val);
+		/// Extracts an Int32 vector.
+
+	virtual bool extract(std::size_t pos, std::deque<Poco::Int32>& val);
+		/// Extracts an Int32 deque.
+
+	virtual bool extract(std::size_t pos, std::list<Poco::Int32>& val);
+		/// Extracts an Int32 list.
+
+	virtual bool extract(std::size_t pos, std::vector<Poco::UInt32>& val);
+		/// Extracts an UInt32 vector.
+
+	virtual bool extract(std::size_t pos, std::deque<Poco::UInt32>& val);
+		/// Extracts an UInt32 deque.
+
+	virtual bool extract(std::size_t pos, std::list<Poco::UInt32>& val);
+		/// Extracts an UInt32 list.
+
+	virtual bool extract(std::size_t pos, std::vector<Poco::Int64>& val);
+		/// Extracts an Int64 vector.
+
+	virtual bool extract(std::size_t pos, std::deque<Poco::Int64>& val);
+		/// Extracts an Int64 deque.
+
+	virtual bool extract(std::size_t pos, std::list<Poco::Int64>& val);
+		/// Extracts an Int64 list.
+
+	virtual bool extract(std::size_t pos, std::vector<Poco::UInt64>& val);
+		/// Extracts an UInt64 vector.
+
+	virtual bool extract(std::size_t pos, std::deque<Poco::UInt64>& val);
+		/// Extracts an UInt64 deque.
+
+	virtual bool extract(std::size_t pos, std::list<Poco::UInt64>& val);
+		/// Extracts an UInt64 list.
+
+#ifndef POCO_LONG_IS_64_BIT
+	virtual bool extract(std::size_t pos, std::vector<long>& val);
+		/// Extracts a long vector.
+
+	virtual bool extract(std::size_t pos, std::deque<long>& val);
+		/// Extracts a long deque.
+
+	virtual bool extract(std::size_t pos, std::list<long>& val);
+		/// Extracts a long list.
+#endif
+
+	virtual bool extract(std::size_t pos, std::vector<bool>& val);
+		/// Extracts a boolean vector.
+
+	virtual bool extract(std::size_t pos, std::deque<bool>& val);
+		/// Extracts a boolean deque.
+
+	virtual bool extract(std::size_t pos, std::list<bool>& val);
+		/// Extracts a boolean list.
+
+	virtual bool extract(std::size_t pos, std::vector<float>& val);
+		/// Extracts a float vector.
+
+	virtual bool extract(std::size_t pos, std::deque<float>& val);
+		/// Extracts a float deque.
+
+	virtual bool extract(std::size_t pos, std::list<float>& val);
+		/// Extracts a float list.
+
+	virtual bool extract(std::size_t pos, std::vector<double>& val);
+		/// Extracts a double vector.
+
+	virtual bool extract(std::size_t pos, std::deque<double>& val);
+		/// Extracts a double deque.
+
+	virtual bool extract(std::size_t pos, std::list<double>& val);
+		/// Extracts a double list.
+
+	virtual bool extract(std::size_t pos, std::vector<char>& val);
+		/// Extracts a character vector.
+
+	virtual bool extract(std::size_t pos, std::deque<char>& val);
+		/// Extracts a character deque.
+
+	virtual bool extract(std::size_t pos, std::list<char>& val);
+		/// Extracts a character list.
+
+	virtual bool extract(std::size_t pos, std::vector<std::string>& val);
+		/// Extracts a string vector.
+
+	virtual bool extract(std::size_t pos, std::deque<std::string>& val);
+		/// Extracts a string deque.
+
+	virtual bool extract(std::size_t pos, std::list<std::string>& val);
+		/// Extracts a string list.
+
+	virtual bool extract(std::size_t pos, std::vector<BLOB>& val);
+		/// Extracts a BLOB vector.
+
+	virtual bool extract(std::size_t pos, std::deque<BLOB>& val);
+		/// Extracts a BLOB deque.
+
+	virtual bool extract(std::size_t pos, std::list<BLOB>& val);
+		/// Extracts a BLOB list.
+
+	virtual bool extract(std::size_t pos, std::vector<DateTime>& val);
+		/// Extracts a DateTime vector.
+
+	virtual bool extract(std::size_t pos, std::deque<DateTime>& val);
+		/// Extracts a DateTime deque.
+
+	virtual bool extract(std::size_t pos, std::list<DateTime>& val);
+		/// Extracts a DateTime list.
+
+	virtual bool extract(std::size_t pos, std::vector<Date>& val);
+		/// Extracts a Date vector.
+
+	virtual bool extract(std::size_t pos, std::deque<Date>& val);
+		/// Extracts a Date deque.
+
+	virtual bool extract(std::size_t pos, std::list<Date>& val);
+		/// Extracts a Date list.
+
+	virtual bool extract(std::size_t pos, std::vector<Time>& val);
+		/// Extracts a Time vector.
+
+	virtual bool extract(std::size_t pos, std::deque<Time>& val);
+		/// Extracts a Time deque.
+
+	virtual bool extract(std::size_t pos, std::list<Time>& val);
+		/// Extracts a Time list.
+
+	virtual bool extract(std::size_t pos, std::vector<Any>& val);
+		/// Extracts an Any vector.
+
+	virtual bool extract(std::size_t pos, std::deque<Any>& val);
+		/// Extracts an Any deque.
+
+	virtual bool extract(std::size_t pos, std::list<Any>& val);
+		/// Extracts an Any list.
+
+	virtual bool extract(std::size_t pos, std::vector<DynamicAny>& val);
+		/// Extracts a DynamicAny vector.
+
+	virtual bool extract(std::size_t pos, std::deque<DynamicAny>& val);
+		/// Extracts a DynamicAny deque.
+
+	virtual bool extract(std::size_t pos, std::list<DynamicAny>& val);
+		/// Extracts a DynamicAny list.
+	
+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

+ 90 - 0
Data/MySQL/include/Poco/Data/MySQL/MySQL.h

@@ -0,0 +1,90 @@
+//
+// MySQL.h
+//
+// $Id: //poco/1.4/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

+ 178 - 0
Data/MySQL/include/Poco/Data/MySQL/MySQLException.h

@@ -0,0 +1,178 @@
+//
+// MySQLException.h
+//
+// $Id: //poco/1.4/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 <typeinfo>
+#include <string>
+
+
+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 from string.
+
+	ConnectionException(const std::string& text, MYSQL* h);
+		/// Creates ConnectionException from string and handle.
+
+private:
+
+	static std::string compose(const std::string& text, MYSQL* h);
+
+};
+
+
+class TransactionException : public ConnectionException
+	/// TrabsactionException
+{
+public:
+
+	TransactionException(const std::string& msg);
+		/// Creates TransactionException from string.
+
+	TransactionException(const std::string& text, MYSQL* h);
+		/// Creates TransactionException from string and handle.
+};
+
+
+class StatementException : public MySQLException
+	/// StatementException
+{
+public:
+
+	StatementException(const std::string& msg);
+		/// Creates StatementException from string.
+
+	StatementException(const std::string& text, MYSQL_STMT* h, const std::string& stmt = "");
+		/// Creates StatementException from string and handle.
+
+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

+ 125 - 0
Data/MySQL/include/Poco/Data/MySQL/MySQLStatementImpl.h

@@ -0,0 +1,125 @@
+//
+// MySQLstatementImpl.h
+//
+// $Id: //poco/1.4/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(SessionImpl& s);
+		/// Creates the MySQLStatementImpl.
+		
+	~MySQLStatementImpl();
+		/// Destroys the MySQLStatementImpl.
+		
+protected:
+
+	virtual Poco::UInt32 columnsReturned() const;
+		/// Returns number of columns returned by query.		
+
+	virtual Poco::UInt32 affectedRowCount() const;
+		/// Returns the number of affected rows.
+		/// Used to find out the number of rows affected by insert, delete or update.
+	
+	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 Poco::UInt32 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 bool canCompile() const;
+		/// Returns true if another compile is possible.
+		
+	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

+ 89 - 0
Data/MySQL/include/Poco/Data/MySQL/ResultMetadata.h

@@ -0,0 +1,89 @@
+//
+// ResultMetadata.h
+//
+// $Id: //poco/1.4/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 <mysql.h>
+#include <vector>
+#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();
+		/// Returns pointer to native row.
+
+	std::size_t length(std::size_t pos) const;
+		/// Returns the length.
+
+	const char* rawData(std::size_t pos) const;
+		/// Returns raw data.
+
+	bool isNull(std::size_t pos) const;
+		/// Returns true if value at pos is null.
+
+private:
+	std::vector<MetaColumn>    _columns;
+	std::vector<MYSQL_BIND>    _row;
+	std::vector<char>          _buffer;
+	std::vector<unsigned long> _lengths;
+	std::vector<my_bool>       _isNull;
+};
+
+}}}
+
+#endif //Data_MySQL_ResultMetadata_INCLUDED

+ 108 - 0
Data/MySQL/include/Poco/Data/MySQL/SessionHandle.h

@@ -0,0 +1,108 @@
+//
+// SesssionHandle.h
+//
+// $Id: //poco/1.4/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 <mysql.h>
+#include "Poco/Data/MySQL/MySQLException.h"
+
+#include <vector>
+
+namespace Poco {
+namespace Data {
+namespace MySQL {
+
+class SessionHandle
+	/// MySQL session handle
+{
+public:
+
+	explicit SessionHandle(MYSQL* mysql);
+        /// Creates session handle
+
+	~SessionHandle();
+        /// Destroy handle, close connection
+
+	void options(mysql_option opt);
+        /// Set connection options
+
+	void options(mysql_option opt, bool b);
+        /// Set connection options
+
+	void connect(const char* host, const char* user, const char* password, const char* db, unsigned int port);
+        /// Connect to server
+
+	void close();
+        /// Close connection
+
+	void startTransaction();
+        /// Start transaction
+
+	void commit();
+        /// Commit transaction
+
+	void rollback();
+        /// Rollback trabsaction
+
+	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

+ 135 - 0
Data/MySQL/include/Poco/Data/MySQL/SessionImpl.h

@@ -0,0 +1,135 @@
+//
+// SessionImpl.h
+//
+// $Id: //poco/1.4/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<SessionImpl>
+	/// Implements SessionImpl interface
+{
+public:
+
+	SessionImpl(const std::string& connectionString);
+		/// Creates the SessionImpl. Opens a connection to the database
+		///
+		/// Connection string format:
+		///     <str> == <assignment> | <assignment> ';' <str>
+		///     <assignment> == <name> '=' <value>
+		///     <name> == 'host' | 'port' | 'user' | 'password' | 'db' } 'compress' | 'auto-reconnect'
+		///     <value> == [~;]*
+		///
+		/// 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
+
+
+    SessionHandle& handle();
+        // Get handle
+
+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)));
+}
+
+inline SessionHandle& SessionImpl::handle()
+{
+    return _mysql;
+}
+
+} } } // namespace Poco::Data::MySQL
+
+
+#endif // Data_MySQL_SessionImpl_INCLUDED

+ 118 - 0
Data/MySQL/include/Poco/Data/MySQL/StatementExecutor.h

@@ -0,0 +1,118 @@
+//
+// StatementExecutor.h
+//
+// $Id: //poco/1.4/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 <mysql.h>
+#include "Poco/Data/MySQL/MySQLException.h"
+
+#include <vector>
+
+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

+ 623 - 0
Data/MySQL/src/Binder.cpp

@@ -0,0 +1,623 @@
+//
+// MySQLException.cpp
+//
+// $Id: //poco/1.4/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, Direction dir)
+{
+    poco_assert(dir == PD_IN);
+	realBind(pos, MYSQL_TYPE_TINY, &val, 0);
+}
+
+
+void Binder::bind(std::size_t pos, const Poco::UInt8& val, Direction dir)
+{
+    poco_assert(dir == PD_IN);
+	realBind(pos, MYSQL_TYPE_TINY, &val, 0);
+}	
+
+
+void Binder::bind(std::size_t pos, const Poco::Int16& val, Direction dir)
+{
+    poco_assert(dir == PD_IN);
+	realBind(pos, MYSQL_TYPE_SHORT, &val, 0);
+}
+
+	
+void Binder::bind(std::size_t pos, const Poco::UInt16& val, Direction dir)
+{
+    poco_assert(dir == PD_IN);
+	realBind(pos, MYSQL_TYPE_SHORT, &val, 0);
+}
+
+	
+void Binder::bind(std::size_t pos, const Poco::Int32& val, Direction dir)
+{
+    poco_assert(dir == PD_IN);
+	realBind(pos, MYSQL_TYPE_LONG, &val, 0);
+}
+
+	
+void Binder::bind(std::size_t pos, const Poco::UInt32& val, Direction dir)
+{
+    poco_assert(dir == PD_IN);
+	realBind(pos, MYSQL_TYPE_LONG, &val, 0);
+}
+
+	
+void Binder::bind(std::size_t pos, const Poco::Int64& val, Direction dir)
+{
+    poco_assert(dir == PD_IN);
+	realBind(pos, MYSQL_TYPE_LONGLONG, &val, 0);
+}
+
+	
+void Binder::bind(std::size_t pos, const Poco::UInt64& val, Direction dir)
+{
+    poco_assert(dir == PD_IN);
+	realBind(pos, MYSQL_TYPE_LONGLONG, &val, 0);
+}
+
+
+#ifndef POCO_LONG_IS_64_BIT
+void Binder::bind(std::size_t pos, const long& val, Direction dir)
+{
+    poco_assert(dir == PD_IN);
+    realBind(pos, MYSQL_TYPE_LONGLONG, &val, 0);
+}
+#endif
+
+
+void Binder::bind(std::size_t pos, const bool& val, Direction dir)
+{
+    poco_assert(dir == PD_IN);
+	realBind(pos, MYSQL_TYPE_TINY, &val, 0);
+}
+
+	
+void Binder::bind(std::size_t pos, const float& val, Direction dir)
+{
+    poco_assert(dir == PD_IN);
+	realBind(pos, MYSQL_TYPE_FLOAT, &val, 0);
+}
+
+	
+void Binder::bind(std::size_t pos, const double& val, Direction dir)
+{
+    poco_assert(dir == PD_IN);
+	realBind(pos, MYSQL_TYPE_DOUBLE, &val, 0);
+}
+
+	
+void Binder::bind(std::size_t pos, const char& val, Direction dir)
+{
+    poco_assert(dir == PD_IN);
+	realBind(pos, MYSQL_TYPE_TINY, &val, 0);
+}
+
+
+void Binder::bind(std::size_t pos, const std::string& val, Direction dir)
+{
+    poco_assert(dir == PD_IN);
+	realBind(pos, MYSQL_TYPE_STRING, val.c_str(), static_cast<int>(val.length()));
+}
+
+	
+void Binder::bind(std::size_t pos, const Poco::Data::BLOB& val, Direction dir)
+{
+    poco_assert(dir == PD_IN);
+	realBind(pos, MYSQL_TYPE_BLOB, val.rawContent(), static_cast<int>(val.size()));
+}
+
+
+void Binder::bind(std::size_t pos, const DateTime& val, Direction dir)
+{
+    poco_assert(dir == PD_IN);
+    MYSQL_TIME mt = {0};
+
+    mt.year        = val.year();
+    mt.month       = val.month();
+    mt.day         = val.day();
+    mt.hour        = val.hour();
+    mt.minute      = val.minute();
+    mt.second      = val.second();
+    mt.second_part = val.millisecond();
+    
+    mt.time_type  = MYSQL_TIMESTAMP_DATETIME;
+    
+    _dates.push_back(mt);
+    
+    realBind(pos, MYSQL_TYPE_DATETIME, &_dates.back(), sizeof(mt));    
+}
+
+
+void Binder::bind(std::size_t pos, const Date& val, Direction dir)
+{
+    poco_assert(dir == PD_IN);
+    MYSQL_TIME mt = {0};
+
+    mt.year  = val.year();
+    mt.month = val.month();
+    mt.day   = val.day();
+
+    _dates.push_back(mt);
+    
+    realBind(pos, MYSQL_TYPE_DATE, &_dates.back(), sizeof(mt));    
+}
+
+
+void Binder::bind(std::size_t pos, const Time& val, Direction dir)
+{
+    poco_assert(dir == PD_IN);
+    MYSQL_TIME mt = {0};
+
+    mt.hour   = val.hour();
+    mt.minute = val.minute();
+    mt.second = val.second();
+
+    mt.time_type = MYSQL_TIMESTAMP_TIME;
+    
+    _dates.push_back(mt);
+    
+    realBind(pos, MYSQL_TYPE_TIME, &_dates.back(), sizeof(mt));    
+}
+
+
+void Binder::bind(std::size_t pos, const NullData&, Direction dir)
+{
+    poco_assert(dir == PD_IN);
+    realBind(pos, MYSQL_TYPE_NULL, 0, 0);
+}
+
+
+size_t Binder::size() const
+{
+	return _bindArray.size();
+}
+
+
+MYSQL_BIND* Binder::getBindArray() const
+{
+	if (_bindArray.size() == 0)
+	{
+		return 0;
+	}
+
+	return const_cast<MYSQL_BIND*>(&_bindArray[0]);
+}
+
+
+/*void Binder::updateDates()
+{
+    for (size_t i = 0; i < _dates.size(); i++)
+    {
+        switch (_dates[i].mt.time_type)
+        {
+        case MYSQL_TIMESTAMP_DATE:
+            _dates[i].mt.year  = _dates[i].link.date->year();
+            _dates[i].mt.month = _dates[i].link.date->month();
+            _dates[i].mt.day   = _dates[i].link.date->day();
+            break;
+        case MYSQL_TIMESTAMP_DATETIME:
+            _dates[i].mt.year        = _dates[i].link.dateTime->year();
+            _dates[i].mt.month       = _dates[i].link.dateTime->month();
+            _dates[i].mt.day         = _dates[i].link.dateTime->day();
+            _dates[i].mt.hour        = _dates[i].link.dateTime->hour();
+            _dates[i].mt.minute      = _dates[i].link.dateTime->minute();
+            _dates[i].mt.second      = _dates[i].link.dateTime->second();
+            _dates[i].mt.second_part = _dates[i].link.dateTime->millisecond();
+            break;
+        case MYSQL_TIMESTAMP_TIME:
+            _dates[i].mt.hour   = _dates[i].link.time->hour();
+            _dates[i].mt.minute = _dates[i].link.time->minute();
+            _dates[i].mt.second = _dates[i].link.time->second();
+            break;
+        }
+    }
+}*/
+
+///////////////////
+//
+// Private 
+//
+////////////////////
+
+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<void*>(buffer);
+	b.buffer_length = length;
+
+	_bindArray[pos] = b;
+}
+
+
+void Binder::bind(std::size_t pos, const std::vector<Poco::Int8>& val, Direction dir) 
+{
+    throw NotImplementedException();
+}
+
+
+void Binder::bind(std::size_t pos, const std::deque<Poco::Int8>& val, Direction dir)
+{
+    throw NotImplementedException();
+}
+
+
+void Binder::bind(std::size_t pos, const std::list<Poco::Int8>& val, Direction dir) 
+{
+    throw NotImplementedException();
+}
+
+
+void Binder::bind(std::size_t pos, const std::vector<Poco::UInt8>& val, Direction dir) 
+{
+    throw NotImplementedException();
+}
+
+
+void Binder::bind(std::size_t pos, const std::deque<Poco::UInt8>& val, Direction dir)
+{
+    throw NotImplementedException();
+}
+
+
+void Binder::bind(std::size_t pos, const std::list<Poco::UInt8>& val, Direction dir) 
+{
+    throw NotImplementedException();
+}
+
+
+void Binder::bind(std::size_t pos, const std::vector<Poco::Int16>& val, Direction dir) 
+{
+    throw NotImplementedException();
+}
+
+
+void Binder::bind(std::size_t pos, const std::deque<Poco::Int16>& val, Direction dir)
+{
+    throw NotImplementedException();
+}
+
+
+void Binder::bind(std::size_t pos, const std::list<Poco::Int16>& val, Direction dir) 
+{
+    throw NotImplementedException();
+}
+
+
+void Binder::bind(std::size_t pos, const std::vector<Poco::UInt16>& val, Direction dir) 
+{
+    throw NotImplementedException();
+}
+
+
+void Binder::bind(std::size_t pos, const std::deque<Poco::UInt16>& val, Direction dir)
+{
+    throw NotImplementedException();
+}
+
+
+void Binder::bind(std::size_t pos, const std::list<Poco::UInt16>& val, Direction dir) 
+{
+    throw NotImplementedException();
+}
+
+
+void Binder::bind(std::size_t pos, const std::vector<Poco::Int32>& val, Direction dir) 
+{
+    throw NotImplementedException();
+}
+
+
+void Binder::bind(std::size_t pos, const std::deque<Poco::Int32>& val, Direction dir)
+{
+    throw NotImplementedException();
+}
+
+
+void Binder::bind(std::size_t pos, const std::list<Poco::Int32>& val, Direction dir) 
+{
+    throw NotImplementedException();
+}
+
+
+void Binder::bind(std::size_t pos, const std::vector<Poco::UInt32>& val, Direction dir) 
+{
+    throw NotImplementedException();
+}
+
+
+void Binder::bind(std::size_t pos, const std::deque<Poco::UInt32>& val, Direction dir)
+{
+    throw NotImplementedException();
+}
+
+
+void Binder::bind(std::size_t pos, const std::list<Poco::UInt32>& val, Direction dir) 
+{
+    throw NotImplementedException();
+}
+
+
+void Binder::bind(std::size_t pos, const std::vector<Poco::Int64>& val, Direction dir) 
+{
+    throw NotImplementedException();
+}
+
+
+void Binder::bind(std::size_t pos, const std::deque<Poco::Int64>& val, Direction dir)
+{
+    throw NotImplementedException();
+}
+
+
+void Binder::bind(std::size_t pos, const std::list<Poco::Int64>& val, Direction dir) 
+{
+    throw NotImplementedException();
+}
+
+
+void Binder::bind(std::size_t pos, const std::vector<Poco::UInt64>& val, Direction dir) 
+{
+    throw NotImplementedException();
+}
+
+
+void Binder::bind(std::size_t pos, const std::deque<Poco::UInt64>& val, Direction dir)
+{
+    throw NotImplementedException();
+}
+
+
+void Binder::bind(std::size_t pos, const std::list<Poco::UInt64>& val, Direction dir) 
+{
+    throw NotImplementedException();
+}
+
+
+void Binder::bind(std::size_t pos, const std::vector<bool>& val, Direction dir) 
+{
+    throw NotImplementedException();
+}
+
+
+void Binder::bind(std::size_t pos, const std::deque<bool>& val, Direction dir)
+{
+    throw NotImplementedException();
+}
+
+
+void Binder::bind(std::size_t pos, const std::list<bool>& val, Direction dir) 
+{
+    throw NotImplementedException();
+}
+
+
+void Binder::bind(std::size_t pos, const std::vector<float>& val, Direction dir) 
+{
+    throw NotImplementedException();
+}
+
+
+void Binder::bind(std::size_t pos, const std::deque<float>& val, Direction dir)
+{
+    throw NotImplementedException();
+}
+
+
+void Binder::bind(std::size_t pos, const std::list<float>& val, Direction dir) 
+{
+    throw NotImplementedException();
+}
+
+
+void Binder::bind(std::size_t pos, const std::vector<double>& val, Direction dir) 
+{
+    throw NotImplementedException();
+}
+
+
+void Binder::bind(std::size_t pos, const std::deque<double>& val, Direction dir)
+{
+    throw NotImplementedException();
+}
+
+
+void Binder::bind(std::size_t pos, const std::list<double>& val, Direction dir) 
+{
+    throw NotImplementedException();
+}
+
+
+void Binder::bind(std::size_t pos, const std::vector<char>& val, Direction dir) 
+{
+    throw NotImplementedException();
+}
+
+
+void Binder::bind(std::size_t pos, const std::deque<char>& val, Direction dir)
+{
+    throw NotImplementedException();
+}
+
+
+void Binder::bind(std::size_t pos, const std::list<char>& val, Direction dir) 
+{
+    throw NotImplementedException();
+}
+
+
+void Binder::bind(std::size_t pos, const std::vector<Poco::Data::BLOB>& val, Direction dir) 
+{
+    throw NotImplementedException();
+}
+
+
+void Binder::bind(std::size_t pos, const std::deque<Poco::Data::BLOB>& val, Direction dir)
+{
+    throw NotImplementedException();
+}
+
+
+void Binder::bind(std::size_t pos, const std::list<Poco::Data::BLOB>& val, Direction dir) 
+{
+    throw NotImplementedException();
+}
+
+
+void Binder::bind(std::size_t pos, const std::vector<Poco::DateTime>& val, Direction dir) 
+{
+    throw NotImplementedException();
+}
+
+
+void Binder::bind(std::size_t pos, const std::deque<Poco::DateTime>& val, Direction dir)
+{
+    throw NotImplementedException();
+}
+
+
+void Binder::bind(std::size_t pos, const std::list<Poco::DateTime>& val, Direction dir) 
+{
+    throw NotImplementedException();
+}
+
+
+void Binder::bind(std::size_t pos, const std::vector<Poco::Data::Date>& val, Direction dir) 
+{
+    throw NotImplementedException();
+}
+
+
+void Binder::bind(std::size_t pos, const std::deque<Poco::Data::Date>& val, Direction dir)
+{
+    throw NotImplementedException();
+}
+
+
+void Binder::bind(std::size_t pos, const std::list<Poco::Data::Date>& val, Direction dir) 
+{
+    throw NotImplementedException();
+}
+
+
+void Binder::bind(std::size_t pos, const std::vector<Poco::Data::Time>& val, Direction dir) 
+{
+    throw NotImplementedException();
+}
+
+
+void Binder::bind(std::size_t pos, const std::deque<Poco::Data::Time>& val, Direction dir)
+{
+    throw NotImplementedException();
+}
+
+
+void Binder::bind(std::size_t pos, const std::list<Poco::Data::Time>& val, Direction dir) 
+{
+    throw NotImplementedException();
+}
+
+
+void Binder::bind(std::size_t pos, const std::vector<Poco::Data::NullData>& val, Direction dir) 
+{
+    throw NotImplementedException();
+}
+
+
+void Binder::bind(std::size_t pos, const std::deque<Poco::Data::NullData>& val, Direction dir)
+{
+    throw NotImplementedException();
+}
+
+
+void Binder::bind(std::size_t pos, const std::list<Poco::Data::NullData>& val, Direction dir) 
+{
+    throw NotImplementedException();
+}
+
+
+void Binder::bind(std::size_t pos, const std::vector<std::string>& val, Direction dir) 
+{
+    throw NotImplementedException();
+}
+
+
+void Binder::bind(std::size_t pos, const std::deque<std::string>& val, Direction dir)
+{
+    throw NotImplementedException();
+}
+
+
+void Binder::bind(std::size_t pos, const std::list<std::string>& val, Direction dir) 
+{
+    throw NotImplementedException();
+}
+
+
+} } } // namespace Poco::Data::MySQL

+ 92 - 0
Data/MySQL/src/Connector.cpp

@@ -0,0 +1,92 @@
+//
+// MySQLException.cpp
+//
+// $Id: //poco/1.4/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 <mysql.h>
+
+
+namespace Poco {
+namespace Data {
+namespace MySQL {
+
+
+std::string Connector::KEY("MySQL");
+
+
+Connector::Connector()
+{
+}
+
+
+Connector::~Connector()
+{
+}
+
+const std::string& Connector::name() const
+{
+    return KEY;
+}
+
+Poco::AutoPtr<Poco::Data::SessionImpl> Connector::createSession(const std::string& connectionString)
+{
+	return Poco::AutoPtr<Poco::Data::SessionImpl>(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(new Connector());
+}
+
+
+void Connector::unregisterConnector()
+{
+	Poco::Data::SessionFactory::instance().remove(KEY);
+	mysql_library_end();
+}
+
+
+} } } // namespace Poco::Data::MySQL
+

+ 622 - 0
Data/MySQL/src/Extractor.cpp

@@ -0,0 +1,622 @@
+//
+// MySQLException.cpp
+//
+// $Id: //poco/1.4/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"
+
+#include "Poco/Data/Date.h"
+#include "Poco/Data/Time.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);
+}
+
+	
+#ifndef POCO_LONG_IS_64_BIT
+bool Extractor::extract(std::size_t pos, long& val)
+		/// Extracts a long. Returns false if null was received.
+{
+    return realExtractFixed(pos, MYSQL_TYPE_LONGLONG, &val);
+}
+#endif
+
+
+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)
+        throw MySQLException("Extractor: attempt to extract more paremeters, than query result contain");
+    
+    if (_metadata.isNull(static_cast<Poco::UInt32>(pos)))
+	return false;
+    
+    if (_metadata.metaColumn(static_cast<Poco::UInt32>(pos)).type() != Poco::Data::MetaColumn::FDT_STRING)
+        throw MySQLException("Extractor: not a string");
+    
+    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)
+        throw MySQLException("Extractor: attempt to extract more paremeters, than query result contain");
+    
+    if (_metadata.isNull(static_cast<Poco::UInt32>(pos)))
+	return false;
+    
+    if (_metadata.metaColumn(static_cast<Poco::UInt32>(pos)).type() != Poco::Data::MetaColumn::FDT_BLOB)
+        throw MySQLException("Extractor: not a blob");
+    
+    val.assignRaw(_metadata.rawData(pos), _metadata.length(pos));
+    return true;
+}
+
+
+bool Extractor::extract(std::size_t pos, DateTime& val)
+{
+    MYSQL_TIME mt = {0};
+
+    if (!realExtractFixed(pos, MYSQL_TYPE_DATETIME, &mt))
+        return false;
+
+    val.assign(mt.year, mt.month, mt.day, mt.hour, mt.minute, mt.second, mt.second_part, 0);
+    return true;
+}
+
+
+bool Extractor::extract(std::size_t pos, Date& val)
+{
+    MYSQL_TIME mt = {0};
+
+    if (!realExtractFixed(pos, MYSQL_TYPE_DATE, &mt))
+        return false;
+
+    val.assign(mt.year, mt.month, mt.day);
+    return true;
+}
+
+
+bool Extractor::extract(std::size_t pos, Time& val)
+{
+    MYSQL_TIME mt = {0};
+
+    if (!realExtractFixed(pos, MYSQL_TYPE_TIME, &mt))
+        return false;
+
+    val.assign(mt.hour, mt.minute, mt.second);
+    return true;
+}
+
+
+bool Extractor::extract(std::size_t pos, Any& val)
+{
+    return false;
+}
+
+
+bool Extractor::extract(std::size_t pos, DynamicAny& val)
+{
+    return false;
+}
+
+
+bool Extractor::isNull(std::size_t col, std::size_t row)
+{
+    poco_assert(row == POCO_DATA_INVALID_ROW);
+
+    if (_metadata.columnsReturned() <= col)
+        throw MySQLException("Extractor: attempt to extract more paremeters, than query result contain");
+
+    if (_metadata.isNull(static_cast<Poco::UInt32>(col)))
+        return true;
+
+    return false;
+}
+
+void Extractor::reset()
+{
+    AbstractExtractor::reset();
+}
+
+
+bool Extractor::realExtractFixed(std::size_t pos, enum_field_types type, void* buffer, size_t length)
+{
+    MYSQL_BIND bind = {0};
+    my_bool isNull = 0;
+
+    bind.is_null       = &isNull;
+    bind.buffer_type   = type;
+    bind.buffer        = buffer;
+    bind.buffer_length = static_cast<unsigned long>(length);
+    
+    if (!_stmt.fetchColumn(pos, &bind))
+        return false;
+
+    return isNull == 0;
+}
+
+
+//////////////
+// Not implemented
+//////////////
+
+
+bool Extractor::extract(std::size_t , std::vector<Poco::Int8>& )
+{
+    throw NotImplementedException("std::vector extractor must be implemented.");
+}
+
+
+bool Extractor::extract(std::size_t , std::deque<Poco::Int8>& )
+{
+    throw NotImplementedException("std::deque extractor must be implemented.");
+}
+
+
+bool Extractor::extract(std::size_t , std::list<Poco::Int8>& )
+{
+    throw NotImplementedException("std::list extractor must be implemented.");
+}
+    
+    
+bool Extractor::extract(std::size_t , std::vector<Poco::UInt8>& )
+{
+    throw NotImplementedException("std::vector extractor must be implemented.");
+}
+
+
+bool Extractor::extract(std::size_t , std::deque<Poco::UInt8>& )
+{
+    throw NotImplementedException("std::deque extractor must be implemented.");
+}
+
+
+bool Extractor::extract(std::size_t , std::list<Poco::UInt8>& )
+{
+    throw NotImplementedException("std::list extractor must be implemented.");
+}
+
+
+bool Extractor::extract(std::size_t , std::vector<Poco::Int16>& )
+{
+    throw NotImplementedException("std::vector extractor must be implemented.");
+}
+
+
+bool Extractor::extract(std::size_t , std::deque<Poco::Int16>& )
+{
+    throw NotImplementedException("std::deque extractor must be implemented.");
+}
+
+
+bool Extractor::extract(std::size_t , std::list<Poco::Int16>& )
+{
+    throw NotImplementedException("std::list extractor must be implemented.");
+}
+
+
+bool Extractor::extract(std::size_t , std::vector<Poco::UInt16>& )
+{
+    throw NotImplementedException("std::vector extractor must be implemented.");
+}
+
+
+bool Extractor::extract(std::size_t , std::deque<Poco::UInt16>& )
+{
+    throw NotImplementedException("std::deque extractor must be implemented.");
+}
+
+
+bool Extractor::extract(std::size_t , std::list<Poco::UInt16>& )
+{
+    throw NotImplementedException("std::list extractor must be implemented.");
+}
+
+
+bool Extractor::extract(std::size_t , std::vector<Poco::Int32>& )
+{
+    throw NotImplementedException("std::vector extractor must be implemented.");
+}
+
+
+bool Extractor::extract(std::size_t , std::deque<Poco::Int32>& )
+{
+    throw NotImplementedException("std::deque extractor must be implemented.");
+}
+
+
+bool Extractor::extract(std::size_t , std::list<Poco::Int32>& )
+{
+    throw NotImplementedException("std::list extractor must be implemented.");
+}
+
+
+bool Extractor::extract(std::size_t , std::vector<Poco::UInt32>& )
+{
+    throw NotImplementedException("std::vector extractor must be implemented.");
+}
+
+
+bool Extractor::extract(std::size_t , std::deque<Poco::UInt32>& )
+{
+    throw NotImplementedException("std::deque extractor must be implemented.");
+}
+
+
+bool Extractor::extract(std::size_t , std::list<Poco::UInt32>& )
+{
+    throw NotImplementedException("std::list extractor must be implemented.");
+}
+
+
+bool Extractor::extract(std::size_t , std::vector<Poco::Int64>& )
+{
+    throw NotImplementedException("std::vector extractor must be implemented.");
+}
+
+
+bool Extractor::extract(std::size_t , std::deque<Poco::Int64>& )
+{
+    throw NotImplementedException("std::deque extractor must be implemented.");
+}
+
+
+bool Extractor::extract(std::size_t , std::list<Poco::Int64>& )
+{
+    throw NotImplementedException("std::list extractor must be implemented.");
+}
+
+
+bool Extractor::extract(std::size_t , std::vector<Poco::UInt64>& )
+{
+    throw NotImplementedException("std::vector extractor must be implemented.");
+}
+
+
+bool Extractor::extract(std::size_t , std::deque<Poco::UInt64>& )
+{
+    throw NotImplementedException("std::deque extractor must be implemented.");
+}
+
+
+bool Extractor::extract(std::size_t , std::list<Poco::UInt64>& )
+{
+    throw NotImplementedException("std::list extractor must be implemented.");
+}
+
+
+#ifndef POCO_LONG_IS_64_BIT
+bool Extractor::extract(std::size_t , std::vector<long>& )
+{
+    throw NotImplementedException("std::vector extractor must be implemented.");
+}
+
+
+bool Extractor::extract(std::size_t , std::deque<long>& )
+{
+    throw NotImplementedException("std::deque extractor must be implemented.");
+}
+
+
+bool Extractor::extract(std::size_t , std::list<long>& )
+{
+    throw NotImplementedException("std::list extractor must be implemented.");
+}
+#endif
+
+
+bool Extractor::extract(std::size_t , std::vector<bool>& )
+{
+    throw NotImplementedException("std::vector extractor must be implemented.");
+}
+
+
+bool Extractor::extract(std::size_t , std::deque<bool>& )
+{
+    throw NotImplementedException("std::deque extractor must be implemented.");
+}
+
+
+bool Extractor::extract(std::size_t , std::list<bool>& )
+{
+    throw NotImplementedException("std::list extractor must be implemented.");
+}
+
+
+bool Extractor::extract(std::size_t , std::vector<float>& )
+{
+    throw NotImplementedException("std::vector extractor must be implemented.");
+}
+
+
+bool Extractor::extract(std::size_t , std::deque<float>& )
+{
+    throw NotImplementedException("std::deque extractor must be implemented.");
+}
+
+
+bool Extractor::extract(std::size_t , std::list<float>& )
+{
+    throw NotImplementedException("std::list extractor must be implemented.");
+}
+
+
+bool Extractor::extract(std::size_t , std::vector<double>& )
+{
+    throw NotImplementedException("std::vector extractor must be implemented.");
+}
+
+
+bool Extractor::extract(std::size_t , std::deque<double>& )
+{
+    throw NotImplementedException("std::deque extractor must be implemented.");
+}
+
+
+bool Extractor::extract(std::size_t , std::list<double>& )
+{
+    throw NotImplementedException("std::list extractor must be implemented.");
+}
+
+
+bool Extractor::extract(std::size_t , std::vector<char>& )
+{
+    throw NotImplementedException("std::vector extractor must be implemented.");
+}
+
+
+bool Extractor::extract(std::size_t , std::deque<char>& )
+{
+    throw NotImplementedException("std::deque extractor must be implemented.");
+}
+
+
+bool Extractor::extract(std::size_t , std::list<char>& )
+{
+    throw NotImplementedException("std::list extractor must be implemented.");
+}
+
+
+bool Extractor::extract(std::size_t , std::vector<std::string>& )
+{
+    throw NotImplementedException("std::vector extractor must be implemented.");
+}
+
+
+bool Extractor::extract(std::size_t , std::deque<std::string>& )
+{
+    throw NotImplementedException("std::deque extractor must be implemented.");
+}
+
+
+bool Extractor::extract(std::size_t , std::list<std::string>& )
+{
+    throw NotImplementedException("std::list extractor must be implemented.");
+}
+
+
+bool Extractor::extract(std::size_t , std::vector<BLOB>& )
+{
+    throw NotImplementedException("std::vector extractor must be implemented.");
+}
+
+
+bool Extractor::extract(std::size_t , std::deque<BLOB>& )
+{
+    throw NotImplementedException("std::deque extractor must be implemented.");
+}
+
+
+bool Extractor::extract(std::size_t , std::list<BLOB>& )
+{
+    throw NotImplementedException("std::list extractor must be implemented.");
+}
+
+
+bool Extractor::extract(std::size_t , std::vector<DateTime>& )
+{
+    throw NotImplementedException("std::vector extractor must be implemented.");
+}
+
+
+bool Extractor::extract(std::size_t , std::deque<DateTime>& )
+{
+    throw NotImplementedException("std::deque extractor must be implemented.");
+}
+
+
+bool Extractor::extract(std::size_t , std::list<DateTime>& )
+{
+    throw NotImplementedException("std::list extractor must be implemented.");
+}
+
+
+bool Extractor::extract(std::size_t , std::vector<Date>& )
+{
+    throw NotImplementedException("std::vector extractor must be implemented.");
+}
+
+
+bool Extractor::extract(std::size_t , std::deque<Date>& )
+{
+    throw NotImplementedException("std::deque extractor must be implemented.");
+}
+
+
+bool Extractor::extract(std::size_t , std::list<Date>& )
+{
+    throw NotImplementedException("std::list extractor must be implemented.");
+}
+
+
+bool Extractor::extract(std::size_t , std::vector<Time>& )
+{
+    throw NotImplementedException("std::vector extractor must be implemented.");
+}
+
+
+bool Extractor::extract(std::size_t , std::deque<Time>& )
+{
+    throw NotImplementedException("std::deque extractor must be implemented.");
+}
+
+
+bool Extractor::extract(std::size_t , std::list<Time>& )
+{
+    throw NotImplementedException("std::list extractor must be implemented.");
+}
+
+
+bool Extractor::extract(std::size_t , std::vector<Any>& )
+{
+    throw NotImplementedException("std::vector extractor must be implemented.");
+}
+
+
+bool Extractor::extract(std::size_t , std::deque<Any>& )
+{
+    throw NotImplementedException("std::deque extractor must be implemented.");
+}
+
+
+bool Extractor::extract(std::size_t , std::list<Any>& )
+{
+    throw NotImplementedException("std::list extractor must be implemented.");
+}
+
+
+bool Extractor::extract(std::size_t , std::vector<DynamicAny>& )
+{
+    throw NotImplementedException("std::vector extractor must be implemented.");
+}
+
+
+bool Extractor::extract(std::size_t , std::deque<DynamicAny>& )
+{
+    throw NotImplementedException("std::deque extractor must be implemented.");
+}
+
+
+bool Extractor::extract(std::size_t , std::list<DynamicAny>& )
+{
+    throw NotImplementedException("std::list extractor must be implemented.");
+}
+
+
+
+} } } // namespace Poco::Data::MySQL

+ 160 - 0
Data/MySQL/src/MySQLException.cpp

@@ -0,0 +1,160 @@
+//
+// MySQLException.cpp
+//
+// $Id: //poco/1.4/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 <mysql.h>
+#include <stdio.h>
+
+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::ConnectionException(const std::string& msg) : MySQLException(msg)
+{
+}
+
+
+ConnectionException::ConnectionException(const std::string& text, MYSQL* h) : MySQLException(compose(text, h))
+{
+}
+
+
+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;
+}
+
+
+/////
+//
+// TransactionException
+//
+/////
+
+
+TransactionException::TransactionException(const std::string& msg) : ConnectionException(msg)
+{
+}
+
+
+TransactionException::TransactionException(const std::string& text, MYSQL* h) : ConnectionException(text, h)
+{
+}
+
+
+/////
+//
+// StatementException
+//
+/////
+
+
+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 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

+ 200 - 0
Data/MySQL/src/MySQLStatementImpl.cpp

@@ -0,0 +1,200 @@
+//
+// MySQLException.cpp
+//
+// $Id: //poco/1.4/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(SessionImpl& h) 
+        : Poco::Data::StatementImpl(h), 
+          _stmt(h.handle()), 
+          _extractor(_stmt, _metadata), 
+	_hasNext(NEXT_DONTKNOW)
+{
+}
+
+
+MySQLStatementImpl::~MySQLStatementImpl()
+{
+}
+
+
+Poco::UInt32 MySQLStatementImpl::columnsReturned() const
+{
+	return _metadata.columnsReturned();
+}
+
+
+Poco::UInt32 MySQLStatementImpl::affectedRowCount() const
+{
+    return 0;
+}
+
+	
+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;
+}
+
+	
+Poco::UInt32 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;
+    return 1;
+}
+
+
+bool MySQLStatementImpl::canBind() const
+{
+	bool ret = false;
+
+	if ((_stmt.state() >= StatementExecutor::STMT_COMPILED) && !bindings().empty())
+		ret = (*bindings().begin())->canBind();
+
+	return ret;
+}
+
+
+bool MySQLStatementImpl::canCompile() const
+{
+	return (_stmt.state() < StatementExecutor::STMT_COMPILED);
+}
+
+	
+void MySQLStatementImpl::compileImpl()
+{
+	_metadata.reset();
+	_stmt.prepare(toString());
+	_metadata.init(_stmt);
+
+	if (_metadata.columnsReturned() > 0)
+	{
+		_stmt.bindResult(_metadata.row());
+	}
+}
+
+	
+void MySQLStatementImpl::bindImpl()
+{
+	//
+	// Bind all bindings
+	//
+
+	{
+		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();
+		}
+	}
+
+	//
+	// And bind them to statement
+	//
+
+	_stmt.bindParams(_binder.getBindArray(), _binder.size());
+
+	//
+	// And execute
+	//
+
+	_stmt.execute();
+
+	_hasNext = NEXT_DONTKNOW;
+}
+
+	
+AbstractExtractor& MySQLStatementImpl::extractor()
+{
+	return _extractor;
+}
+
+	
+AbstractBinder& MySQLStatementImpl::binder()
+{
+	return _binder;
+}
+
+
+} } } // namespace Poco::Data::MySQL

+ 243 - 0
Data/MySQL/src/ResultMetadata.cpp

@@ -0,0 +1,243 @@
+//
+// MySQLException.cpp
+//
+// $Id: //poco/1.4/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_DATE:
+        case MYSQL_TYPE_TIME:
+        case MYSQL_TYPE_DATETIME:
+            return sizeof(MYSQL_TIME);
+
+        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:
+			return field.length;
+        
+		default:
+			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;
+		default:
+		    return Poco::Data::MetaColumn::FDT_UNKNOWN;
+		}
+	}	
+} // namespace
+
+
+namespace Poco {
+namespace Data {
+namespace MySQL {
+
+void ResultMetadata::reset()
+{
+	_columns.resize(0);
+	_row.resize(0);
+	_buffer.resize(0);
+	_lengths.resize(0);
+	_isNull.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);
+	_isNull.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<unsigned int>(_columns[i].length());
+		_row[i].buffer        = &_buffer[0] + offset;
+		_row[i].length        = &_lengths[i];
+		_row[i].is_null       = &_isNull[i];
+		
+		offset += _row[i].buffer_length;
+	}}
+}
+
+Poco::UInt32 ResultMetadata::columnsReturned() const
+{
+	return static_cast<Poco::UInt32>(_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) const
+{
+	return _lengths[pos];
+}
+
+const char* ResultMetadata::rawData(size_t pos) const 
+{
+	return reinterpret_cast<const char*>(_row[pos].buffer);
+}
+
+bool ResultMetadata::isNull(size_t pos) const 
+{
+    return (_isNull[pos] != 0);
+}
+
+}}} // namespace Poco::Data::MySQL

+ 135 - 0
Data/MySQL/src/SessionHandle.cpp

@@ -0,0 +1,135 @@
+//
+// SesssionHandle.cpp
+//
+// $Id: //poco/1.4/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::startTransaction()
+{
+    int res = mysql_autocommit(h, false);
+
+	if (res != 0)
+	{
+		throw TransactionException("Start transaction failed.", h);
+	}
+}
+
+void SessionHandle::commit()
+{
+    int res = mysql_commit(h);
+
+	if (res != 0)
+	{
+		throw TransactionException("Commit failed.", h);
+	}
+}
+
+void SessionHandle::rollback()
+{
+    int res = mysql_rollback(h);
+
+	if (res != 0)
+	{
+		throw TransactionException("Rollback failed.", h);
+	}
+} 
+
+
+}}} // Poco::Data::MySQL

+ 226 - 0
Data/MySQL/src/SessionImpl.cpp

@@ -0,0 +1,226 @@
+//
+// MySQLException.cpp
+//
+// $Id: //poco/1.4/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<std::string, std::string> 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()) || (finish + 1 == 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(*this);
+}	
+
+
+void SessionImpl::begin()
+{
+    _mysql.startTransaction();
+	_inTransaction++;
+}
+
+
+void SessionImpl::commit()
+{
+    _mysql.commit();
+	_inTransaction--;
+}
+	
+
+void SessionImpl::rollback()
+{
+    _mysql.rollback();
+	_inTransaction--;
+}
+	
+
+void SessionImpl::close()
+{
+	if (_connected)
+	{
+		_mysql.close();
+		_connected = false;
+	}
+}
+	
+
+bool SessionImpl::isConnected()
+{
+	return _connected;
+}
+	
+
+bool SessionImpl::isTransaction()
+{
+	return (_inTransaction > 0);
+}
+
+
+}}}

+ 197 - 0
Data/MySQL/src/StatementExecutor.cpp

@@ -0,0 +1,197 @@
+//
+// 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 <mysql.h>
+#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)
+    {
+        _state = STMT_COMPILED;
+        return;
+        //throw StatementException("Satement is already compiled");
+    }
+	
+    // compile
+    int res = mysql_stmt_prepare(h, query.c_str(), static_cast<unsigned int>(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<unsigned int>(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);
+}
+
+
+}}}

+ 21 - 0
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

+ 259 - 0
Data/MySQL/testsuite/TestSuite_VS80.vcproj

@@ -0,0 +1,259 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8,00"
+	Name="TestSuite"
+	ProjectGUID="{1B30A91B-375F-11DB-837B-00123FC423B5}"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="debug_shared|Win32"
+			OutputDirectory="obj\debug_shared"
+			IntermediateDirectory="obj\debug_shared"
+			ConfigurationType="1"
+			UseOfMFC="2"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\include;..\..\..\Foundation\include;..\..\..\CppUnit\include;..\..\..\CppUnit\WinTestRunner\include;..\..\..\Data\include"
+				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;POCO_DLL;WINVER=0x0500"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				BufferSecurityCheck="true"
+				TreatWChar_tAsBuiltInType="true"
+				ForceConformanceInForLoopScope="true"
+				RuntimeTypeInfo="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="CppUnitd.lib WinTestRunnerd.lib PocoFoundationd.lib PocoDatad.lib libmysql.lib"
+				OutputFile="bin/TestSuited.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="..\..\..\lib"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="bin/TestSuited.pdb"
+				SubSystem="2"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="release_shared|Win32"
+			OutputDirectory="obj\release_shared"
+			IntermediateDirectory="obj\release_shared"
+			ConfigurationType="1"
+			UseOfMFC="2"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="4"
+				InlineFunctionExpansion="1"
+				EnableIntrinsicFunctions="true"
+				FavorSizeOrSpeed="1"
+				OmitFramePointers="true"
+				AdditionalIncludeDirectories="..\include;..\..\..\Foundation\include;..\..\..\CppUnit\include;..\..\..\CppUnit\WinTestRunner\include;..\..\..\Data\include"
+				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;POCO_DLL;WINVER=0x0500"
+				StringPooling="true"
+				RuntimeLibrary="2"
+				BufferSecurityCheck="false"
+				TreatWChar_tAsBuiltInType="true"
+				ForceConformanceInForLoopScope="true"
+				RuntimeTypeInfo="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="CppUnit.lib WinTestRunner.lib PocoFoundation.lib PocoData.lib libmysql.lib"
+				OutputFile="bin/TestSuite.exe"
+				LinkIncremental="1"
+				AdditionalLibraryDirectories="..\..\..\lib"
+				GenerateDebugInformation="false"
+				ProgramDatabaseFile=""
+				SubSystem="2"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="MySQL"
+			>
+			<Filter
+				Name="Header Files"
+				>
+				<File
+					RelativePath=".\src\MySQLTest.h"
+					>
+				</File>
+				<File
+					RelativePath=".\src\SQLExecutor.h"
+					>
+				</File>
+			</Filter>
+			<Filter
+				Name="Source Files"
+				>
+				<File
+					RelativePath=".\src\MySQLTest.cpp"
+					>
+				</File>
+				<File
+					RelativePath=".\src\SQLExecutor.cpp"
+					>
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="_Suite"
+			>
+			<Filter
+				Name="Header Files"
+				>
+				<File
+					RelativePath=".\src\MySQLTestSuite.h"
+					>
+				</File>
+			</Filter>
+			<Filter
+				Name="Source Files"
+				>
+				<File
+					RelativePath=".\src\MySQLTestSuite.cpp"
+					>
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="_Driver"
+			>
+			<Filter
+				Name="Source Files"
+				>
+				<File
+					RelativePath=".\src\WinDriver.cpp"
+					>
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>

+ 39 - 0
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)

+ 816 - 0
Data/MySQL/testsuite/src/MySQLTest.cpp

@@ -0,0 +1,816 @@
+//
+// MySQLTest.cpp
+//
+// $Id: //poco/1.4/Data/MySQL/testsuite/src/MySQLTest.cpp#1 $
+//
+// 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/Tuple.h"
+#include "Poco/NamedTuple.h"
+#include "Poco/Exception.h"
+#include "Poco/Data/BLOB.h"
+#include "Poco/Data/StatementImpl.h"
+#include "Poco/Data/MySQL/Connector.h"
+#include "Poco/Data/MySQL/MySQLException.h"
+#include "Poco/Data/Nullable.h"
+#include <iostream>
+
+using namespace Poco::Data;
+using namespace Poco::Data::Keywords;
+using Poco::Data::MySQL::ConnectionException;
+using Poco::Data::MySQL::StatementException;
+using Poco::format;
+using Poco::NotFoundException;
+using Poco::Int32;
+using Poco::Data::Nullable;
+using Poco::Tuple;
+using Poco::NamedTuple;
+
+Poco::SharedPtr<Poco::Data::Session> MySQLTest::_pSession = 0;
+Poco::SharedPtr<SQLExecutor> MySQLTest::_pExecutor = 0;
+
+//
+// Parameters for barebone-test
+#define MYSQL_USER "wmcloader"
+#define MYSQL_PWD  ""
+#define MYSQL_HOST "localhost"
+#define MYSQL_PORT 3306
+#define MYSQL_DB   "robot"
+
+//
+// Connection string to POCO
+std::string MySQLTest::_dbConnString = "user=wmcloader;password=;db=robot;compress=true;auto-reconnect=true";
+
+
+MySQLTest::MySQLTest(const std::string& name): 
+	CppUnit::TestCase(name)
+{
+    MySQL::Connector::registerConnector();
+
+	/*static bool beenHere = false;
+	
+
+	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.toString() << 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::testNull()
+{
+	if (!_pSession) fail ("Test not available.");
+
+	recreateVectorsTable();
+	_pExecutor->doNull();
+}
+
+
+void MySQLTest::testNullableInt()
+{
+	if (!_pSession) fail ("Test not available.");
+
+	recreateNullableIntTable();
+
+	Nullable<Int32> i1(1);
+	Nullable<Int32> i2;
+
+	int id = 1;
+	*_pSession << "INSERT INTO NullableIntTest VALUES(?, ?)", use(id), use(i1), now;
+	id = 2;
+	*_pSession << "INSERT INTO NullableIntTest VALUES(?, ?)", use(id), use(i2), now;
+	id = 3;
+	i2 = 3;
+	*_pSession << "INSERT INTO NullableIntTest VALUES(?, ?)", use(id), use(i2), now;
+
+	int count = 0;
+	*_pSession << "SELECT COUNT(*) FROM NullableIntTest", into(count), now;
+	assert (count == 3);
+
+	Nullable<Int32> ci1;
+	Nullable<Int32> ci2;
+	Nullable<Int32> ci3;
+	id = 1;
+	*_pSession << "SELECT Value FROM NullableIntTest WHERE Id = ?", into(ci1), use(id), now;
+	assert (ci1 == i1);
+	id = 2;
+	*_pSession << "SELECT Value FROM NullableIntTest WHERE Id = ?", into(ci2), use(id), now;
+	assert (ci2.isNull());
+	assert (!(0 == ci2));
+	assert (0 != ci2);
+	assert (!(ci2 == 0));
+	assert (ci2 != 0);
+	ci2 = 10;
+	assert (10 == ci2);
+	assert (ci2 == 10);
+	assert (!ci2.isNull());
+	id = 3;
+	*_pSession << "SELECT Value FROM NullableIntTest WHERE Id = ?", into(ci3), use(id), now;
+	assert (!ci3.isNull());
+	assert (ci3 == 3);
+	assert (3 == ci3);
+}
+
+
+void MySQLTest::testNullableString()
+{
+	if (!_pSession) fail ("Test not available.");
+
+	recreateNullableStringTable();
+
+	Int32 id = 0;
+	Nullable<std::string> address("Address");
+	Nullable<Int32> age = 10;
+	*_pSession << "INSERT INTO NullableStringTest VALUES(?, ?, ?)", use(id), use(address), use(age), now;
+	id++;
+	address = null;
+	age = null;
+	*_pSession << "INSERT INTO NullableStringTest VALUES(?, ?, ?)", use(id), use(address), use(age), now;
+
+	Nullable<std::string> resAddress;
+	Nullable<Int32> resAge;
+	*_pSession << "SELECT Address, Age FROM NullableStringTest WHERE Id = ?", into(resAddress), into(resAge), use(id), now;
+	assert(resAddress == address);
+	assert(resAge == age);
+	assert(resAddress.isNull());
+	assert(null == resAddress);
+	assert(resAddress == null);
+
+	resAddress = std::string("Test");
+	assert(!resAddress.isNull());
+	assert(resAddress == std::string("Test"));
+	assert(std::string("Test") == resAddress);
+	assert(null != resAddress);
+	assert(resAddress != null);
+}
+
+
+void MySQLTest::testTupleWithNullable()
+{
+	if (!_pSession) fail ("Test not available.");
+
+	recreateNullableStringTable();
+
+	typedef Poco::Tuple<Int32, Nullable<std::string>, Nullable<Int32> > Info;
+
+	Info info(0, std::string("Address"), 10);
+ 	*_pSession << "INSERT INTO NullableStringTest VALUES(?, ?, ?)", use(info), now;
+	
+	info.set<0>(info.get<0>()++);
+	info.set<1>(null);
+ 	*_pSession << "INSERT INTO NullableStringTest VALUES(?, ?, ?)", use(info), now;
+
+	info.set<0>(info.get<0>()++);
+	info.set<1>(std::string("Address!"));
+	info.set<2>(null);
+ 	*_pSession << "INSERT INTO NullableStringTest VALUES(?, ?, ?)", use(info), now;
+
+	std::vector<Info> infos;
+	infos.push_back(Info(10, std::string("A"), 0));
+	infos.push_back(Info(11, null, 12));
+	infos.push_back(Info(12, std::string("B"), null));
+
+ 	*_pSession << "INSERT INTO NullableStringTest VALUES(?, ?, ?)", use(infos), now;
+
+	std::vector<Info> result;
+
+ 	*_pSession << "SELECT Id, Address, Age FROM NullableStringTest", into(result), now;
+
+	assert(result[0].get<1>() == std::string("Address"));
+	assert(result[0].get<2>() == 10);
+
+	assert(result[1].get<1>() == null);
+	assert(result[1].get<2>() == 10);
+
+	assert(result[2].get<1>() == std::string("Address!"));
+	assert(result[2].get<2>() == null);
+
+	assert(result[3].get<1>() == std::string("A"));
+	assert(result[3].get<2>() == 0);
+
+	assert(result[4].get<1>() == null);
+	assert(result[4].get<2>() == 12);
+
+	assert(result[5].get<1>() == std::string("B"));
+	assert(result[5].get<2>() == null);
+
+}
+
+
+void MySQLTest::dropTable(const std::string& tableName)
+{
+    
+    try { *_pSession << format("DROP TABLE IF EXISTS %s", tableName), now; }
+    catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail ("dropTable()"); }
+    catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail ("dropTable()"); }
+}
+
+
+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::recreateNullableIntTable()
+{
+	dropTable("NullableIntTest");
+	try { 
+	    *_pSession << "CREATE TABLE NullableIntTest (Id INTEGER(10), Value INTEGER(10))", now;
+	}
+	catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail ("recreateNullableIntTable()"); }
+	catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail ("recreateNullableIntTable()"); }
+}
+
+
+void MySQLTest::recreateNullableStringTable()
+{
+	dropTable("NullableStringTest");
+	try { 
+	    *_pSession << "CREATE TABLE NullableStringTest (Id INTEGER(10), Address VARCHAR(30), Age INTEGER(10))", now;
+	}
+	catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail ("recreateNullableStringTable()"); }
+	catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail ("recreateNullableStringTable()"); }
+}
+
+
+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()
+{
+	MySQL::Connector::registerConnector();
+
+	try
+	{
+		_pSession = new Session(MySQL::Connector::KEY, _dbConnString);
+	}
+    catch (ConnectionException& ex)
+	{
+		std::cout << ex.displayText() << std::endl;
+		return 0;
+	}
+
+	std::cout << "*** Connected to [" << "MySQL" << "] test database." << std::endl;
+
+	_pExecutor = new SQLExecutor("MySQL SQL Executor", _pSession);
+
+    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);
+    CppUnit_addTest(pSuite, MySQLTest, testNull);
+    CppUnit_addTest(pSuite, MySQLTest, testNullableInt);
+    CppUnit_addTest(pSuite, MySQLTest, testNullableString);
+    CppUnit_addTest(pSuite, MySQLTest, testTupleWithNullable);
+
+    return pSuite;
+}

+ 141 - 0
Data/MySQL/testsuite/src/MySQLTest.h

@@ -0,0 +1,141 @@
+//
+// ODBCMySQLTest.h
+//
+// $Id: //poco/1.4/Data/MySQL/testsuite/src/ODBCMySQLTest.h#1 $
+//
+// 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 testNull();
+	void testNullVector();
+
+	void testNullableInt();
+	void testNullableString();
+	void testTupleWithNullable();
+	
+	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();
+	void recreateNullableIntTable();
+	void recreateNullableStringTable();
+
+	static std::string _dbConnString;
+	static Poco::SharedPtr<Poco::Data::Session> _pSession;
+	static Poco::SharedPtr<SQLExecutor> _pExecutor;
+	static const bool bindValues[8];
+};
+
+
+#endif // MySQLTest_INCLUDED

+ 48 - 0
Data/MySQL/testsuite/src/MySQLTestSuite.cpp

@@ -0,0 +1,48 @@
+//
+// ODBCTestSuite.cpp
+//
+// $Id: //poco/1.4/Data/MySQL/testsuite/src/MySQLTestSuite.cpp#1 $
+//
+// 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");
+
+	addTest(pSuite, MySQLTest::suite());
+	return pSuite;
+}
+
+
+void MySQLTestSuite::addTest(CppUnit::TestSuite* pSuite, CppUnit::Test* pT)
+{
+	if (pSuite && pT) pSuite->addTest(pT);
+}

+ 51 - 0
Data/MySQL/testsuite/src/MySQLTestSuite.h

@@ -0,0 +1,51 @@
+//
+// ODBCTestSuite.h
+//
+// $Id: //poco/1.4/Data/MySQL/testsuite/src/MySQLTestSuite.h#1 $
+//
+// 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();
+
+private:
+	static void addTest(CppUnit::TestSuite* pSuite, CppUnit::Test* pT);
+};
+
+
+#endif // MySQLTestSuite_INCLUDED

+ 1520 - 0
Data/MySQL/testsuite/src/SQLExecutor.cpp

@@ -0,0 +1,1520 @@
+//
+// SQLExecutor.cpp
+//
+// $Id: //poco/1.4/Data/MySQL/testsuite/src/SQLExecutor.cpp#1 $
+//
+// 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/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 <Winsock2.h>
+#endif 
+
+#include <mysql.h>
+#include <iostream>
+
+
+using namespace Poco::Data;
+using namespace Poco::Data::Keywords;
+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<Person>
+{
+public:
+	static void bind(std::size_t pos, const Person& obj, AbstractBinder* pBinder, AbstractBinder::Direction dir)
+	{
+		// 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, dir);
+		pBinder->bind(pos++, obj.firstName, dir);
+		pBinder->bind(pos++, obj.address, dir);
+		pBinder->bind(pos++, obj.age, dir);
+	}
+
+	static void prepare(std::size_t pos, 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<unsigned long>(sql.length()));
+	
+	sql = tableCreateString;
+	rc = mysql_stmt_prepare(hstmt, sql.c_str(), static_cast<unsigned long>(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<unsigned long>(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<char*>(str[0].c_str());
+	bind_param[0].buffer_length = static_cast<unsigned long>(str[0].length());
+	bind_param[0].buffer_type   = MYSQL_TYPE_STRING;
+
+	bind_param[1].buffer        = const_cast<char*>(str[1].c_str());
+	bind_param[1].buffer_length = static_cast<unsigned long>(str[1].length());
+	bind_param[1].buffer_type   = MYSQL_TYPE_STRING;
+
+	bind_param[2].buffer        = const_cast<char*>(str[2].c_str());
+	bind_param[2].buffer_length = static_cast<unsigned long>(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<unsigned long>(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<unsigned long>(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<std::string> lastNames;
+	std::vector<std::string> firstNames;
+	std::vector<std::string> addresses;
+	std::vector<int> 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<std::string> lastNamesR;
+	std::vector<std::string> firstNamesR;
+	std::vector<std::string> addressesR;
+	std::vector<int> 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<Person> 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<Person> 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<std::string> 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<std::string> 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<int> 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<int> 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<int> 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<int> 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<int> 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<int> 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<int> 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<int> 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<int> 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<int> 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<std::string> lastNames;
+	std::set<std::string> firstNames;
+	std::set<std::string> addresses;
+	std::set<int> 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<std::string> lastNamesR;
+	std::set<std::string> firstNamesR;
+	std::set<std::string> addressesR;
+	std::set<int> 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<Person> 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<Person> 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<Person> 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<Person> 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<std::string> lastNames;
+	std::multiset<std::string> firstNames;
+	std::multiset<std::string> addresses;
+	std::multiset<int> 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<std::string> lastNamesR;
+	std::multiset<std::string> firstNamesR;
+	std::multiset<std::string> addressesR;
+	std::multiset<int> 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<Person> 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<Person> 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<std::string, Person> 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<std::string, Person> 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<std::string, Person> 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<std::string, Person> 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<std::string, Person> 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<std::string, Person> 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<std::string, Person> 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<std::string, Person> 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<std::string, Person> 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<std::string, Person> 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<std::string, Person> 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<std::string, Person> 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<std::string, Person> 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 <Person> 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<std::string, Person> 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 <Person> 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<std::string, Person> 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<std::string, Person> 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<char> v(bigSize, 'x');
+	big.assignRaw(&v[0], v.size());
+
+	assert (big.size() == (size_t)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<int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int> 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<int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int> 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<int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int> 
+		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<TupleType> 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() == (size_t)count);
+
+	std::vector<Tuple<int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int> > 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<Tuple<int, double, std::string> > v;
+	v.push_back(Tuple<int, double, std::string>(1, 1.5f, "3"));
+	v.push_back(Tuple<int, double, std::string>(2, 2.5f, "4"));
+	v.push_back(Tuple<int, double, std::string>(3, 3.5f, "5"));
+	v.push_back(Tuple<int, double, std::string>(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<int>(0,0);
+		assert (1 == i);
+
+		std::string s = rset.value(0,0);
+		assert ("1" == s);
+
+		int a = rset.value<int>(0,2);
+		assert (3 == a);
+
+		try
+		{
+			double d = rset.value<double>(1,1);
+			assert (2.5 == d);
+		}
+		catch (BadCastException&)
+		{
+			float f = rset.value<float>(1,1);
+			assert (2.5 == f);
+		}
+
+		s = rset.value<std::string>(2,2);
+		assert ("5" == s);
+		i = rset.value("str0", 2);
+		assert (5 == i);
+		
+		const Column<int>& col = rset.column<int>(0);
+		Column<int>::Iterator it = col.begin();
+		Column<int>::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<int>(0,0);
+			assert (4 == i);
+		}
+		catch(BadCastException&)
+		{
+			try
+			{
+				//this is for Oracle
+				double i = rset.value<double>(0,0);
+				assert (4 == int(i));
+			}
+			catch(BadCastException&)
+			{
+				//this is for PostgreSQL
+				Poco::Int64 big = rset.value<Poco::Int64>(0,0);
+				assert (4 == big);
+			}
+		}
+
+		s = rset.value("cnt", 0).convert<std::string>();
+		assert ("4" == s);
+
+		try { const Column<int>& col1 = rset.column<int>(100); fail ("must fail"); }
+		catch (RangeException&) { }
+
+		try	{ rset.value<std::string>(0,0); fail ("must fail"); }
+		catch (BadCastException&) {	}
+		
+		stmt = (*_pSession << "DELETE FROM Vectors", now);
+		rset = stmt;
+
+		try { const Column<int>& col1 = rset.column<int>(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); }
+*/
+}
+
+
+void SQLExecutor::doNull()
+{
+	std::string funct = "null()";
+	
+    *_pSession << "INSERT INTO Vectors VALUES (?, ?, ?)", 
+                        use(Poco::Data::Keywords::null), 
+                        use(Poco::Data::Keywords::null), 
+                        use(Poco::Data::Keywords::null), now;
+
+    int count = 0;
+    try { *_pSession << "SELECT COUNT(*) FROM Vectors", 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);
+
+	int i0 = 0;
+	Statement stmt1 = (*_pSession << "SELECT i0 FROM Vectors", into(i0, Poco::Data::Position(0), -1));
+    try { stmt1.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 (i0 == -1);
+
+	float flt0 = 0;
+    Statement stmt2 = (*_pSession << "SELECT flt0 FROM Vectors", into(flt0, Poco::Data::Position(0), 3.25f));
+    try { stmt2.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 (flt0 == 3.25);
+
+	std::string str0("string");
+    Statement stmt3 = (*_pSession << "SELECT str0 FROM Vectors", into(str0, Poco::Data::Position(0), std::string("DEFAULT")));
+    try { stmt3.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 (str0 == "DEFAULT");
+}

+ 118 - 0
Data/MySQL/testsuite/src/SQLExecutor.h

@@ -0,0 +1,118 @@
+//
+// SQLExecutor.h
+//
+// $Id: //poco/1.4/Data/MySQL/testsuite/src/SQLExecutor.h#1 $
+//
+// 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();
+	void doNull();
+
+private:
+	Poco::Data::Session* _pSession;
+};
+
+
+#endif // SQLExecutor_INCLUDED

+ 50 - 0
Data/MySQL/testsuite/src/WinDriver.cpp

@@ -0,0 +1,50 @@
+//
+// WinDriver.cpp
+//
+// $Id: //poco/1.4/Data/MySQL/testsuite/src/WinDriver.cpp#1 $
+//
+// 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;