merge Data changes (ODBC Sybase, PostgreSQL etc)

This commit is contained in:
Alex Fabijanic 2016-02-28 11:06:08 -06:00
parent e84d50dfaa
commit 32f3f4a146
79 changed files with 3174 additions and 1545 deletions

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations"> <ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="debug_shared|Win32"> <ProjectConfiguration Include="debug_shared|Win32">
@ -125,7 +125,7 @@
<AdditionalIncludeDirectories>.\include;..\Foundation\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>.\include;..\Foundation\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;Data_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;Data_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling> <StringPooling>true</StringPooling>
<MinimalRebuild>true</MinimalRebuild> <MinimalRebuild>false</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<BufferSecurityCheck>true</BufferSecurityCheck> <BufferSecurityCheck>true</BufferSecurityCheck>
@ -136,6 +136,7 @@
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
<Link> <Link>
<OutputFile>..\bin\PocoDatad.dll</OutputFile> <OutputFile>..\bin\PocoDatad.dll</OutputFile>
@ -186,7 +187,7 @@
<AdditionalIncludeDirectories>.\include;..\Foundation\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>.\include;..\Foundation\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;POCO_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;POCO_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling> <StringPooling>true</StringPooling>
<MinimalRebuild>true</MinimalRebuild> <MinimalRebuild>false</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<BufferSecurityCheck>true</BufferSecurityCheck> <BufferSecurityCheck>true</BufferSecurityCheck>
@ -198,6 +199,7 @@
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
<Lib> <Lib>
<OutputFile>..\lib\PocoDatamtd.lib</OutputFile> <OutputFile>..\lib\PocoDatamtd.lib</OutputFile>
@ -233,7 +235,7 @@
<AdditionalIncludeDirectories>.\include;..\Foundation\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>.\include;..\Foundation\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;POCO_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;POCO_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling> <StringPooling>true</StringPooling>
<MinimalRebuild>true</MinimalRebuild> <MinimalRebuild>false</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<BufferSecurityCheck>true</BufferSecurityCheck> <BufferSecurityCheck>true</BufferSecurityCheck>
@ -245,6 +247,7 @@
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
<Lib> <Lib>
<OutputFile>..\lib\PocoDatamdd.lib</OutputFile> <OutputFile>..\lib\PocoDatamdd.lib</OutputFile>

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations"> <ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="debug_shared|x64"> <ProjectConfiguration Include="debug_shared|x64">
@ -125,7 +125,7 @@
<AdditionalIncludeDirectories>.\include;..\Foundation\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>.\include;..\Foundation\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;Data_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;Data_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling> <StringPooling>true</StringPooling>
<MinimalRebuild>true</MinimalRebuild> <MinimalRebuild>false</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<BufferSecurityCheck>true</BufferSecurityCheck> <BufferSecurityCheck>true</BufferSecurityCheck>
@ -137,6 +137,7 @@
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
<Link> <Link>
<OutputFile>..\bin64\PocoData64d.dll</OutputFile> <OutputFile>..\bin64\PocoData64d.dll</OutputFile>
@ -169,6 +170,7 @@
<DebugInformationFormat /> <DebugInformationFormat />
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
<Link> <Link>
<OutputFile>..\bin64\PocoData64.dll</OutputFile> <OutputFile>..\bin64\PocoData64.dll</OutputFile>
@ -188,7 +190,7 @@
<AdditionalIncludeDirectories>.\include;..\Foundation\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>.\include;..\Foundation\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;POCO_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;POCO_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling> <StringPooling>true</StringPooling>
<MinimalRebuild>true</MinimalRebuild> <MinimalRebuild>false</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<BufferSecurityCheck>true</BufferSecurityCheck> <BufferSecurityCheck>true</BufferSecurityCheck>
@ -201,6 +203,7 @@
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
<Lib> <Lib>
<OutputFile>..\lib64\PocoDatamtd.lib</OutputFile> <OutputFile>..\lib64\PocoDatamtd.lib</OutputFile>
@ -226,6 +229,7 @@
<DebugInformationFormat /> <DebugInformationFormat />
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
<Lib> <Lib>
<OutputFile>..\lib64\PocoDatamt.lib</OutputFile> <OutputFile>..\lib64\PocoDatamt.lib</OutputFile>
@ -237,7 +241,7 @@
<AdditionalIncludeDirectories>.\include;..\Foundation\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>.\include;..\Foundation\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;POCO_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;POCO_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling> <StringPooling>true</StringPooling>
<MinimalRebuild>true</MinimalRebuild> <MinimalRebuild>false</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<BufferSecurityCheck>true</BufferSecurityCheck> <BufferSecurityCheck>true</BufferSecurityCheck>
@ -250,6 +254,7 @@
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
<Lib> <Lib>
<OutputFile>..\lib64\PocoDatamdd.lib</OutputFile> <OutputFile>..\lib64\PocoDatamdd.lib</OutputFile>
@ -275,6 +280,7 @@
<DebugInformationFormat /> <DebugInformationFormat />
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
<Lib> <Lib>
<OutputFile>..\lib64\PocoDatamd.lib</OutputFile> <OutputFile>..\lib64\PocoDatamd.lib</OutputFile>

View File

@ -42,71 +42,71 @@ public:
virtual ~Binder(); virtual ~Binder();
/// Destroys the Binder. /// Destroys the Binder.
virtual void bind(std::size_t pos, const Poco::Int8& val, Direction dir); virtual void bind(std::size_t pos, const Poco::Int8& val, Direction dir, const WhenNullCb& nullCb);
/// Binds an Int8. /// Binds an Int8.
virtual void bind(std::size_t pos, const Poco::UInt8& val, Direction dir); virtual void bind(std::size_t pos, const Poco::UInt8& val, Direction dir, const WhenNullCb& nullCb);
/// Binds an UInt8. /// Binds an UInt8.
virtual void bind(std::size_t pos, const Poco::Int16& val, Direction dir); virtual void bind(std::size_t pos, const Poco::Int16& val, Direction dir, const WhenNullCb& nullCb);
/// Binds an Int16. /// Binds an Int16.
virtual void bind(std::size_t pos, const Poco::UInt16& val, Direction dir); virtual void bind(std::size_t pos, const Poco::UInt16& val, Direction dir, const WhenNullCb& nullCb);
/// Binds an UInt16. /// Binds an UInt16.
virtual void bind(std::size_t pos, const Poco::Int32& val, Direction dir); virtual void bind(std::size_t pos, const Poco::Int32& val, Direction dir, const WhenNullCb& nullCb);
/// Binds an Int32. /// Binds an Int32.
virtual void bind(std::size_t pos, const Poco::UInt32& val, Direction dir); virtual void bind(std::size_t pos, const Poco::UInt32& val, Direction dir, const WhenNullCb& nullCb);
/// Binds an UInt32. /// Binds an UInt32.
virtual void bind(std::size_t pos, const Poco::Int64& val, Direction dir); virtual void bind(std::size_t pos, const Poco::Int64& val, Direction dir, const WhenNullCb& nullCb);
/// Binds an Int64. /// Binds an Int64.
virtual void bind(std::size_t pos, const Poco::UInt64& val, Direction dir); virtual void bind(std::size_t pos, const Poco::UInt64& val, Direction dir, const WhenNullCb& nullCb);
/// Binds an UInt64. /// Binds an UInt64.
#ifndef POCO_LONG_IS_64_BIT #ifndef POCO_LONG_IS_64_BIT
virtual void bind(std::size_t pos, const long& val, Direction dir = PD_IN); virtual void bind(std::size_t pos, const long& val, Direction dir, const WhenNullCb& nullCb);
/// Binds a long. /// Binds a long.
virtual void bind(std::size_t pos, const unsigned long& val, Direction dir = PD_IN); virtual void bind(std::size_t pos, const unsigned long& val, Direction dir, const WhenNullCb& nullCb);
/// Binds an unsigned long. /// Binds an unsigned long.
#endif // POCO_LONG_IS_64_BIT #endif // POCO_LONG_IS_64_BIT
virtual void bind(std::size_t pos, const bool& val, Direction dir); virtual void bind(std::size_t pos, const bool& val, Direction dir, const WhenNullCb& nullCb);
/// Binds a boolean. /// Binds a boolean.
virtual void bind(std::size_t pos, const float& val, Direction dir); virtual void bind(std::size_t pos, const float& val, Direction dir, const WhenNullCb& nullCb);
/// Binds a float. /// Binds a float.
virtual void bind(std::size_t pos, const double& val, Direction dir); virtual void bind(std::size_t pos, const double& val, Direction dir, const WhenNullCb& nullCb);
/// Binds a double. /// Binds a double.
virtual void bind(std::size_t pos, const char& val, Direction dir); virtual void bind(std::size_t pos, const char& val, Direction dir, const WhenNullCb& nullCb);
/// Binds a single character. /// Binds a single character.
virtual void bind(std::size_t pos, const std::string& val, Direction dir); virtual void bind(std::size_t pos, const std::string& val, Direction dir, const WhenNullCb& nullCb);
/// Binds a string. /// Binds a string.
virtual void bind(std::size_t pos, const Poco::Data::BLOB& val, Direction dir); virtual void bind(std::size_t pos, const Poco::Data::BLOB& val, Direction dir, const WhenNullCb& nullCb);
/// Binds a BLOB. /// Binds a BLOB.
virtual void bind(std::size_t pos, const Poco::Data::CLOB& val, Direction dir); virtual void bind(std::size_t pos, const Poco::Data::CLOB& val, Direction dir, const WhenNullCb& nullCb);
/// Binds a CLOB. /// Binds a CLOB.
virtual void bind(std::size_t pos, const DateTime& val, Direction dir); virtual void bind(std::size_t pos, const DateTime& val, Direction dir, const WhenNullCb& nullCb);
/// Binds a DateTime. /// Binds a DateTime.
virtual void bind(std::size_t pos, const Date& val, Direction dir); virtual void bind(std::size_t pos, const Date& val, Direction dir, const WhenNullCb& nullCb);
/// Binds a Date. /// Binds a Date.
virtual void bind(std::size_t pos, const Time& val, Direction dir); virtual void bind(std::size_t pos, const Time& val, Direction dir, const WhenNullCb& nullCb);
/// Binds a Time. /// Binds a Time.
virtual void bind(std::size_t pos, const NullData& val, Direction dir); virtual void bind(std::size_t pos, const NullData& val, Direction dir, const std::type_info& bindType);
/// Binds a null. /// Binds a null.
@ -212,11 +212,11 @@ public:
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::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::vector<NullData>& val, Direction dir, const std::type_info& bindType);
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::deque<NullData>& val, Direction dir, const std::type_info& bindType);
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::list<NullData>& val, Direction dir, const std::type_info& bindType);
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::vector<std::string>& val, Direction dir = PD_IN);
@ -237,7 +237,7 @@ private:
Binder(const Binder&); Binder(const Binder&);
/// Don't copy the binder /// Don't copy the binder
virtual void bind(std::size_t, const char* const&, Direction) virtual void bind(std::size_t, const char* const&, Direction, const WhenNullCb& )
/// Binds a const char ptr. /// Binds a const char ptr.
/// This is a private no-op in this implementation /// This is a private no-op in this implementation
/// due to security risk. /// due to security risk.

View File

@ -54,7 +54,7 @@ protected:
/// Returns the number of affected rows. /// Returns the number of affected rows.
/// Used to find out the number of rows affected by insert, delete or update. /// Used to find out the number of rows affected by insert, delete or update.
virtual const MetaColumn& metaColumn(std::size_t pos) const; virtual const MetaColumn& metaColumn(std::size_t pos, std::size_t dataSet) const;
/// Returns column meta data. /// Returns column meta data.
virtual bool hasNext(); virtual bool hasNext();

View File

@ -37,56 +37,56 @@ Binder::~Binder()
} }
void Binder::bind(std::size_t pos, const Poco::Int8& val, Direction dir) void Binder::bind(std::size_t pos, const Poco::Int8& val, Direction dir, const WhenNullCb& nullCb)
{ {
poco_assert(dir == PD_IN); poco_assert(dir == PD_IN);
realBind(pos, MYSQL_TYPE_TINY, &val, 0); realBind(pos, MYSQL_TYPE_TINY, &val, 0);
} }
void Binder::bind(std::size_t pos, const Poco::UInt8& val, Direction dir) void Binder::bind(std::size_t pos, const Poco::UInt8& val, Direction dir, const WhenNullCb& nullCb)
{ {
poco_assert(dir == PD_IN); poco_assert(dir == PD_IN);
realBind(pos, MYSQL_TYPE_TINY, &val, 0, true); realBind(pos, MYSQL_TYPE_TINY, &val, 0, true);
} }
void Binder::bind(std::size_t pos, const Poco::Int16& val, Direction dir) void Binder::bind(std::size_t pos, const Poco::Int16& val, Direction dir, const WhenNullCb& nullCb)
{ {
poco_assert(dir == PD_IN); poco_assert(dir == PD_IN);
realBind(pos, MYSQL_TYPE_SHORT, &val, 0); realBind(pos, MYSQL_TYPE_SHORT, &val, 0);
} }
void Binder::bind(std::size_t pos, const Poco::UInt16& val, Direction dir) void Binder::bind(std::size_t pos, const Poco::UInt16& val, Direction dir, const WhenNullCb& nullCb)
{ {
poco_assert(dir == PD_IN); poco_assert(dir == PD_IN);
realBind(pos, MYSQL_TYPE_SHORT, &val, 0, true); realBind(pos, MYSQL_TYPE_SHORT, &val, 0, true);
} }
void Binder::bind(std::size_t pos, const Poco::Int32& val, Direction dir) void Binder::bind(std::size_t pos, const Poco::Int32& val, Direction dir, const WhenNullCb& nullCb)
{ {
poco_assert(dir == PD_IN); poco_assert(dir == PD_IN);
realBind(pos, MYSQL_TYPE_LONG, &val, 0); realBind(pos, MYSQL_TYPE_LONG, &val, 0);
} }
void Binder::bind(std::size_t pos, const Poco::UInt32& val, Direction dir) void Binder::bind(std::size_t pos, const Poco::UInt32& val, Direction dir, const WhenNullCb& nullCb)
{ {
poco_assert(dir == PD_IN); poco_assert(dir == PD_IN);
realBind(pos, MYSQL_TYPE_LONG, &val, 0, true); realBind(pos, MYSQL_TYPE_LONG, &val, 0, true);
} }
void Binder::bind(std::size_t pos, const Poco::Int64& val, Direction dir) void Binder::bind(std::size_t pos, const Poco::Int64& val, Direction dir, const WhenNullCb& nullCb)
{ {
poco_assert(dir == PD_IN); poco_assert(dir == PD_IN);
realBind(pos, MYSQL_TYPE_LONGLONG, &val, 0); realBind(pos, MYSQL_TYPE_LONGLONG, &val, 0);
} }
void Binder::bind(std::size_t pos, const Poco::UInt64& val, Direction dir) void Binder::bind(std::size_t pos, const Poco::UInt64& val, Direction dir, const WhenNullCb& nullCb)
{ {
poco_assert(dir == PD_IN); poco_assert(dir == PD_IN);
realBind(pos, MYSQL_TYPE_LONGLONG, &val, 0, true); realBind(pos, MYSQL_TYPE_LONGLONG, &val, 0, true);
@ -95,14 +95,14 @@ void Binder::bind(std::size_t pos, const Poco::UInt64& val, Direction dir)
#ifndef POCO_LONG_IS_64_BIT #ifndef POCO_LONG_IS_64_BIT
void Binder::bind(std::size_t pos, const long& val, Direction dir) void Binder::bind(std::size_t pos, const long& val, Direction dir, const WhenNullCb& nullCb)
{ {
poco_assert(dir == PD_IN); poco_assert(dir == PD_IN);
realBind(pos, MYSQL_TYPE_LONG, &val, 0); realBind(pos, MYSQL_TYPE_LONG, &val, 0);
} }
void Binder::bind(std::size_t pos, const unsigned long& val, Direction dir) void Binder::bind(std::size_t pos, const unsigned long& val, Direction dir, const WhenNullCb& nullCb)
{ {
poco_assert(dir == PD_IN); poco_assert(dir == PD_IN);
realBind(pos, MYSQL_TYPE_LONG, &val, 0, true); realBind(pos, MYSQL_TYPE_LONG, &val, 0, true);
@ -111,56 +111,56 @@ void Binder::bind(std::size_t pos, const unsigned long& val, Direction dir)
#endif // POCO_LONG_IS_64_BIT #endif // POCO_LONG_IS_64_BIT
void Binder::bind(std::size_t pos, const bool& val, Direction dir) void Binder::bind(std::size_t pos, const bool& val, Direction dir, const WhenNullCb& nullCb)
{ {
poco_assert(dir == PD_IN); poco_assert(dir == PD_IN);
realBind(pos, MYSQL_TYPE_TINY, &val, 0); realBind(pos, MYSQL_TYPE_TINY, &val, 0);
} }
void Binder::bind(std::size_t pos, const float& val, Direction dir) void Binder::bind(std::size_t pos, const float& val, Direction dir, const WhenNullCb& nullCb)
{ {
poco_assert(dir == PD_IN); poco_assert(dir == PD_IN);
realBind(pos, MYSQL_TYPE_FLOAT, &val, 0); realBind(pos, MYSQL_TYPE_FLOAT, &val, 0);
} }
void Binder::bind(std::size_t pos, const double& val, Direction dir) void Binder::bind(std::size_t pos, const double& val, Direction dir, const WhenNullCb& nullCb)
{ {
poco_assert(dir == PD_IN); poco_assert(dir == PD_IN);
realBind(pos, MYSQL_TYPE_DOUBLE, &val, 0); realBind(pos, MYSQL_TYPE_DOUBLE, &val, 0);
} }
void Binder::bind(std::size_t pos, const char& val, Direction dir) void Binder::bind(std::size_t pos, const char& val, Direction dir, const WhenNullCb& nullCb)
{ {
poco_assert(dir == PD_IN); poco_assert(dir == PD_IN);
realBind(pos, MYSQL_TYPE_TINY, &val, 0); realBind(pos, MYSQL_TYPE_TINY, &val, 0);
} }
void Binder::bind(std::size_t pos, const std::string& val, Direction dir) void Binder::bind(std::size_t pos, const std::string& val, Direction dir, const WhenNullCb& nullCb)
{ {
poco_assert(dir == PD_IN); poco_assert(dir == PD_IN);
realBind(pos, MYSQL_TYPE_STRING, val.c_str(), static_cast<int>(val.length())); 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) void Binder::bind(std::size_t pos, const Poco::Data::BLOB& val, Direction dir, const WhenNullCb& nullCb)
{ {
poco_assert(dir == PD_IN); poco_assert(dir == PD_IN);
realBind(pos, MYSQL_TYPE_BLOB, val.rawContent(), static_cast<int>(val.size())); realBind(pos, MYSQL_TYPE_BLOB, val.rawContent(), static_cast<int>(val.size()));
} }
void Binder::bind(std::size_t pos, const Poco::Data::CLOB& val, Direction dir) void Binder::bind(std::size_t pos, const Poco::Data::CLOB& val, Direction dir, const WhenNullCb& nullCb)
{ {
poco_assert(dir == PD_IN); poco_assert(dir == PD_IN);
realBind(pos, MYSQL_TYPE_BLOB, val.rawContent(), static_cast<int>(val.size())); realBind(pos, MYSQL_TYPE_BLOB, val.rawContent(), static_cast<int>(val.size()));
} }
void Binder::bind(std::size_t pos, const DateTime& val, Direction dir) void Binder::bind(std::size_t pos, const DateTime& val, Direction dir, const WhenNullCb& nullCb)
{ {
poco_assert(dir == PD_IN); poco_assert(dir == PD_IN);
MYSQL_TIME mt = {0}; MYSQL_TIME mt = {0};
@ -181,7 +181,7 @@ void Binder::bind(std::size_t pos, const DateTime& val, Direction dir)
} }
void Binder::bind(std::size_t pos, const Date& val, Direction dir) void Binder::bind(std::size_t pos, const Date& val, Direction dir, const WhenNullCb& nullCb)
{ {
poco_assert(dir == PD_IN); poco_assert(dir == PD_IN);
MYSQL_TIME mt = {0}; MYSQL_TIME mt = {0};
@ -198,7 +198,7 @@ void Binder::bind(std::size_t pos, const Date& val, Direction dir)
} }
void Binder::bind(std::size_t pos, const Time& val, Direction dir) void Binder::bind(std::size_t pos, const Time& val, Direction dir, const WhenNullCb& nullCb)
{ {
poco_assert(dir == PD_IN); poco_assert(dir == PD_IN);
MYSQL_TIME mt = {0}; MYSQL_TIME mt = {0};
@ -215,7 +215,7 @@ void Binder::bind(std::size_t pos, const Time& val, Direction dir)
} }
void Binder::bind(std::size_t pos, const NullData&, Direction dir) void Binder::bind(std::size_t pos, const NullData&, Direction dir, const std::type_info& bindType)
{ {
poco_assert(dir == PD_IN); poco_assert(dir == PD_IN);
realBind(pos, MYSQL_TYPE_NULL, 0, 0); realBind(pos, MYSQL_TYPE_NULL, 0, 0);
@ -601,19 +601,19 @@ void Binder::bind(std::size_t pos, const std::list<Poco::Data::Time>& val, Direc
} }
void Binder::bind(std::size_t pos, const std::vector<Poco::Data::NullData>& val, Direction dir) void Binder::bind(std::size_t pos, const std::vector<Poco::Data::NullData>& val, Direction dir, const std::type_info& bindType)
{ {
throw NotImplementedException(); throw NotImplementedException();
} }
void Binder::bind(std::size_t pos, const std::deque<Poco::Data::NullData>& val, Direction dir) void Binder::bind(std::size_t pos, const std::deque<Poco::Data::NullData>& val, Direction dir, const std::type_info& bindType)
{ {
throw NotImplementedException(); throw NotImplementedException();
} }
void Binder::bind(std::size_t pos, const std::list<Poco::Data::NullData>& val, Direction dir) void Binder::bind(std::size_t pos, const std::list<Poco::Data::NullData>& val, Direction dir, const std::type_info& bindType)
{ {
throw NotImplementedException(); throw NotImplementedException();
} }

View File

@ -48,8 +48,10 @@ int MySQLStatementImpl::affectedRowCount() const
} }
const MetaColumn& MySQLStatementImpl::metaColumn(std::size_t pos) const const MetaColumn& MySQLStatementImpl::metaColumn(std::size_t pos, std::size_t dataSet) const
{ {
// mysql doesn't support multiple result sets
poco_assert_dbg(dataSet == 0);
return _metadata.metaColumn(pos); return _metadata.metaColumn(pos);
} }

View File

@ -125,7 +125,8 @@
<AdditionalIncludeDirectories>.\include;..\..\Foundation\include;..\..\Data\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>.\include;..\..\Foundation\include;..\..\Data\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;THREADSAFE;ODBC_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;THREADSAFE;ODBC_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling> <StringPooling>true</StringPooling>
<MinimalRebuild>true</MinimalRebuild> <MinimalRebuild>false</MinimalRebuild>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<BufferSecurityCheck>true</BufferSecurityCheck> <BufferSecurityCheck>true</BufferSecurityCheck>
@ -188,7 +189,8 @@
<AdditionalIncludeDirectories>.\include;..\..\Foundation\include;..\..\Data\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>.\include;..\..\Foundation\include;..\..\Data\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;POCO_STATIC;THREADSAFE;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;POCO_STATIC;THREADSAFE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling> <StringPooling>true</StringPooling>
<MinimalRebuild>true</MinimalRebuild> <MinimalRebuild>false</MinimalRebuild>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<BufferSecurityCheck>true</BufferSecurityCheck> <BufferSecurityCheck>true</BufferSecurityCheck>
@ -235,7 +237,8 @@
<AdditionalIncludeDirectories>.\include;..\..\Foundation\include;..\..\Data\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>.\include;..\..\Foundation\include;..\..\Data\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;POCO_STATIC;THREADSAFE;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;POCO_STATIC;THREADSAFE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling> <StringPooling>true</StringPooling>
<MinimalRebuild>true</MinimalRebuild> <MinimalRebuild>false</MinimalRebuild>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<BufferSecurityCheck>true</BufferSecurityCheck> <BufferSecurityCheck>true</BufferSecurityCheck>

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations"> <ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="debug_shared|x64"> <ProjectConfiguration Include="debug_shared|x64">
@ -125,7 +125,7 @@
<AdditionalIncludeDirectories>.\include;..\..\Foundation\include;..\..\Data\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>.\include;..\..\Foundation\include;..\..\Data\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;THREADSAFE;ODBC_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;THREADSAFE;ODBC_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling> <StringPooling>true</StringPooling>
<MinimalRebuild>true</MinimalRebuild> <MinimalRebuild>false</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<BufferSecurityCheck>true</BufferSecurityCheck> <BufferSecurityCheck>true</BufferSecurityCheck>
@ -136,6 +136,7 @@
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
<Link> <Link>
<AdditionalDependencies>odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
@ -168,6 +169,7 @@
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat /> <DebugInformationFormat />
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
<Link> <Link>
<AdditionalDependencies>odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
@ -188,7 +190,7 @@
<AdditionalIncludeDirectories>.\include;..\..\Foundation\include;..\..\Data\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>.\include;..\..\Foundation\include;..\..\Data\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;POCO_STATIC;THREADSAFE;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;POCO_STATIC;THREADSAFE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling> <StringPooling>true</StringPooling>
<MinimalRebuild>true</MinimalRebuild> <MinimalRebuild>false</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<BufferSecurityCheck>true</BufferSecurityCheck> <BufferSecurityCheck>true</BufferSecurityCheck>
@ -200,6 +202,7 @@
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
<Lib> <Lib>
<OutputFile>..\..\lib64\PocoDataODBCmtd.lib</OutputFile> <OutputFile>..\..\lib64\PocoDataODBCmtd.lib</OutputFile>
@ -224,6 +227,7 @@
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat /> <DebugInformationFormat />
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
<Lib> <Lib>
<OutputFile>..\..\lib64\PocoDataODBCmt.lib</OutputFile> <OutputFile>..\..\lib64\PocoDataODBCmt.lib</OutputFile>
@ -235,7 +239,7 @@
<AdditionalIncludeDirectories>.\include;..\..\Foundation\include;..\..\Data\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>.\include;..\..\Foundation\include;..\..\Data\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;POCO_STATIC;THREADSAFE;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;POCO_STATIC;THREADSAFE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling> <StringPooling>true</StringPooling>
<MinimalRebuild>true</MinimalRebuild> <MinimalRebuild>false</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<BufferSecurityCheck>true</BufferSecurityCheck> <BufferSecurityCheck>true</BufferSecurityCheck>
@ -247,6 +251,7 @@
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
<Lib> <Lib>
<OutputFile>..\..\lib64\PocoDataODBCmdd.lib</OutputFile> <OutputFile>..\..\lib64\PocoDataODBCmdd.lib</OutputFile>
@ -271,6 +276,7 @@
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat /> <DebugInformationFormat />
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
<Lib> <Lib>
<OutputFile>..\..\lib64\PocoDataODBCmd.lib</OutputFile> <OutputFile>..\..\lib64\PocoDataODBCmd.lib</OutputFile>

View File

@ -58,12 +58,28 @@ namespace ODBC {
class ODBC_API Binder: public Poco::Data::AbstractBinder class ODBC_API Binder: public Poco::Data::AbstractBinder
/// Binds placeholders in the sql query to the provided values. Performs data types mapping. /// Binds placeholders in the sql query to the provided values. Performs data types mapping.
{ {
struct ParamDescriptor
{
ParamDescriptor() : colSize(0), cDataType(0), decDigits(-1)
{}
ParamDescriptor(SQLINTEGER colSize_, SQLSMALLINT cDataType_, SQLSMALLINT decDigits_) : colSize(colSize_), cDataType(cDataType_), decDigits(decDigits_)
{}
bool defined() const { return cDataType != 0; }
SQLINTEGER colSize;
SQLSMALLINT cDataType;
SQLSMALLINT decDigits;
};
public: public:
typedef AbstractBinder::Direction Direction; typedef AbstractBinder::Direction Direction;
typedef std::map<SQLPOINTER, SQLLEN> ParamMap; typedef std::map<SQLPOINTER, SQLLEN> ParamMap;
static const size_t DEFAULT_PARAM_SIZE = 1024; static const size_t DEFAULT_PARAM_SIZE = 1024;
enum ParameterBinding enum ParameterBinding
{ {
PB_IMMEDIATE, PB_IMMEDIATE,
@ -72,14 +88,16 @@ public:
Binder(const StatementHandle& rStmt, Binder(const StatementHandle& rStmt,
std::size_t maxFieldSize, std::size_t maxFieldSize,
ParameterBinding dataBinding = PB_IMMEDIATE, ParameterBinding dataBinding,
TypeInfo* pDataTypes = 0); TypeInfo* pDataTypes,
ODBCMetaColumn::NumericConversion numericConversion,
bool insertOnly);
/// Creates the Binder. /// Creates the Binder.
~Binder(); ~Binder();
/// Destroys the Binder. /// Destroys the Binder.
void bind(std::size_t pos, const Poco::Int8& val, Direction dir); void bind(std::size_t pos, const Poco::Int8& val, Direction dir, const WhenNullCb& nullCb);
/// Binds an Int8. /// Binds an Int8.
void bind(std::size_t pos, const std::vector<Poco::Int8>& val, Direction dir); void bind(std::size_t pos, const std::vector<Poco::Int8>& val, Direction dir);
@ -91,7 +109,7 @@ public:
void bind(std::size_t pos, const std::list<Poco::Int8>& val, Direction dir); void bind(std::size_t pos, const std::list<Poco::Int8>& val, Direction dir);
/// Binds an Int8 list. /// Binds an Int8 list.
void bind(std::size_t pos, const Poco::UInt8& val, Direction dir); void bind(std::size_t pos, const Poco::UInt8& val, Direction dir, const WhenNullCb& nullCb);
/// Binds an UInt8. /// Binds an UInt8.
void bind(std::size_t pos, const std::vector<Poco::UInt8>& val, Direction dir); void bind(std::size_t pos, const std::vector<Poco::UInt8>& val, Direction dir);
@ -103,7 +121,7 @@ public:
void bind(std::size_t pos, const std::list<Poco::UInt8>& val, Direction dir); void bind(std::size_t pos, const std::list<Poco::UInt8>& val, Direction dir);
/// Binds an UInt8 list. /// Binds an UInt8 list.
void bind(std::size_t pos, const Poco::Int16& val, Direction dir); void bind(std::size_t pos, const Poco::Int16& val, Direction dir, const WhenNullCb& nullCb);
/// Binds an Int16. /// Binds an Int16.
void bind(std::size_t pos, const std::vector<Poco::Int16>& val, Direction dir); void bind(std::size_t pos, const std::vector<Poco::Int16>& val, Direction dir);
@ -115,7 +133,7 @@ public:
void bind(std::size_t pos, const std::list<Poco::Int16>& val, Direction dir); void bind(std::size_t pos, const std::list<Poco::Int16>& val, Direction dir);
/// Binds an Int16 list. /// Binds an Int16 list.
void bind(std::size_t pos, const Poco::UInt16& val, Direction dir); void bind(std::size_t pos, const Poco::UInt16& val, Direction dir, const WhenNullCb& nullCb);
/// Binds an UInt16. /// Binds an UInt16.
void bind(std::size_t pos, const std::vector<Poco::UInt16>& val, Direction dir); void bind(std::size_t pos, const std::vector<Poco::UInt16>& val, Direction dir);
@ -127,7 +145,7 @@ public:
void bind(std::size_t pos, const std::list<Poco::UInt16>& val, Direction dir); void bind(std::size_t pos, const std::list<Poco::UInt16>& val, Direction dir);
/// Binds an UInt16 list. /// Binds an UInt16 list.
void bind(std::size_t pos, const Poco::Int32& val, Direction dir); void bind(std::size_t pos, const Poco::Int32& val, Direction dir, const WhenNullCb& nullCb);
/// Binds an Int32. /// Binds an Int32.
void bind(std::size_t pos, const std::vector<Poco::Int32>& val, Direction dir); void bind(std::size_t pos, const std::vector<Poco::Int32>& val, Direction dir);
@ -139,7 +157,7 @@ public:
void bind(std::size_t pos, const std::list<Poco::Int32>& val, Direction dir); void bind(std::size_t pos, const std::list<Poco::Int32>& val, Direction dir);
/// Binds an Int32 list. /// Binds an Int32 list.
void bind(std::size_t pos, const Poco::UInt32& val, Direction dir); void bind(std::size_t pos, const Poco::UInt32& val, Direction dir, const WhenNullCb& nullCb);
/// Binds an UInt32. /// Binds an UInt32.
void bind(std::size_t pos, const std::vector<Poco::UInt32>& val, Direction dir); void bind(std::size_t pos, const std::vector<Poco::UInt32>& val, Direction dir);
@ -151,7 +169,7 @@ public:
void bind(std::size_t pos, const std::list<Poco::UInt32>& val, Direction dir); void bind(std::size_t pos, const std::list<Poco::UInt32>& val, Direction dir);
/// Binds an UInt32 list. /// Binds an UInt32 list.
void bind(std::size_t pos, const Poco::Int64& val, Direction dir); void bind(std::size_t pos, const Poco::Int64& val, Direction dir, const WhenNullCb& nullCb);
/// Binds an Int64. /// Binds an Int64.
void bind(std::size_t pos, const std::vector<Poco::Int64>& val, Direction dir); void bind(std::size_t pos, const std::vector<Poco::Int64>& val, Direction dir);
@ -163,7 +181,7 @@ public:
void bind(std::size_t pos, const std::list<Poco::Int64>& val, Direction dir); void bind(std::size_t pos, const std::list<Poco::Int64>& val, Direction dir);
/// Binds an Int64 list. /// Binds an Int64 list.
void bind(std::size_t pos, const Poco::UInt64& val, Direction dir); void bind(std::size_t pos, const Poco::UInt64& val, Direction dir, const WhenNullCb& nullCb);
/// Binds an UInt64. /// Binds an UInt64.
void bind(std::size_t pos, const std::vector<Poco::UInt64>& val, Direction dir); void bind(std::size_t pos, const std::vector<Poco::UInt64>& val, Direction dir);
@ -176,10 +194,10 @@ public:
/// Binds an UInt64 list. /// Binds an UInt64 list.
#ifndef POCO_LONG_IS_64_BIT #ifndef POCO_LONG_IS_64_BIT
void bind(std::size_t pos, const long& val, Direction dir); void bind(std::size_t pos, const long& val, Direction dir, const WhenNullCb& nullCb);
/// Binds a long. /// Binds a long.
void bind(std::size_t pos, const unsigned long& val, Direction dir); void bind(std::size_t pos, const unsigned long& val, Direction dir, const WhenNullCb& nullCb);
/// Binds an unsigned long. /// Binds an unsigned long.
void bind(std::size_t pos, const std::vector<long>& val, Direction dir); void bind(std::size_t pos, const std::vector<long>& val, Direction dir);
@ -192,7 +210,7 @@ public:
/// Binds a long list. /// Binds a long list.
#endif #endif
void bind(std::size_t pos, const bool& val, Direction dir); void bind(std::size_t pos, const bool& val, Direction dir, const WhenNullCb& nullCb);
/// Binds a boolean. /// Binds a boolean.
void bind(std::size_t pos, const std::vector<bool>& val, Direction dir); void bind(std::size_t pos, const std::vector<bool>& val, Direction dir);
@ -204,7 +222,7 @@ public:
void bind(std::size_t pos, const std::list<bool>& val, Direction dir); void bind(std::size_t pos, const std::list<bool>& val, Direction dir);
/// Binds a boolean list. /// Binds a boolean list.
void bind(std::size_t pos, const float& val, Direction dir); void bind(std::size_t pos, const float& val, Direction dir, const WhenNullCb& nullCb);
/// Binds a float. /// Binds a float.
void bind(std::size_t pos, const std::vector<float>& val, Direction dir); void bind(std::size_t pos, const std::vector<float>& val, Direction dir);
@ -216,7 +234,7 @@ public:
void bind(std::size_t pos, const std::list<float>& val, Direction dir); void bind(std::size_t pos, const std::list<float>& val, Direction dir);
/// Binds a float list. /// Binds a float list.
void bind(std::size_t pos, const double& val, Direction dir); void bind(std::size_t pos, const double& val, Direction dir, const WhenNullCb& nullCb);
/// Binds a double. /// Binds a double.
void bind(std::size_t pos, const std::vector<double>& val, Direction dir); void bind(std::size_t pos, const std::vector<double>& val, Direction dir);
@ -228,7 +246,7 @@ public:
void bind(std::size_t pos, const std::list<double>& val, Direction dir); void bind(std::size_t pos, const std::list<double>& val, Direction dir);
/// Binds a double list. /// Binds a double list.
void bind(std::size_t pos, const char& val, Direction dir); void bind(std::size_t pos, const char& val, Direction dir, const WhenNullCb& nullCb);
/// Binds a single character. /// Binds a single character.
void bind(std::size_t pos, const std::vector<char>& val, Direction dir); void bind(std::size_t pos, const std::vector<char>& val, Direction dir);
@ -240,7 +258,7 @@ public:
void bind(std::size_t pos, const std::list<char>& val, Direction dir); void bind(std::size_t pos, const std::list<char>& val, Direction dir);
/// Binds a character list. /// Binds a character list.
void bind(std::size_t pos, const std::string& val, Direction dir); void bind(std::size_t pos, const std::string& val, Direction dir, const WhenNullCb& nullCb);
/// Binds a string. /// Binds a string.
void bind(std::size_t pos, const std::vector<std::string>& val, Direction dir); void bind(std::size_t pos, const std::vector<std::string>& val, Direction dir);
@ -252,7 +270,7 @@ public:
void bind(std::size_t pos, const std::list<std::string>& val, Direction dir); void bind(std::size_t pos, const std::list<std::string>& val, Direction dir);
/// Binds a string list. /// Binds a string list.
void bind(std::size_t pos, const UTF16String& val, Direction dir); void bind(std::size_t pos, const UTF16String& val, Direction dir, const WhenNullCb& nullCb);
/// Binds a string. /// Binds a string.
void bind(std::size_t pos, const std::vector<UTF16String>& val, Direction dir); void bind(std::size_t pos, const std::vector<UTF16String>& val, Direction dir);
@ -264,10 +282,10 @@ public:
void bind(std::size_t pos, const std::list<UTF16String>& val, Direction dir); void bind(std::size_t pos, const std::list<UTF16String>& val, Direction dir);
/// Binds a string list. /// Binds a string list.
void bind(std::size_t pos, const BLOB& val, Direction dir); void bind(std::size_t pos, const BLOB& val, Direction dir, const WhenNullCb& nullCb);
/// Binds a BLOB. In-bound only. /// Binds a BLOB. In-bound only.
void bind(std::size_t pos, const CLOB& val, Direction dir); void bind(std::size_t pos, const CLOB& val, Direction dir, const WhenNullCb& nullCb);
/// Binds a CLOB. In-bound only. /// Binds a CLOB. In-bound only.
void bind(std::size_t pos, const std::vector<BLOB>& val, Direction dir); void bind(std::size_t pos, const std::vector<BLOB>& val, Direction dir);
@ -288,7 +306,7 @@ public:
void bind(std::size_t pos, const std::list<CLOB>& val, Direction dir); void bind(std::size_t pos, const std::list<CLOB>& val, Direction dir);
/// Binds a CLOB list. /// Binds a CLOB list.
void bind(std::size_t pos, const Date& val, Direction dir); void bind(std::size_t pos, const Date& val, Direction dir, const WhenNullCb& nullCb);
/// Binds a Date. /// Binds a Date.
void bind(std::size_t pos, const std::vector<Date>& val, Direction dir); void bind(std::size_t pos, const std::vector<Date>& val, Direction dir);
@ -300,7 +318,7 @@ public:
void bind(std::size_t pos, const std::list<Date>& val, Direction dir); void bind(std::size_t pos, const std::list<Date>& val, Direction dir);
/// Binds a Date list. /// Binds a Date list.
void bind(std::size_t pos, const Time& val, Direction dir); void bind(std::size_t pos, const Time& val, Direction dir, const WhenNullCb& nullCb);
/// Binds a Time. /// Binds a Time.
void bind(std::size_t pos, const std::vector<Time>& val, Direction dir); void bind(std::size_t pos, const std::vector<Time>& val, Direction dir);
@ -312,7 +330,7 @@ public:
void bind(std::size_t pos, const std::list<Time>& val, Direction dir); void bind(std::size_t pos, const std::list<Time>& val, Direction dir);
/// Binds a Time list. /// Binds a Time list.
void bind(std::size_t pos, const DateTime& val, Direction dir); void bind(std::size_t pos, const DateTime& val, Direction dir, const WhenNullCb& nullCb);
/// Binds a DateTime. /// Binds a DateTime.
void bind(std::size_t pos, const std::vector<DateTime>& val, Direction dir); void bind(std::size_t pos, const std::vector<DateTime>& val, Direction dir);
@ -324,16 +342,16 @@ public:
void bind(std::size_t pos, const std::list<DateTime>& val, Direction dir); void bind(std::size_t pos, const std::list<DateTime>& val, Direction dir);
/// Binds a DateTime list. /// Binds a DateTime list.
void bind(std::size_t pos, const NullData& val, Direction dir); void bind(std::size_t pos, const NullData& val, Direction dir, const std::type_info& bindType);
/// Binds a null. In-bound only. /// Binds a null. In-bound only.
void bind(std::size_t pos, const std::vector<NullData>& val, Direction dir); void bind(std::size_t pos, const std::vector<NullData>& val, Direction dir, const std::type_info& bindType);
/// Binds a null vector. /// Binds a null vector.
void bind(std::size_t pos, const std::deque<NullData>& val, Direction dir); void bind(std::size_t pos, const std::deque<NullData>& val, Direction dir, const std::type_info& bindType);
/// Binds a null deque. /// Binds a null deque.
void bind(std::size_t pos, const std::list<NullData>& val, Direction dir); void bind(std::size_t pos, const std::list<NullData>& val, Direction dir, const std::type_info& bindType);
/// Binds a null list. /// Binds a null list.
void setDataBinding(ParameterBinding binding); void setDataBinding(ParameterBinding binding);
@ -353,6 +371,7 @@ public:
/// Clears the cached storage. /// Clears the cached storage.
private: private:
typedef std::vector<ParamDescriptor> ParameterInfoVec;
typedef std::vector<SQLLEN*> LengthPtrVec; typedef std::vector<SQLLEN*> LengthPtrVec;
typedef std::vector<SQLLEN> LengthVec; typedef std::vector<SQLLEN> LengthVec;
typedef std::vector<LengthVec*> LengthVecVec; typedef std::vector<LengthVec*> LengthVecVec;
@ -365,18 +384,19 @@ private:
typedef std::vector<TimeVec*> TimeVecVec; typedef std::vector<TimeVec*> TimeVecVec;
typedef std::vector<SQL_TIMESTAMP_STRUCT> DateTimeVec; typedef std::vector<SQL_TIMESTAMP_STRUCT> DateTimeVec;
typedef std::vector<DateTimeVec*> DateTimeVecVec; typedef std::vector<DateTimeVec*> DateTimeVecVec;
typedef std::vector<Poco::Any> AnyVec; typedef std::vector<Poco::Any*> AnyPtrVec;
typedef std::vector<AnyVec> AnyVecVec; typedef std::vector<AnyPtrVec> AnyPtrVecVec;
typedef std::map<char*, std::string*> StringMap; typedef std::map<char*, std::string*> StringMap;
typedef std::map<UTF16String::value_type*, UTF16String*> UTF16StringMap; typedef std::map<UTF16String::value_type*, UTF16String*> UTF16StringMap;
typedef std::map<SQL_DATE_STRUCT*, Date*> DateMap; typedef std::map<SQL_DATE_STRUCT*, Date*> DateMap;
typedef std::map<SQL_TIME_STRUCT*, Time*> TimeMap; typedef std::map<SQL_TIME_STRUCT*, Time*> TimeMap;
typedef std::map<SQL_TIMESTAMP_STRUCT*, DateTime*> TimestampMap; typedef std::map<SQL_TIMESTAMP_STRUCT*, DateTime*> TimestampMap;
typedef std::map<SQLLEN*, WhenNullCb> NullCbMap;
void describeParameter(std::size_t pos); void describeParameter(std::size_t pos);
/// Sets the description field for the parameter, if needed. /// Sets the description field for the parameter, if needed.
void bind(std::size_t pos, const char* const& pVal, Direction dir); void bind(std::size_t pos, const char* const& pVal, Direction dir, const WhenNullCb& nullCb);
/// Binds a const char ptr. /// Binds a const char ptr.
/// This is a private no-op in this implementation /// This is a private no-op in this implementation
/// due to security risk. /// due to security risk.
@ -386,13 +406,19 @@ private:
/// specified by user. /// specified by user.
template <typename T> template <typename T>
void bindImpl(std::size_t pos, T& val, SQLSMALLINT cDataType, Direction dir) void bindImpl(std::size_t pos, T& val, SQLSMALLINT cDataType, Direction dir, const WhenNullCb& nullCb)
{ {
SQLINTEGER colSize = 0; SQLINTEGER colSize = 0;
SQLSMALLINT decDigits = 0; SQLSMALLINT decDigits = 0;
getColSizeAndPrecision(pos, cDataType, colSize, decDigits); getColSizeAndPrecision(pos, cDataType, colSize, decDigits);
SQLLEN* pLenIn = NULL;
_lengthIndicator.push_back(0); if (isOutBound(dir) && nullCb.defined())
{
pLenIn = new SQLLEN;
*pLenIn = SQL_NTS; // microsoft example does that, otherwise no null indicator is returned
_nullCbMap.insert(NullCbMap::value_type(pLenIn, nullCb));
}
_lengthIndicator.push_back(pLenIn);
if (Utility::isError(SQLBindParameter(_rStmt, if (Utility::isError(SQLBindParameter(_rStmt,
(SQLUSMALLINT) pos + 1, (SQLUSMALLINT) pos + 1,
@ -401,14 +427,15 @@ private:
Utility::sqlDataType(cDataType), Utility::sqlDataType(cDataType),
colSize, colSize,
decDigits, decDigits,
(SQLPOINTER) &val, 0, 0))) (SQLPOINTER)&val, 0,
_lengthIndicator.back())))
{ {
throw StatementException(_rStmt, "SQLBindParameter()"); throw StatementException(_rStmt, "SQLBindParameter()");
} }
} }
template <typename L> template <typename L>
void bindImplLOB(std::size_t pos, const L& val, Direction dir) void bindImplLOB(std::size_t pos, const L& val, Direction dir, const WhenNullCb& nullCb)
{ {
if (isOutBound(dir) || !isInBound(dir)) if (isOutBound(dir) || !isInBound(dir))
throw NotImplementedException("LOB parameter type can only be inbound."); throw NotImplementedException("LOB parameter type can only be inbound.");
@ -424,13 +451,17 @@ private:
if (PB_AT_EXEC == _paramBinding) if (PB_AT_EXEC == _paramBinding)
*pLenIn = SQL_LEN_DATA_AT_EXEC(size); *pLenIn = SQL_LEN_DATA_AT_EXEC(size);
if (isOutBound(dir) && nullCb.defined())
_nullCbMap.insert(NullCbMap::value_type(pLenIn, nullCb));
_lengthIndicator.push_back(pLenIn); _lengthIndicator.push_back(pLenIn);
SQLSMALLINT sqlType = (isInBound(dir) && size <= _maxVarBinColSize) ? SQL_VARBINARY : SQL_LONGVARBINARY;
if (Utility::isError(SQLBindParameter(_rStmt, if (Utility::isError(SQLBindParameter(_rStmt,
(SQLUSMALLINT) pos + 1, (SQLUSMALLINT) pos + 1,
SQL_PARAM_INPUT, SQL_PARAM_INPUT,
SQL_C_BINARY, SQL_C_BINARY,
SQL_LONGVARBINARY, sqlType,
(SQLUINTEGER) size, (SQLUINTEGER) size,
0, 0,
pVal, pVal,
@ -485,9 +516,9 @@ private:
if (_containers.size() <= pos) if (_containers.size() <= pos)
_containers.resize(pos + 1); _containers.resize(pos + 1);
_containers[pos].push_back(std::vector<Type>()); _containers[pos].push_back( new Any(std::vector<Type>()) );
std::vector<Type>& cont = RefAnyCast<std::vector<Type> >(_containers[pos].back()); std::vector<Type>& cont = RefAnyCast<std::vector<Type> >( *_containers[pos].back() );
cont.assign(val.begin(), val.end()); cont.assign(val.begin(), val.end());
bindImplVec(pos, cont, cDataType, dir); bindImplVec(pos, cont, cDataType, dir);
} }
@ -586,12 +617,13 @@ private:
std::memcpy(_charPtrs[pos] + offset, it->c_str(), strSize); std::memcpy(_charPtrs[pos] + offset, it->c_str(), strSize);
offset += size; offset += size;
} }
SQLSMALLINT sqlType = (isInBound(dir) && size < _maxCharColLength) ? SQL_VARCHAR : SQL_LONGVARCHAR;
if (Utility::isError(SQLBindParameter(_rStmt, if (Utility::isError(SQLBindParameter(_rStmt,
(SQLUSMALLINT) pos + 1, (SQLUSMALLINT) pos + 1,
toODBCDirection(dir), toODBCDirection(dir),
SQL_C_CHAR, SQL_C_CHAR,
SQL_LONGVARCHAR, sqlType,
(SQLUINTEGER) size - 1, (SQLUINTEGER) size - 1,
0, 0,
_charPtrs[pos], _charPtrs[pos],
@ -652,12 +684,12 @@ private:
std::memcpy(_utf16CharPtrs[pos] + offset, it->data(), strSize); std::memcpy(_utf16CharPtrs[pos] + offset, it->data(), strSize);
offset += (size / sizeof(UTF16Char)); offset += (size / sizeof(UTF16Char));
} }
SQLSMALLINT sqlType = (isInBound(dir) && size < _maxWCharColLength) ? SQL_WVARCHAR : SQL_WLONGVARCHAR;
if (Utility::isError(SQLBindParameter(_rStmt, if (Utility::isError(SQLBindParameter(_rStmt,
(SQLUSMALLINT)pos + 1, (SQLUSMALLINT)pos + 1,
toODBCDirection(dir), toODBCDirection(dir),
SQL_C_WCHAR, SQL_C_WCHAR,
SQL_WLONGVARCHAR, sqlType,
(SQLUINTEGER)size - 1, (SQLUINTEGER)size - 1,
0, 0,
_utf16CharPtrs[pos], _utf16CharPtrs[pos],
@ -722,12 +754,13 @@ private:
std::memcpy(_charPtrs[pos] + offset, cIt->rawContent(), blobSize * sizeof(CharType)); std::memcpy(_charPtrs[pos] + offset, cIt->rawContent(), blobSize * sizeof(CharType));
offset += size; offset += size;
} }
SQLSMALLINT sqlType = (isInBound(dir) && size <= _maxVarBinColSize) ? SQL_VARBINARY : SQL_LONGVARBINARY;
if (Utility::isError(SQLBindParameter(_rStmt, if (Utility::isError(SQLBindParameter(_rStmt,
(SQLUSMALLINT) pos + 1, (SQLUSMALLINT) pos + 1,
SQL_PARAM_INPUT, SQL_PARAM_INPUT,
SQL_C_BINARY, SQL_C_BINARY,
SQL_LONGVARBINARY, sqlType,
(SQLUINTEGER) size, (SQLUINTEGER) size,
0, 0,
_charPtrs[pos], _charPtrs[pos],
@ -754,8 +787,6 @@ private:
setParamSetSize(length); setParamSetSize(length);
SQLINTEGER size = (SQLINTEGER) sizeof(SQL_DATE_STRUCT);
if (_vecLengthIndicator.size() <= pos) if (_vecLengthIndicator.size() <= pos)
{ {
_vecLengthIndicator.resize(pos + 1, 0); _vecLengthIndicator.resize(pos + 1, 0);
@ -804,8 +835,6 @@ private:
setParamSetSize(val.size()); setParamSetSize(val.size());
SQLINTEGER size = (SQLINTEGER) sizeof(SQL_TIME_STRUCT);
if (_vecLengthIndicator.size() <= pos) if (_vecLengthIndicator.size() <= pos)
{ {
_vecLengthIndicator.resize(pos + 1, 0); _vecLengthIndicator.resize(pos + 1, 0);
@ -855,8 +884,6 @@ private:
setParamSetSize(length); setParamSetSize(length);
SQLINTEGER size = (SQLINTEGER) sizeof(SQL_TIMESTAMP_STRUCT);
if (_vecLengthIndicator.size() <= pos) if (_vecLengthIndicator.size() <= pos)
{ {
_vecLengthIndicator.resize(pos + 1, 0); _vecLengthIndicator.resize(pos + 1, 0);
@ -891,7 +918,7 @@ private:
} }
template<typename C> template<typename C>
void bindImplNullContainer(std::size_t pos, const C& val, Direction dir) void bindImplNullContainer(std::size_t pos, const C& val, Direction dir, const std::type_info& bindElemType)
{ {
if (isOutBound(dir) || !isInBound(dir)) if (isOutBound(dir) || !isInBound(dir))
throw NotImplementedException("Null container parameter type can only be inbound."); throw NotImplementedException("Null container parameter type can only be inbound.");
@ -906,8 +933,6 @@ private:
setParamSetSize(length); setParamSetSize(length);
SQLINTEGER size = SQL_NULL_DATA;
if (_vecLengthIndicator.size() <= pos) if (_vecLengthIndicator.size() <= pos)
{ {
_vecLengthIndicator.resize(pos + 1, 0); _vecLengthIndicator.resize(pos + 1, 0);
@ -916,13 +941,14 @@ private:
SQLINTEGER colSize = 0; SQLINTEGER colSize = 0;
SQLSMALLINT decDigits = 0; SQLSMALLINT decDigits = 0;
getColSizeAndPrecision(pos, SQL_C_STINYINT, colSize, decDigits); SQLSMALLINT colType = _pTypeInfo->tryTypeidToCType(bindElemType, SQL_C_STINYINT);
getColSizeAndPrecision(pos, colType, colSize, decDigits);
if (Utility::isError(SQLBindParameter(_rStmt, if (Utility::isError(SQLBindParameter(_rStmt,
(SQLUSMALLINT) pos + 1, (SQLUSMALLINT) pos + 1,
SQL_PARAM_INPUT, SQL_PARAM_INPUT,
SQL_C_STINYINT, colType,
Utility::sqlDataType(SQL_C_STINYINT), Utility::sqlDataType(colType),
colSize, colSize,
decDigits, decDigits,
0, 0,
@ -957,6 +983,7 @@ private:
void freeMemory(); void freeMemory();
/// Frees all dynamically allocated memory resources. /// Frees all dynamically allocated memory resources.
template<typename T> template<typename T>
void getMinValueSize(T& val, SQLINTEGER& size) void getMinValueSize(T& val, SQLINTEGER& size)
/// Some ODBC drivers return DB-wide maximum allowed size for variable size columns, /// Some ODBC drivers return DB-wide maximum allowed size for variable size columns,
@ -995,6 +1022,7 @@ private:
ParamMap _inParams; ParamMap _inParams;
ParamMap _outParams; ParamMap _outParams;
ParameterBinding _paramBinding; ParameterBinding _paramBinding;
ParameterInfoVec _parameters;
DateMap _dates; DateMap _dates;
TimeMap _times; TimeMap _times;
@ -1011,16 +1039,22 @@ private:
const TypeInfo* _pTypeInfo; const TypeInfo* _pTypeInfo;
SQLINTEGER _paramSetSize; SQLINTEGER _paramSetSize;
std::size_t _maxFieldSize; std::size_t _maxFieldSize;
AnyVecVec _containers; AnyPtrVecVec _containers;
std::size_t _maxCharColLength;
std::size_t _maxWCharColLength;
std::size_t _maxVarBinColSize;
ODBCMetaColumn::NumericConversion _numericConversion;
NullCbMap _nullCbMap;
bool _insertOnly;
}; };
// //
// inlines // inlines
// //
inline void Binder::bind(std::size_t pos, const Poco::Int8& val, Direction dir) inline void Binder::bind(std::size_t pos, const Poco::Int8& val, Direction dir, const WhenNullCb& nullCb)
{ {
bindImpl(pos, val, SQL_C_STINYINT, dir); bindImpl(pos, val, SQL_C_STINYINT, dir, nullCb);
} }
@ -1042,9 +1076,9 @@ inline void Binder::bind(std::size_t pos, const std::list<Poco::Int8>& val, Dire
} }
inline void Binder::bind(std::size_t pos, const Poco::UInt8& val, Direction dir) inline void Binder::bind(std::size_t pos, const Poco::UInt8& val, Direction dir, const WhenNullCb& nullCb)
{ {
bindImpl(pos, val, SQL_C_UTINYINT, dir); bindImpl(pos, val, SQL_C_UTINYINT, dir, nullCb);
} }
@ -1066,9 +1100,9 @@ inline void Binder::bind(std::size_t pos, const std::list<Poco::UInt8>& val, Dir
} }
inline void Binder::bind(std::size_t pos, const Poco::Int16& val, Direction dir) inline void Binder::bind(std::size_t pos, const Poco::Int16& val, Direction dir, const WhenNullCb& nullCb)
{ {
bindImpl(pos, val, SQL_C_SSHORT, dir); bindImpl(pos, val, SQL_C_SSHORT, dir, nullCb);
} }
@ -1090,9 +1124,9 @@ inline void Binder::bind(std::size_t pos, const std::list<Poco::Int16>& val, Dir
} }
inline void Binder::bind(std::size_t pos, const Poco::UInt16& val, Direction dir) inline void Binder::bind(std::size_t pos, const Poco::UInt16& val, Direction dir, const WhenNullCb& nullCb)
{ {
bindImpl(pos, val, SQL_C_USHORT, dir); bindImpl(pos, val, SQL_C_USHORT, dir, nullCb);
} }
@ -1114,9 +1148,9 @@ inline void Binder::bind(std::size_t pos, const std::list<Poco::UInt16>& val, Di
} }
inline void Binder::bind(std::size_t pos, const Poco::Int32& val, Direction dir) inline void Binder::bind(std::size_t pos, const Poco::Int32& val, Direction dir, const WhenNullCb& nullCb)
{ {
bindImpl(pos, val, SQL_C_SLONG, dir); bindImpl(pos, val, SQL_C_SLONG, dir, nullCb);
} }
@ -1138,9 +1172,9 @@ inline void Binder::bind(std::size_t pos, const std::list<Poco::Int32>& val, Dir
} }
inline void Binder::bind(std::size_t pos, const Poco::UInt32& val, Direction dir) inline void Binder::bind(std::size_t pos, const Poco::UInt32& val, Direction dir, const WhenNullCb& nullCb)
{ {
bindImpl(pos, val, SQL_C_ULONG, dir); bindImpl(pos, val, SQL_C_ULONG, dir, nullCb);
} }
@ -1162,9 +1196,9 @@ inline void Binder::bind(std::size_t pos, const std::list<Poco::UInt32>& val, Di
} }
inline void Binder::bind(std::size_t pos, const Poco::Int64& val, Direction dir) inline void Binder::bind(std::size_t pos, const Poco::Int64& val, Direction dir, const WhenNullCb& nullCb)
{ {
bindImpl(pos, val, SQL_C_SBIGINT, dir); bindImpl(pos, val, SQL_C_SBIGINT, dir, nullCb);
} }
@ -1186,9 +1220,9 @@ inline void Binder::bind(std::size_t pos, const std::list<Poco::Int64>& val, Dir
} }
inline void Binder::bind(std::size_t pos, const Poco::UInt64& val, Direction dir) inline void Binder::bind(std::size_t pos, const Poco::UInt64& val, Direction dir, const WhenNullCb& nullCb)
{ {
bindImpl(pos, val, SQL_C_UBIGINT, dir); bindImpl(pos, val, SQL_C_UBIGINT, dir, nullCb);
} }
@ -1211,15 +1245,15 @@ inline void Binder::bind(std::size_t pos, const std::list<Poco::UInt64>& val, Di
#ifndef POCO_LONG_IS_64_BIT #ifndef POCO_LONG_IS_64_BIT
inline void Binder::bind(std::size_t pos, const long& val, Direction dir) inline void Binder::bind(std::size_t pos, const long& val, Direction dir, const WhenNullCb& nullCb)
{ {
bindImpl(pos, val, SQL_C_SLONG, dir); bindImpl(pos, val, SQL_C_SLONG, dir, nullCb);
} }
inline void Binder::bind(std::size_t pos, const unsigned long& val, Direction dir) inline void Binder::bind(std::size_t pos, const unsigned long& val, Direction dir, const WhenNullCb& nullCb)
{ {
bindImpl(pos, val, SQL_C_SLONG, dir); bindImpl(pos, val, SQL_C_SLONG, dir, nullCb);
} }
@ -1242,9 +1276,9 @@ inline void Binder::bind(std::size_t pos, const std::list<long>& val, Direction
#endif #endif
inline void Binder::bind(std::size_t pos, const float& val, Direction dir) inline void Binder::bind(std::size_t pos, const float& val, Direction dir, const WhenNullCb& nullCb)
{ {
bindImpl(pos, val, SQL_C_FLOAT, dir); bindImpl(pos, val, SQL_C_FLOAT, dir, nullCb);
} }
@ -1266,9 +1300,9 @@ inline void Binder::bind(std::size_t pos, const std::list<float>& val, Direction
} }
inline void Binder::bind(std::size_t pos, const double& val, Direction dir) inline void Binder::bind(std::size_t pos, const double& val, Direction dir, const WhenNullCb& nullCb)
{ {
bindImpl(pos, val, SQL_C_DOUBLE, dir); bindImpl(pos, val, SQL_C_DOUBLE, dir, nullCb);
} }
@ -1290,9 +1324,9 @@ inline void Binder::bind(std::size_t pos, const std::list<double>& val, Directio
} }
inline void Binder::bind(std::size_t pos, const bool& val, Direction dir) inline void Binder::bind(std::size_t pos, const bool& val, Direction dir, const WhenNullCb& nullCb)
{ {
bindImpl(pos, val, SQL_C_BIT, dir); bindImpl(pos, val, SQL_C_BIT, dir, nullCb);
} }
@ -1314,9 +1348,9 @@ inline void Binder::bind(std::size_t pos, const std::list<bool>& val, Direction
} }
inline void Binder::bind(std::size_t pos, const char& val, Direction dir) inline void Binder::bind(std::size_t pos, const char& val, Direction dir, const WhenNullCb& nullCb)
{ {
bindImpl(pos, val, SQL_C_STINYINT, dir); bindImpl(pos, val, SQL_C_STINYINT, dir, nullCb);
} }
@ -1373,15 +1407,15 @@ inline void Binder::bind(std::size_t pos, const std::list<UTF16String>& val, Dir
bindImplContainerUTF16String(pos, val, dir); bindImplContainerUTF16String(pos, val, dir);
} }
inline void Binder::bind(std::size_t pos, const BLOB& val, Direction dir) inline void Binder::bind(std::size_t pos, const BLOB& val, Direction dir, const WhenNullCb& nullCb)
{ {
bindImplLOB<BLOB>(pos, val, dir); bindImplLOB<BLOB>(pos, val, dir, nullCb);
} }
inline void Binder::bind(std::size_t pos, const CLOB& val, Direction dir) inline void Binder::bind(std::size_t pos, const CLOB& val, Direction dir, const WhenNullCb& nullCb)
{ {
bindImplLOB<CLOB>(pos, val, dir); bindImplLOB<CLOB>(pos, val, dir, nullCb);
} }
@ -1475,21 +1509,21 @@ inline void Binder::bind(std::size_t pos, const std::list<DateTime>& val, Direct
} }
inline void Binder::bind(std::size_t pos, const std::vector<NullData>& val, Direction dir) inline void Binder::bind(std::size_t pos, const std::vector<NullData>& val, Direction dir, const std::type_info& bindElemType)
{ {
bindImplNullContainer(pos, val, dir); bindImplNullContainer(pos, val, dir, bindElemType);
} }
inline void Binder::bind(std::size_t pos, const std::deque<NullData>& val, Direction dir) inline void Binder::bind(std::size_t pos, const std::deque<NullData>& val, Direction dir, const std::type_info& bindElemType)
{ {
bindImplNullContainer(pos, val, dir); bindImplNullContainer(pos, val, dir, bindElemType);
} }
inline void Binder::bind(std::size_t pos, const std::list<NullData>& val, Direction dir) inline void Binder::bind(std::size_t pos, const std::list<NullData>& val, Direction dir, const std::type_info& bindElemType)
{ {
bindImplNullContainer(pos, val, dir); bindImplNullContainer(pos, val, dir, bindElemType);
} }

View File

@ -19,7 +19,6 @@
#ifndef Data_ODBC_ConnectionHandle_INCLUDED #ifndef Data_ODBC_ConnectionHandle_INCLUDED
#define Data_ODBC_ConnectionHandle_INCLUDED #define Data_ODBC_ConnectionHandle_INCLUDED
#include "Poco/Data/ODBC/ODBC.h" #include "Poco/Data/ODBC/ODBC.h"
#include "Poco/Data/ODBC/EnvironmentHandle.h" #include "Poco/Data/ODBC/EnvironmentHandle.h"
#ifdef POCO_OS_FAMILY_WINDOWS #ifdef POCO_OS_FAMILY_WINDOWS
@ -49,6 +48,9 @@ public:
const SQLHDBC& handle() const; const SQLHDBC& handle() const;
/// Returns const reference to handle; /// Returns const reference to handle;
operator bool() const;
/// Returns true if the handle is valid
private: private:
operator SQLHDBC& (); operator SQLHDBC& ();
/// Conversion operator into reference to native type. /// Conversion operator into reference to native type.
@ -59,9 +61,8 @@ private:
ConnectionHandle(const ConnectionHandle&); ConnectionHandle(const ConnectionHandle&);
const ConnectionHandle& operator=(const ConnectionHandle&); const ConnectionHandle& operator=(const ConnectionHandle&);
const EnvironmentHandle* _pEnvironment; const EnvironmentHandle _environment;
SQLHDBC _hdbc; SQLHDBC _hdbc;
bool _ownsEnvironment;
}; };
@ -92,6 +93,11 @@ inline SQLHDBC& ConnectionHandle::handle()
} }
inline ConnectionHandle::operator bool () const
{
return _hdbc != SQL_NULL_HDBC;
}
} } } // namespace Poco::Data::ODBC } } } // namespace Poco::Data::ODBC

View File

@ -59,12 +59,12 @@ public:
typedef std::vector<DiagnosticFields> FieldVec; typedef std::vector<DiagnosticFields> FieldVec;
typedef typename FieldVec::const_iterator Iterator; typedef typename FieldVec::const_iterator Iterator;
explicit Diagnostics(const H& handle): _handle(handle) explicit Diagnostics(const H& handle)
/// Creates and initializes the Diagnostics. /// Creates and initializes the Diagnostics.
{ {
std::memset(_connectionName, 0, sizeof(_connectionName)); std::memset(_connectionName, 0, sizeof(_connectionName));
std::memset(_serverName, 0, sizeof(_serverName)); std::memset(_serverName, 0, sizeof(_serverName));
diagnostics(); diagnostics(handle);
} }
~Diagnostics() ~Diagnostics()
@ -138,7 +138,7 @@ public:
return _fields.end(); return _fields.end();
} }
const Diagnostics& diagnostics() const Diagnostics& diagnostics(const H& handle)
{ {
DiagnosticFields df; DiagnosticFields df;
SQLSMALLINT count = 1; SQLSMALLINT count = 1;
@ -149,7 +149,7 @@ public:
reset(); reset();
while (!Utility::isError(SQLGetDiagRec(handleType, while (!Utility::isError(SQLGetDiagRec(handleType,
_handle, handle,
count, count,
df._sqlState, df._sqlState,
&df._nativeError, &df._nativeError,
@ -163,7 +163,7 @@ public:
// (they fail if connection has not been established yet // (they fail if connection has not been established yet
// or return empty string if not applicable for the context) // or return empty string if not applicable for the context)
if (Utility::isError(SQLGetDiagField(handleType, if (Utility::isError(SQLGetDiagField(handleType,
_handle, handle,
count, count,
SQL_DIAG_CONNECTION_NAME, SQL_DIAG_CONNECTION_NAME,
_connectionName, _connectionName,
@ -182,7 +182,7 @@ public:
} }
if (Utility::isError(SQLGetDiagField(handleType, if (Utility::isError(SQLGetDiagField(handleType,
_handle, handle,
count, count,
SQL_DIAG_SERVER_NAME, SQL_DIAG_SERVER_NAME,
_serverName, _serverName,
@ -223,9 +223,6 @@ private:
/// Diagnostics container /// Diagnostics container
FieldVec _fields; FieldVec _fields;
/// Context handle
const H& _handle;
}; };

View File

@ -39,6 +39,9 @@ public:
EnvironmentHandle(); EnvironmentHandle();
/// Creates the EnvironmentHandle. /// Creates the EnvironmentHandle.
explicit EnvironmentHandle(const SQLHENV* henv);
/// Creates the EnvironmentHandle which doesn't own the handle
~EnvironmentHandle(); ~EnvironmentHandle();
/// Destroys the EnvironmentHandle. /// Destroys the EnvironmentHandle.
@ -52,8 +55,7 @@ private:
operator SQLHENV& (); operator SQLHENV& ();
/// Conversion operator into reference to native type. /// Conversion operator into reference to native type.
SQLHENV& handle(); void init();
/// Returns reference to handle.
EnvironmentHandle(const EnvironmentHandle&); EnvironmentHandle(const EnvironmentHandle&);
const EnvironmentHandle& operator=(const EnvironmentHandle&); const EnvironmentHandle& operator=(const EnvironmentHandle&);
@ -79,12 +81,6 @@ inline const SQLHENV& EnvironmentHandle::handle() const
inline EnvironmentHandle::operator SQLHENV& () inline EnvironmentHandle::operator SQLHENV& ()
{
return handle();
}
inline SQLHENV& EnvironmentHandle::handle()
{ {
return _henv; return _henv;
} }

View File

@ -491,6 +491,9 @@ private:
return true; return true;
} }
template<typename T>
bool extractManualLOBImpl(std::size_t pos, Poco::Data::LOB<T>& val, SQLSMALLINT cType);
template <typename T, typename NT> template <typename T, typename NT>
bool extAny(std::size_t pos, T& val) bool extAny(std::size_t pos, T& val)
{ {
@ -511,7 +514,7 @@ private:
bool extractImpl(std::size_t pos, T& val) bool extractImpl(std::size_t pos, T& val)
/// Utility function for extraction of Any and DynamicAny. /// Utility function for extraction of Any and DynamicAny.
{ {
ODBCMetaColumn column(_rStmt, pos); ODBCMetaColumn column(_rStmt, pos, _pPreparator->numericConversion());
switch (column.type()) switch (column.type())
{ {
@ -717,7 +720,7 @@ inline bool Extractor::isNullLengthIndicator(SQLLEN val) const
inline SQLINTEGER Extractor::columnSize(std::size_t pos) const inline SQLINTEGER Extractor::columnSize(std::size_t pos) const
{ {
std::size_t size = ODBCMetaColumn(_rStmt, pos).length(); std::size_t size = ODBCMetaColumn(_rStmt, pos, _pPreparator->numericConversion()).length();
std::size_t maxSize = _pPreparator->maxDataSize(pos); std::size_t maxSize = _pPreparator->maxDataSize(pos);
if (size > maxSize) size = maxSize; if (size > maxSize) size = maxSize;
return (SQLINTEGER) size; return (SQLINTEGER) size;

View File

@ -43,7 +43,9 @@ template <class H, SQLSMALLINT handleType>
class HandleException: public ODBCException class HandleException: public ODBCException
{ {
public: public:
HandleException(const H& handle): _error(handle) HandleException(const H& handle, int code = 0) :
ODBCException(code),
_error(handle)
/// Creates HandleException /// Creates HandleException
{ {
message(_error.toString()); message(_error.toString());
@ -129,12 +131,24 @@ public:
_error.toString()); _error.toString());
} }
std::string errorString() const
/// Returns the error diagnostics string
{
return _error.toString();
}
static std::string errorString(const H& handle) static std::string errorString(const H& handle)
/// Returns the error diagnostics string for the handle. /// Returns the error diagnostics string for the handle.
{ {
return Error<H, handleType>(handle).toString(); return Error<H, handleType>(handle).toString();
} }
protected:
const Error<H, handleType>& error() const
{
return _error;
}
private: private:
Error<H, handleType> _error; Error<H, handleType> _error;
}; };

View File

@ -39,7 +39,15 @@ namespace ODBC {
class ODBC_API ODBCMetaColumn: public MetaColumn class ODBC_API ODBCMetaColumn: public MetaColumn
{ {
public: public:
explicit ODBCMetaColumn(const StatementHandle& rStmt, std::size_t position);
enum NumericConversion
{
NC_BEST_FIT = 0,
NC_FORCE_STRING = 1,
NC_BEST_FIT_DBL_LIMIT = 2
};
ODBCMetaColumn(const StatementHandle& rStmt, std::size_t position, NumericConversion numericConversion);
/// Creates the ODBCMetaColumn. /// Creates the ODBCMetaColumn.
~ODBCMetaColumn(); ~ODBCMetaColumn();
@ -73,6 +81,7 @@ private:
SQLLEN _dataLength; SQLLEN _dataLength;
const StatementHandle& _rStmt; const StatementHandle& _rStmt;
ColumnDescription _columnDesc; ColumnDescription _columnDesc;
NumericConversion _numericConversion;
}; };

View File

@ -60,7 +60,7 @@ protected:
/// Returns the number of affected rows. /// Returns the number of affected rows.
/// Used to find out the number of rows affected by insert or update. /// Used to find out the number of rows affected by insert or update.
const MetaColumn& metaColumn(std::size_t pos) const; const MetaColumn& metaColumn(std::size_t pos, size_t dataSet) const;
/// Returns column meta data. /// Returns column meta data.
bool hasNext(); bool hasNext();
@ -93,6 +93,10 @@ protected:
std::string nativeSQL(); std::string nativeSQL();
/// Returns the SQL string as modified by the driver. /// Returns the SQL string as modified by the driver.
protected:
virtual void insertHint();
private: private:
typedef Poco::Data::AbstractBindingVec Bindings; typedef Poco::Data::AbstractBindingVec Bindings;
typedef Poco::SharedPtr<Binder> BinderPtr; typedef Poco::SharedPtr<Binder> BinderPtr;
@ -140,9 +144,10 @@ private:
void getData(); void getData();
void addPreparator(); bool addPreparator(bool addAlways = true);
void fillColumns(); void fillColumns(size_t dataSetPos);
void checkError(SQLRETURN rc, const std::string& msg=""); void checkError(SQLRETURN rc, const std::string& msg="");
bool nextResultSet();
const SQLHDBC& _rConnection; const SQLHDBC& _rConnection;
const StatementHandle _stmt; const StatementHandle _stmt;
@ -155,6 +160,9 @@ private:
bool _prepared; bool _prepared;
mutable std::size_t _affectedRowCount; mutable std::size_t _affectedRowCount;
bool _canCompile; bool _canCompile;
ODBCMetaColumn::NumericConversion _numericConversion;
bool _isPostgres;
bool _insertHint;
}; };

View File

@ -101,7 +101,10 @@ public:
Preparator(const StatementHandle& rStmt, Preparator(const StatementHandle& rStmt,
const std::string& statement, const std::string& statement,
std::size_t maxFieldSize, std::size_t maxFieldSize,
DataExtraction dataExtraction = DE_BOUND); DataExtraction dataExtraction,
ODBCMetaColumn::NumericConversion numericConversion ,
bool isPostgres
);
/// Creates the Preparator. /// Creates the Preparator.
Preparator(const Preparator& other); Preparator(const Preparator& other);
@ -416,6 +419,9 @@ public:
DataExtraction getDataExtraction() const; DataExtraction getDataExtraction() const;
/// Returns data extraction mode. /// Returns data extraction mode.
ODBCMetaColumn::NumericConversion numericConversion() const;
/// Tells if numeric values are always converted to string
private: private:
typedef std::vector<Poco::Any> ValueVec; typedef std::vector<Poco::Any> ValueVec;
typedef std::vector<SQLLEN> LengthVec; typedef std::vector<SQLLEN> LengthVec;
@ -429,7 +435,7 @@ private:
void prepareImpl(std::size_t pos, const C* pVal = 0) void prepareImpl(std::size_t pos, const C* pVal = 0)
/// Utility function to prepare Any and DynamicAny. /// Utility function to prepare Any and DynamicAny.
{ {
ODBCMetaColumn col(_rStmt, pos); ODBCMetaColumn col(_rStmt, pos, _numericConversion);
switch (col.type()) switch (col.type())
{ {
@ -681,6 +687,7 @@ private:
mutable IndexMap _varLengthArrays; mutable IndexMap _varLengthArrays;
std::size_t _maxFieldSize; std::size_t _maxFieldSize;
DataExtraction _dataExtraction; DataExtraction _dataExtraction;
ODBCMetaColumn::NumericConversion _numericConversion;
}; };
@ -1267,6 +1274,12 @@ inline Poco::Any& Preparator::at(std::size_t pos)
} }
inline ODBCMetaColumn::NumericConversion Preparator::numericConversion() const
{
return _numericConversion;
}
} } } // namespace Poco::Data::ODBC } } } // namespace Poco::Data::ODBC

View File

@ -45,6 +45,7 @@ class ODBC_API SessionImpl: public Poco::Data::AbstractSessionImpl<SessionImpl>
{ {
public: public:
static const std::size_t ODBC_MAX_FIELD_SIZE = 1024u; static const std::size_t ODBC_MAX_FIELD_SIZE = 1024u;
static const char* const NUMERIC_CONVERSION_PROPERTY;
enum TransactionCapability enum TransactionCapability
{ {
@ -167,10 +168,24 @@ public:
Poco::Any dataTypeInfo(const std::string& rName=""); Poco::Any dataTypeInfo(const std::string& rName="");
/// Returns the data types information. /// Returns the data types information.
ODBCMetaColumn::NumericConversion numericConversion() const;
/// Tells if NUMERIC values to be always
/// converted to string
void setNumericConversion(ODBCMetaColumn::NumericConversion value);
/// Sets flag to tell if NUMERIC values are always returned as
/// string
private: private:
void setDataTypeInfo(const std::string& rName, const Poco::Any& rValue); void setDataTypeInfo(const std::string& rName, const Poco::Any& rValue);
/// No-op. Throws InvalidAccessException. /// No-op. Throws InvalidAccessException.
void setNumericConversion(const std::string&, const Poco::Any& rValue);
Poco::Any numericConversion(const std::string& nm);
void init();
static const int FUNCTIONS = SQL_API_ODBC3_ALL_FUNCTIONS_SIZE; static const int FUNCTIONS = SQL_API_ODBC3_ALL_FUNCTIONS_SIZE;
void checkError(SQLRETURN rc, const std::string& msg=""); void checkError(SQLRETURN rc, const std::string& msg="");
@ -184,6 +199,7 @@ private:
Poco::Any _maxFieldSize; Poco::Any _maxFieldSize;
bool _autoBind; bool _autoBind;
bool _autoExtract; bool _autoExtract;
ODBCMetaColumn::NumericConversion _numericConversion;
TypeInfo _dataTypes; TypeInfo _dataTypes;
char _canTransact; char _canTransact;
bool _inTransaction; bool _inTransaction;
@ -286,6 +302,30 @@ inline int SessionImpl::queryTimeout() const
} }
inline ODBCMetaColumn::NumericConversion SessionImpl::numericConversion() const
{
return _numericConversion;
}
inline Poco::Any SessionImpl::numericConversion(const std::string&)
{
return numericConversion();
}
inline void SessionImpl::setNumericConversion(ODBCMetaColumn::NumericConversion value)
{
_numericConversion = value;
}
inline void SessionImpl::setNumericConversion(const std::string&, const Poco::Any& rValue)
{
setNumericConversion( Poco::AnyCast<ODBCMetaColumn::NumericConversion>(rValue) );
}
} } } // namespace Poco::Data::ODBC } } } // namespace Poco::Data::ODBC

View File

@ -23,8 +23,10 @@
#include "Poco/Data/ODBC/ODBC.h" #include "Poco/Data/ODBC/ODBC.h"
#include "Poco/NamedTuple.h" #include "Poco/NamedTuple.h"
#include "Poco/DynamicAny.h" #include "Poco/DynamicAny.h"
#include "Poco/Data/AbstractBinder.h"
#include <vector> #include <vector>
#include <map> #include <map>
#include <typeinfo>
#ifdef POCO_OS_FAMILY_WINDOWS #ifdef POCO_OS_FAMILY_WINDOWS
#include <windows.h> #include <windows.h>
#endif #endif
@ -71,6 +73,17 @@ public:
SQLINTEGER, SQLINTEGER,
SQLSMALLINT> TypeInfoTup; SQLSMALLINT> TypeInfoTup;
typedef std::vector<TypeInfoTup> TypeInfoVec; typedef std::vector<TypeInfoTup> TypeInfoVec;
typedef const std::type_info* TypeInfoPtr;
struct TypeInfoComp : public std::binary_function<TypeInfoPtr, TypeInfoPtr, bool>
{
bool operator()(const TypeInfoPtr& left, const TypeInfoPtr& right) const
{ // apply operator< to operands
return ( left->before( *right ) );
}
};
typedef std::map<TypeInfoPtr, SQLSMALLINT, TypeInfoComp> CppTypeInfoMap;
explicit TypeInfo(SQLHDBC* pHDBC=0); explicit TypeInfo(SQLHDBC* pHDBC=0);
/// Creates the TypeInfo. /// Creates the TypeInfo.
@ -102,6 +115,13 @@ public:
/// Prints all the types (as reported by the underlying database) /// Prints all the types (as reported by the underlying database)
/// to the supplied output stream. /// to the supplied output stream.
SQLSMALLINT tryTypeidToCType(const std::type_info& ti, SQLSMALLINT defaultVal = SQL_C_TINYINT) const;
/// try to find mapping of the given C++ typeid to the ODBC C-Type Code
/// will return the defaultVal if no match is found
SQLSMALLINT nullDataType(const NullData val) const;
/// Map the null value type to ODBC buffer type
private: private:
void fillCTypes(); void fillCTypes();
void fillSQLTypes(); void fillSQLTypes();
@ -109,6 +129,7 @@ private:
DataTypeMap _cDataTypes; DataTypeMap _cDataTypes;
DataTypeMap _sqlDataTypes; DataTypeMap _sqlDataTypes;
TypeInfoVec _typeInfo; TypeInfoVec _typeInfo;
CppTypeInfoMap _cppDataTypes;
SQLHDBC* _pHDBC; SQLHDBC* _pHDBC;
}; };

View File

@ -40,13 +40,6 @@ void makeUTF8(Poco::Buffer<SQLWCHAR>& buffer, SQLINTEGER length, SQLPOINTER pTar
/// Utility function for conversion from UTF-16 to UTF-8. /// Utility function for conversion from UTF-16 to UTF-8.
inline void makeUTF8(Poco::Buffer<SQLWCHAR>& buffer, int length, SQLPOINTER pTarget, SQLSMALLINT targetLength)
/// Utility function for conversion from UTF-16 to UTF-8.
{
makeUTF8(buffer, length, pTarget, (SQLINTEGER) targetLength);
}
} } } // namespace Poco::Data::ODBC } } } // namespace Poco::Data::ODBC

View File

@ -27,17 +27,39 @@ namespace Poco {
namespace Data { namespace Data {
namespace ODBC { namespace ODBC {
static void getProp(const TypeInfo& dataTypes, SQLSMALLINT sqlType, size_t& val)
{
const std::string NM("COLUMN_SIZE");
Poco::DynamicAny r;
if (dataTypes.tryGetInfo(sqlType, NM, r))
{
long sz = r.convert<long>();
// Postgres driver returns SQL_NO_TOTAL(-4) in some cases
if (sz >= 0)
val = static_cast<size_t>(sz);
}
}
Binder::Binder(const StatementHandle& rStmt, Binder::Binder(const StatementHandle& rStmt,
std::size_t maxFieldSize, std::size_t maxFieldSize,
Binder::ParameterBinding dataBinding, Binder::ParameterBinding dataBinding,
TypeInfo* pDataTypes): TypeInfo* pDataTypes,
ODBCMetaColumn::NumericConversion numericConversion,
bool insertOnly) :
_rStmt(rStmt), _rStmt(rStmt),
_paramBinding(dataBinding), _paramBinding(dataBinding),
_pTypeInfo(pDataTypes), _pTypeInfo(pDataTypes),
_paramSetSize(0), _paramSetSize(0),
_maxFieldSize(maxFieldSize) _maxFieldSize(maxFieldSize),
_maxCharColLength(1024),
_maxWCharColLength(1024),
_maxVarBinColSize(1024),
_numericConversion(numericConversion),
_insertOnly(insertOnly)
{ {
getProp(*_pTypeInfo, SQL_WVARCHAR, _maxWCharColLength);
getProp(*_pTypeInfo, SQL_VARCHAR, _maxCharColLength);
getProp(*_pTypeInfo, SQL_VARBINARY, _maxVarBinColSize);
} }
@ -48,62 +70,111 @@ Binder::~Binder()
void Binder::freeMemory() void Binder::freeMemory()
{
if (_lengthIndicator.size() > 0)
{ {
LengthPtrVec::iterator itLen = _lengthIndicator.begin(); LengthPtrVec::iterator itLen = _lengthIndicator.begin();
LengthPtrVec::iterator itLenEnd = _lengthIndicator.end(); LengthPtrVec::iterator itLenEnd = _lengthIndicator.end();
for (; itLen != itLenEnd; ++itLen) delete *itLen; for (; itLen != itLenEnd; ++itLen) delete *itLen;
}
if (_vecLengthIndicator.size() > 0)
{
LengthVecVec::iterator itVecLen = _vecLengthIndicator.begin(); LengthVecVec::iterator itVecLen = _vecLengthIndicator.begin();
LengthVecVec::iterator itVecLenEnd = _vecLengthIndicator.end(); LengthVecVec::iterator itVecLenEnd = _vecLengthIndicator.end();
for (; itVecLen != itVecLenEnd; ++itVecLen) delete *itVecLen; for (; itVecLen != itVecLenEnd; ++itVecLen) delete *itVecLen;
}
if (_times.size() > 0)
{
TimeMap::iterator itT = _times.begin(); TimeMap::iterator itT = _times.begin();
TimeMap::iterator itTEnd = _times.end(); TimeMap::iterator itTEnd = _times.end();
for (; itT != itTEnd; ++itT) delete itT->first; for (; itT != itTEnd; ++itT) delete itT->first;
}
if (_dates.size() > 0)
{
DateMap::iterator itD = _dates.begin(); DateMap::iterator itD = _dates.begin();
DateMap::iterator itDEnd = _dates.end(); DateMap::iterator itDEnd = _dates.end();
for (; itD != itDEnd; ++itD) delete itD->first; for (; itD != itDEnd; ++itD) delete itD->first;
}
if (_timestamps.size() > 0)
{
TimestampMap::iterator itTS = _timestamps.begin(); TimestampMap::iterator itTS = _timestamps.begin();
TimestampMap::iterator itTSEnd = _timestamps.end(); TimestampMap::iterator itTSEnd = _timestamps.end();
for (; itTS != itTSEnd; ++itTS) delete itTS->first; for (; itTS != itTSEnd; ++itTS) delete itTS->first;
}
if (_strings.size() > 0)
{
StringMap::iterator itStr = _strings.begin(); StringMap::iterator itStr = _strings.begin();
StringMap::iterator itStrEnd = _strings.end(); StringMap::iterator itStrEnd = _strings.end();
for (; itStr != itStrEnd; ++itStr) std::free(itStr->first); for (; itStr != itStrEnd; ++itStr) std::free(itStr->first);
}
if (_charPtrs.size() > 0)
{
CharPtrVec::iterator itChr = _charPtrs.begin(); CharPtrVec::iterator itChr = _charPtrs.begin();
CharPtrVec::iterator endChr = _charPtrs.end(); CharPtrVec::iterator endChr = _charPtrs.end();
for (; itChr != endChr; ++itChr) std::free(*itChr); for (; itChr != endChr; ++itChr) std::free(*itChr);
}
if (_utf16CharPtrs.size() > 0)
{
UTF16CharPtrVec::iterator itUTF16Chr = _utf16CharPtrs.begin(); UTF16CharPtrVec::iterator itUTF16Chr = _utf16CharPtrs.begin();
UTF16CharPtrVec::iterator endUTF16Chr = _utf16CharPtrs.end(); UTF16CharPtrVec::iterator endUTF16Chr = _utf16CharPtrs.end();
for (; itUTF16Chr != endUTF16Chr; ++itUTF16Chr) std::free(*itUTF16Chr); for (; itUTF16Chr != endUTF16Chr; ++itUTF16Chr) std::free(*itUTF16Chr);
}
if (_boolPtrs.size() > 0)
{
BoolPtrVec::iterator itBool = _boolPtrs.begin(); BoolPtrVec::iterator itBool = _boolPtrs.begin();
BoolPtrVec::iterator endBool = _boolPtrs.end(); BoolPtrVec::iterator endBool = _boolPtrs.end();
for (; itBool != endBool; ++itBool) delete[] * itBool; for (; itBool != endBool; ++itBool) delete[] * itBool;
}
if (_dateVecVec.size() > 0)
{
DateVecVec::iterator itDateVec = _dateVecVec.begin(); DateVecVec::iterator itDateVec = _dateVecVec.begin();
DateVecVec::iterator itDateVecEnd = _dateVecVec.end(); DateVecVec::iterator itDateVecEnd = _dateVecVec.end();
for (; itDateVec != itDateVecEnd; ++itDateVec) delete *itDateVec; for (; itDateVec != itDateVecEnd; ++itDateVec) delete *itDateVec;
}
if (_timeVecVec.size() > 0)
{
TimeVecVec::iterator itTimeVec = _timeVecVec.begin(); TimeVecVec::iterator itTimeVec = _timeVecVec.begin();
TimeVecVec::iterator itTimeVecEnd = _timeVecVec.end(); TimeVecVec::iterator itTimeVecEnd = _timeVecVec.end();
for (; itTimeVec != itTimeVecEnd; ++itTimeVec) delete *itTimeVec; for (; itTimeVec != itTimeVecEnd; ++itTimeVec) delete *itTimeVec;
}
if (_dateTimeVecVec.size() > 0)
{
DateTimeVecVec::iterator itDateTimeVec = _dateTimeVecVec.begin(); DateTimeVecVec::iterator itDateTimeVec = _dateTimeVecVec.begin();
DateTimeVecVec::iterator itDateTimeVecEnd = _dateTimeVecVec.end(); DateTimeVecVec::iterator itDateTimeVecEnd = _dateTimeVecVec.end();
for (; itDateTimeVec != itDateTimeVecEnd; ++itDateTimeVec) delete *itDateTimeVec; for (; itDateTimeVec != itDateTimeVecEnd; ++itDateTimeVec) delete *itDateTimeVec;
} }
if (_containers.size() > 0)
{
AnyPtrVecVec::iterator itAnyVec = _containers.begin();
AnyPtrVecVec::iterator itAnyVecEnd = _containers.end();
for (; itAnyVec != itAnyVecEnd; ++itAnyVec)
{
AnyPtrVec::iterator b = itAnyVec->begin();
AnyPtrVec::iterator e = itAnyVec->end();
for (; b != e; ++b) delete *b;
}
}
}
void Binder::bind(std::size_t pos, const std::string& val, Direction dir)
void Binder::bind(std::size_t pos, const std::string& val, Direction dir, const WhenNullCb& nullCb)
{ {
SQLPOINTER pVal = 0; SQLPOINTER pVal = 0;
SQLINTEGER size = (SQLINTEGER) val.size(); SQLINTEGER size = (SQLINTEGER) val.size();
SQLSMALLINT sqType = SQL_LONGVARCHAR;
if (isOutBound(dir)) if (isOutBound(dir))
{ {
getColumnOrParameterSize(pos, size); getColumnOrParameterSize(pos, size);
@ -111,16 +182,20 @@ void Binder::bind(std::size_t pos, const std::string& val, Direction dir)
pVal = (SQLPOINTER) pChar; pVal = (SQLPOINTER) pChar;
_outParams.insert(ParamMap::value_type(pVal, size)); _outParams.insert(ParamMap::value_type(pVal, size));
_strings.insert(StringMap::value_type(pChar, const_cast<std::string*>(&val))); _strings.insert(StringMap::value_type(pChar, const_cast<std::string*>(&val)));
if (size < _maxCharColLength) sqType = SQL_VARCHAR;
} }
else if (isInBound(dir)) else if (isInBound(dir))
{ {
pVal = (SQLPOINTER) val.c_str(); pVal = (SQLPOINTER) val.c_str();
_inParams.insert(ParamMap::value_type(pVal, size)); _inParams.insert(ParamMap::value_type(pVal, size));
if (size < _maxCharColLength) sqType = SQL_VARCHAR;
} }
else else
throw InvalidArgumentException("Parameter must be [in] OR [out] bound."); throw InvalidArgumentException("Parameter must be [in] OR [out] bound.");
SQLLEN* pLenIn = new SQLLEN; SQLLEN* pLenIn = new SQLLEN;
if (isOutBound(dir) && nullCb.defined())
_nullCbMap.insert(NullCbMap::value_type( pLenIn, nullCb) );
SQLINTEGER colSize = 0; SQLINTEGER colSize = 0;
SQLSMALLINT decDigits = 0; SQLSMALLINT decDigits = 0;
getColSizeAndPrecision(pos, SQL_C_CHAR, colSize, decDigits); getColSizeAndPrecision(pos, SQL_C_CHAR, colSize, decDigits);
@ -135,7 +210,7 @@ void Binder::bind(std::size_t pos, const std::string& val, Direction dir)
(SQLUSMALLINT) pos + 1, (SQLUSMALLINT) pos + 1,
toODBCDirection(dir), toODBCDirection(dir),
SQL_C_CHAR, SQL_C_CHAR,
SQL_LONGVARCHAR, sqType,
(SQLUINTEGER) colSize, (SQLUINTEGER) colSize,
0, 0,
pVal, pVal,
@ -147,13 +222,13 @@ void Binder::bind(std::size_t pos, const std::string& val, Direction dir)
} }
void Binder::bind(std::size_t pos, const UTF16String& val, Direction dir) void Binder::bind(std::size_t pos, const UTF16String& val, Direction dir, const WhenNullCb& nullCb)
{ {
typedef UTF16String::value_type CharT; typedef UTF16String::value_type CharT;
SQLPOINTER pVal = 0; SQLPOINTER pVal = 0;
SQLINTEGER size = (SQLINTEGER)(val.size() * sizeof(CharT)); SQLINTEGER size = (SQLINTEGER)(val.size() * sizeof(CharT));
SQLSMALLINT sqType = (val.size() < _maxWCharColLength) ? SQL_WVARCHAR : SQL_WLONGVARCHAR;
if (isOutBound(dir)) if (isOutBound(dir))
{ {
getColumnOrParameterSize(pos, size); getColumnOrParameterSize(pos, size);
@ -171,6 +246,9 @@ void Binder::bind(std::size_t pos, const UTF16String& val, Direction dir)
throw InvalidArgumentException("Parameter must be [in] OR [out] bound."); throw InvalidArgumentException("Parameter must be [in] OR [out] bound.");
SQLLEN* pLenIn = new SQLLEN; SQLLEN* pLenIn = new SQLLEN;
if (isOutBound(dir) && nullCb.defined())
_nullCbMap.insert(NullCbMap::value_type(pLenIn, nullCb));
SQLINTEGER colSize = 0; SQLINTEGER colSize = 0;
SQLSMALLINT decDigits = 0; SQLSMALLINT decDigits = 0;
getColSizeAndPrecision(pos, SQL_C_WCHAR, colSize, decDigits); getColSizeAndPrecision(pos, SQL_C_WCHAR, colSize, decDigits);
@ -187,7 +265,7 @@ void Binder::bind(std::size_t pos, const UTF16String& val, Direction dir)
(SQLUSMALLINT)pos + 1, (SQLUSMALLINT)pos + 1,
toODBCDirection(dir), toODBCDirection(dir),
SQL_C_WCHAR, SQL_C_WCHAR,
SQL_WLONGVARCHAR, sqType,
(SQLUINTEGER)colSize, (SQLUINTEGER)colSize,
0, 0,
pVal, pVal,
@ -199,14 +277,14 @@ void Binder::bind(std::size_t pos, const UTF16String& val, Direction dir)
} }
void Binder::bind(std::size_t pos, const Date& val, Direction dir) void Binder::bind(std::size_t pos, const Date& val, Direction dir, const WhenNullCb& nullCb)
{ {
SQLINTEGER size = (SQLINTEGER) sizeof(SQL_DATE_STRUCT);
SQLLEN* pLenIn = new SQLLEN; SQLLEN* pLenIn = new SQLLEN;
*pLenIn = size; *pLenIn = SQL_NTS; // microsoft example does that, otherwise no null indicator is returned
_lengthIndicator.push_back(pLenIn); _lengthIndicator.push_back(pLenIn);
if (isOutBound(dir) && nullCb.defined())
_nullCbMap.insert(NullCbMap::value_type(pLenIn, nullCb));
SQL_DATE_STRUCT* pDS = new SQL_DATE_STRUCT; SQL_DATE_STRUCT* pDS = new SQL_DATE_STRUCT;
Utility::dateSync(*pDS, val); Utility::dateSync(*pDS, val);
@ -232,11 +310,12 @@ void Binder::bind(std::size_t pos, const Date& val, Direction dir)
} }
void Binder::bind(std::size_t pos, const Time& val, Direction dir) void Binder::bind(std::size_t pos, const Time& val, Direction dir, const WhenNullCb& nullCb)
{ {
SQLINTEGER size = (SQLINTEGER) sizeof(SQL_TIME_STRUCT);
SQLLEN* pLenIn = new SQLLEN; SQLLEN* pLenIn = new SQLLEN;
*pLenIn = size; *pLenIn = SQL_NTS; // microsoft example does that, otherwise no null indicator is returned
if (isOutBound(dir) && nullCb.defined())
_nullCbMap.insert(NullCbMap::value_type(pLenIn, nullCb));
_lengthIndicator.push_back(pLenIn); _lengthIndicator.push_back(pLenIn);
@ -265,11 +344,12 @@ void Binder::bind(std::size_t pos, const Time& val, Direction dir)
} }
void Binder::bind(std::size_t pos, const Poco::DateTime& val, Direction dir) void Binder::bind(std::size_t pos, const Poco::DateTime& val, Direction dir, const WhenNullCb& nullCb)
{ {
SQLINTEGER size = (SQLINTEGER) sizeof(SQL_TIMESTAMP_STRUCT);
SQLLEN* pLenIn = new SQLLEN; SQLLEN* pLenIn = new SQLLEN;
*pLenIn = size; *pLenIn = SQL_NTS; // microsoft example does that, otherwise no null indicator is returned
if (isOutBound(dir) && nullCb.defined())
_nullCbMap.insert(NullCbMap::value_type(pLenIn, nullCb));
_lengthIndicator.push_back(pLenIn); _lengthIndicator.push_back(pLenIn);
@ -298,7 +378,7 @@ void Binder::bind(std::size_t pos, const Poco::DateTime& val, Direction dir)
} }
void Binder::bind(std::size_t pos, const NullData& val, Direction dir) void Binder::bind(std::size_t pos, const NullData& val, Direction dir, const std::type_info& bindType)
{ {
if (isOutBound(dir) || !isInBound(dir)) if (isOutBound(dir) || !isInBound(dir))
throw NotImplementedException("NULL parameter type can only be inbound."); throw NotImplementedException("NULL parameter type can only be inbound.");
@ -312,13 +392,16 @@ void Binder::bind(std::size_t pos, const NullData& val, Direction dir)
SQLINTEGER colSize = 0; SQLINTEGER colSize = 0;
SQLSMALLINT decDigits = 0; SQLSMALLINT decDigits = 0;
getColSizeAndPrecision(pos, SQL_C_STINYINT, colSize, decDigits);
const SQLSMALLINT colType = (bindType == typeid(void) || bindType == typeid(NullData) || bindType == typeid(NullType)) ?
_pTypeInfo->nullDataType(val) : _pTypeInfo->tryTypeidToCType(bindType, SQL_C_TINYINT);
getColSizeAndPrecision(pos, colType, colSize, decDigits);
if (Utility::isError(SQLBindParameter(_rStmt, if (Utility::isError(SQLBindParameter(_rStmt,
(SQLUSMALLINT) pos + 1, (SQLUSMALLINT) pos + 1,
SQL_PARAM_INPUT, SQL_PARAM_INPUT,
SQL_C_STINYINT, colType,
Utility::sqlDataType(SQL_C_STINYINT), Utility::sqlDataType(colType),
colSize, colSize,
decDigits, decDigits,
0, 0,
@ -342,7 +425,7 @@ std::size_t Binder::parameterSize(SQLPOINTER pAddr) const
} }
void Binder::bind(std::size_t pos, const char* const &pVal, Direction dir) void Binder::bind(std::size_t pos, const char* const &pVal, Direction dir, const WhenNullCb& nullCb)
{ {
throw NotImplementedException("char* binding not implemented, Use std::string instead."); throw NotImplementedException("char* binding not implemented, Use std::string instead.");
} }
@ -364,6 +447,7 @@ SQLSMALLINT Binder::toODBCDirection(Direction dir) const
void Binder::synchronize() void Binder::synchronize()
{ {
if (_dates.size()) if (_dates.size())
{ {
DateMap::iterator it = _dates.begin(); DateMap::iterator it = _dates.begin();
@ -395,26 +479,52 @@ void Binder::synchronize()
for(; it != end; ++it) for(; it != end; ++it)
it->second->assign(it->first, std::strlen(it->first)); it->second->assign(it->first, std::strlen(it->first));
} }
if (_nullCbMap.size())
{
NullCbMap::iterator it = _nullCbMap.begin();
NullCbMap::iterator end = _nullCbMap.end();
for (; it != end; ++it)
if (*it->first == SQL_NULL_DATA) it->second.onNull();
}
} }
void Binder::reset() void Binder::reset()
{ {
freeMemory(); freeMemory();
if (_lengthIndicator.size() > 0)
LengthPtrVec().swap(_lengthIndicator); LengthPtrVec().swap(_lengthIndicator);
if (_inParams.size() > 0)
_inParams.clear(); _inParams.clear();
if (_outParams.size() > 0)
_outParams.clear(); _outParams.clear();
if (_dates.size() > 0)
_dates.clear(); _dates.clear();
if (_times.size() > 0)
_times.clear(); _times.clear();
if (_timestamps.size() > 0)
_timestamps.clear(); _timestamps.clear();
if (_strings.size() > 0)
_strings.clear(); _strings.clear();
if (_dateVecVec.size() > 0)
_dateVecVec.clear(); _dateVecVec.clear();
if (_timeVecVec.size() > 0)
_timeVecVec.clear(); _timeVecVec.clear();
if (_dateTimeVecVec.size() > 0)
_dateTimeVecVec.clear(); _dateTimeVecVec.clear();
if (_charPtrs.size() > 0)
_charPtrs.clear(); _charPtrs.clear();
if (_boolPtrs.size() > 0)
_boolPtrs.clear(); _boolPtrs.clear();
if (_containers.size() > 0)
_containers.clear(); _containers.clear();
if (_nullCbMap.size() > 0)
_nullCbMap.clear();
_paramSetSize = 0; _paramSetSize = 0;
if (!_insertOnly)
_parameters.clear();
} }
@ -425,11 +535,11 @@ void Binder::getColSizeAndPrecision(std::size_t pos,
{ {
// Not all drivers are equally willing to cooperate in this matter. // Not all drivers are equally willing to cooperate in this matter.
// Hence the funky flow control. // Hence the funky flow control.
DynamicAny tmp;
bool found(false);
if (_pTypeInfo) if (_pTypeInfo)
{ {
found = _pTypeInfo->tryGetInfo(cDataType, "COLUMN_SIZE", tmp); DynamicAny tmp;
bool found = _pTypeInfo->tryGetInfo(cDataType, "COLUMN_SIZE", tmp);
if (found) colSize = tmp; if (found) colSize = tmp;
found = _pTypeInfo->tryGetInfo(cDataType, "MINIMUM_SCALE", tmp); found = _pTypeInfo->tryGetInfo(cDataType, "MINIMUM_SCALE", tmp);
if (found) if (found)
@ -439,27 +549,34 @@ void Binder::getColSizeAndPrecision(std::size_t pos,
} }
} }
if (_parameters.size() <= pos || !_parameters[pos].defined())
{
if (_parameters.size() <= pos)
_parameters.resize(pos + 1);
_parameters[pos] = ParamDescriptor(0, cDataType, 0);
try try
{
{ {
Parameter p(_rStmt, pos); Parameter p(_rStmt, pos);
colSize = (SQLINTEGER) p.columnSize(); _parameters[pos] = ParamDescriptor(static_cast<SQLINTEGER>(p.columnSize()), cDataType, static_cast<SQLSMALLINT>(p.decimalDigits()));
decDigits = (SQLSMALLINT) p.decimalDigits(); }
return; }
} catch (StatementException&) { } catch (StatementException&)
{
try try
{ {
ODBCMetaColumn c(_rStmt, pos); ODBCMetaColumn c(_rStmt, pos, _numericConversion);
colSize = (SQLINTEGER) c.length(); _parameters[pos] = ParamDescriptor(static_cast<SQLINTEGER>(c.length()), cDataType, static_cast<SQLSMALLINT>(c.precision()));
decDigits = (SQLSMALLINT) c.precision(); }
return; catch (StatementException&) {}
} catch (StatementException&) { } }
}
// no success, set to zero and hope for the best // we may have no success, so use zeros and hope for the best
// (most drivers do not require these most of the times anyway) // (most drivers do not require these most of the times anyway)
colSize = 0; colSize = _parameters[pos].colSize;
decDigits = 0; decDigits = _parameters[pos].decDigits;
return;
} }
@ -470,7 +587,7 @@ void Binder::getColumnOrParameterSize(std::size_t pos, SQLINTEGER& size)
try try
{ {
ODBCMetaColumn col(_rStmt, pos); ODBCMetaColumn col(_rStmt, pos, _numericConversion);
colSize = col.length(); colSize = col.length();
} }
catch (StatementException&) { } catch (StatementException&) { }
@ -486,10 +603,10 @@ void Binder::getColumnOrParameterSize(std::size_t pos, SQLINTEGER& size)
//On Linux, PostgreSQL driver segfaults on SQLGetDescField, so this is disabled for now //On Linux, PostgreSQL driver segfaults on SQLGetDescField, so this is disabled for now
#ifdef POCO_OS_FAMILY_WINDOWS #ifdef POCO_OS_FAMILY_WINDOWS
SQLHDESC hIPD = 0; SQLHDESC hIPD = 0;
if (!Utility::isError(SQLGetStmtAttr(_rStmt, SQL_ATTR_IMP_PARAM_DESC, &hIPD, SQL_IS_POINTER, 0))) if (!Utility::isError(Poco::Data::ODBC::SQLGetStmtAttr(_rStmt, SQL_ATTR_IMP_PARAM_DESC, &hIPD, SQL_IS_POINTER, 0)))
{ {
SQLUINTEGER sz = 0; SQLUINTEGER sz = 0;
if (!Utility::isError(SQLGetDescField(hIPD, (SQLSMALLINT) pos + 1, SQL_DESC_LENGTH, &sz, SQL_IS_UINTEGER, 0)) && if (!Utility::isError(Poco::Data::ODBC::SQLGetDescField(hIPD, (SQLSMALLINT)pos + 1, SQL_DESC_LENGTH, &sz, SQL_IS_UINTEGER, 0)) &&
sz > 0) sz > 0)
{ {
size = sz; size = sz;

View File

@ -25,12 +25,11 @@ namespace ODBC {
ConnectionHandle::ConnectionHandle(EnvironmentHandle* pEnvironment): ConnectionHandle::ConnectionHandle(EnvironmentHandle* pEnvironment):
_pEnvironment(pEnvironment ? pEnvironment : new EnvironmentHandle), _environment(pEnvironment ? &pEnvironment->handle() : 0),
_hdbc(SQL_NULL_HDBC), _hdbc(SQL_NULL_HDBC)
_ownsEnvironment(pEnvironment ? false : true)
{ {
if (Utility::isError(SQLAllocHandle(SQL_HANDLE_DBC, if (Utility::isError(SQLAllocHandle(SQL_HANDLE_DBC,
_pEnvironment->handle(), _environment.handle(),
&_hdbc))) &_hdbc)))
{ {
throw ODBCException("Could not allocate connection handle."); throw ODBCException("Could not allocate connection handle.");
@ -41,14 +40,16 @@ ConnectionHandle::ConnectionHandle(EnvironmentHandle* pEnvironment):
ConnectionHandle::~ConnectionHandle() ConnectionHandle::~ConnectionHandle()
{ {
try try
{
if (_hdbc != SQL_NULL_HDBC)
{ {
SQLDisconnect(_hdbc); SQLDisconnect(_hdbc);
SQLRETURN rc = SQLFreeHandle(SQL_HANDLE_DBC, _hdbc); SQLRETURN rc = SQLFreeHandle(SQL_HANDLE_DBC, _hdbc);
_hdbc = SQL_NULL_HDBC;
if (_ownsEnvironment) delete _pEnvironment;
poco_assert(!Utility::isError(rc)); poco_assert(!Utility::isError(rc));
} }
}
catch (...) catch (...)
{ {
poco_unexpected(); poco_unexpected();

View File

@ -24,7 +24,22 @@ namespace Data {
namespace ODBC { namespace ODBC {
EnvironmentHandle::EnvironmentHandle(): _henv(SQL_NULL_HENV) EnvironmentHandle::EnvironmentHandle(): _henv(SQL_NULL_HENV),
_isOwner(false)
{
init();
}
EnvironmentHandle::EnvironmentHandle(const SQLHENV* henv) : _henv(SQL_NULL_HENV),
_isOwner(false)
{
if (!henv || *henv == SQL_NULL_HENV)
init();
else
_henv = *henv;
}
void EnvironmentHandle::init()
{ {
if (Utility::isError(SQLAllocHandle(SQL_HANDLE_ENV, if (Utility::isError(SQLAllocHandle(SQL_HANDLE_ENV,
SQL_NULL_HANDLE, SQL_NULL_HANDLE,
@ -36,16 +51,20 @@ EnvironmentHandle::EnvironmentHandle(): _henv(SQL_NULL_HENV)
{ {
throw ODBCException("Could not initialize environment."); throw ODBCException("Could not initialize environment.");
} }
_isOwner = true;
} }
EnvironmentHandle::~EnvironmentHandle() EnvironmentHandle::~EnvironmentHandle()
{ {
try try
{
if (_isOwner && _henv != SQL_NULL_HENV)
{ {
SQLRETURN rc = SQLFreeHandle(SQL_HANDLE_ENV, _henv); SQLRETURN rc = SQLFreeHandle(SQL_HANDLE_ENV, _henv);
_henv = SQL_NULL_HENV;
poco_assert(!Utility::isError(rc)); poco_assert(!Utility::isError(rc));
} }
}
catch (...) catch (...)
{ {
poco_unexpected(); poco_unexpected();

View File

@ -355,15 +355,34 @@ template<>
bool Extractor::extractManualImpl<Poco::Data::CLOB>(std::size_t pos, bool Extractor::extractManualImpl<Poco::Data::CLOB>(std::size_t pos,
Poco::Data::CLOB& val, Poco::Data::CLOB& val,
SQLSMALLINT cType) SQLSMALLINT cType)
{
return extractManualLOBImpl(pos, val, cType);
}
template<>
bool Extractor::extractManualImpl<Poco::Data::BLOB>(std::size_t pos,
Poco::Data::BLOB& val,
SQLSMALLINT cType)
{
return extractManualLOBImpl(pos, val, cType);
}
template<typename T>
bool Extractor::extractManualLOBImpl(std::size_t pos,
Poco::Data::LOB<T>& val,
SQLSMALLINT cType)
{ {
std::size_t maxSize = _pPreparator->getMaxFieldSize(); std::size_t maxSize = _pPreparator->getMaxFieldSize();
std::size_t fetchedSize = 0; const int bufSize = CHUNK_SIZE;
std::size_t fetchedSize = bufSize;
std::size_t totalSize = 0; std::size_t totalSize = 0;
SQLLEN len; SQLLEN len;
const int bufSize = CHUNK_SIZE;
Poco::Buffer<char> apChar(bufSize); Poco::Buffer<T> apChar(bufSize);
char* pChar = apChar.begin(); T* pChar = apChar.begin();
SQLRETURN rc = 0; SQLRETURN rc = 0;
val.clear(); val.clear();
@ -371,7 +390,9 @@ bool Extractor::extractManualImpl<Poco::Data::CLOB>(std::size_t pos,
do do
{ {
std::memset(pChar, 0, bufSize); // clear out the latest data in the buffer
if (fetchedSize > 0)
std::memset(pChar, 0, fetchedSize);
len = 0; len = 0;
rc = SQLGetData(_rStmt, rc = SQLGetData(_rStmt,
(SQLUSMALLINT) pos + 1, (SQLUSMALLINT) pos + 1,
@ -394,7 +415,7 @@ bool Extractor::extractManualImpl<Poco::Data::CLOB>(std::size_t pos,
if (SQL_NO_DATA == rc || !len) if (SQL_NO_DATA == rc || !len)
break; break;
fetchedSize = len > CHUNK_SIZE ? CHUNK_SIZE : len; fetchedSize = len > bufSize ? bufSize : len;
totalSize += fetchedSize; totalSize += fetchedSize;
if (totalSize <= maxSize) if (totalSize <= maxSize)
val.appendRaw(pChar, fetchedSize); val.appendRaw(pChar, fetchedSize);

View File

@ -23,9 +23,10 @@ namespace Data {
namespace ODBC { namespace ODBC {
ODBCMetaColumn::ODBCMetaColumn(const StatementHandle& rStmt, std::size_t position) : ODBCMetaColumn::ODBCMetaColumn(const StatementHandle& rStmt, std::size_t position, NumericConversion numericConversion) :
MetaColumn(position), MetaColumn(position),
_rStmt(rStmt) _rStmt(rStmt),
_numericConversion(numericConversion)
{ {
init(); init();
} }
@ -92,6 +93,7 @@ void ODBCMetaColumn::init()
case SQL_WCHAR: case SQL_WCHAR:
case SQL_WVARCHAR: case SQL_WVARCHAR:
case SQL_WLONGVARCHAR: case SQL_WLONGVARCHAR:
case -350: // IBM DB2 CLOB, which long unicode string
setType(MetaColumn::FDT_WSTRING); break; setType(MetaColumn::FDT_WSTRING); break;
case SQL_TINYINT: case SQL_TINYINT:
@ -112,11 +114,45 @@ void ODBCMetaColumn::init()
case SQL_NUMERIC: case SQL_NUMERIC:
case SQL_DECIMAL: case SQL_DECIMAL:
{
bool toString = false;
switch (_numericConversion)
{
case NC_BEST_FIT:
case NC_BEST_FIT_DBL_LIMIT:
if (0 == _columnDesc.decimalDigits) if (0 == _columnDesc.decimalDigits)
{
if (_columnDesc.size <= 9)
setType(MetaColumn::FDT_INT32); setType(MetaColumn::FDT_INT32);
else if (_columnDesc.size <= 18)
setType(MetaColumn::FDT_INT64);
else if (_numericConversion != NC_BEST_FIT_DBL_LIMIT)
toString = true;
else else
setType(MetaColumn::FDT_DOUBLE); setType(MetaColumn::FDT_DOUBLE);
}
else
{
// we can't have more than 16 digits in double, but we may be asked to
if (_columnDesc.size > 16 && _numericConversion != NC_BEST_FIT_DBL_LIMIT)
toString = true;
else
setType(MetaColumn::FDT_DOUBLE);
}
break;
case NC_FORCE_STRING:
toString = true;
}
if (toString)
{
setLength(_columnDesc.size + 4);
#if defined(UNICODE)
setType(MetaColumn::FDT_WSTRING);
#else
setType(MetaColumn::FDT_STRING);
#endif
}
}
break; break;
case SQL_REAL: case SQL_REAL:
@ -126,8 +162,12 @@ void ODBCMetaColumn::init()
case SQL_VARBINARY: case SQL_VARBINARY:
case SQL_LONGVARBINARY: case SQL_LONGVARBINARY:
case -98:// IBM DB2 non-standard type case -98:// IBM DB2 non-standard type
case -370: // IBM DB2 XML, documentation advises to bind it as BLOB, not CLOB
setType(MetaColumn::FDT_BLOB); break; setType(MetaColumn::FDT_BLOB); break;
case -99: // IBM DB2 CLOB
setType(MetaColumn::FDT_CLOB); break;
case SQL_TYPE_DATE: case SQL_TYPE_DATE:
setType(MetaColumn::FDT_DATE); break; setType(MetaColumn::FDT_DATE); break;

View File

@ -46,7 +46,10 @@ ODBCStatementImpl::ODBCStatementImpl(SessionImpl& rSession):
_nextResponse(0), _nextResponse(0),
_prepared(false), _prepared(false),
_affectedRowCount(0), _affectedRowCount(0),
_canCompile(true) _canCompile(true),
_numericConversion(rSession.numericConversion()),
_isPostgres(false),
_insertHint(false)
{ {
int queryTimeout = rSession.queryTimeout(); int queryTimeout = rSession.queryTimeout();
if (queryTimeout >= 0) if (queryTimeout >= 0)
@ -57,6 +60,15 @@ ODBCStatementImpl::ODBCStatementImpl(SessionImpl& rSession):
(SQLPOINTER) uqt, (SQLPOINTER) uqt,
0); 0);
} }
SQLSMALLINT t;
SQLRETURN r = Poco::Data::ODBC::SQLGetInfo(_rConnection, SQL_DRIVER_NAME, NULL, 0, &t);
if (!Utility::isError(r) && t > 0)
{
std::string serverString;
serverString.resize(static_cast<std::size_t>(t) + 2);
r = Poco::Data::ODBC::SQLGetInfo(_rConnection, SQL_DRIVER_NAME, &serverString[0], SQLSMALLINT((serverString.length() - 1) * sizeof(serverString[0])), &t);
_isPostgres = (!Utility::isError(r) && Poco::toUpperInPlace(serverString).find("PSQLODBC") == 0);
}
} }
@ -95,9 +107,10 @@ void ODBCStatementImpl::compileImpl()
pDT = AnyCast<TypeInfo*>(dti); pDT = AnyCast<TypeInfo*>(dti);
}catch (NotSupportedException&) { } }catch (NotSupportedException&) { }
std::size_t maxFieldSize = AnyCast<std::size_t>(session().getProperty("maxFieldSize")); const std::size_t maxFieldSize = AnyCast<std::size_t>(session().getProperty("maxFieldSize"));
const ODBCMetaColumn::NumericConversion numericConversion = dynamic_cast<SessionImpl&>(session()).numericConversion();
_pBinder = new Binder(_stmt, maxFieldSize, bind, pDT); _pBinder = new Binder(_stmt, maxFieldSize, bind, pDT, numericConversion, _insertHint);
makeInternalExtractors(); makeInternalExtractors();
doPrepare(); doPrepare();
@ -112,7 +125,7 @@ void ODBCStatementImpl::makeInternalExtractors()
{ {
try try
{ {
fillColumns(); fillColumns(currentDataSet());
} catch (DataFormatException&) } catch (DataFormatException&)
{ {
if (isStoredProcedure()) return; if (isStoredProcedure()) return;
@ -125,8 +138,9 @@ void ODBCStatementImpl::makeInternalExtractors()
} }
void ODBCStatementImpl::addPreparator() bool ODBCStatementImpl::addPreparator(bool addAlways)
{ {
Preparator* prep = 0;
if (0 == _preparations.size()) if (0 == _preparations.size())
{ {
std::string statement(toString()); std::string statement(toString());
@ -138,12 +152,20 @@ void ODBCStatementImpl::addPreparator()
std::size_t maxFieldSize = AnyCast<std::size_t>(session().getProperty("maxFieldSize")); std::size_t maxFieldSize = AnyCast<std::size_t>(session().getProperty("maxFieldSize"));
_preparations.push_back(new Preparator(_stmt, statement, maxFieldSize, ext)); prep = new Preparator(_stmt, statement, maxFieldSize, ext, _numericConversion, _isPostgres);
} }
else else
_preparations.push_back(new Preparator(*_preparations[0])); prep = new Preparator(*_preparations[0]);
if (addAlways || prep->columns() > 0)
{
_preparations.push_back(prep);
_extractors.push_back(new Extractor(_stmt, _preparations.back())); _extractors.push_back(new Extractor(_stmt, _preparations.back()));
return true;
}
delete prep;
return false;
} }
@ -214,7 +236,6 @@ void ODBCStatementImpl::doBind()
void ODBCStatementImpl::bindImpl() void ODBCStatementImpl::bindImpl()
{ {
doBind(); doBind();
SQLRETURN rc = SQLExecute(_stmt); SQLRETURN rc = SQLExecute(_stmt);
if (SQL_NEED_DATA == rc) putData(); if (SQL_NEED_DATA == rc) putData();
@ -279,6 +300,24 @@ void ODBCStatementImpl::clear()
} }
} }
bool ODBCStatementImpl::nextResultSet()
{
SQLRETURN ret = SQLMoreResults(_stmt);
if (SQL_NO_DATA == ret)
return false;
if (Utility::isError(ret)) {
throw StatementException(_stmt, "SQLMoreResults()");
}
// need to remove old bindings, as Sybase doesn't like old ones
if (Utility::isError(SQLFreeStmt(_stmt, SQL_UNBIND))) {
throw StatementException(_stmt, "SQLFreeStmt(SQL_UNBIND)");
}
return true;
}
bool ODBCStatementImpl::hasNext() bool ODBCStatementImpl::hasNext()
{ {
@ -296,16 +335,28 @@ bool ODBCStatementImpl::hasNext()
if (!nextRowReady()) if (!nextRowReady())
{ {
if (hasMoreDataSets()) activateNextDataSet(); // have a loop here, as there could be one or more empty results
else return false; do {
if (hasMoreDataSets()) {
if (SQL_NO_DATA == SQLMoreResults(_stmt)) activateNextDataSet();
if (!nextResultSet())
return false; return false;
addPreparator(); addPreparator();
}
else {
if (nextResultSet()) {
if (!addPreparator(false)) // skip the result set if it has no columns
continue;
fillColumns(currentDataSet() + 1);
makeExtractors(_preparations.back()->columns(), static_cast<Position::PositionType>(currentDataSet() + 1));
activateNextDataSet();
}
else return false;
}
doPrepare(); doPrepare();
fixupExtraction(); fixupExtraction();
makeStep(); makeStep();
} while (!nextRowReady());
} }
else if (Utility::isError(_nextResponse)) else if (Utility::isError(_nextResponse))
checkError(_nextResponse, "SQLFetch()"); checkError(_nextResponse, "SQLFetch()");
@ -405,15 +456,16 @@ void ODBCStatementImpl::checkError(SQLRETURN rc, const std::string& msg)
} }
void ODBCStatementImpl::fillColumns() void ODBCStatementImpl::fillColumns(size_t dataSetPos)
{ {
std::size_t colCount = columnsReturned(); poco_assert_dbg(dataSetPos < _preparations.size());
std::size_t curDataSet = currentDataSet(); poco_assert_dbg(_preparations[dataSetPos]);
if (curDataSet >= _columnPtrs.size()) std::size_t colCount = static_cast<std::size_t>(_preparations[dataSetPos]->columns());
_columnPtrs.resize(curDataSet + 1); if (dataSetPos >= _columnPtrs.size())
_columnPtrs.resize(dataSetPos + 1);
for (int i = 0; i < colCount; ++i) for (int i = 0; i < colCount; ++i)
_columnPtrs[curDataSet].push_back(new ODBCMetaColumn(_stmt, i)); _columnPtrs[dataSetPos].push_back(new ODBCMetaColumn(_stmt, i, _numericConversion));
} }
@ -426,17 +478,16 @@ bool ODBCStatementImpl::isStoredProcedure() const
} }
const MetaColumn& ODBCStatementImpl::metaColumn(std::size_t pos) const const MetaColumn& ODBCStatementImpl::metaColumn(std::size_t pos, size_t dataSet) const
{ {
std::size_t curDataSet = currentDataSet(); poco_assert_dbg(dataSet < _columnPtrs.size());
poco_assert_dbg (curDataSet < _columnPtrs.size());
std::size_t sz = _columnPtrs[curDataSet].size(); std::size_t sz = _columnPtrs[dataSet].size();
if (0 == sz || pos > sz - 1) if (0 == sz || pos > sz - 1)
throw InvalidAccessException(format("Invalid column number: %u", pos)); throw InvalidAccessException(format("Invalid column number: %u", pos));
return *_columnPtrs[curDataSet][pos]; return *_columnPtrs[dataSet][pos];
} }
@ -453,4 +504,10 @@ int ODBCStatementImpl::affectedRowCount() const
} }
void ODBCStatementImpl::insertHint()
{
_insertHint = true;
}
} } } // namespace Poco::Data::ODBC } } } // namespace Poco::Data::ODBC

View File

@ -30,21 +30,35 @@ namespace ODBC {
Preparator::Preparator(const StatementHandle& rStmt, Preparator::Preparator(const StatementHandle& rStmt,
const std::string& statement, const std::string& statement,
std::size_t maxFieldSize, std::size_t maxFieldSize,
DataExtraction dataExtraction): DataExtraction dataExtraction,
ODBCMetaColumn::NumericConversion numericConversion,
bool isPostgres) :
_rStmt(rStmt), _rStmt(rStmt),
_maxFieldSize(maxFieldSize), _maxFieldSize(maxFieldSize),
_dataExtraction(dataExtraction) _dataExtraction(dataExtraction),
_numericConversion(numericConversion)
{ {
SQLCHAR* pStr = (SQLCHAR*) statement.c_str(); SQLCHAR* pStr = (SQLCHAR*) statement.c_str();
if (Utility::isError(Poco::Data::ODBC::SQLPrepare(_rStmt, pStr, (SQLINTEGER) statement.length()))) if (Utility::isError(Poco::Data::ODBC::SQLPrepare(_rStmt, pStr, (SQLINTEGER) statement.length())))
throw StatementException(_rStmt); throw StatementException(_rStmt);
// PostgreSQL error swallowing workaround:
// Postgres may execute a statement with sintax error fine,
// but would return error once num of columns requested!
if (isPostgres)
{
SQLSMALLINT t = 0;
SQLRETURN r = SQLNumResultCols(rStmt, &t);
if (r != SQL_NO_DATA && Utility::isError(r))
throw StatementException(rStmt, "Failed to get number of columns");
}
} }
Preparator::Preparator(const Preparator& other): Preparator::Preparator(const Preparator& other):
_rStmt(other._rStmt), _rStmt(other._rStmt),
_maxFieldSize(other._maxFieldSize), _maxFieldSize(other._maxFieldSize),
_dataExtraction(other._dataExtraction) _dataExtraction(other._dataExtraction),
_numericConversion(other._numericConversion)
{ {
resize(); resize();
} }
@ -155,7 +169,7 @@ std::size_t Preparator::maxDataSize(std::size_t pos) const
try try
{ {
ODBCMetaColumn mc(_rStmt, pos); ODBCMetaColumn mc(_rStmt, pos, _numericConversion);
sz = mc.length(); sz = mc.length();
// accommodate for terminating zero (non-bulk only!) // accommodate for terminating zero (non-bulk only!)

View File

@ -29,6 +29,8 @@ namespace Data {
namespace ODBC { namespace ODBC {
const char* const SessionImpl::NUMERIC_CONVERSION_PROPERTY= "numericConversion";
SessionImpl::SessionImpl(const std::string& connect, SessionImpl::SessionImpl(const std::string& connect,
std::size_t loginTimeout, std::size_t loginTimeout,
std::size_t maxFieldSize, std::size_t maxFieldSize,
@ -39,13 +41,12 @@ SessionImpl::SessionImpl(const std::string& connect,
_maxFieldSize(maxFieldSize), _maxFieldSize(maxFieldSize),
_autoBind(autoBind), _autoBind(autoBind),
_autoExtract(autoExtract), _autoExtract(autoExtract),
_numericConversion(ODBCMetaColumn::NC_BEST_FIT),
_canTransact(ODBC_TXN_CAPABILITY_UNKNOWN), _canTransact(ODBC_TXN_CAPABILITY_UNKNOWN),
_inTransaction(false), _inTransaction(false),
_queryTimeout(-1) _queryTimeout(-1)
{ {
setFeature("bulk", true); init();
open();
setProperty("handle", _db.handle());
} }
@ -62,6 +63,15 @@ SessionImpl::SessionImpl(const std::string& connect,
_inTransaction(false), _inTransaction(false),
_queryTimeout(-1) _queryTimeout(-1)
{ {
init();
}
void SessionImpl::init()
{
addProperty(NUMERIC_CONVERSION_PROPERTY,
&SessionImpl::setNumericConversion,
&SessionImpl::numericConversion);
setFeature("bulk", true); setFeature("bulk", true);
open(); open();
setProperty("handle", _db.handle()); setProperty("handle", _db.handle());
@ -72,7 +82,7 @@ SessionImpl::~SessionImpl()
{ {
try try
{ {
if (isTransaction() && !getFeature("autoCommit")) if (static_cast<bool>(_db) && isTransaction() && !getFeature("autoCommit"))
{ {
try { rollback(); } try { rollback(); }
catch (...) { } catch (...) { }
@ -107,13 +117,13 @@ void SessionImpl::open(const std::string& connect)
poco_assert_dbg (!connectionString().empty()); poco_assert_dbg (!connectionString().empty());
SQLULEN tout = static_cast<SQLULEN>(getLoginTimeout()); SQLULEN tout = static_cast<SQLULEN>(getLoginTimeout());
if (Utility::isError(SQLSetConnectAttr(_db, SQL_ATTR_LOGIN_TIMEOUT, (SQLPOINTER) tout, 0))) if (Utility::isError(Poco::Data::ODBC::SQLSetConnectAttr(_db, SQL_ATTR_LOGIN_TIMEOUT, (SQLPOINTER)tout, 0)))
{ {
if (Utility::isError(SQLGetConnectAttr(_db, SQL_ATTR_LOGIN_TIMEOUT, &tout, 0, 0)) || if (Utility::isError(Poco::Data::ODBC::SQLGetConnectAttr(_db, SQL_ATTR_LOGIN_TIMEOUT, &tout, 0, 0)) ||
getLoginTimeout() != tout) getLoginTimeout() != tout)
{ {
ConnectionError e(_db); ConnectionException e(_db);
throw ConnectionFailedException(e.toString()); throw ConnectionFailedException(e.errorString(), e);
} }
} }
@ -129,10 +139,9 @@ void SessionImpl::open(const std::string& connect)
, &result , &result
, SQL_DRIVER_NOPROMPT))) , SQL_DRIVER_NOPROMPT)))
{ {
ConnectionError err(_db); ConnectionException e(_db);
std::string errStr = err.toString();
close(); close();
throw ConnectionFailedException(errStr); throw ConnectionFailedException(e.errorString(), e);
} }
_dataTypes.fillTypeInfo(_db); _dataTypes.fillTypeInfo(_db);
@ -171,7 +180,7 @@ bool SessionImpl::isConnected()
{ {
SQLULEN value = 0; SQLULEN value = 0;
if (Utility::isError(Poco::Data::ODBC::SQLGetConnectAttr(_db, if (!static_cast<bool>(_db) || Utility::isError(Poco::Data::ODBC::SQLGetConnectAttr(_db,
SQL_ATTR_CONNECTION_DEAD, SQL_ATTR_CONNECTION_DEAD,
&value, &value,
0, 0,
@ -211,13 +220,19 @@ bool SessionImpl::canTransact()
if (ODBC_TXN_CAPABILITY_UNKNOWN == _canTransact) if (ODBC_TXN_CAPABILITY_UNKNOWN == _canTransact)
{ {
SQLUSMALLINT ret; SQLUSMALLINT ret;
checkError(Poco::Data::ODBC::SQLGetInfo(_db, SQL_TXN_CAPABLE, &ret, 0, 0), SQLRETURN res = Poco::Data::ODBC::SQLGetInfo(_db, SQL_TXN_CAPABLE, &ret, 0, 0);
"Failed to obtain transaction capability info."); if (!Utility::isError(res))
{
_canTransact = (SQL_TC_NONE != ret) ? _canTransact = (SQL_TC_NONE != ret) ?
ODBC_TXN_CAPABILITY_TRUE : ODBC_TXN_CAPABILITY_TRUE :
ODBC_TXN_CAPABILITY_FALSE; ODBC_TXN_CAPABILITY_FALSE;
} }
else
{
Error<SQLHDBC, SQL_HANDLE_DBC> err(_db);
_canTransact = ODBC_TXN_CAPABILITY_FALSE;
}
}
return ODBC_TXN_CAPABILITY_TRUE == _canTransact; return ODBC_TXN_CAPABILITY_TRUE == _canTransact;
} }
@ -239,14 +254,14 @@ void SessionImpl::setTransactionIsolation(Poco::UInt32 ti)
if (ti & Session::TRANSACTION_SERIALIZABLE) if (ti & Session::TRANSACTION_SERIALIZABLE)
isolation |= SQL_TXN_SERIALIZABLE; isolation |= SQL_TXN_SERIALIZABLE;
checkError(SQLSetConnectAttr(_db, SQL_ATTR_TXN_ISOLATION, (SQLPOINTER) isolation, 0)); checkError(Poco::Data::ODBC::SQLSetConnectAttr(_db, SQL_ATTR_TXN_ISOLATION, (SQLPOINTER)isolation, 0));
} }
Poco::UInt32 SessionImpl::getTransactionIsolation() Poco::UInt32 SessionImpl::getTransactionIsolation()
{ {
SQLULEN isolation = 0; SQLULEN isolation = 0;
checkError(SQLGetConnectAttr(_db, SQL_ATTR_TXN_ISOLATION, checkError(Poco::Data::ODBC::SQLGetConnectAttr(_db, SQL_ATTR_TXN_ISOLATION,
&isolation, &isolation,
0, 0,
0)); 0));
@ -271,7 +286,7 @@ bool SessionImpl::hasTransactionIsolation(Poco::UInt32 ti)
Poco::UInt32 SessionImpl::getDefaultTransactionIsolation() Poco::UInt32 SessionImpl::getDefaultTransactionIsolation()
{ {
SQLUINTEGER isolation = 0; SQLUINTEGER isolation = 0;
checkError(SQLGetInfo(_db, SQL_DEFAULT_TXN_ISOLATION, checkError(Poco::Data::ODBC::SQLGetInfo(_db, SQL_DEFAULT_TXN_ISOLATION,
&isolation, &isolation,
0, 0,
0)); 0));

View File

@ -16,6 +16,7 @@
#include "Poco/Data/ODBC/TypeInfo.h" #include "Poco/Data/ODBC/TypeInfo.h"
#include "Poco/Data/ODBC/ODBCException.h" #include "Poco/Data/ODBC/ODBCException.h"
#include "Poco/Data/LOB.h"
#include "Poco/Format.h" #include "Poco/Format.h"
#include "Poco/Exception.h" #include "Poco/Exception.h"
#include <iostream> #include <iostream>
@ -30,6 +31,17 @@ TypeInfo::TypeInfo(SQLHDBC* pHDBC): _pHDBC(pHDBC)
fillCTypes(); fillCTypes();
fillSQLTypes(); fillSQLTypes();
if (_pHDBC) fillTypeInfo(*_pHDBC); if (_pHDBC) fillTypeInfo(*_pHDBC);
_cppDataTypes.insert(CppTypeInfoMap::value_type(&typeid(std::string), SQL_C_CHAR));
_cppDataTypes.insert(CppTypeInfoMap::value_type(&typeid(std::wstring), SQL_C_WCHAR));
_cppDataTypes.insert(CppTypeInfoMap::value_type(&typeid(Poco::UTF16String), SQL_C_WCHAR));
_cppDataTypes.insert(CppTypeInfoMap::value_type(&typeid(Date), SQL_TYPE_DATE));
_cppDataTypes.insert(CppTypeInfoMap::value_type(&typeid(Time), SQL_TYPE_TIME));
_cppDataTypes.insert(CppTypeInfoMap::value_type(&typeid(DateTime), SQL_TYPE_TIMESTAMP));
_cppDataTypes.insert(CppTypeInfoMap::value_type(&typeid(BLOB), SQL_BINARY));
_cppDataTypes.insert(CppTypeInfoMap::value_type(&typeid(float), SQL_REAL));
_cppDataTypes.insert(CppTypeInfoMap::value_type(&typeid(double), SQL_DOUBLE));
_cppDataTypes.insert(CppTypeInfoMap::value_type(&typeid(bool), SQL_BIT));
} }
@ -102,7 +114,7 @@ void TypeInfo::fillTypeInfo(SQLHDBC pHDBC)
if (!SQL_SUCCEEDED(rc)) if (!SQL_SUCCEEDED(rc))
throw StatementException(hstmt, "SQLGetData()"); throw StatementException(hstmt, "SQLGetData()");
rc = SQLGetTypeInfo(hstmt, SQL_ALL_TYPES); rc = Poco::Data::ODBC::SQLGetTypeInfo(hstmt, SQL_ALL_TYPES);
if (SQL_SUCCEEDED(rc)) if (SQL_SUCCEEDED(rc))
{ {
while (SQLFetch(hstmt) != SQL_NO_DATA_FOUND) while (SQLFetch(hstmt) != SQL_NO_DATA_FOUND)
@ -264,4 +276,43 @@ void TypeInfo::print(std::ostream& ostr)
} }
SQLSMALLINT TypeInfo::tryTypeidToCType(const std::type_info& ti, SQLSMALLINT defaultVal) const
{
CppTypeInfoMap::const_iterator res = _cppDataTypes.find(&ti);
if (res == _cppDataTypes.end())
return defaultVal;
return res->second;
}
SQLSMALLINT TypeInfo::nullDataType(const NullData val) const
{
switch (val)
{
case NULL_GENERIC:
case DATA_NULL_INTEGER:
return SQL_C_TINYINT;
case DATA_NULL_STRING:
return SQL_C_CHAR;
case DATA_NULL_DATE:
return SQL_C_TYPE_DATE;
case DATA_NULL_TIME:
return SQL_C_TYPE_TIME;
case DATA_NULL_DATETIME:
return SQL_C_TYPE_TIMESTAMP;
case DATA_NULL_BLOB:
return SQL_C_BINARY;
case DATA_NULL_FLOAT:
return SQL_C_FLOAT;
}
return SQL_C_TINYINT;
}
} } } // namespace Poco::Data::ODBC } } } // namespace Poco::Data::ODBC

View File

@ -31,6 +31,7 @@ using Poco::TextConverter;
using Poco::InvalidArgumentException; using Poco::InvalidArgumentException;
using Poco::NotImplementedException; using Poco::NotImplementedException;
#ifdef POCO_ODBC_UNICODE
namespace Poco { namespace Poco {
namespace Data { namespace Data {
@ -775,3 +776,4 @@ SQLRETURN SQLDrivers(SQLHENV henv,
} } } // namespace Poco::Data::ODBC } } } // namespace Poco::Data::ODBC
#endif

View File

@ -43,7 +43,7 @@ Utility::DriverMap& Utility::drivers(Utility::DriverMap& driverMap)
SQLSMALLINT len2 = length; SQLSMALLINT len2 = length;
RETCODE rc = 0; RETCODE rc = 0;
if (!Utility::isError(rc = SQLDrivers(henv, if (!Utility::isError(rc = Poco::Data::ODBC::SQLDrivers(henv,
SQL_FETCH_FIRST, SQL_FETCH_FIRST,
desc, desc,
length, length,
@ -59,7 +59,7 @@ Utility::DriverMap& Utility::drivers(Utility::DriverMap& driverMap)
std::memset(desc, 0, length); std::memset(desc, 0, length);
std::memset(attr, 0, length); std::memset(attr, 0, length);
len2 = length; len2 = length;
}while (!Utility::isError(rc = SQLDrivers(henv, }while (!Utility::isError(rc = Poco::Data::ODBC::SQLDrivers(henv,
SQL_FETCH_NEXT, SQL_FETCH_NEXT,
desc, desc,
length, length,

View File

@ -29,7 +29,7 @@ endif
objects = ODBCTestSuite Driver \ objects = ODBCTestSuite Driver \
ODBCDB2Test ODBCMySQLTest ODBCOracleTest ODBCPostgreSQLTest \ ODBCDB2Test ODBCMySQLTest ODBCOracleTest ODBCPostgreSQLTest \
ODBCSQLiteTest ODBCSQLServerTest ODBCTest SQLExecutor ODBCSQLiteTest ODBCSQLServerTest ODBCTest SQLExecutor ODBCSybaseTest
ifeq ($(POCO_CONFIG),MinGW) ifeq ($(POCO_CONFIG),MinGW)
objects += ODBCAccessTest objects += ODBCAccessTest

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations"> <ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="debug_shared|Win32"> <ProjectConfiguration Include="debug_shared|Win32">
@ -129,7 +129,7 @@
<AdditionalIncludeDirectories>..\include;..\..\..\CppUnit\include;..\..\..\CppUnit\WinTestRunner\include;..\..\..\Foundation\include;..\..\..\Data\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\include;..\..\..\CppUnit\include;..\..\..\CppUnit\WinTestRunner\include;..\..\..\Foundation\include;..\..\..\Data\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;WINVER=0x0600;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;WINVER=0x0600;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling> <StringPooling>true</StringPooling>
<MinimalRebuild>true</MinimalRebuild> <MinimalRebuild>false</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<BufferSecurityCheck>true</BufferSecurityCheck> <BufferSecurityCheck>true</BufferSecurityCheck>
@ -140,6 +140,7 @@
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
<Link> <Link>
<AdditionalDependencies>CppUnitd.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>CppUnitd.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
@ -189,7 +190,7 @@
<AdditionalIncludeDirectories>..\include;..\..\..\CppUnit\include;..\..\..\CppUnit\WinTestRunner\include;..\..\..\Foundation\include;..\..\..\Data\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\include;..\..\..\CppUnit\include;..\..\..\CppUnit\WinTestRunner\include;..\..\..\Foundation\include;..\..\..\Data\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;WINVER=0x0600;POCO_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;WINVER=0x0600;POCO_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling> <StringPooling>true</StringPooling>
<MinimalRebuild>true</MinimalRebuild> <MinimalRebuild>false</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<BufferSecurityCheck>true</BufferSecurityCheck> <BufferSecurityCheck>true</BufferSecurityCheck>
@ -200,6 +201,7 @@
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
<Link> <Link>
<AdditionalDependencies>CppUnitmtd.lib;iphlpapi.lib;winmm.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>CppUnitmtd.lib;iphlpapi.lib;winmm.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
@ -249,7 +251,7 @@
<AdditionalIncludeDirectories>..\include;..\..\..\CppUnit\include;..\..\..\CppUnit\WinTestRunner\include;..\..\..\Foundation\include;..\..\..\Data\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\include;..\..\..\CppUnit\include;..\..\..\CppUnit\WinTestRunner\include;..\..\..\Foundation\include;..\..\..\Data\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;WINVER=0x0600;POCO_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;WINVER=0x0600;POCO_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling> <StringPooling>true</StringPooling>
<MinimalRebuild>true</MinimalRebuild> <MinimalRebuild>false</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<BufferSecurityCheck>true</BufferSecurityCheck> <BufferSecurityCheck>true</BufferSecurityCheck>
@ -260,6 +262,7 @@
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
<Link> <Link>
<AdditionalDependencies>CppUnitmdd.lib;iphlpapi.lib;winmm.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>CppUnitmdd.lib;iphlpapi.lib;winmm.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
@ -314,6 +317,7 @@
<ClInclude Include="src\ODBCTest.h"/> <ClInclude Include="src\ODBCTest.h"/>
<ClInclude Include="src\ODBCTestSuite.h"/> <ClInclude Include="src\ODBCTestSuite.h"/>
<ClInclude Include="src\SQLExecutor.h"/> <ClInclude Include="src\SQLExecutor.h"/>
<ClInclude Include="src\ODBCSybaseTest.h"/>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="src\Driver.cpp"/> <ClCompile Include="src\Driver.cpp"/>
@ -327,6 +331,7 @@
<ClCompile Include="src\ODBCTest.cpp"/> <ClCompile Include="src\ODBCTest.cpp"/>
<ClCompile Include="src\ODBCTestSuite.cpp"/> <ClCompile Include="src\ODBCTestSuite.cpp"/>
<ClCompile Include="src\SQLExecutor.cpp"/> <ClCompile Include="src\SQLExecutor.cpp"/>
<ClCompile Include="src\ODBCSybaseTest.cpp"/>
</ItemGroup> </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets"/> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets"/>
<ImportGroup Label="ExtensionTargets"/> <ImportGroup Label="ExtensionTargets"/>

View File

@ -54,8 +54,11 @@
<ClInclude Include="src\SQLExecutor.h"> <ClInclude Include="src\SQLExecutor.h">
<Filter>ODBC\Header Files</Filter> <Filter>ODBC\Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="src\ODBCSybaseTest.h">
<Filter>ODBC\Header Files</Filter>
</ClInclude>
<ClInclude Include="src\ODBCTestSuite.h"> <ClInclude Include="src\ODBCTestSuite.h">
<Filter>_Suite\Header Files</Filter> <Filter>ODBC\Header Files</Filter>
</ClInclude> </ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@ -92,5 +95,8 @@
<ClCompile Include="src\Driver.cpp"> <ClCompile Include="src\Driver.cpp">
<Filter>_Driver\Source Files</Filter> <Filter>_Driver\Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="src\ODBCSybaseTest.cpp">
<Filter>ODBC\Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -322,6 +322,7 @@
<ClInclude Include="src\ODBCTest.h"/> <ClInclude Include="src\ODBCTest.h"/>
<ClInclude Include="src\SQLExecutor.h"/> <ClInclude Include="src\SQLExecutor.h"/>
<ClInclude Include="src\ODBCTestSuite.h"/> <ClInclude Include="src\ODBCTestSuite.h"/>
<ClInclude Include="src\ODBCSybaseTest.h"/>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="src\ODBCAccessTest.cpp"/> <ClCompile Include="src\ODBCAccessTest.cpp"/>
@ -334,6 +335,7 @@
<ClCompile Include="src\ODBCTest.cpp"/> <ClCompile Include="src\ODBCTest.cpp"/>
<ClCompile Include="src\SQLExecutor.cpp"/> <ClCompile Include="src\SQLExecutor.cpp"/>
<ClCompile Include="src\ODBCTestSuite.cpp"/> <ClCompile Include="src\ODBCTestSuite.cpp"/>
<ClCompile Include="src\/ODBCSybaseTest.cpp"/>
<ClCompile Include="src\WinDriver.cpp"/> <ClCompile Include="src\WinDriver.cpp"/>
</ItemGroup> </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets"/> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets"/>

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations"> <ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="debug_shared|x64"> <ProjectConfiguration Include="debug_shared|x64">
@ -129,7 +129,7 @@
<AdditionalIncludeDirectories>..\include;..\..\..\CppUnit\include;..\..\..\CppUnit\WinTestRunner\include;..\..\..\Foundation\include;..\..\..\Data\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\include;..\..\..\CppUnit\include;..\..\..\CppUnit\WinTestRunner\include;..\..\..\Foundation\include;..\..\..\Data\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;WINVER=0x0600;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;WINVER=0x0600;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling> <StringPooling>true</StringPooling>
<MinimalRebuild>true</MinimalRebuild> <MinimalRebuild>false</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<BufferSecurityCheck>true</BufferSecurityCheck> <BufferSecurityCheck>true</BufferSecurityCheck>
@ -140,6 +140,7 @@
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
<Link> <Link>
<AdditionalDependencies>CppUnitd.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>CppUnitd.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
@ -171,6 +172,7 @@
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat /> <DebugInformationFormat />
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
<Link> <Link>
<AdditionalDependencies>CppUnit.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>CppUnit.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
@ -189,7 +191,7 @@
<AdditionalIncludeDirectories>..\include;..\..\..\CppUnit\include;..\..\..\CppUnit\WinTestRunner\include;..\..\..\Foundation\include;..\..\..\Data\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\include;..\..\..\CppUnit\include;..\..\..\CppUnit\WinTestRunner\include;..\..\..\Foundation\include;..\..\..\Data\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;WINVER=0x0600;POCO_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;WINVER=0x0600;POCO_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling> <StringPooling>true</StringPooling>
<MinimalRebuild>true</MinimalRebuild> <MinimalRebuild>false</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<BufferSecurityCheck>true</BufferSecurityCheck> <BufferSecurityCheck>true</BufferSecurityCheck>
@ -200,6 +202,7 @@
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
<Link> <Link>
<AdditionalDependencies>CppUnitmtd.lib;iphlpapi.lib;winmm.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>CppUnitmtd.lib;iphlpapi.lib;winmm.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
@ -231,6 +234,7 @@
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat /> <DebugInformationFormat />
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
<Link> <Link>
<AdditionalDependencies>CppUnitmt.lib;iphlpapi.lib;winmm.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>CppUnitmt.lib;iphlpapi.lib;winmm.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
@ -249,7 +253,7 @@
<AdditionalIncludeDirectories>..\include;..\..\..\CppUnit\include;..\..\..\CppUnit\WinTestRunner\include;..\..\..\Foundation\include;..\..\..\Data\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\include;..\..\..\CppUnit\include;..\..\..\CppUnit\WinTestRunner\include;..\..\..\Foundation\include;..\..\..\Data\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;WINVER=0x0600;POCO_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;WINVER=0x0600;POCO_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling> <StringPooling>true</StringPooling>
<MinimalRebuild>true</MinimalRebuild> <MinimalRebuild>false</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<BufferSecurityCheck>true</BufferSecurityCheck> <BufferSecurityCheck>true</BufferSecurityCheck>
@ -260,6 +264,7 @@
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
<Link> <Link>
<AdditionalDependencies>CppUnitmdd.lib;iphlpapi.lib;winmm.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>CppUnitmdd.lib;iphlpapi.lib;winmm.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
@ -291,6 +296,7 @@
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat /> <DebugInformationFormat />
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
<Link> <Link>
<AdditionalDependencies>CppUnitmd.lib;iphlpapi.lib;winmm.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>CppUnitmd.lib;iphlpapi.lib;winmm.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
@ -314,6 +320,7 @@
<ClInclude Include="src\ODBCTest.h" /> <ClInclude Include="src\ODBCTest.h" />
<ClInclude Include="src\ODBCTestSuite.h" /> <ClInclude Include="src\ODBCTestSuite.h" />
<ClInclude Include="src\SQLExecutor.h" /> <ClInclude Include="src\SQLExecutor.h" />
<ClInclude Include="src\ODBCSybaseTest.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="src\Driver.cpp" /> <ClCompile Include="src\Driver.cpp" />
@ -327,6 +334,7 @@
<ClCompile Include="src\ODBCTest.cpp" /> <ClCompile Include="src\ODBCTest.cpp" />
<ClCompile Include="src\ODBCTestSuite.cpp" /> <ClCompile Include="src\ODBCTestSuite.cpp" />
<ClCompile Include="src\SQLExecutor.cpp" /> <ClCompile Include="src\SQLExecutor.cpp" />
<ClCompile Include="src\ODBCSybaseTest.cpp" />
</ItemGroup> </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets" /> <ImportGroup Label="ExtensionTargets" />

View File

@ -57,6 +57,9 @@
<ClInclude Include="src\ODBCTestSuite.h"> <ClInclude Include="src\ODBCTestSuite.h">
<Filter>_Suite\Header Files</Filter> <Filter>_Suite\Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="src\ODBCSybaseTest.h">
<Filter>ODBC\Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="src\ODBCAccessTest.cpp"> <ClCompile Include="src\ODBCAccessTest.cpp">
@ -89,8 +92,14 @@
<ClCompile Include="src\ODBCTestSuite.cpp"> <ClCompile Include="src\ODBCTestSuite.cpp">
<Filter>_Suite\Source Files</Filter> <Filter>_Suite\Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="src\ODBCSybaseTest.cpp">
<Filter>_Suite\Source Files</Filter>
</ClCompile>
<ClCompile Include="src\Driver.cpp"> <ClCompile Include="src\Driver.cpp">
<Filter>_Driver\Source Files</Filter> <Filter>_Driver\Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="src\ODBCSybaseTest.cpp">
<Filter>ODBC\Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -114,8 +114,8 @@ void ODBCAccessTest::dropTable(const std::string& tableName)
void ODBCAccessTest::recreatePersonTable() void ODBCAccessTest::recreatePersonTable()
{ {
dropTable("Person"); dropTable(ExecUtil::person());
*_pSession << "CREATE TABLE Person (LastName TEXT(30), FirstName TEXT(30), Address TEXT(30), Age INTEGER)", now; *_pSession << "CREATE TABLE " << ExecUtil::person() << " (LastName TEXT(30), FirstName TEXT(30), Address TEXT(30), Age INTEGER)", now;
} }
@ -176,7 +176,7 @@ void ODBCAccessTest::setUp()
void ODBCAccessTest::tearDown() void ODBCAccessTest::tearDown()
{ {
dropTable("Person"); dropTable(ExecUtil::person());
} }

View File

@ -21,11 +21,13 @@
#include "Poco/Exception.h" #include "Poco/Exception.h"
#include "Poco/Data/LOB.h" #include "Poco/Data/LOB.h"
#include "Poco/Data/StatementImpl.h" #include "Poco/Data/StatementImpl.h"
#include "Poco/Data/RecordSet.h"
#include "Poco/Data/ODBC/Connector.h" #include "Poco/Data/ODBC/Connector.h"
#include "Poco/Data/ODBC/Utility.h" #include "Poco/Data/ODBC/Utility.h"
#include "Poco/Data/ODBC/Diagnostics.h" #include "Poco/Data/ODBC/Diagnostics.h"
#include "Poco/Data/ODBC/ODBCException.h" #include "Poco/Data/ODBC/ODBCException.h"
#include "Poco/Data/ODBC/ODBCStatementImpl.h" #include "Poco/Data/ODBC/ODBCStatementImpl.h"
#include "Poco/Environment.h"
#include <sqltypes.h> #include <sqltypes.h>
#include <iostream> #include <iostream>
@ -43,29 +45,58 @@ using Poco::AnyCast;
using Poco::DynamicAny; using Poco::DynamicAny;
using Poco::NotFoundException; using Poco::NotFoundException;
static std::string db2Driver()
{
return Poco::Environment::get("POCO_TEST_DB2_DRIVER",
#if defined(POCO_OS_FAMILY_WINDOWS)
"IBM DB2 ODBC DRIVER - DB2COPY1"
#else
"libdb2o.so"
#endif
);
}
static std::string db2Uid()
{
return Poco::Environment::get("POCO_TEST_DB2_UID", "db2admin");
}
static std::string db2Db()
{
return Poco::Environment::get("POCO_TEST_DB2_DB", "POCOTEST");
}
static std::string db2Pwd()
{
return Poco::Environment::get("POCO_TEST_DB2_PWD", "db2admin");
}
static std::string db2Extra()
{
std::string e = Poco::Environment::get("POCO_TEST_DB2_EXTRA", "");
return (e.empty() ? "" : e + ";");
}
#define DB2_ODBC_DRIVER "IBM DB2 ODBC DRIVER - DB2COPY1"
#define DB2_DSN "PocoDataDB2Test" #define DB2_DSN "PocoDataDB2Test"
#define DB2_SERVER POCO_ODBC_TEST_DATABASE_SERVER #define DB2_SERVER POCO_ODBC_TEST_DATABASE_SERVER
#define DB2_PORT "50000" #define DB2_PORT "50000"
#define DB2_DB "POCOTEST"
#define DB2_UID "db2admin"
#define DB2_PWD "db2admin"
ODBCTest::SessionPtr ODBCDB2Test::_pSession; ODBCTest::SessionPtr ODBCDB2Test::_pSession;
ODBCTest::ExecPtr ODBCDB2Test::_pExecutor; ODBCTest::ExecPtr ODBCDB2Test::_pExecutor;
std::string ODBCDB2Test::_driver = DB2_ODBC_DRIVER; std::string ODBCDB2Test::_driver = db2Driver();
std::string ODBCDB2Test::_dsn = DB2_DSN; std::string ODBCDB2Test::_dsn = DB2_DSN;
std::string ODBCDB2Test::_uid = DB2_UID; std::string ODBCDB2Test::_uid = db2Uid();
std::string ODBCDB2Test::_pwd = DB2_PWD; std::string ODBCDB2Test::_pwd = db2Pwd();
std::string ODBCDB2Test::_connectString = "Driver=" DB2_ODBC_DRIVER ";" std::string ODBCDB2Test::_connectString = "Driver=" + db2Driver() + ";"
"Database=" DB2_DB ";" + db2Extra() +
"Database=" + db2Db() + ";"
"Hostname=" DB2_SERVER ";" "Hostname=" DB2_SERVER ";"
"Port=" DB2_PORT ";" "Port=" DB2_PORT ";"
"Protocol=TCPIP;" "Protocol=TCPIP;"
"Uid=" DB2_UID ";" "Uid=" + db2Uid() + ";"
"Pwd=" DB2_PWD ";"; "Pwd=" + db2Pwd() + ";"
;
ODBCDB2Test::ODBCDB2Test(const std::string& name): ODBCDB2Test::ODBCDB2Test(const std::string& name):
@ -81,9 +112,9 @@ ODBCDB2Test::~ODBCDB2Test()
void ODBCDB2Test::testBareboneODBC() void ODBCDB2Test::testBareboneODBC()
{ {
if (!_pSession) fail ("Test not available."); if (! &session()) fail ("Test not available.");
std::string tableCreateString = "CREATE TABLE Test " std::string tableCreateString = "CREATE TABLE " + ExecUtil::test_tbl() +
"(First VARCHAR(30)," "(First VARCHAR(30),"
"Second VARCHAR(30)," "Second VARCHAR(30),"
"Third BLOB," "Third BLOB,"
@ -91,55 +122,55 @@ void ODBCDB2Test::testBareboneODBC()
"Fifth FLOAT," "Fifth FLOAT,"
"Sixth TIMESTAMP)"; "Sixth TIMESTAMP)";
_pExecutor->bareboneODBCTest(dbConnString(), tableCreateString, SQLExecutor::PB_IMMEDIATE, SQLExecutor::DE_MANUAL); executor().bareboneODBCTest(dbConnString(), tableCreateString, SQLExecutor::PB_IMMEDIATE, SQLExecutor::DE_MANUAL);
_pExecutor->bareboneODBCTest(dbConnString(), tableCreateString, SQLExecutor::PB_IMMEDIATE, SQLExecutor::DE_BOUND); executor().bareboneODBCTest(dbConnString(), tableCreateString, SQLExecutor::PB_IMMEDIATE, SQLExecutor::DE_BOUND);
_pExecutor->bareboneODBCTest(dbConnString(), tableCreateString, SQLExecutor::PB_AT_EXEC, SQLExecutor::DE_MANUAL); executor().bareboneODBCTest(dbConnString(), tableCreateString, SQLExecutor::PB_AT_EXEC, SQLExecutor::DE_MANUAL);
_pExecutor->bareboneODBCTest(dbConnString(), tableCreateString, SQLExecutor::PB_AT_EXEC, SQLExecutor::DE_BOUND); executor().bareboneODBCTest(dbConnString(), tableCreateString, SQLExecutor::PB_AT_EXEC, SQLExecutor::DE_BOUND);
tableCreateString = "CREATE TABLE Test " tableCreateString = "CREATE TABLE " + ExecUtil::test_tbl() +
"(First VARCHAR(30)," "(First VARCHAR(30),"
"Second INTEGER," "Second INTEGER,"
"Third FLOAT)"; "Third FLOAT)";
_pExecutor->bareboneODBCMultiResultTest(dbConnString(), tableCreateString, SQLExecutor::PB_IMMEDIATE, SQLExecutor::DE_MANUAL); executor().bareboneODBCMultiResultTest(dbConnString(), tableCreateString, SQLExecutor::PB_IMMEDIATE, SQLExecutor::DE_MANUAL);
_pExecutor->bareboneODBCMultiResultTest(dbConnString(), tableCreateString, SQLExecutor::PB_IMMEDIATE, SQLExecutor::DE_BOUND); executor().bareboneODBCMultiResultTest(dbConnString(), tableCreateString, SQLExecutor::PB_IMMEDIATE, SQLExecutor::DE_BOUND);
_pExecutor->bareboneODBCMultiResultTest(dbConnString(), tableCreateString, SQLExecutor::PB_AT_EXEC, SQLExecutor::DE_MANUAL); executor().bareboneODBCMultiResultTest(dbConnString(), tableCreateString, SQLExecutor::PB_AT_EXEC, SQLExecutor::DE_MANUAL);
_pExecutor->bareboneODBCMultiResultTest(dbConnString(), tableCreateString, SQLExecutor::PB_AT_EXEC, SQLExecutor::DE_BOUND); executor().bareboneODBCMultiResultTest(dbConnString(), tableCreateString, SQLExecutor::PB_AT_EXEC, SQLExecutor::DE_BOUND);
} }
void ODBCDB2Test::testBLOB() void ODBCDB2Test::testBLOB()
{ {
if (!_pSession) fail ("Test not available."); if (! &session()) fail ("Test not available.");
const std::size_t maxFldSize = 1000000; const std::size_t maxFldSize = 1000000;
_pSession->setProperty("maxFieldSize", Poco::Any(maxFldSize-1)); session().setProperty("maxFieldSize", Poco::Any(maxFldSize-1));
recreatePersonBLOBTable(); recreatePersonBLOBTable();
try try
{ {
_pExecutor->blob(maxFldSize); executor().blob(maxFldSize);
fail ("must fail"); fail ("must fail");
} }
catch (DataException&) catch (DataException&)
{ {
_pSession->setProperty("maxFieldSize", Poco::Any(maxFldSize)); session().setProperty("maxFieldSize", Poco::Any(maxFldSize));
} }
for (int i = 0; i < 8;) for (int i = 0; i < 8;)
{ {
recreatePersonBLOBTable(); recreatePersonBLOBTable();
_pSession->setFeature("autoBind", bindValue(i)); session().setFeature("autoBind", bindValue(i));
_pSession->setFeature("autoExtract", bindValue(i+1)); session().setFeature("autoExtract", bindValue(i+1));
_pExecutor->blob(maxFldSize); executor().blob(maxFldSize);
i += 2; i += 2;
} }
recreatePersonBLOBTable(); recreatePersonBLOBTable();
try try
{ {
_pExecutor->blob(maxFldSize+1); executor().blob(maxFldSize+1);
fail ("must fail"); fail ("must fail");
} }
catch (DataException&) { } catch (DataException&) { }
@ -148,14 +179,14 @@ void ODBCDB2Test::testBLOB()
void ODBCDB2Test::testFilter() void ODBCDB2Test::testFilter()
{ {
if (!_pSession) fail ("Test not available."); if (! &session()) fail ("Test not available.");
for (int i = 0; i < 8;) for (int i = 0; i < 8;)
{ {
recreateVectorsTable(); recreateVectorsTable();
_pSession->setFeature("autoBind", bindValue(i)); session().setFeature("autoBind", bindValue(i));
_pSession->setFeature("autoExtract", bindValue(i+1)); session().setFeature("autoExtract", bindValue(i+1));
_pExecutor->filter("SELECT * FROM Vectors ORDER BY i0 ASC", "i0"); executor().filter("SELECT * FROM " + ExecUtil::vectors() + " ORDER BY i0 ASC", "i0");
i += 2; i += 2;
} }
} }
@ -163,50 +194,54 @@ void ODBCDB2Test::testFilter()
void ODBCDB2Test::testStoredProcedure() void ODBCDB2Test::testStoredProcedure()
{ {
if (!_pSession) fail ("Test not available."); if (! &session()) fail ("Test not available.");
const std::string nm = ExecUtil::stored_proc();
dropObject("PROCEDURE", nm + "(INTEGER)");
dropObject("PROCEDURE", nm + "(INTEGER, INTEGER)");
dropObject("PROCEDURE", nm + "(VARCHAR(1000), VARCHAR(1000))");
for (int k = 0; k < 8;) for (int k = 0; k < 8;)
{ {
_pSession->setFeature("autoBind", bindValue(k)); session().setFeature("autoBind", bindValue(k));
_pSession->setFeature("autoExtract", bindValue(k+1)); session().setFeature("autoExtract", bindValue(k+1));
dropObject("PROCEDURE", "storedProcedure"); session() << "CREATE PROCEDURE " << nm << "(OUT outParam INTEGER) "
*_pSession << "CREATE PROCEDURE storedProcedure(OUT outParam INTEGER) "
"BEGIN " "BEGIN "
" SET outParam = -1; " " SET outParam = -1; "
"END" , now; "END" , now;
int i = 0; int i = 0;
*_pSession << "{call storedProcedure(?)}", out(i), now; session() << "{call " + db2Db() + "." << nm << "(?)}", out(i), now;
dropObject("PROCEDURE", nm + "(INTEGER)");
assert(-1 == i); assert(-1 == i);
dropObject("PROCEDURE", "storedProcedure");
*_pSession << "CREATE PROCEDURE storedProcedure(inParam INTEGER, OUT outParam INTEGER) " session() << "CREATE PROCEDURE " << nm << "(inParam INTEGER, OUT outParam INTEGER) "
"BEGIN " "BEGIN "
" SET outParam = inParam*inParam; " " SET outParam = inParam*inParam; "
"END" , now; "END" , now;
i = 2; i = 2;
int j = 0; int j = 0;
*_pSession << "{call storedProcedure(?, ?)}", in(i), out(j), now; session() << "{call " + db2Db() + "." << nm << "(?, ?)}", in(i), out(j), now;
dropObject("PROCEDURE", nm + "(INTEGER, INTEGER)");
assert(4 == j); assert(4 == j);
dropObject("PROCEDURE", "storedProcedure");
*_pSession << "CREATE PROCEDURE storedProcedure(INOUT ioParam INTEGER) " session() << "CREATE PROCEDURE " << nm << "(INOUT ioParam INTEGER) "
"BEGIN " "BEGIN "
" SET ioParam = ioParam*ioParam; " " SET ioParam = ioParam*ioParam; "
"END" , now; "END" , now;
i = 2; i = 2;
*_pSession << "{call storedProcedure(?)}", io(i), now; session() << "{call " + db2Db() + "." << nm << "(?)}", io(i), now;
dropObject("PROCEDURE", nm + "(INTEGER)");
assert(4 == i); assert(4 == i);
dropObject("PROCEDURE", "storedProcedure");
//TIMESTAMP is not supported as stored procedure parameter in DB2 //TIMESTAMP is not supported as stored procedure parameter in DB2
//(SQL0182N An expression with a datetime value or a labeled duration is not valid.) //(SQL0182N An expression with a datetime value or a labeled duration is not valid.)
*_pSession << "CREATE PROCEDURE storedProcedure(inParam VARCHAR(1000), OUT outParam VARCHAR(1000)) " session() << "CREATE PROCEDURE " << nm << "(inParam VARCHAR(1000), OUT outParam VARCHAR(1000)) "
"BEGIN " "BEGIN "
" SET outParam = inParam; " " SET outParam = inParam; "
"END" , now; "END" , now;
@ -222,9 +257,9 @@ void ODBCDB2Test::testStoredProcedure()
"1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890" "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"
"1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"; "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890";
std::string outParam; std::string outParam;
*_pSession << "{call storedProcedure(?,?)}", in(inParam), out(outParam), now; session() << "{call " + db2Db() + "." << nm << "(?,?)}", in(inParam), out(outParam), now;
dropObject("PROCEDURE", nm + "(VARCHAR(1000), VARCHAR(1000))");
assert(inParam == outParam); assert(inParam == outParam);
dropObject("PROCEDURE", "storedProcedure");
k += 2; k += 2;
} }
@ -233,34 +268,38 @@ void ODBCDB2Test::testStoredProcedure()
void ODBCDB2Test::testStoredProcedureAny() void ODBCDB2Test::testStoredProcedureAny()
{ {
if (!_pSession) fail ("Test not available."); if (! &session()) fail ("Test not available.");
const std::string nm = ExecUtil::stored_proc();
dropObject("PROCEDURE", nm + "(INTEGER)");
dropObject("PROCEDURE", nm + "(INTEGER, INTEGER)");
for (int k = 0; k < 8;) for (int k = 0; k < 8;)
{ {
_pSession->setFeature("autoBind", bindValue(k)); session().setFeature("autoBind", bindValue(k));
_pSession->setFeature("autoExtract", bindValue(k+1)); session().setFeature("autoExtract", bindValue(k+1));
Any i = 2; Any i = 2;
Any j = 0; Any j = 0;
*_pSession << "CREATE PROCEDURE storedProcedure(inParam INTEGER, OUT outParam INTEGER) " session() << "CREATE PROCEDURE " << nm << "(inParam INTEGER, OUT outParam INTEGER) "
"BEGIN " "BEGIN "
" SET outParam = inParam*inParam; " " SET outParam = inParam*inParam; "
"END" , now; "END" , now;
*_pSession << "{call storedProcedure(?, ?)}", in(i), out(j), now; session() << "{call " + db2Db() + "." << nm << "(?, ?)}", in(i), out(j), now;
dropObject("PROCEDURE", nm + "(INTEGER, INTEGER)");
assert(4 == AnyCast<int>(j)); assert(4 == AnyCast<int>(j));
*_pSession << "DROP PROCEDURE storedProcedure;", now;
*_pSession << "CREATE PROCEDURE storedProcedure(INOUT ioParam INTEGER) " session() << "CREATE PROCEDURE " << nm << "(INOUT ioParam INTEGER) "
"BEGIN " "BEGIN "
" SET ioParam = ioParam*ioParam; " " SET ioParam = ioParam*ioParam; "
"END" , now; "END" , now;
i = 2; i = 2;
*_pSession << "{call storedProcedure(?)}", io(i), now; session() << "{call " + db2Db() + "." << nm << "(?)}", io(i), now;
dropObject("PROCEDURE", nm + "(INTEGER)");
assert(4 == AnyCast<int>(i)); assert(4 == AnyCast<int>(i));
dropObject("PROCEDURE", "storedProcedure");
k += 2; k += 2;
} }
@ -269,33 +308,37 @@ void ODBCDB2Test::testStoredProcedureAny()
void ODBCDB2Test::testStoredProcedureDynamicAny() void ODBCDB2Test::testStoredProcedureDynamicAny()
{ {
if (!_pSession) fail ("Test not available."); if (! &session()) fail ("Test not available.");
const std::string nm = ExecUtil::stored_proc();
dropObject("PROCEDURE", nm + "(INTEGER)");
dropObject("PROCEDURE", nm + "(INTEGER, INTEGER)");
for (int k = 0; k < 8;) for (int k = 0; k < 8;)
{ {
_pSession->setFeature("autoBind", bindValue(k)); session().setFeature("autoBind", bindValue(k));
DynamicAny i = 2; DynamicAny i = 2;
DynamicAny j = 0; DynamicAny j = 0;
*_pSession << "CREATE PROCEDURE storedProcedure(inParam INTEGER, OUT outParam INTEGER) " session() << "CREATE PROCEDURE " << nm << "(inParam INTEGER, OUT outParam INTEGER) "
"BEGIN " "BEGIN "
" SET outParam = inParam*inParam; " " SET outParam = inParam*inParam; "
"END" , now; "END" , now;
*_pSession << "{call storedProcedure(?, ?)}", in(i), out(j), now; session() << "{call " + db2Db() + "." << nm << "(?, ?)}", in(i), out(j), now;
dropObject("PROCEDURE", nm + "(INTEGER, INTEGER)");
assert(4 == j); assert(4 == j);
*_pSession << "DROP PROCEDURE storedProcedure;", now;
*_pSession << "CREATE PROCEDURE storedProcedure(INOUT ioParam INTEGER) " session() << "CREATE PROCEDURE " << nm << "(INOUT ioParam INTEGER) "
"BEGIN " "BEGIN "
" SET ioParam = ioParam*ioParam; " " SET ioParam = ioParam*ioParam; "
"END" , now; "END" , now;
i = 2; i = 2;
*_pSession << "{call storedProcedure(?)}", io(i), now; session() << "{call " + db2Db() + "." << nm << "(?)}", io(i), now;
dropObject("PROCEDURE", nm + "(INTEGER)");
assert(4 == i); assert(4 == i);
dropObject("PROCEDURE", "storedProcedure");
k += 2; k += 2;
} }
@ -304,36 +347,89 @@ void ODBCDB2Test::testStoredProcedureDynamicAny()
void ODBCDB2Test::testStoredFunction() void ODBCDB2Test::testStoredFunction()
{ {
if (!_pSession) fail ("Test not available."); const std::string nm = ExecUtil::stored_func();
if (! &session()) fail ("Test not available.");
dropObject("PROCEDURE", nm + "()");
dropObject("PROCEDURE", nm + "(INTEGER)");
dropObject("PROCEDURE", nm + "(INTEGER, INTEGER)");
dropObject("PROCEDURE", nm + "(VARCHAR(10), DATE, TIME, TIMESTAMP, INTEGER, SMALLINT, REAL, DOUBLE, VARCHAR(10), INTEGER)");
dropObject("PROCEDURE", nm + "(VARCHAR(10), VARCHAR(10))");
for (int k = 0; k < 8;) for (int k = 0; k < 8;)
{ {
_pSession->setFeature("autoBind", bindValue(k)); session().setFeature("autoBind", bindValue(k));
_pSession->setFeature("autoExtract", bindValue(k+1)); session().setFeature("autoExtract", bindValue(k + 1));
dropObject("PROCEDURE", "storedFunction"); {
*_pSession << "CREATE PROCEDURE storedFunction() " session() << "CREATE PROCEDURE " << nm << "() "
"BEGIN "
" DECLARE C1 CURSOR FOR select * from sysibm.sysdummy1 where 1=2;"
" OPEN C1;"
" RETURN;"
"END", now;
Poco::Data::Statement stat(session());
stat << "{ call " + db2Db() + "." << nm << "()}", now;
Poco::Data::RecordSet rs(stat);
assert(0 == rs.rowCount());
dropObject("PROCEDURE", nm + "()");
}
{
session() << "CREATE PROCEDURE " << nm << "(inp VARCHAR(10), out dt DATE, out tm TIME, out tms TIMESTAMP, out int32 INTEGER, "
"out si SMALLINT, out fl REAL, out dbl DOUBLE, out s2 VARCHAR(10), out an INTEGER)"
"BEGIN "
"set dt =null; set tm =null; set tms =null; set int32 =null; set si =null; set fl =null; set dbl =null; set s2 = inp; set an = inp;"
"END", now;
Poco::Data::Statement stat(session());
Poco::Nullable<std::string> ns;
Poco::Nullable<Poco::Data::Date> nd = Poco::Nullable<Poco::Data::Date>(Poco::Data::Date());
Poco::Nullable<int> n_i(1);
Poco::Nullable<Poco::Data::Time> tm = Poco::Nullable<Poco::Data::Time>(Poco::Data::Time());
Poco::Nullable<Poco::DateTime> tms = Poco::Nullable<Poco::DateTime>(Poco::DateTime());
Poco::Nullable<Poco::Int16> i16(1);
Poco::Nullable<float> flt(1);
Poco::Nullable<double> dbl(1);
Poco::Nullable<std::string> s2("ddd");
Poco::Nullable<Any> an(Any(2));
stat << "{call " + db2Db() + "." << nm << "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)}", useRef(ns), out(nd), out(tm), out(tms), out(n_i), out(i16), out(flt), out(dbl), out(s2), out(an), now;
dropObject("PROCEDURE", nm + "(VARCHAR(10), DATE, TIME, TIMESTAMP, INTEGER, SMALLINT, REAL, DOUBLE, VARCHAR(10), INTEGER)");
assert(nd.isNull());
assert(n_i.isNull());
assert(tm.isNull());
assert(tms.isNull());
assert(i16.isNull());
assert(flt.isNull());
assert(dbl.isNull());
assert(s2.isNull());
assert(an.isNull());
}
session() << "CREATE PROCEDURE " << nm << "() "
"BEGIN " "BEGIN "
" RETURN -1; " " RETURN -1; "
"END" , now; "END" , now;
int i = 0; int i = 0;
*_pSession << "{? = call storedFunction()}", out(i), now; session() << "{? = call " + db2Db() + "." << nm << "()}", out(i), now;
dropObject("PROCEDURE", nm + "()");
assert(-1 == i); assert(-1 == i);
dropObject("PROCEDURE", "storedFunction");
*_pSession << "CREATE PROCEDURE storedFunction(inParam INTEGER) "
session() << "CREATE PROCEDURE " << nm << "(inParam INTEGER) "
"BEGIN " "BEGIN "
" RETURN inParam*inParam; " " RETURN inParam*inParam; "
"END" , now; "END" , now;
i = 2; i = 2;
int result = 0; int result = 0;
*_pSession << "{? = call storedFunction(?)}", out(result), in(i), now; session() << "{? = call " + db2Db() + "." << nm << "(?)}", out(result), in(i), now;
dropObject("PROCEDURE", nm + "(INTEGER)");
assert(4 == result); assert(4 == result);
dropObject("PROCEDURE", "storedFunction");
*_pSession << "CREATE PROCEDURE storedFunction(inParam INTEGER, OUT outParam INTEGER) " session() << "CREATE PROCEDURE " << nm << "(inParam INTEGER, OUT outParam INTEGER) "
"BEGIN " "BEGIN "
" SET outParam = inParam*inParam; " " SET outParam = inParam*inParam; "
" RETURN outParam; " " RETURN outParam; "
@ -342,12 +438,12 @@ void ODBCDB2Test::testStoredFunction()
i = 2; i = 2;
int j = 0; int j = 0;
result = 0; result = 0;
*_pSession << "{? = call storedFunction(?, ?)}", out(result), in(i), out(j), now; session() << "{? = call " + db2Db() + "." << nm << "(?, ?)}", out(result), in(i), out(j), now;
dropObject("PROCEDURE", nm + "(INTEGER, INTEGER)");
assert(4 == j); assert(4 == j);
assert(j == result); assert(j == result);
dropObject("PROCEDURE", "storedFunction");
*_pSession << "CREATE PROCEDURE storedFunction(INOUT param1 INTEGER, INOUT param2 INTEGER) " session() << "CREATE PROCEDURE " << nm << "(INOUT param1 INTEGER, INOUT param2 INTEGER) "
"BEGIN " "BEGIN "
" DECLARE temp INTEGER;" " DECLARE temp INTEGER;"
" SET temp = param1; " " SET temp = param1; "
@ -359,7 +455,7 @@ void ODBCDB2Test::testStoredFunction()
i = 1; i = 1;
j = 2; j = 2;
result = 0; result = 0;
*_pSession << "{? = call storedFunction(?, ?)}", out(result), io(i), io(j), now; session() << "{? = call " + db2Db() + "." << nm << "(?, ?)}", out(result), io(i), io(j), now;
assert(1 == j); assert(1 == j);
assert(2 == i); assert(2 == i);
assert(3 == result); assert(3 == result);
@ -368,16 +464,15 @@ void ODBCDB2Test::testStoredFunction()
assert(1 == params.get<0>()); assert(1 == params.get<0>());
assert(2 == params.get<1>()); assert(2 == params.get<1>());
result = 0; result = 0;
*_pSession << "{? = call storedFunction(?, ?)}", out(result), io(params), now; session() << "{? = call " + db2Db() + "." << nm << "(?, ?)}", out(result), io(params), now;
dropObject("PROCEDURE", nm + "(INTEGER, INTEGER)");
assert(1 == params.get<1>()); assert(1 == params.get<1>());
assert(2 == params.get<0>()); assert(2 == params.get<0>());
assert(3 == result); assert(3 == result);
dropObject("PROCEDURE", "storedFunction"); session().setFeature("autoBind", true);
_pSession->setFeature("autoBind", true); session() << "CREATE PROCEDURE " << nm << "(inParam VARCHAR(10), OUT outParam VARCHAR(10)) "
*_pSession << "CREATE PROCEDURE storedFunction(inParam VARCHAR(10), OUT outParam VARCHAR(10)) "
"BEGIN " "BEGIN "
" SET outParam = inParam; " " SET outParam = inParam; "
" RETURN LENGTH(outParam);"//DB2 allows only integer as return type " RETURN LENGTH(outParam);"//DB2 allows only integer as return type
@ -386,21 +481,74 @@ void ODBCDB2Test::testStoredFunction()
std::string inParam = "123456789"; std::string inParam = "123456789";
std::string outParam; std::string outParam;
int ret; int ret;
*_pSession << "{? = call storedFunction(?,?)}", out(ret), in(inParam), out(outParam), now; session() << "{? = call " + db2Db() + "." << nm << "(?,?)}", out(ret), in(inParam), out(outParam), now;
dropObject("PROCEDURE", nm + "(VARCHAR(10), VARCHAR(10))");
assert(inParam == outParam); assert(inParam == outParam);
assert(ret == inParam.size()); assert(ret == inParam.size());
dropObject("PROCEDURE", "storedFunction");
k += 2; k += 2;
} }
} }
void ODBCDB2Test::testXMLColumn()
{
const std::string tbl = ExecUtil::mangleTable("xmlColumn");
dropObject("TABLE", tbl);
try {
const std::string xmlStr = "<a> xml text </a>";
Poco::UTF16String uStr;
for (unsigned c = 0x400; c < 0x409; ++c) uStr.append(3, Poco::UTF16Char(c) );
session() << "CREATE TABLE " << tbl << " (id integer, x XML, cl CLOB, dbcl DBCLOB)", now;
session() << "INSERT INTO " << tbl << " (id , x, cl, dbcl) VALUES(1, '" << xmlStr << "', ?, ?)", bind(xmlStr), bind(uStr), now;
Poco::Data::Statement stat(session());
stat << "SELECT id, x,cl, dbcl FROM " << tbl, now;
Poco::Data::RecordSet rs(stat);
assert(1 == rs.rowCount());
assert(4 == rs.columnCount());
int id = rs.value<int>(0);
assert(1 == id);
Poco::Data::BLOB xml = rs.value<Poco::Data::BLOB>(1);
std::string readStr(reinterpret_cast<const char*>(xml.rawContent()), xml.size());
assert(readStr.find(xmlStr) < readStr.length());
Poco::Data::CLOB cl = rs.value<Poco::Data::CLOB>(2);
assert(xmlStr == std::string(cl.rawContent(), cl.size()));
const Poco::UTF16String us = rs.value<Poco::UTF16String>(3);
assert(uStr == us);
// check nullables
Poco::Nullable<Poco::Data::CLOB> ncl = Poco::Nullable<Poco::Data::CLOB>(Poco::Data::CLOB());
assert(false == ncl.isNull());
Poco::Nullable<Poco::Data::BLOB> nbl = Poco::Nullable<Poco::Data::BLOB>(Poco::Data::BLOB());
assert(false == nbl.isNull());
Poco::Nullable<Poco::UTF16String> usn(Poco::UTF16String(2, Poco::UTF16Char('a')));
assert(false == usn.isNull());
session() << "INSERT INTO " << tbl << " (id) VALUES (99) ", now;
session() << "SELECT x,cl, dbcl FROM " << tbl << " WHERE id > 1", into(nbl), into(ncl), into(usn), now;
assert(true == ncl.isNull());
assert(true == nbl.isNull());
assert(true == usn.isNull());
}
catch (const Poco::Exception& e)
{
dropObject("TABLE", tbl);
std::cerr << e.message() << std::endl;
throw;
}
dropObject("TABLE", tbl);
}
void ODBCDB2Test::dropObject(const std::string& type, const std::string& name) void ODBCDB2Test::dropObject(const std::string& type, const std::string& name)
{ {
try try
{ {
*_pSession << format("DROP %s %s", type, name), now; session() << format("DROP %s %s", type, name), now;
} }
catch (StatementException& ex) catch (StatementException& ex)
{ {
@ -409,7 +557,8 @@ void ODBCDB2Test::dropObject(const std::string& type, const std::string& name)
StatementDiagnostics::Iterator it = flds.begin(); StatementDiagnostics::Iterator it = flds.begin();
for (; it != flds.end(); ++it) for (; it != flds.end(); ++it)
{ {
if (-204 == it->_nativeError)//(table does not exist) //(table does not exist) // procedure not found
if (-204 == it->_nativeError || (-458 == it->_nativeError) )
{ {
ignoreError = true; ignoreError = true;
break; break;
@ -423,17 +572,28 @@ void ODBCDB2Test::dropObject(const std::string& type, const std::string& name)
void ODBCDB2Test::recreateNullableTable() void ODBCDB2Test::recreateNullableTable()
{ {
dropObject("TABLE", "NullableTest"); dropObject("TABLE", ExecUtil::nullabletest());
try { *_pSession << "CREATE TABLE NullableTest (EmptyString VARCHAR(30) NULL, EmptyInteger INTEGER NULL, EmptyFloat FLOAT NULL , EmptyDateTime TIMESTAMP NULL)", now; } try { session() << "CREATE TABLE " << ExecUtil::nullabletest() << " (EmptyString VARCHAR(30), EmptyInteger INTEGER , EmptyFloat FLOAT , EmptyDateTime TIMESTAMP)", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonTable()"); }
} }
void ODBCDB2Test::recreateNumericTable()
{
dropObject("TABLE", ExecUtil::numeric_tbl());
try {
session() << "CREATE TABLE " << ExecUtil::numeric_tbl() <<
" (id integer, num8 NUMERIC(8), num16_3 NUMERIC(16,3), num18 NUMERIC(18), num18_8 NUMERIC(18,8), num22 NUMERIC(22))", now;
}
catch (ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail("recreateNumericTable()"); }
catch (StatementException& se){ std::cout << se.toString() << std::endl; fail("recreateNumericTable()"); }
}
void ODBCDB2Test::recreatePersonTable() void ODBCDB2Test::recreatePersonTable()
{ {
dropObject("TABLE", "Person"); dropObject("TABLE", ExecUtil::person());
try { *_pSession << "CREATE TABLE Person (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), Age INTEGER)", now; } try { session() << "CREATE TABLE " << ExecUtil::person() <<" (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), Age INTEGER)", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonTable()"); }
} }
@ -441,8 +601,8 @@ void ODBCDB2Test::recreatePersonTable()
void ODBCDB2Test::recreatePersonBLOBTable() void ODBCDB2Test::recreatePersonBLOBTable()
{ {
dropObject("TABLE", "Person"); dropObject("TABLE", ExecUtil::person());
try { *_pSession << "CREATE TABLE Person (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), Image BLOB)", now; } try { session() << "CREATE TABLE " << ExecUtil::person() <<" (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), Image BLOB)", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonBLOBTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonBLOBTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonBLOBTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonBLOBTable()"); }
} }
@ -450,8 +610,8 @@ void ODBCDB2Test::recreatePersonBLOBTable()
void ODBCDB2Test::recreatePersonDateTable() void ODBCDB2Test::recreatePersonDateTable()
{ {
dropObject("TABLE", "Person"); dropObject("TABLE", ExecUtil::person());
try { *_pSession << "CREATE TABLE Person (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), BornDate DATE)", now; } try { session() << "CREATE TABLE " << ExecUtil::person() <<" (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), BornDate DATE)", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonDateTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonDateTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonDateTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonDateTable()"); }
} }
@ -459,8 +619,8 @@ void ODBCDB2Test::recreatePersonDateTable()
void ODBCDB2Test::recreatePersonTimeTable() void ODBCDB2Test::recreatePersonTimeTable()
{ {
dropObject("TABLE", "Person"); dropObject("TABLE", ExecUtil::person());
try { *_pSession << "CREATE TABLE Person (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), BornTime TIME)", now; } try { session() << "CREATE TABLE " << ExecUtil::person() <<" (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), BornTime TIME)", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonTimeTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonTimeTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonTimeTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonTimeTable()"); }
} }
@ -468,8 +628,8 @@ void ODBCDB2Test::recreatePersonTimeTable()
void ODBCDB2Test::recreatePersonDateTimeTable() void ODBCDB2Test::recreatePersonDateTimeTable()
{ {
dropObject("TABLE", "Person"); dropObject("TABLE", ExecUtil::person());
try { *_pSession << "CREATE TABLE Person (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), Born TIMESTAMP)", now; } try { session() << "CREATE TABLE " << ExecUtil::person() <<" (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), Born TIMESTAMP)", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonDateTimeTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonDateTimeTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonDateTimeTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonDateTimeTable()"); }
} }
@ -477,8 +637,8 @@ void ODBCDB2Test::recreatePersonDateTimeTable()
void ODBCDB2Test::recreateIntsTable() void ODBCDB2Test::recreateIntsTable()
{ {
dropObject("TABLE", "Strings"); dropObject("TABLE", ExecUtil::strings());
try { *_pSession << "CREATE TABLE Strings (str INTEGER)", now; } try { session() << "CREATE TABLE " << ExecUtil::strings() << " (str INTEGER)", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateIntsTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateIntsTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateIntsTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateIntsTable()"); }
} }
@ -486,8 +646,8 @@ void ODBCDB2Test::recreateIntsTable()
void ODBCDB2Test::recreateStringsTable() void ODBCDB2Test::recreateStringsTable()
{ {
dropObject("TABLE", "Strings"); dropObject("TABLE", ExecUtil::strings());
try { *_pSession << "CREATE TABLE Strings (str VARCHAR(30))", now; } try { session() << "CREATE TABLE " << ExecUtil::strings() << " (str VARCHAR(30))", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateStringsTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateStringsTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateStringsTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateStringsTable()"); }
} }
@ -495,8 +655,8 @@ void ODBCDB2Test::recreateStringsTable()
void ODBCDB2Test::recreateFloatsTable() void ODBCDB2Test::recreateFloatsTable()
{ {
dropObject("TABLE", "Strings"); dropObject("TABLE", ExecUtil::strings());
try { *_pSession << "CREATE TABLE Strings (str FLOAT)", now; } try { session() << "CREATE TABLE " << ExecUtil::strings() << " (str FLOAT)", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateFloatsTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateFloatsTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateFloatsTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateFloatsTable()"); }
} }
@ -504,8 +664,8 @@ void ODBCDB2Test::recreateFloatsTable()
void ODBCDB2Test::recreateTuplesTable() void ODBCDB2Test::recreateTuplesTable()
{ {
dropObject("TABLE", "Tuples"); dropObject("TABLE", ExecUtil::tuples());
try { *_pSession << "CREATE TABLE Tuples " try { session() << "CREATE TABLE " << ExecUtil::tuples() <<
"(int0 INTEGER, int1 INTEGER, int2 INTEGER, int3 INTEGER, int4 INTEGER, int5 INTEGER, int6 INTEGER, " "(int0 INTEGER, int1 INTEGER, int2 INTEGER, int3 INTEGER, int4 INTEGER, int5 INTEGER, int6 INTEGER, "
"int7 INTEGER, int8 INTEGER, int9 INTEGER, int10 INTEGER, int11 INTEGER, int12 INTEGER, int13 INTEGER," "int7 INTEGER, int8 INTEGER, int9 INTEGER, int10 INTEGER, int11 INTEGER, int12 INTEGER, int13 INTEGER,"
"int14 INTEGER, int15 INTEGER, int16 INTEGER, int17 INTEGER, int18 INTEGER, int19 INTEGER)", now; } "int14 INTEGER, int15 INTEGER, int16 INTEGER, int17 INTEGER, int18 INTEGER, int19 INTEGER)", now; }
@ -516,8 +676,8 @@ void ODBCDB2Test::recreateTuplesTable()
void ODBCDB2Test::recreateVectorsTable() void ODBCDB2Test::recreateVectorsTable()
{ {
dropObject("TABLE", "Vectors"); dropObject("TABLE", ExecUtil::vectors());
try { *_pSession << "CREATE TABLE Vectors (i0 INTEGER, flt0 FLOAT, str0 VARCHAR(30))", now; } try { session() << "CREATE TABLE " << ExecUtil::vectors() << " (i0 INTEGER, flt0 FLOAT, str0 VARCHAR(30))", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateVectorsTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateVectorsTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateVectorsTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateVectorsTable()"); }
} }
@ -525,8 +685,8 @@ void ODBCDB2Test::recreateVectorsTable()
void ODBCDB2Test::recreateAnysTable() void ODBCDB2Test::recreateAnysTable()
{ {
dropObject("TABLE", "Anys"); dropObject("TABLE", ExecUtil::anys() );
try { *_pSession << "CREATE TABLE Anys (i0 INTEGER, flt0 FLOAT, str0 VARCHAR(30))", now; } try { session() << "CREATE TABLE " << ExecUtil::anys() << " (i0 INTEGER, flt0 FLOAT, str0 VARCHAR(30))", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateAnysTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateAnysTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateAnysTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateAnysTable()"); }
} }
@ -534,8 +694,8 @@ void ODBCDB2Test::recreateAnysTable()
void ODBCDB2Test::recreateNullsTable(const std::string& notNull) void ODBCDB2Test::recreateNullsTable(const std::string& notNull)
{ {
dropObject("TABLE", "NullTest"); dropObject("TABLE", ExecUtil::nulltest());
try { *_pSession << format("CREATE TABLE NullTest (i INTEGER %s, r FLOAT %s, v VARCHAR(30) %s)", try { session() << format("CREATE TABLE %s (i INTEGER %s, r FLOAT %s, v VARCHAR(30) %s)", ExecUtil::nulltest(),
notNull, notNull,
notNull, notNull,
notNull), now; } notNull), now; }
@ -546,10 +706,10 @@ void ODBCDB2Test::recreateNullsTable(const std::string& notNull)
void ODBCDB2Test::recreateMiscTable() void ODBCDB2Test::recreateMiscTable()
{ {
dropObject("TABLE", "MiscTest"); dropObject("TABLE", ExecUtil::misctest());
try try
{ {
session() << "CREATE TABLE MiscTest " session() << "CREATE TABLE " << ExecUtil::misctest() <<
"(First VARCHAR(30)," "(First VARCHAR(30),"
"Second BLOB," "Second BLOB,"
"Third INTEGER," "Third INTEGER,"
@ -562,8 +722,8 @@ void ODBCDB2Test::recreateMiscTable()
void ODBCDB2Test::recreateLogTable() void ODBCDB2Test::recreateLogTable()
{ {
dropObject("TABLE", "T_POCO_LOG"); dropObject("TABLE", ExecUtil::pocolog());;
dropObject("TABLE", "T_POCO_LOG_ARCHIVE"); dropObject("TABLE", ExecUtil::pocolog_a());;
try try
{ {
@ -577,8 +737,8 @@ void ODBCDB2Test::recreateLogTable()
"Text VARCHAR(100)," "Text VARCHAR(100),"
"DateTime TIMESTAMP)"; "DateTime TIMESTAMP)";
session() << sql, "T_POCO_LOG", now; session() << sql, ExecUtil::pocolog(), now;
session() << sql, "T_POCO_LOG_ARCHIVE", now; session() << sql, ExecUtil::pocolog_a(), now;
} catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateLogTable()"); } } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateLogTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateLogTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateLogTable()"); }
@ -597,6 +757,7 @@ CppUnit::Test* ODBCDB2Test::suite()
CppUnit_addTest(pSuite, ODBCDB2Test, testBareboneODBC); CppUnit_addTest(pSuite, ODBCDB2Test, testBareboneODBC);
CppUnit_addTest(pSuite, ODBCDB2Test, testZeroRows); CppUnit_addTest(pSuite, ODBCDB2Test, testZeroRows);
CppUnit_addTest(pSuite, ODBCDB2Test, testSyntaxError);
CppUnit_addTest(pSuite, ODBCDB2Test, testSimpleAccess); CppUnit_addTest(pSuite, ODBCDB2Test, testSimpleAccess);
CppUnit_addTest(pSuite, ODBCDB2Test, testComplexType); CppUnit_addTest(pSuite, ODBCDB2Test, testComplexType);
CppUnit_addTest(pSuite, ODBCDB2Test, testSimpleAccessVector); CppUnit_addTest(pSuite, ODBCDB2Test, testSimpleAccessVector);
@ -666,13 +827,20 @@ CppUnit::Test* ODBCDB2Test::suite()
CppUnit_addTest(pSuite, ODBCDB2Test, testAny); CppUnit_addTest(pSuite, ODBCDB2Test, testAny);
CppUnit_addTest(pSuite, ODBCDB2Test, testDynamicAny); CppUnit_addTest(pSuite, ODBCDB2Test, testDynamicAny);
CppUnit_addTest(pSuite, ODBCDB2Test, testMultipleResults); CppUnit_addTest(pSuite, ODBCDB2Test, testMultipleResults);
CppUnit_addTest(pSuite, ODBCDB2Test, testMultipleResultsNoProj);
CppUnit_addTest(pSuite, ODBCDB2Test, testSQLChannel); CppUnit_addTest(pSuite, ODBCDB2Test, testSQLChannel);
CppUnit_addTest(pSuite, ODBCDB2Test, testSQLLogger); CppUnit_addTest(pSuite, ODBCDB2Test, testSQLLogger);
CppUnit_addTest(pSuite, ODBCDB2Test, testSessionTransaction); //CppUnit_addTest(pSuite, ODBCDB2Test, testSessionTransaction); // this test fails when connection is fast
CppUnit_addTest(pSuite, ODBCDB2Test, testTransaction); CppUnit_addTest(pSuite, ODBCDB2Test, testTransaction);
CppUnit_addTest(pSuite, ODBCDB2Test, testTransactor); CppUnit_addTest(pSuite, ODBCDB2Test, testTransactor);
CppUnit_addTest(pSuite, ODBCDB2Test, testNullable); CppUnit_addTest(pSuite, ODBCDB2Test, testNullable);
CppUnit_addTest(pSuite, ODBCDB2Test, testReconnect); CppUnit_addTest(pSuite, ODBCDB2Test, testReconnect);
CppUnit_addTest(pSuite, ODBCDB2Test, testNumeric);
CppUnit_addTest(pSuite, ODBCDB2Test, testXMLColumn);
CppUnit_addTest(pSuite, ODBCDB2Test, testInsertStatReuse);
ODBCDB2Test::_pExecutor = 0;
ODBCDB2Test::_pSession = 0;
return pSuite; return pSuite;
} }

View File

@ -41,6 +41,7 @@ public:
void testStoredProcedureAny(); void testStoredProcedureAny();
void testStoredProcedureDynamicAny(); void testStoredProcedureDynamicAny();
void testStoredFunction(); void testStoredFunction();
void testXMLColumn();
static CppUnit::Test* suite(); static CppUnit::Test* suite();
@ -61,6 +62,7 @@ private:
void recreateNullsTable(const std::string& notNull = ""); void recreateNullsTable(const std::string& notNull = "");
void recreateMiscTable(); void recreateMiscTable();
void recreateLogTable(); void recreateLogTable();
void recreateNumericTable();
static ODBCTest::SessionPtr _pSession; static ODBCTest::SessionPtr _pSession;
static ODBCTest::ExecPtr _pExecutor; static ODBCTest::ExecPtr _pExecutor;

View File

@ -77,7 +77,7 @@ void ODBCMySQLTest::testBareboneODBC()
{ {
if (!_pSession) fail ("Test not available."); if (!_pSession) fail ("Test not available.");
std::string tableCreateString = "CREATE TABLE Test " std::string tableCreateString = "CREATE TABLE " + ExecUtil::test_tbl() +
"(First VARCHAR(30)," "(First VARCHAR(30),"
"Second VARCHAR(30)," "Second VARCHAR(30),"
"Third VARBINARY(30)," "Third VARBINARY(30),"
@ -97,7 +97,7 @@ has different SQL syntax for it and behaves differently
compared to other DBMS systems in regards to SQLMoreResults. compared to other DBMS systems in regards to SQLMoreResults.
So, we skip this test. So, we skip this test.
tableCreateString = "CREATE TABLE Test " tableCreateString = "CREATE TABLE " + ExecUtil::test_tbl() +
"(First VARCHAR(30)," "(First VARCHAR(30),"
"Second INTEGER," "Second INTEGER,"
"Third FLOAT)"; "Third FLOAT)";
@ -236,7 +236,7 @@ void ODBCMySQLTest::testFilter()
recreateVectorsTable(); recreateVectorsTable();
_pSession->setFeature("autoBind", bindValue(i)); _pSession->setFeature("autoBind", bindValue(i));
_pSession->setFeature("autoExtract", bindValue(i+1)); _pSession->setFeature("autoExtract", bindValue(i+1));
_pExecutor->filter("SELECT * FROM Vectors ORDER BY i0 ASC", "i0"); _pExecutor->filter("SELECT * FROM " + ExecUtil::vectors() + " ORDER BY i0 ASC", "i0");
i += 2; i += 2;
} }
} }
@ -250,8 +250,8 @@ void ODBCMySQLTest::dropObject(const std::string& type, const std::string& name)
void ODBCMySQLTest::recreateNullableTable() void ODBCMySQLTest::recreateNullableTable()
{ {
dropObject("TABLE", "NullableTest"); dropObject("TABLE", ExecUtil::nullabletest());
try { *_pSession << "CREATE TABLE NullableTest (EmptyString VARCHAR(30) NULL, EmptyInteger INTEGER NULL, EmptyFloat FLOAT NULL , EmptyDateTime TIMESTAMP NULL)", now; } try { *_pSession << "CREATE TABLE " << ExecUtil::nullabletest() << " (EmptyString VARCHAR(30) NULL, EmptyInteger INTEGER NULL, EmptyFloat FLOAT NULL , EmptyDateTime TIMESTAMP NULL)", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonTable()"); }
} }
@ -259,8 +259,8 @@ void ODBCMySQLTest::recreateNullableTable()
void ODBCMySQLTest::recreatePersonTable() void ODBCMySQLTest::recreatePersonTable()
{ {
dropObject("TABLE", "Person"); dropObject("TABLE", ExecUtil::person());
try { *_pSession << "CREATE TABLE Person (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), Age INTEGER)", now; } try { *_pSession << "CREATE TABLE " << ExecUtil::person() << " (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), Age INTEGER)", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonTable()"); }
} }
@ -268,8 +268,8 @@ void ODBCMySQLTest::recreatePersonTable()
void ODBCMySQLTest::recreatePersonBLOBTable() void ODBCMySQLTest::recreatePersonBLOBTable()
{ {
dropObject("TABLE", "Person"); dropObject("TABLE", ExecUtil::person());
try { *_pSession << "CREATE TABLE Person (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), Image BLOB)", now; } try { *_pSession << "CREATE TABLE " << ExecUtil::person() << " (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), Image BLOB)", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonBLOBTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonBLOBTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonBLOBTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonBLOBTable()"); }
} }
@ -277,8 +277,8 @@ void ODBCMySQLTest::recreatePersonBLOBTable()
void ODBCMySQLTest::recreatePersonDateTable() void ODBCMySQLTest::recreatePersonDateTable()
{ {
dropObject("TABLE", "Person"); dropObject("TABLE", ExecUtil::person());
try { *_pSession << "CREATE TABLE Person (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), BornDate DATE)", now; } try { *_pSession << "CREATE TABLE " << ExecUtil::person() << " (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), BornDate DATE)", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonDateTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonDateTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonDateTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonDateTable()"); }
} }
@ -286,8 +286,8 @@ void ODBCMySQLTest::recreatePersonDateTable()
void ODBCMySQLTest::recreatePersonTimeTable() void ODBCMySQLTest::recreatePersonTimeTable()
{ {
dropObject("TABLE", "Person"); dropObject("TABLE", ExecUtil::person());
try { *_pSession << "CREATE TABLE Person (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), BornTime TIME)", now; } try { *_pSession << "CREATE TABLE " << ExecUtil::person() << " (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), BornTime TIME)", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonTimeTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonTimeTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonTimeTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonTimeTable()"); }
} }
@ -295,8 +295,8 @@ void ODBCMySQLTest::recreatePersonTimeTable()
void ODBCMySQLTest::recreatePersonDateTimeTable() void ODBCMySQLTest::recreatePersonDateTimeTable()
{ {
dropObject("TABLE", "Person"); dropObject("TABLE", ExecUtil::person());
try { *_pSession << "CREATE TABLE Person (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), Born DATETIME)", now; } try { *_pSession << "CREATE TABLE " << ExecUtil::person() << " (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), Born DATETIME)", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonDateTimeTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonDateTimeTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonDateTimeTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonDateTimeTable()"); }
} }
@ -304,8 +304,8 @@ void ODBCMySQLTest::recreatePersonDateTimeTable()
void ODBCMySQLTest::recreateIntsTable() void ODBCMySQLTest::recreateIntsTable()
{ {
dropObject("TABLE", "Strings"); dropObject("TABLE", ExecUtil::strings());
try { *_pSession << "CREATE TABLE Strings (str INTEGER)", now; } try { *_pSession << "CREATE TABLE " << ExecUtil::strings() << " (str INTEGER)", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateIntsTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateIntsTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateIntsTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateIntsTable()"); }
} }
@ -313,8 +313,8 @@ void ODBCMySQLTest::recreateIntsTable()
void ODBCMySQLTest::recreateStringsTable() void ODBCMySQLTest::recreateStringsTable()
{ {
dropObject("TABLE", "Strings"); dropObject("TABLE", ExecUtil::strings());
try { *_pSession << "CREATE TABLE Strings (str VARCHAR(30))", now; } try { *_pSession << "CREATE TABLE " << ExecUtil::strings() << " (str VARCHAR(30))", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateStringsTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateStringsTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateStringsTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateStringsTable()"); }
} }
@ -322,8 +322,8 @@ void ODBCMySQLTest::recreateStringsTable()
void ODBCMySQLTest::recreateFloatsTable() void ODBCMySQLTest::recreateFloatsTable()
{ {
dropObject("TABLE", "Strings"); dropObject("TABLE", ExecUtil::strings());
try { *_pSession << "CREATE TABLE Strings (str FLOAT)", now; } try { *_pSession << "CREATE TABLE " << ExecUtil::person() << " (str FLOAT)", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateFloatsTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateFloatsTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateFloatsTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateFloatsTable()"); }
} }
@ -331,8 +331,8 @@ void ODBCMySQLTest::recreateFloatsTable()
void ODBCMySQLTest::recreateTuplesTable() void ODBCMySQLTest::recreateTuplesTable()
{ {
dropObject("TABLE", "Tuples"); dropObject("TABLE", ExecUtil::tuples());
try { *_pSession << "CREATE TABLE Tuples " try { *_pSession << "CREATE TABLE " << ExecUtil::tuples() <<
"(i0 INTEGER, i1 INTEGER, i2 INTEGER, i3 INTEGER, i4 INTEGER, i5 INTEGER, i6 INTEGER, " "(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," "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; } "i14 INTEGER, i15 INTEGER, i16 INTEGER, i17 INTEGER, i18 INTEGER, i19 INTEGER)", now; }
@ -343,8 +343,8 @@ void ODBCMySQLTest::recreateTuplesTable()
void ODBCMySQLTest::recreateVectorsTable() void ODBCMySQLTest::recreateVectorsTable()
{ {
dropObject("TABLE", "Vectors"); dropObject("TABLE", ExecUtil::vectors() );
try { *_pSession << "CREATE TABLE Vectors (i0 INTEGER, flt0 FLOAT, str0 VARCHAR(30))", now; } try { *_pSession << "CREATE TABLE " << ExecUtil::vectors() << " (i0 INTEGER, flt0 FLOAT, str0 VARCHAR(30))", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateVectorsTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateVectorsTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateVectorsTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateVectorsTable()"); }
} }
@ -352,8 +352,8 @@ void ODBCMySQLTest::recreateVectorsTable()
void ODBCMySQLTest::recreateAnysTable() void ODBCMySQLTest::recreateAnysTable()
{ {
dropObject("TABLE", "Anys"); dropObject("TABLE", ExecUtil::anys() );
try { *_pSession << "CREATE TABLE Anys (i0 INTEGER, flt0 DOUBLE, str0 VARCHAR(30))", now; } try { *_pSession << "CREATE TABLE " << ExecUtil::anys() << " (i0 INTEGER, flt0 DOUBLE, str0 VARCHAR(30))", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateAnysTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateAnysTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateAnysTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateAnysTable()"); }
} }
@ -361,8 +361,8 @@ void ODBCMySQLTest::recreateAnysTable()
void ODBCMySQLTest::recreateNullsTable(const std::string& notNull) void ODBCMySQLTest::recreateNullsTable(const std::string& notNull)
{ {
dropObject("TABLE", "NullTest"); dropObject("TABLE", ExecUtil::nulltest());
try { *_pSession << format("CREATE TABLE NullTest (i INTEGER %s, r FLOAT %s, v VARCHAR(30) %s)", try { *_pSession << format("CREATE TABLE %s (i INTEGER %s, r FLOAT %s, v VARCHAR(30) %s)", ExecUtil::nulltest(),
notNull, notNull,
notNull, notNull,
notNull), now; } notNull), now; }
@ -373,8 +373,8 @@ void ODBCMySQLTest::recreateNullsTable(const std::string& notNull)
void ODBCMySQLTest::recreateMiscTable() void ODBCMySQLTest::recreateMiscTable()
{ {
dropObject("TABLE", "MiscTest"); dropObject("TABLE", ExecUtil::misctest());
try { *_pSession << "CREATE TABLE MiscTest " try { *_pSession << "CREATE TABLE "<< ExecUtil::misctest() <<
"(First VARCHAR(30)," "(First VARCHAR(30),"
"Second VARBINARY(30)," "Second VARBINARY(30),"
"Third INTEGER," "Third INTEGER,"
@ -387,8 +387,8 @@ void ODBCMySQLTest::recreateMiscTable()
void ODBCMySQLTest::recreateLogTable() void ODBCMySQLTest::recreateLogTable()
{ {
dropObject("TABLE", "T_POCO_LOG"); dropObject("TABLE", ExecUtil::pocolog());;
dropObject("TABLE", "T_POCO_LOG_ARCHIVE"); dropObject("TABLE", ExecUtil::pocolog_a());;
try try
{ {
@ -402,8 +402,8 @@ void ODBCMySQLTest::recreateLogTable()
"Text VARCHAR(100)," "Text VARCHAR(100),"
"DateTime DATETIME)"; "DateTime DATETIME)";
session() << sql, "T_POCO_LOG", now; session() << sql, ExecUtil::pocolog(), now;
session() << sql, "T_POCO_LOG_ARCHIVE", now; session() << sql, ExecUtil::pocolog_a(), now;
} catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateLogTable()"); } } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateLogTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateLogTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateLogTable()"); }
@ -422,6 +422,7 @@ CppUnit::Test* ODBCMySQLTest::suite()
CppUnit_addTest(pSuite, ODBCMySQLTest, testBareboneODBC); CppUnit_addTest(pSuite, ODBCMySQLTest, testBareboneODBC);
CppUnit_addTest(pSuite, ODBCMySQLTest, testZeroRows); CppUnit_addTest(pSuite, ODBCMySQLTest, testZeroRows);
CppUnit_addTest(pSuite, ODBCMySQLTest, testSyntaxError);
CppUnit_addTest(pSuite, ODBCMySQLTest, testSimpleAccess); CppUnit_addTest(pSuite, ODBCMySQLTest, testSimpleAccess);
CppUnit_addTest(pSuite, ODBCMySQLTest, testComplexType); CppUnit_addTest(pSuite, ODBCMySQLTest, testComplexType);
CppUnit_addTest(pSuite, ODBCMySQLTest, testSimpleAccessVector); CppUnit_addTest(pSuite, ODBCMySQLTest, testSimpleAccessVector);

View File

@ -85,11 +85,11 @@ std::string ODBCOracleTest::_connectString = "DRIVER={" ORACLE_ODBC_DRI
const std::string ODBCOracleTest::MULTI_INSERT = const std::string ODBCOracleTest::MULTI_INSERT =
"BEGIN " "BEGIN "
"INSERT INTO Test VALUES ('1', 2, 3.5);" "INSERT INTO " + ExecUtil::test_tbl() + " VALUES ('1', 2, 3.5);"
"INSERT INTO Test VALUES ('2', 3, 4.5);" "INSERT INTO " + ExecUtil::test_tbl() + " VALUES ('2', 3, 4.5);"
"INSERT INTO Test VALUES ('3', 4, 5.5);" "INSERT INTO " + ExecUtil::test_tbl() + " VALUES ('3', 4, 5.5);"
"INSERT INTO Test VALUES ('4', 5, 6.5);" "INSERT INTO " + ExecUtil::test_tbl() + " VALUES ('4', 5, 6.5);"
"INSERT INTO Test VALUES ('5', 6, 7.5);" "INSERT INTO " + ExecUtil::test_tbl() + " VALUES ('5', 6, 7.5);"
"END;"; "END;";
const std::string ODBCOracleTest::MULTI_SELECT = const std::string ODBCOracleTest::MULTI_SELECT =
@ -109,7 +109,7 @@ ODBCOracleTest::~ODBCOracleTest()
void ODBCOracleTest::testBarebone() void ODBCOracleTest::testBarebone()
{ {
std::string tableCreateString = "CREATE TABLE Test " std::string tableCreateString = "CREATE TABLE " + ExecUtil::test_tbl() +
"(First VARCHAR(30)," "(First VARCHAR(30),"
"Second VARCHAR(30)," "Second VARCHAR(30),"
"Third BLOB," "Third BLOB,"
@ -122,7 +122,7 @@ void ODBCOracleTest::testBarebone()
_pExecutor->bareboneODBCTest(_connectString, tableCreateString, SQLExecutor::PB_AT_EXEC, SQLExecutor::DE_MANUAL); _pExecutor->bareboneODBCTest(_connectString, tableCreateString, SQLExecutor::PB_AT_EXEC, SQLExecutor::DE_MANUAL);
_pExecutor->bareboneODBCTest(_connectString, tableCreateString, SQLExecutor::PB_AT_EXEC, SQLExecutor::DE_BOUND); _pExecutor->bareboneODBCTest(_connectString, tableCreateString, SQLExecutor::PB_AT_EXEC, SQLExecutor::DE_BOUND);
tableCreateString = "CREATE TABLE Test " tableCreateString = "CREATE TABLE " + ExecUtil::test_tbl() +
"(First VARCHAR(30)," "(First VARCHAR(30),"
"Second INTEGER," "Second INTEGER,"
"Third NUMBER)"; "Third NUMBER)";
@ -134,11 +134,11 @@ void ODBCOracleTest::testBarebone()
"ret4 OUT SYS_REFCURSOR," "ret4 OUT SYS_REFCURSOR,"
"ret5 OUT SYS_REFCURSOR) IS " "ret5 OUT SYS_REFCURSOR) IS "
"BEGIN " "BEGIN "
"OPEN ret1 FOR SELECT * FROM Test WHERE First = '1';" "OPEN ret1 FOR SELECT * FROM " + ExecUtil::test_tbl() + " WHERE First = '1';"
"OPEN ret2 FOR SELECT * FROM Test WHERE First = '2';" "OPEN ret2 FOR SELECT * FROM " + ExecUtil::test_tbl() + " WHERE First = '2';"
"OPEN ret3 FOR SELECT * FROM Test WHERE First = '3';" "OPEN ret3 FOR SELECT * FROM " + ExecUtil::test_tbl() + " WHERE First = '3';"
"OPEN ret4 FOR SELECT * FROM Test WHERE First = '4';" "OPEN ret4 FOR SELECT * FROM " + ExecUtil::test_tbl() + " WHERE First = '4';"
"OPEN ret5 FOR SELECT * FROM Test WHERE First = '5';" "OPEN ret5 FOR SELECT * FROM " + ExecUtil::test_tbl() + " WHERE First = '5';"
"END multiResultsProcedure;" , now; "END multiResultsProcedure;" , now;
_pExecutor->bareboneODBCMultiResultTest(_connectString, _pExecutor->bareboneODBCMultiResultTest(_connectString,
@ -385,14 +385,14 @@ void ODBCOracleTest::testCursorStoredProcedure()
people.push_back(Person("Simpson", "Homer", "Springfield", 42)); people.push_back(Person("Simpson", "Homer", "Springfield", 42));
people.push_back(Person("Simpson", "Bart", "Springfield", 12)); people.push_back(Person("Simpson", "Bart", "Springfield", 12));
people.push_back(Person("Simpson", "Lisa", "Springfield", 10)); people.push_back(Person("Simpson", "Lisa", "Springfield", 10));
*_pSession << "INSERT INTO Person VALUES (?, ?, ?, ?)", use(people), now; *_pSession << "INSERT INTO " << ExecUtil::person() << " VALUES (?, ?, ?, ?)", use(people), now;
*_pSession << "CREATE OR REPLACE " *_pSession << "CREATE OR REPLACE "
"PROCEDURE storedCursorProcedure(ret OUT SYS_REFCURSOR, ageLimit IN NUMBER) IS " "PROCEDURE storedCursorProcedure(ret OUT SYS_REFCURSOR, ageLimit IN NUMBER) IS "
" BEGIN " " BEGIN "
" OPEN ret FOR " " OPEN ret FOR "
" SELECT * " " SELECT * "
" FROM Person " " FROM " << ExecUtil::person() <<
" WHERE Age < ageLimit " " WHERE Age < ageLimit "
" ORDER BY Age DESC; " " ORDER BY Age DESC; "
" END storedCursorProcedure;" , now; " END storedCursorProcedure;" , now;
@ -413,7 +413,7 @@ void ODBCOracleTest::testCursorStoredProcedure()
assert (rs["Address"] == "Springfield"); assert (rs["Address"] == "Springfield");
assert (rs["Age"] == 12); assert (rs["Age"] == 12);
dropObject("TABLE", "Person"); dropObject("TABLE", ExecUtil::person());
dropObject("PROCEDURE", "storedCursorProcedure"); dropObject("PROCEDURE", "storedCursorProcedure");
k += 2; k += 2;
@ -523,7 +523,7 @@ void ODBCOracleTest::testCursorStoredFunction()
people.push_back(Person("Simpson", "Homer", "Springfield", 42)); people.push_back(Person("Simpson", "Homer", "Springfield", 42));
people.push_back(Person("Simpson", "Bart", "Springfield", 12)); people.push_back(Person("Simpson", "Bart", "Springfield", 12));
people.push_back(Person("Simpson", "Lisa", "Springfield", 10)); people.push_back(Person("Simpson", "Lisa", "Springfield", 10));
*_pSession << "INSERT INTO Person VALUES (?, ?, ?, ?)", use(people), now; *_pSession << "INSERT INTO " << ExecUtil::person() << " VALUES (?, ?, ?, ?)", use(people), now;
*_pSession << "CREATE OR REPLACE " *_pSession << "CREATE OR REPLACE "
"FUNCTION storedCursorFunction(ageLimit IN NUMBER) RETURN SYS_REFCURSOR IS " "FUNCTION storedCursorFunction(ageLimit IN NUMBER) RETURN SYS_REFCURSOR IS "
@ -531,7 +531,7 @@ void ODBCOracleTest::testCursorStoredFunction()
" BEGIN " " BEGIN "
" OPEN ret FOR " " OPEN ret FOR "
" SELECT * " " SELECT * "
" FROM Person " " FROM " << ExecUtil::person() <<
" WHERE Age < ageLimit " " WHERE Age < ageLimit "
" ORDER BY Age DESC; " " ORDER BY Age DESC; "
" RETURN ret; " " RETURN ret; "
@ -553,7 +553,7 @@ void ODBCOracleTest::testCursorStoredFunction()
assert (rs["Address"] == "Springfield"); assert (rs["Address"] == "Springfield");
assert (rs["Age"] == 12); assert (rs["Age"] == 12);
dropObject("TABLE", "Person"); dropObject("TABLE", ExecUtil::person());
dropObject("FUNCTION", "storedCursorFunction"); dropObject("FUNCTION", "storedCursorFunction");
k += 2; k += 2;
@ -571,9 +571,9 @@ void ODBCOracleTest::testMultipleResults()
" ret2 OUT SYS_REFCURSOR," " ret2 OUT SYS_REFCURSOR,"
" ret3 OUT SYS_REFCURSOR) IS " " ret3 OUT SYS_REFCURSOR) IS "
"BEGIN " "BEGIN "
" OPEN ret1 FOR SELECT * FROM Person WHERE Age = paramAge1;" " OPEN ret1 FOR SELECT * FROM " + ExecUtil::person() + " WHERE Age = paramAge1;"
" OPEN ret2 FOR SELECT Age FROM Person WHERE FirstName = 'Bart';" " OPEN ret2 FOR SELECT Age FROM " + ExecUtil::person() + " WHERE FirstName = 'Bart';"
" OPEN ret3 FOR SELECT * FROM Person WHERE Age = paramAge2 OR Age = paramAge3 ORDER BY Age;" " OPEN ret3 FOR SELECT * FROM " + ExecUtil::person() + " WHERE Age = paramAge2 OR Age = paramAge3 ORDER BY Age;"
"END multiResultsProcedure;"; "END multiResultsProcedure;";
for (int i = 0; i < 8;) for (int i = 0; i < 8;)
@ -598,18 +598,18 @@ void ODBCOracleTest::testAutoTransaction()
recreateIntsTable(); recreateIntsTable();
session().setFeature("autoCommit", true); session().setFeature("autoCommit", true);
session() << "INSERT INTO Strings VALUES (1)", now; session() << "INSERT INTO " << ExecUtil::strings() << " VALUES (1)", now;
localSession << "SELECT count(*) FROM Strings", into(count), now; localSession << "SELECT count(*) FROM " << ExecUtil::person() , into(count), now;
assert (1 == count); assert (1 == count);
session() << "INSERT INTO Strings VALUES (2)", now; session() << "INSERT INTO " << ExecUtil::strings() << " VALUES (2)", now;
localSession << "SELECT count(*) FROM Strings", into(count), now; localSession << "SELECT count(*) FROM " << ExecUtil::strings(), into(count), now;
assert (2 == count); assert (2 == count);
session() << "INSERT INTO Strings VALUES (3)", now; session() << "INSERT INTO " << ExecUtil::strings() << " VALUES (3)", now;
localSession << "SELECT count(*) FROM Strings", into(count), now; localSession << "SELECT count(*) FROM " << ExecUtil::strings(), into(count), now;
assert (3 == count); assert (3 == count);
session() << "DELETE FROM Strings", now; session() << "DELETE FROM " << ExecUtil::strings(), now;
localSession << "SELECT count(*) FROM Strings", into(count), now; localSession << "SELECT count(*) FROM " << ExecUtil::strings(), into(count), now;
assert (0 == count); assert (0 == count);
session().setFeature("autoCommit", false); session().setFeature("autoCommit", false);
@ -617,26 +617,26 @@ void ODBCOracleTest::testAutoTransaction()
try try
{ {
AutoTransaction at(session()); AutoTransaction at(session());
session() << "INSERT INTO Strings VALUES (1)", now; session() << "INSERT INTO " << ExecUtil::strings() << " VALUES (1)", now;
session() << "INSERT INTO Strings VALUES (2)", now; session() << "INSERT INTO " << ExecUtil::strings() << " VALUES (2)", now;
session() << "BAD QUERY", now; session() << "BAD QUERY", now;
} catch (Poco::Exception&) {} } catch (Poco::Exception&) {}
session() << "SELECT count(*) FROM Strings", into(count), now; session() << "SELECT count(*) FROM " << ExecUtil::strings(), into(count), now;
assert (0 == count); assert (0 == count);
AutoTransaction at(session()); AutoTransaction at(session());
session() << "INSERT INTO Strings VALUES (1)", now; session() << "INSERT INTO " << ExecUtil::strings() << " VALUES (1)", now;
session() << "INSERT INTO Strings VALUES (2)", now; session() << "INSERT INTO " << ExecUtil::strings() << " VALUES (2)", now;
session() << "INSERT INTO Strings VALUES (3)", now; session() << "INSERT INTO " << ExecUtil::strings() << " VALUES (3)", now;
localSession << "SELECT count(*) FROM Strings", into(count), now; localSession << "SELECT count(*) FROM " << ExecUtil::strings(), into(count), now;
assert (0 == count); assert (0 == count);
at.commit(); at.commit();
localSession << "SELECT count(*) FROM Strings", into(count), now; localSession << "SELECT count(*) FROM " << ExecUtil::strings(), into(count), now;
assert (3 == count); assert (3 == count);
session().setFeature("autoCommit", ac); session().setFeature("autoCommit", ac);
@ -671,8 +671,8 @@ void ODBCOracleTest::dropObject(const std::string& type, const std::string& name
void ODBCOracleTest::recreateNullableTable() void ODBCOracleTest::recreateNullableTable()
{ {
dropObject("TABLE", "NullableTest"); dropObject("TABLE", ExecUtil::nullabletest());
try { *_pSession << "CREATE TABLE NullableTest (EmptyString VARCHAR2(30) NULL, EmptyInteger INTEGER NULL, EmptyFloat NUMBER NULL , EmptyDateTime TIMESTAMP NULL)", now; } try { *_pSession << "CREATE TABLE " << ExecUtil::nullabletest() << " (EmptyString VARCHAR2(30) NULL, EmptyInteger INTEGER NULL, EmptyFloat NUMBER NULL , EmptyDateTime TIMESTAMP NULL)", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonTable()"); }
} }
@ -680,8 +680,8 @@ void ODBCOracleTest::recreateNullableTable()
void ODBCOracleTest::recreatePersonTable() void ODBCOracleTest::recreatePersonTable()
{ {
dropObject("TABLE", "Person"); dropObject("TABLE", ExecUtil::person());
try { *_pSession << "CREATE TABLE Person (LastName VARCHAR2(30), FirstName VARCHAR2(30), Address VARCHAR2(30), Age INTEGER)", now; } try { *_pSession << "CREATE TABLE " << ExecUtil::person() << " (LastName VARCHAR2(30), FirstName VARCHAR2(30), Address VARCHAR2(30), Age INTEGER)", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonTable()"); }
} }
@ -689,8 +689,8 @@ void ODBCOracleTest::recreatePersonTable()
void ODBCOracleTest::recreatePersonTupleTable() void ODBCOracleTest::recreatePersonTupleTable()
{ {
dropObject("TABLE", "Person"); dropObject("TABLE", ExecUtil::person());
try { *_pSession << "CREATE TABLE Person (LastName1 VARCHAR2(30), FirstName1 VARCHAR2(30), Address1 VARCHAR2(30), Age1 INTEGER," try { *_pSession << "CREATE TABLE " << ExecUtil::person() << " (LastName1 VARCHAR2(30), FirstName1 VARCHAR2(30), Address1 VARCHAR2(30), Age1 INTEGER,"
"LastName2 VARCHAR2(30), FirstName2 VARCHAR2(30), Address2 VARCHAR2(30), Age2 INTEGER)", now; } "LastName2 VARCHAR2(30), FirstName2 VARCHAR2(30), Address2 VARCHAR2(30), Age2 INTEGER)", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonTupleTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonTupleTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonTupleTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonTupleTable()"); }
@ -699,8 +699,8 @@ void ODBCOracleTest::recreatePersonTupleTable()
void ODBCOracleTest::recreatePersonBLOBTable() void ODBCOracleTest::recreatePersonBLOBTable()
{ {
dropObject("TABLE", "Person"); dropObject("TABLE", ExecUtil::person());
try { *_pSession << "CREATE TABLE Person (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), Image BLOB)", now; } try { *_pSession << "CREATE TABLE " << ExecUtil::person() << " (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), Image BLOB)", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonBLOBTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonBLOBTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonBLOBTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonBLOBTable()"); }
} }
@ -708,8 +708,8 @@ void ODBCOracleTest::recreatePersonBLOBTable()
void ODBCOracleTest::recreatePersonDateTimeTable() void ODBCOracleTest::recreatePersonDateTimeTable()
{ {
dropObject("TABLE", "Person"); dropObject("TABLE", ExecUtil::person());
try { *_pSession << "CREATE TABLE Person (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), Born TIMESTAMP)", now; } try { *_pSession << "CREATE TABLE " << ExecUtil::person() << " (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), Born TIMESTAMP)", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonDateTimeTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonDateTimeTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonDateTimeTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonDateTimeTable()"); }
} }
@ -717,8 +717,8 @@ void ODBCOracleTest::recreatePersonDateTimeTable()
void ODBCOracleTest::recreatePersonDateTable() void ODBCOracleTest::recreatePersonDateTable()
{ {
dropObject("TABLE", "Person"); dropObject("TABLE", ExecUtil::person());
try { *_pSession << "CREATE TABLE Person (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), BornDate DATE)", now; } try { *_pSession << "CREATE TABLE " << ExecUtil::person() << " (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), BornDate DATE)", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonDateTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonDateTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonDateTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonDateTable()"); }
} }
@ -726,8 +726,8 @@ void ODBCOracleTest::recreatePersonDateTable()
void ODBCOracleTest::recreateIntsTable() void ODBCOracleTest::recreateIntsTable()
{ {
dropObject("TABLE", "Strings"); dropObject("TABLE", ExecUtil::strings());
try { *_pSession << "CREATE TABLE Strings (str INTEGER)", now; } try { *_pSession << "CREATE TABLE " << ExecUtil::strings() <<" (str INTEGER)", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateIntsTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateIntsTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateIntsTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateIntsTable()"); }
} }
@ -735,8 +735,8 @@ void ODBCOracleTest::recreateIntsTable()
void ODBCOracleTest::recreateStringsTable() void ODBCOracleTest::recreateStringsTable()
{ {
dropObject("TABLE", "Strings"); dropObject("TABLE", ExecUtil::strings());
try { *_pSession << "CREATE TABLE Strings (str VARCHAR(30))", now; } try { *_pSession << "CREATE TABLE " << ExecUtil::strings() <<" (str VARCHAR(30))", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateStringsTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateStringsTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateStringsTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateStringsTable()"); }
} }
@ -744,8 +744,8 @@ void ODBCOracleTest::recreateStringsTable()
void ODBCOracleTest::recreateFloatsTable() void ODBCOracleTest::recreateFloatsTable()
{ {
dropObject("TABLE", "Strings"); dropObject("TABLE", ExecUtil::strings());
try { *_pSession << "CREATE TABLE Strings (str NUMBER)", now; } try { *_pSession << "CREATE TABLE " << ExecUtil::strings() <<" (str NUMBER)", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateFloatsTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateFloatsTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateFloatsTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateFloatsTable()"); }
} }
@ -753,8 +753,8 @@ void ODBCOracleTest::recreateFloatsTable()
void ODBCOracleTest::recreateTuplesTable() void ODBCOracleTest::recreateTuplesTable()
{ {
dropObject("TABLE", "Tuples"); dropObject("TABLE", ExecUtil::tuples());
try { *_pSession << "CREATE TABLE Tuples " try { *_pSession << "CREATE TABLE " << ExecUtil::tuples() <<
"(int0 INTEGER, int1 INTEGER, int2 INTEGER, int3 INTEGER, int4 INTEGER, int5 INTEGER, int6 INTEGER, " "(int0 INTEGER, int1 INTEGER, int2 INTEGER, int3 INTEGER, int4 INTEGER, int5 INTEGER, int6 INTEGER, "
"int7 INTEGER, int8 INTEGER, int9 INTEGER, int10 INTEGER, int11 INTEGER, int12 INTEGER, int13 INTEGER," "int7 INTEGER, int8 INTEGER, int9 INTEGER, int10 INTEGER, int11 INTEGER, int12 INTEGER, int13 INTEGER,"
"int14 INTEGER, int15 INTEGER, int16 INTEGER, int17 INTEGER, int18 INTEGER, int19 INTEGER)", now; } "int14 INTEGER, int15 INTEGER, int16 INTEGER, int17 INTEGER, int18 INTEGER, int19 INTEGER)", now; }
@ -765,8 +765,8 @@ void ODBCOracleTest::recreateTuplesTable()
void ODBCOracleTest::recreateVectorsTable() void ODBCOracleTest::recreateVectorsTable()
{ {
dropObject("TABLE", "Vectors"); dropObject("TABLE", ExecUtil::vectors());
try { *_pSession << "CREATE TABLE Vectors (int0 INTEGER, flt0 NUMBER(5,2), str0 VARCHAR(30))", now; } try { *_pSession << "CREATE TABLE " << ExecUtil::vectors() << " (int0 INTEGER, flt0 NUMBER(5,2), str0 VARCHAR(30))", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateVectorsTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateVectorsTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateVectorsTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateVectorsTable()"); }
} }
@ -774,8 +774,8 @@ void ODBCOracleTest::recreateVectorsTable()
void ODBCOracleTest::recreateAnysTable() void ODBCOracleTest::recreateAnysTable()
{ {
dropObject("TABLE", "Anys"); dropObject("TABLE", ExecUtil::anys() );
try { *_pSession << "CREATE TABLE Anys (int0 INTEGER, flt0 NUMBER, str0 VARCHAR(30))", now; } try { *_pSession << "CREATE TABLE " << ExecUtil::anys() << " (int0 INTEGER, flt0 NUMBER, str0 VARCHAR(30))", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateAnysTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateAnysTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateAnysTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateAnysTable()"); }
} }
@ -783,8 +783,8 @@ void ODBCOracleTest::recreateAnysTable()
void ODBCOracleTest::recreateNullsTable(const std::string& notNull) void ODBCOracleTest::recreateNullsTable(const std::string& notNull)
{ {
dropObject("TABLE", "NullTest"); dropObject("TABLE", ExecUtil::nulltest());
try { *_pSession << format("CREATE TABLE NullTest (i INTEGER %s, r NUMBER %s, v VARCHAR(30) %s)", try { *_pSession << format("CREATE TABLE %s (i INTEGER %s, r NUMBER %s, v VARCHAR(30) %s)",ExecUtil::nulltest(),
notNull, notNull,
notNull, notNull,
notNull), now; } notNull), now; }
@ -795,10 +795,10 @@ void ODBCOracleTest::recreateNullsTable(const std::string& notNull)
void ODBCOracleTest::recreateMiscTable() void ODBCOracleTest::recreateMiscTable()
{ {
dropObject("TABLE", "MiscTest"); dropObject("TABLE", ExecUtil::misctest());
try try
{ {
session() << "CREATE TABLE MiscTest " session() << "CREATE TABLE " << ExecUtil::misctest() <<
"(First VARCHAR(30)," "(First VARCHAR(30),"
"Second BLOB," "Second BLOB,"
"Third INTEGER," "Third INTEGER,"
@ -811,8 +811,8 @@ void ODBCOracleTest::recreateMiscTable()
void ODBCOracleTest::recreateLogTable() void ODBCOracleTest::recreateLogTable()
{ {
dropObject("TABLE", "T_POCO_LOG"); dropObject("TABLE", ExecUtil::pocolog());;
dropObject("TABLE", "T_POCO_LOG_ARCHIVE"); dropObject("TABLE", ExecUtil::pocolog_a());;
try try
{ {
@ -826,8 +826,8 @@ void ODBCOracleTest::recreateLogTable()
"Text VARCHAR(100)," "Text VARCHAR(100),"
"DateTime TIMESTAMP)"; "DateTime TIMESTAMP)";
session() << sql, "T_POCO_LOG", now; session() << sql, ExecUtil::pocolog(), now;
session() << sql, "T_POCO_LOG_ARCHIVE", now; session() << sql, ExecUtil::pocolog_a(), now;
} catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateLogTable()"); } } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateLogTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateLogTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateLogTable()"); }
@ -857,6 +857,7 @@ CppUnit::Test* ODBCOracleTest::suite()
CppUnit_addTest(pSuite, ODBCOracleTest, testBareboneODBC); CppUnit_addTest(pSuite, ODBCOracleTest, testBareboneODBC);
CppUnit_addTest(pSuite, ODBCOracleTest, testZeroRows); CppUnit_addTest(pSuite, ODBCOracleTest, testZeroRows);
CppUnit_addTest(pSuite, ODBCOracleTest, testSyntaxError);
CppUnit_addTest(pSuite, ODBCOracleTest, testSimpleAccess); CppUnit_addTest(pSuite, ODBCOracleTest, testSimpleAccess);
CppUnit_addTest(pSuite, ODBCOracleTest, testComplexType); CppUnit_addTest(pSuite, ODBCOracleTest, testComplexType);
CppUnit_addTest(pSuite, ODBCOracleTest, testComplexTypeTuple); CppUnit_addTest(pSuite, ODBCOracleTest, testComplexTypeTuple);

View File

@ -21,6 +21,7 @@
#include "Poco/Data/ODBC/Diagnostics.h" #include "Poco/Data/ODBC/Diagnostics.h"
#include "Poco/Data/ODBC/ODBCException.h" #include "Poco/Data/ODBC/ODBCException.h"
#include <iostream> #include <iostream>
#include "Poco/Environment.h"
using namespace Poco::Data::Keywords; using namespace Poco::Data::Keywords;
@ -58,12 +59,42 @@ using Poco::DateTime;
#endif #endif
#define POSTGRESQL_SERVER POCO_ODBC_TEST_DATABASE_SERVER #define POSTGRESQL_SERVER POCO_ODBC_TEST_DATABASE_SERVER
#define POSTGRESQL_PORT "5432"
#define POSTGRESQL_DB "postgres" static std::string postgreSchema()
#define POSTGRESQL_UID "postgres" {
#define POSTGRESQL_PWD "postgres" return Poco::Environment::get("POCO_TEST_POSTGRES_SCHEMA", "public");
}
static std::string postgreDriver()
{
return Poco::Environment::get("POCO_TEST_POSTGRES_DRIVER", POSTGRESQL_ODBC_DRIVER);
}
static std::string postgreSettings()
{
return Poco::Environment::get("POCO_TEST_POSTGRES_SETTINGS", "");
}
#define POSTGRESQL_VERSION "9.3" #define POSTGRESQL_VERSION "9.3"
static std::string postgreConnParams()
{
return Poco::Environment::get("POCO_TEST_POSTGRES_CONN", "DATABASE=postgres;"
"SERVER=postgres;"
"PORT=5432;");
}
static std::string postgreUid()
{
return Poco::Environment::get("POCO_TEST_POSTGRES_UID", "");
}
static std::string postgrePwd()
{
return Poco::Environment::get("POCO_TEST_POSTGRES_PWD", "");
}
#ifdef POCO_OS_FAMILY_WINDOWS #ifdef POCO_OS_FAMILY_WINDOWS
const std::string ODBCPostgreSQLTest::_libDir = "C:\\\\Program Files\\\\PostgreSQL\\\\" POSTGRESQL_VERSION "\\\\lib\\\\"; const std::string ODBCPostgreSQLTest::_libDir = "C:\\\\Program Files\\\\PostgreSQL\\\\" POSTGRESQL_VERSION "\\\\lib\\\\";
#else #else
@ -73,17 +104,15 @@ const std::string ODBCPostgreSQLTest::_libDir = "/usr/local/pgsql/lib/";
ODBCTest::SessionPtr ODBCPostgreSQLTest::_pSession; ODBCTest::SessionPtr ODBCPostgreSQLTest::_pSession;
ODBCTest::ExecPtr ODBCPostgreSQLTest::_pExecutor; ODBCTest::ExecPtr ODBCPostgreSQLTest::_pExecutor;
std::string ODBCPostgreSQLTest::_driver = POSTGRESQL_ODBC_DRIVER; std::string ODBCPostgreSQLTest::_driver = postgreDriver();
std::string ODBCPostgreSQLTest::_dsn = POSTGRESQL_DSN; std::string ODBCPostgreSQLTest::_dsn = POSTGRESQL_DSN;
std::string ODBCPostgreSQLTest::_uid = POSTGRESQL_UID; std::string ODBCPostgreSQLTest::_uid = postgreUid();
std::string ODBCPostgreSQLTest::_pwd = POSTGRESQL_PWD; std::string ODBCPostgreSQLTest::_pwd = postgrePwd();
std::string ODBCPostgreSQLTest::_connectString = std::string ODBCPostgreSQLTest::_connectString =
"DRIVER=" POSTGRESQL_ODBC_DRIVER ";" "DRIVER=" + postgreDriver() + ";"
"DATABASE=" POSTGRESQL_DB ";" + postgreConnParams() + ";" +
"SERVER=" POSTGRESQL_SERVER ";" "UID=" + postgreUid() + ";"
"PORT=" POSTGRESQL_PORT ";" "PWD=" + postgrePwd() + ";"
"UID=" POSTGRESQL_UID ";"
"PWD=" POSTGRESQL_PWD ";"
"SSLMODE=prefer;" "SSLMODE=prefer;"
"LowerCaseIdentifier=0;" "LowerCaseIdentifier=0;"
"UseServerSidePrepare=0;" "UseServerSidePrepare=0;"
@ -108,7 +137,7 @@ std::string ODBCPostgreSQLTest::_connectString =
"UnknownSizes=0;" "UnknownSizes=0;"
"Socket=8192;" "Socket=8192;"
"Fetch=100;" "Fetch=100;"
"ConnSettings=;" "ConnSettings=" + postgreSettings() + ";"
"ShowSystemTables=0;" "ShowSystemTables=0;"
"RowVersioning=0;" "RowVersioning=0;"
"ShowOidColumn=0;" "ShowOidColumn=0;"
@ -129,7 +158,7 @@ ODBCPostgreSQLTest::~ODBCPostgreSQLTest()
void ODBCPostgreSQLTest::testBareboneODBC() void ODBCPostgreSQLTest::testBareboneODBC()
{ {
std::string tableCreateString = "CREATE TABLE Test " std::string tableCreateString = "CREATE TABLE " + ExecUtil::test_tbl() +
"(First VARCHAR(30)," "(First VARCHAR(30),"
"Second VARCHAR(30)," "Second VARCHAR(30),"
"Third BYTEA," "Third BYTEA,"
@ -142,7 +171,7 @@ void ODBCPostgreSQLTest::testBareboneODBC()
executor().bareboneODBCTest(_connectString, tableCreateString, SQLExecutor::PB_AT_EXEC, SQLExecutor::DE_MANUAL); executor().bareboneODBCTest(_connectString, tableCreateString, SQLExecutor::PB_AT_EXEC, SQLExecutor::DE_MANUAL);
executor().bareboneODBCTest(_connectString, tableCreateString, SQLExecutor::PB_AT_EXEC, SQLExecutor::DE_BOUND); executor().bareboneODBCTest(_connectString, tableCreateString, SQLExecutor::PB_AT_EXEC, SQLExecutor::DE_BOUND);
tableCreateString = "CREATE TABLE Test " tableCreateString = "CREATE TABLE " + ExecUtil::test_tbl() +
"(First VARCHAR(30)," "(First VARCHAR(30),"
"Second VARCHAR(30)," "Second VARCHAR(30),"
"Third BYTEA," "Third BYTEA,"
@ -157,7 +186,7 @@ void ODBCPostgreSQLTest::testBareboneODBC()
//neither pSQL ODBC nor Mammoth drivers support multiple results properly //neither pSQL ODBC nor Mammoth drivers support multiple results properly
/* /*
tableCreateString = "CREATE TABLE Test " tableCreateString = "CREATE TABLE " + ExecUtil::test_tbl() +
"(First VARCHAR(30)," "(First VARCHAR(30),"
"Second INTEGER," "Second INTEGER,"
"Third FLOAT)"; "Third FLOAT)";
@ -201,17 +230,18 @@ void ODBCPostgreSQLTest::testStoredFunction()
{ {
configurePLPgSQL(); configurePLPgSQL();
std::string func("testStoredFunction()"); const std::string func("testStoredFunction()");
const std::string nm = ExecUtil::stored_func();
for (int k = 0; k < 8;) for (int k = 0; k < 8;)
{ {
session().setFeature("autoBind", bindValue(k)); session().setFeature("autoBind", bindValue(k));
session().setFeature("autoExtract", bindValue(k+1)); session().setFeature("autoExtract", bindValue(k+1));
dropObject("FUNCTION", "storedFunction()"); dropObject("FUNCTION", nm + "()");
try try
{ {
session() << "CREATE FUNCTION storedFunction() RETURNS INTEGER AS '" session() << "CREATE FUNCTION " << nm << "() RETURNS INTEGER AS '"
"BEGIN " "BEGIN "
" return -1; " " return -1; "
"END;'" "END;'"
@ -221,13 +251,13 @@ void ODBCPostgreSQLTest::testStoredFunction()
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (func); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (func); }
int i = 0; int i = 0;
session() << "{? = call storedFunction()}", out(i), now; session() << "{? = call "<< nm << "()}", out(i), now;
assert(-1 == i); assert(-1 == i);
dropObject("FUNCTION", "storedFunction()"); dropObject("FUNCTION", nm + "(INTEGER)");
try try
{ {
session() << "CREATE FUNCTION storedFunction(INTEGER) RETURNS INTEGER AS '" session() << "CREATE FUNCTION " << nm << "(INTEGER) RETURNS INTEGER AS '"
"BEGIN " "BEGIN "
" RETURN $1 * $1; " " RETURN $1 * $1; "
"END;'" "END;'"
@ -238,14 +268,14 @@ void ODBCPostgreSQLTest::testStoredFunction()
i = 2; i = 2;
int result = 0; int result = 0;
session() << "{? = call storedFunction(?)}", out(result), in(i), now; session() << "{? = call " << nm << "(?)}", out(result), in(i), now;
assert(4 == result); assert(4 == result);
dropObject("FUNCTION", "storedFunction(INTEGER)"); dropObject("FUNCTION", nm + "(INTEGER)");
dropObject("FUNCTION", "storedFunction(TIMESTAMP)"); dropObject("FUNCTION", nm + "(TIMESTAMP)");
try try
{ {
session() << "CREATE FUNCTION storedFunction(TIMESTAMP) RETURNS TIMESTAMP AS '" session() << "CREATE FUNCTION " << nm << "(TIMESTAMP) RETURNS TIMESTAMP AS '"
"BEGIN " "BEGIN "
" RETURN $1; " " RETURN $1; "
"END;'" "END;'"
@ -256,14 +286,14 @@ void ODBCPostgreSQLTest::testStoredFunction()
DateTime dtIn(1965, 6, 18, 5, 35, 1); DateTime dtIn(1965, 6, 18, 5, 35, 1);
DateTime dtOut; DateTime dtOut;
session() << "{? = call storedFunction(?)}", out(dtOut), in(dtIn), now; session() << "{? = call " << nm << "(?)}", out(dtOut), in(dtIn), now;
assert(dtOut == dtIn); assert(dtOut == dtIn);
dropObject("FUNCTION", "storedFunction(TIMESTAMP)"); dropObject("FUNCTION", nm + "(TIMESTAMP)");
dropObject("FUNCTION", "storedFunction(TEXT, TEXT)"); dropObject("FUNCTION", nm + "(TEXT, TEXT)");
try try
{ {
session() << "CREATE FUNCTION storedFunction(TEXT,TEXT) RETURNS TEXT AS '" session() << "CREATE FUNCTION " << nm << "(TEXT,TEXT) RETURNS TEXT AS '"
"BEGIN " "BEGIN "
" RETURN $1 || '', '' || $2 || ''!'';" " RETURN $1 || '', '' || $2 || ''!'';"
"END;'" "END;'"
@ -277,13 +307,13 @@ void ODBCPostgreSQLTest::testStoredFunction()
std::string ret; std::string ret;
try try
{ {
session() << "{? = call storedFunction(?,?)}", out(ret), in(param1), in(param2), now; session() << "{? = call " << nm << "(?,?)}", out(ret), in(param1), in(param2), now;
} }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (func); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (func); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (func); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (func); }
assert(ret == "Hello, world!"); assert(ret == "Hello, world!");
dropObject("FUNCTION", "storedFunction(TEXT, TEXT)"); dropObject("FUNCTION", nm + "(TEXT, TEXT)");
k += 2; k += 2;
} }
@ -292,7 +322,10 @@ void ODBCPostgreSQLTest::testStoredFunction()
void ODBCPostgreSQLTest::testStoredFunctionAny() void ODBCPostgreSQLTest::testStoredFunctionAny()
{ {
session() << "CREATE FUNCTION storedFunction(INTEGER) RETURNS INTEGER AS '" const std::string nm = ExecUtil::stored_func();
dropObject("FUNCTION", nm + "(INTEGER)");
session() << "CREATE FUNCTION "<< nm << "(INTEGER) RETURNS INTEGER AS '"
"BEGIN " "BEGIN "
" RETURN $1 * $1; " " RETURN $1 * $1; "
"END;'" "END;'"
@ -305,19 +338,23 @@ void ODBCPostgreSQLTest::testStoredFunctionAny()
Any i = 2; Any i = 2;
Any result = 0; Any result = 0;
session() << "{? = call storedFunction(?)}", out(result), in(i), now; session() << "{? = call " << nm << "(?)}", out(result), in(i), now;
assert(4 == AnyCast<int>(result)); assert(4 == AnyCast<int>(result));
k += 2; k += 2;
} }
dropObject("FUNCTION", "storedFunction(INTEGER)"); dropObject("FUNCTION", nm + "(INTEGER)");
} }
void ODBCPostgreSQLTest::testStoredFunctionDynamicAny() void ODBCPostgreSQLTest::testStoredFunctionDynamicAny()
{ {
session() << "CREATE FUNCTION storedFunction(INTEGER) RETURNS INTEGER AS '" const std::string nm = ExecUtil::stored_func();
dropObject("FUNCTION", nm + "(INTEGER)");
session() << "CREATE FUNCTION " << nm << "(INTEGER) RETURNS INTEGER AS '"
"BEGIN " "BEGIN "
" RETURN $1 * $1; " " RETURN $1 * $1; "
"END;'" "END;'"
@ -330,13 +367,13 @@ void ODBCPostgreSQLTest::testStoredFunctionDynamicAny()
DynamicAny i = 2; DynamicAny i = 2;
DynamicAny result = 0; DynamicAny result = 0;
session() << "{? = call storedFunction(?)}", out(result), in(i), now; session() << "{? = call " << nm << "(?)}", out(result), in(i), now;
assert(4 == result); assert(4 == result);
k += 2; k += 2;
} }
dropObject("FUNCTION", "storedFunction(INTEGER)"); dropObject("FUNCTION", nm + "(INTEGER)");
} }
@ -390,8 +427,8 @@ void ODBCPostgreSQLTest::dropObject(const std::string& type, const std::string&
void ODBCPostgreSQLTest::recreateNullableTable() void ODBCPostgreSQLTest::recreateNullableTable()
{ {
dropObject("TABLE", "NullableTest"); dropObject("TABLE", ExecUtil::nullabletest());
try { *_pSession << "CREATE TABLE NullableTest (EmptyString VARCHAR(30) NULL, EmptyInteger INTEGER NULL, EmptyFloat FLOAT NULL , EmptyDateTime TIMESTAMP NULL)", now; } try { *_pSession << "CREATE TABLE "<< ExecUtil::nullabletest() << " (EmptyString VARCHAR(30) NULL, EmptyInteger INTEGER NULL, EmptyFloat FLOAT NULL , EmptyDateTime TIMESTAMP NULL)", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonTable()"); }
} }
@ -399,8 +436,8 @@ void ODBCPostgreSQLTest::recreateNullableTable()
void ODBCPostgreSQLTest::recreatePersonTable() void ODBCPostgreSQLTest::recreatePersonTable()
{ {
dropObject("TABLE", "Person"); dropObject("TABLE", ExecUtil::person());
try { session() << "CREATE TABLE Person (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), Age INTEGER)", now; } try { session() << "CREATE TABLE " << ExecUtil::person() << " (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), Age INTEGER)", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonTable()"); }
} }
@ -408,8 +445,8 @@ void ODBCPostgreSQLTest::recreatePersonTable()
void ODBCPostgreSQLTest::recreatePersonBLOBTable() void ODBCPostgreSQLTest::recreatePersonBLOBTable()
{ {
dropObject("TABLE", "Person"); dropObject("TABLE", ExecUtil::person());
try { session() << "CREATE TABLE Person (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), Image BYTEA)", now; } try { session() << "CREATE TABLE " << ExecUtil::person() << " (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), Image BYTEA)", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonBLOBTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonBLOBTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonBLOBTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonBLOBTable()"); }
} }
@ -418,8 +455,8 @@ void ODBCPostgreSQLTest::recreatePersonBLOBTable()
void ODBCPostgreSQLTest::recreatePersonDateTimeTable() void ODBCPostgreSQLTest::recreatePersonDateTimeTable()
{ {
dropObject("TABLE", "Person"); dropObject("TABLE", ExecUtil::person());
try { session() << "CREATE TABLE Person (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), Born TIMESTAMP)", now; } try { session() << "CREATE TABLE " << ExecUtil::person() << " (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), Born TIMESTAMP)", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonDateTimeTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonDateTimeTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonDateTimeTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonDateTimeTable()"); }
} }
@ -427,8 +464,8 @@ void ODBCPostgreSQLTest::recreatePersonDateTimeTable()
void ODBCPostgreSQLTest::recreatePersonDateTable() void ODBCPostgreSQLTest::recreatePersonDateTable()
{ {
dropObject("TABLE", "Person"); dropObject("TABLE", ExecUtil::person());
try { session() << "CREATE TABLE Person (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), BornDate DATE)", now; } try { session() << "CREATE TABLE " << ExecUtil::person() << " (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), BornDate DATE)", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonDateTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonDateTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonDateTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonDateTable()"); }
} }
@ -436,8 +473,8 @@ void ODBCPostgreSQLTest::recreatePersonDateTable()
void ODBCPostgreSQLTest::recreatePersonTimeTable() void ODBCPostgreSQLTest::recreatePersonTimeTable()
{ {
dropObject("TABLE", "Person"); dropObject("TABLE", ExecUtil::person());
try { session() << "CREATE TABLE Person (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), BornTime TIME)", now; } try { session() << "CREATE TABLE " << ExecUtil::person() << " (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), BornTime TIME)", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonTimeTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonTimeTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonTimeTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonTimeTable()"); }
} }
@ -445,8 +482,8 @@ void ODBCPostgreSQLTest::recreatePersonTimeTable()
void ODBCPostgreSQLTest::recreateIntsTable() void ODBCPostgreSQLTest::recreateIntsTable()
{ {
dropObject("TABLE", "Strings"); dropObject("TABLE", ExecUtil::strings());
try { session() << "CREATE TABLE Strings (str INTEGER)", now; } try { session() << "CREATE TABLE " << ExecUtil::strings() <<" (str INTEGER)", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateIntsTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateIntsTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateIntsTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateIntsTable()"); }
} }
@ -454,8 +491,8 @@ void ODBCPostgreSQLTest::recreateIntsTable()
void ODBCPostgreSQLTest::recreateStringsTable() void ODBCPostgreSQLTest::recreateStringsTable()
{ {
dropObject("TABLE", "Strings"); dropObject("TABLE", ExecUtil::strings());
try { session() << "CREATE TABLE Strings (str VARCHAR(30))", now; } try { session() << "CREATE TABLE " << ExecUtil::strings() <<" (str VARCHAR(30))", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateStringsTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateStringsTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateStringsTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateStringsTable()"); }
} }
@ -463,8 +500,8 @@ void ODBCPostgreSQLTest::recreateStringsTable()
void ODBCPostgreSQLTest::recreateFloatsTable() void ODBCPostgreSQLTest::recreateFloatsTable()
{ {
dropObject("TABLE", "Strings"); dropObject("TABLE", ExecUtil::strings());
try { session() << "CREATE TABLE Strings (str FLOAT)", now; } try { session() << "CREATE TABLE " << ExecUtil::strings() <<" (str FLOAT)", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateFloatsTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateFloatsTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateFloatsTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateFloatsTable()"); }
} }
@ -472,8 +509,8 @@ void ODBCPostgreSQLTest::recreateFloatsTable()
void ODBCPostgreSQLTest::recreateTuplesTable() void ODBCPostgreSQLTest::recreateTuplesTable()
{ {
dropObject("TABLE", "Tuples"); dropObject("TABLE", ExecUtil::tuples());
try { session() << "CREATE TABLE Tuples " try { session() << "CREATE TABLE " << ExecUtil::tuples() <<
"(int0 INTEGER, int1 INTEGER, int2 INTEGER, int3 INTEGER, int4 INTEGER, int5 INTEGER, int6 INTEGER, " "(int0 INTEGER, int1 INTEGER, int2 INTEGER, int3 INTEGER, int4 INTEGER, int5 INTEGER, int6 INTEGER, "
"int7 INTEGER, int8 INTEGER, int9 INTEGER, int10 INTEGER, int11 INTEGER, int12 INTEGER, int13 INTEGER," "int7 INTEGER, int8 INTEGER, int9 INTEGER, int10 INTEGER, int11 INTEGER, int12 INTEGER, int13 INTEGER,"
"int14 INTEGER, int15 INTEGER, int16 INTEGER, int17 INTEGER, int18 INTEGER, int19 INTEGER)", now; } "int14 INTEGER, int15 INTEGER, int16 INTEGER, int17 INTEGER, int18 INTEGER, int19 INTEGER)", now; }
@ -484,8 +521,8 @@ void ODBCPostgreSQLTest::recreateTuplesTable()
void ODBCPostgreSQLTest::recreateVectorsTable() void ODBCPostgreSQLTest::recreateVectorsTable()
{ {
dropObject("TABLE", "Vectors"); dropObject("TABLE", ExecUtil::vectors());
try { session() << "CREATE TABLE Vectors (int0 INTEGER, flt0 FLOAT, str0 VARCHAR(30))", now; } try { session() << "CREATE TABLE " << ExecUtil::vectors() << " (i0 INTEGER, flt0 FLOAT, str0 VARCHAR(30))", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateVectorsTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateVectorsTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateVectorsTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateVectorsTable()"); }
} }
@ -493,8 +530,8 @@ void ODBCPostgreSQLTest::recreateVectorsTable()
void ODBCPostgreSQLTest::recreateAnysTable() void ODBCPostgreSQLTest::recreateAnysTable()
{ {
dropObject("TABLE", "Anys"); dropObject("TABLE", ExecUtil::anys() );
try { session() << "CREATE TABLE Anys (int0 INTEGER, flt0 FLOAT, str0 VARCHAR(30))", now; } try { session() << "CREATE TABLE " << ExecUtil::anys() << " (int0 INTEGER, flt0 FLOAT, str0 VARCHAR(30))", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateAnysTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateAnysTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateAnysTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateAnysTable()"); }
} }
@ -502,8 +539,8 @@ void ODBCPostgreSQLTest::recreateAnysTable()
void ODBCPostgreSQLTest::recreateNullsTable(const std::string& notNull) void ODBCPostgreSQLTest::recreateNullsTable(const std::string& notNull)
{ {
dropObject("TABLE", "NullTest"); dropObject("TABLE", ExecUtil::nulltest());
try { session() << format("CREATE TABLE NullTest (i INTEGER %s, r FLOAT %s, v VARCHAR(30) %s)", try { session() << format("CREATE TABLE %s (i INTEGER %s, r FLOAT %s, v VARCHAR(30) %s)",ExecUtil::nulltest(),
notNull, notNull,
notNull, notNull,
notNull), now; } notNull), now; }
@ -523,11 +560,11 @@ void ODBCPostgreSQLTest::recreateBoolTable()
void ODBCPostgreSQLTest::recreateMiscTable() void ODBCPostgreSQLTest::recreateMiscTable()
{ {
dropObject("TABLE", "MiscTest"); dropObject("TABLE", ExecUtil::misctest());
try try
{ {
// Mammoth does not bind columns properly // Mammoth does not bind columns properly
session() << "CREATE TABLE MiscTest " session() << "CREATE TABLE "<< ExecUtil::misctest() <<
"(First VARCHAR(30)," "(First VARCHAR(30),"
"Second BYTEA," "Second BYTEA,"
"Third INTEGER," "Third INTEGER,"
@ -540,8 +577,8 @@ void ODBCPostgreSQLTest::recreateMiscTable()
void ODBCPostgreSQLTest::recreateLogTable() void ODBCPostgreSQLTest::recreateLogTable()
{ {
dropObject("TABLE", "T_POCO_LOG"); dropObject("TABLE", ExecUtil::pocolog());;
dropObject("TABLE", "T_POCO_LOG_ARCHIVE"); dropObject("TABLE", ExecUtil::pocolog_a());;
try try
{ {
@ -555,8 +592,8 @@ void ODBCPostgreSQLTest::recreateLogTable()
"Text VARCHAR," "Text VARCHAR,"
"DateTime TIMESTAMP)"; "DateTime TIMESTAMP)";
session() << sql, "T_POCO_LOG", now; session() << sql, ExecUtil::pocolog(), now;
session() << sql, "T_POCO_LOG_ARCHIVE", now; session() << sql, ExecUtil::pocolog_a(), now;
} catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateLogTable()"); } } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateLogTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateLogTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateLogTable()"); }
@ -580,12 +617,20 @@ CppUnit::Test* ODBCPostgreSQLTest::suite()
{ {
std::cout << "*** Connected to [" << _driver << "] test database." << std::endl; std::cout << "*** Connected to [" << _driver << "] test database." << std::endl;
_pExecutor = new SQLExecutor(_driver + " SQL Executor", _pSession); std::string initSql;
if (!postgreSchema().empty())
{
initSql = "SET search_path TO " + postgreSchema() + (postgreSchema() != std::string("public") ? ", public;" : ";");
(*_pSession) << initSql, now;
}
_pExecutor = new SQLExecutor(_driver + " SQL Executor", _pSession, initSql, postgreSchema());
CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("ODBCPostgreSQLTest"); CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("ODBCPostgreSQLTest");
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testBareboneODBC); CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testBareboneODBC);
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testZeroRows); CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testZeroRows);
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testSyntaxError);
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testSimpleAccess); CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testSimpleAccess);
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testComplexType); CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testComplexType);
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testSimpleAccessVector); CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testSimpleAccessVector);
@ -668,7 +713,8 @@ CppUnit::Test* ODBCPostgreSQLTest::suite()
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testAny); CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testAny);
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testDynamicAny); CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testDynamicAny);
//neither pSQL ODBC nor Mammoth drivers support multiple results properly //neither pSQL ODBC nor Mammoth drivers support multiple results properly
//CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testMultipleResults); CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testMultipleResults);
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testMultipleResultsNoProj);
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testSQLChannel); CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testSQLChannel);
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testSQLLogger); CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testSQLLogger);
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testSessionTransaction); CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testSessionTransaction);
@ -677,6 +723,7 @@ CppUnit::Test* ODBCPostgreSQLTest::suite()
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testNullable); CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testNullable);
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testUnicode); CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testUnicode);
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testReconnect); CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testReconnect);
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testInsertStatReuse);
return pSuite; return pSuite;
} }

View File

@ -121,7 +121,7 @@ ODBCSQLServerTest::~ODBCSQLServerTest()
void ODBCSQLServerTest::testBareboneODBC() void ODBCSQLServerTest::testBareboneODBC()
{ {
std::string tableCreateString = "CREATE TABLE Test " std::string tableCreateString = "CREATE TABLE " + ExecUtil::test_tbl() +
"(First VARCHAR(30)," "(First VARCHAR(30),"
"Second VARCHAR(30)," "Second VARCHAR(30),"
"Third VARBINARY(30)," "Third VARBINARY(30),"
@ -138,7 +138,7 @@ void ODBCSQLServerTest::testBareboneODBC()
executor().bareboneODBCTest(dbConnString(), tableCreateString, executor().bareboneODBCTest(dbConnString(), tableCreateString,
SQLExecutor::PB_AT_EXEC, SQLExecutor::DE_BOUND, true, "CONVERT(VARBINARY(30),?)"); SQLExecutor::PB_AT_EXEC, SQLExecutor::DE_BOUND, true, "CONVERT(VARBINARY(30),?)");
tableCreateString = "CREATE TABLE Test " tableCreateString = "CREATE TABLE " + ExecUtil::test_tbl() +
"(First VARCHAR(30)," "(First VARCHAR(30),"
"Second INTEGER," "Second INTEGER,"
"Third FLOAT)"; "Third FLOAT)";
@ -334,13 +334,13 @@ void ODBCSQLServerTest::testCursorStoredProcedure()
people.push_back(Person("Simpson", "Homer", "Springfield", 42)); people.push_back(Person("Simpson", "Homer", "Springfield", 42));
people.push_back(Person("Simpson", "Bart", "Springfield", 12)); people.push_back(Person("Simpson", "Bart", "Springfield", 12));
people.push_back(Person("Simpson", "Lisa", "Springfield", 10)); people.push_back(Person("Simpson", "Lisa", "Springfield", 10));
session() << "INSERT INTO Person VALUES (?, ?, ?, ?)", use(people), now; session() << "INSERT INTO " << ExecUtil::person() << " VALUES (?, ?, ?, ?)", use(people), now;
dropObject("PROCEDURE", "storedCursorProcedure"); dropObject("PROCEDURE", "storedCursorProcedure");
session() << "CREATE PROCEDURE storedCursorProcedure(@ageLimit int) AS " session() << "CREATE PROCEDURE storedCursorProcedure(@ageLimit int) AS "
"BEGIN " "BEGIN "
" SELECT * " " SELECT * "
" FROM Person " " FROM " << ExecUtil::person() <<
" WHERE Age < @ageLimit " " WHERE Age < @ageLimit "
" ORDER BY Age DESC; " " ORDER BY Age DESC; "
"END;" "END;"
@ -362,7 +362,7 @@ void ODBCSQLServerTest::testCursorStoredProcedure()
assert (rs["Address"] == "Springfield"); assert (rs["Address"] == "Springfield");
assert (rs["Age"] == 12); assert (rs["Age"] == 12);
dropObject("TABLE", "Person"); dropObject("TABLE", ExecUtil::person());
dropObject("PROCEDURE", "storedCursorProcedure"); dropObject("PROCEDURE", "storedCursorProcedure");
k += 2; k += 2;
@ -553,8 +553,8 @@ void ODBCSQLServerTest::dropObject(const std::string& type, const std::string& n
void ODBCSQLServerTest::recreateNullableTable() void ODBCSQLServerTest::recreateNullableTable()
{ {
dropObject("TABLE", "NullableTest"); dropObject("TABLE", ExecUtil::nullabletest());
try { *_pSession << "CREATE TABLE NullableTest (EmptyString VARCHAR(30) NULL, EmptyInteger INTEGER NULL, EmptyFloat FLOAT NULL , EmptyDateTime DATETIME NULL)", now; } try { *_pSession << "CREATE TABLE " << ExecUtil::nullabletest() << " (EmptyString VARCHAR(30) NULL, EmptyInteger INTEGER NULL, EmptyFloat FLOAT NULL , EmptyDateTime DATETIME NULL)", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonTable()"); }
} }
@ -562,8 +562,8 @@ void ODBCSQLServerTest::recreateNullableTable()
void ODBCSQLServerTest::recreatePersonTable() void ODBCSQLServerTest::recreatePersonTable()
{ {
dropObject("TABLE", "Person"); dropObject("TABLE", ExecUtil::person());
try { session() << "CREATE TABLE Person (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), Age INTEGER)", now; } try { session() << "CREATE TABLE " << ExecUtil::person() << " (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), Age INTEGER)", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonTable()"); }
} }
@ -571,8 +571,8 @@ void ODBCSQLServerTest::recreatePersonTable()
void ODBCSQLServerTest::recreatePersonBLOBTable() void ODBCSQLServerTest::recreatePersonBLOBTable()
{ {
dropObject("TABLE", "Person"); dropObject("TABLE", ExecUtil::person());
try { session() << "CREATE TABLE Person (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), Image VARBINARY(MAX))", now; } try { session() << "CREATE TABLE " << ExecUtil::person() << " (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), Image VARBINARY(MAX))", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonBLOBTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonBLOBTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonBLOBTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonBLOBTable()"); }
} }
@ -580,8 +580,8 @@ void ODBCSQLServerTest::recreatePersonBLOBTable()
void ODBCSQLServerTest::recreatePersonDateTimeTable() void ODBCSQLServerTest::recreatePersonDateTimeTable()
{ {
dropObject("TABLE", "Person"); dropObject("TABLE", ExecUtil::person());
try { session() << "CREATE TABLE Person (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), Born DATETIME)", now; } try { session() << "CREATE TABLE " << ExecUtil::person() << " (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), Born DATETIME)", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonDateTimeTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonDateTimeTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonDateTimeTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonDateTimeTable()"); }
} }
@ -589,8 +589,8 @@ void ODBCSQLServerTest::recreatePersonDateTimeTable()
void ODBCSQLServerTest::recreateIntsTable() void ODBCSQLServerTest::recreateIntsTable()
{ {
dropObject("TABLE", "Strings"); dropObject("TABLE", ExecUtil::strings());
try { session() << "CREATE TABLE Strings (str INTEGER)", now; } try { session() << "CREATE TABLE " << ExecUtil::strings() <<" (str INTEGER)", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateIntsTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateIntsTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateIntsTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateIntsTable()"); }
} }
@ -598,8 +598,8 @@ void ODBCSQLServerTest::recreateIntsTable()
void ODBCSQLServerTest::recreateStringsTable() void ODBCSQLServerTest::recreateStringsTable()
{ {
dropObject("TABLE", "Strings"); dropObject("TABLE", ExecUtil::strings());
try { session() << "CREATE TABLE Strings (str VARCHAR(30))", now; } try { session() << "CREATE TABLE " << ExecUtil::strings() <<" (str VARCHAR(30))", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateStringsTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateStringsTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateStringsTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateStringsTable()"); }
} }
@ -607,8 +607,8 @@ void ODBCSQLServerTest::recreateStringsTable()
void ODBCSQLServerTest::recreateFloatsTable() void ODBCSQLServerTest::recreateFloatsTable()
{ {
dropObject("TABLE", "Strings"); dropObject("TABLE", ExecUtil::strings());
try { session() << "CREATE TABLE Strings (str FLOAT)", now; } try { session() << "CREATE TABLE " << ExecUtil::strings() <<" (str FLOAT)", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateFloatsTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateFloatsTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateFloatsTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateFloatsTable()"); }
} }
@ -616,8 +616,8 @@ void ODBCSQLServerTest::recreateFloatsTable()
void ODBCSQLServerTest::recreateTuplesTable() void ODBCSQLServerTest::recreateTuplesTable()
{ {
dropObject("TABLE", "Tuples"); dropObject("TABLE", ExecUtil::tuples());
try { session() << "CREATE TABLE Tuples " try { session() << "CREATE TABLE " << ExecUtil::tuples() <<
"(int0 INTEGER, int1 INTEGER, int2 INTEGER, int3 INTEGER, int4 INTEGER, int5 INTEGER, int6 INTEGER, " "(int0 INTEGER, int1 INTEGER, int2 INTEGER, int3 INTEGER, int4 INTEGER, int5 INTEGER, int6 INTEGER, "
"int7 INTEGER, int8 INTEGER, int9 INTEGER, int10 INTEGER, int11 INTEGER, int12 INTEGER, int13 INTEGER," "int7 INTEGER, int8 INTEGER, int9 INTEGER, int10 INTEGER, int11 INTEGER, int12 INTEGER, int13 INTEGER,"
"int14 INTEGER, int15 INTEGER, int16 INTEGER, int17 INTEGER, int18 INTEGER, int19 INTEGER)", now; } "int14 INTEGER, int15 INTEGER, int16 INTEGER, int17 INTEGER, int18 INTEGER, int19 INTEGER)", now; }
@ -637,8 +637,8 @@ void ODBCSQLServerTest::recreateVectorTable()
void ODBCSQLServerTest::recreateVectorsTable() void ODBCSQLServerTest::recreateVectorsTable()
{ {
dropObject("TABLE", "Vectors"); dropObject("TABLE", ExecUtil::vectors());
try { session() << "CREATE TABLE Vectors (int0 INTEGER, flt0 FLOAT, str0 VARCHAR(30))", now; } try { session() << "CREATE TABLE " << ExecUtil::vectors() << " (int0 INTEGER, flt0 FLOAT, str0 VARCHAR(30))", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateVectorsTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateVectorsTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateVectorsTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateVectorsTable()"); }
} }
@ -646,8 +646,8 @@ void ODBCSQLServerTest::recreateVectorsTable()
void ODBCSQLServerTest::recreateAnysTable() void ODBCSQLServerTest::recreateAnysTable()
{ {
dropObject("TABLE", "Anys"); dropObject("TABLE", ExecUtil::anys() );
try { session() << "CREATE TABLE Anys (int0 INTEGER, flt0 FLOAT, str0 VARCHAR(30))", now; } try { session() << "CREATE TABLE " << ExecUtil::anys() << " (int0 INTEGER, flt0 FLOAT, str0 VARCHAR(30))", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateAnysTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateAnysTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateAnysTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateAnysTable()"); }
} }
@ -655,8 +655,8 @@ void ODBCSQLServerTest::recreateAnysTable()
void ODBCSQLServerTest::recreateNullsTable(const std::string& notNull) void ODBCSQLServerTest::recreateNullsTable(const std::string& notNull)
{ {
dropObject("TABLE", "NullTest"); dropObject("TABLE", ExecUtil::nulltest());
try { session() << format("CREATE TABLE NullTest (i INTEGER %s, r FLOAT %s, v VARCHAR(30) %s)", try { session() << format("CREATE TABLE %s (i INTEGER %s, r FLOAT %s, v VARCHAR(30) %s)", ExecUtil::nulltest(),
notNull, notNull,
notNull, notNull,
notNull), now; } notNull), now; }
@ -675,10 +675,10 @@ void ODBCSQLServerTest::recreateBoolTable()
void ODBCSQLServerTest::recreateMiscTable() void ODBCSQLServerTest::recreateMiscTable()
{ {
dropObject("TABLE", "MiscTest"); dropObject("TABLE", ExecUtil::misctest());
try try
{ {
session() << "CREATE TABLE MiscTest " session() << "CREATE TABLE "<< ExecUtil::misctest() <<
"(First VARCHAR(30)," "(First VARCHAR(30),"
"Second VARBINARY(30)," "Second VARBINARY(30),"
"Third INTEGER," "Third INTEGER,"
@ -692,8 +692,8 @@ void ODBCSQLServerTest::recreateMiscTable()
void ODBCSQLServerTest::recreateLogTable() void ODBCSQLServerTest::recreateLogTable()
{ {
dropObject("TABLE", "T_POCO_LOG"); dropObject("TABLE", ExecUtil::pocolog());;
dropObject("TABLE", "T_POCO_LOG_ARCHIVE"); dropObject("TABLE", ExecUtil::pocolog_a());;
try try
{ {
@ -707,8 +707,8 @@ void ODBCSQLServerTest::recreateLogTable()
"Text VARCHAR(max)," "Text VARCHAR(max),"
"DateTime DATETIME)"; "DateTime DATETIME)";
session() << sql, "T_POCO_LOG", now; session() << sql, ExecUtil::pocolog(), now;
session() << sql, "T_POCO_LOG_ARCHIVE", now; session() << sql, ExecUtil::pocolog_a(), now;
} catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateLogTable()"); } } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateLogTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateLogTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateLogTable()"); }
@ -738,6 +738,7 @@ CppUnit::Test* ODBCSQLServerTest::suite()
CppUnit_addTest(pSuite, ODBCSQLServerTest, testBareboneODBC); CppUnit_addTest(pSuite, ODBCSQLServerTest, testBareboneODBC);
CppUnit_addTest(pSuite, ODBCSQLServerTest, testZeroRows); CppUnit_addTest(pSuite, ODBCSQLServerTest, testZeroRows);
CppUnit_addTest(pSuite, ODBCSQLServerTest, testSyntaxError);
CppUnit_addTest(pSuite, ODBCSQLServerTest, testSimpleAccess); CppUnit_addTest(pSuite, ODBCSQLServerTest, testSimpleAccess);
CppUnit_addTest(pSuite, ODBCSQLServerTest, testComplexType); CppUnit_addTest(pSuite, ODBCSQLServerTest, testComplexType);
CppUnit_addTest(pSuite, ODBCSQLServerTest, testSimpleAccessVector); CppUnit_addTest(pSuite, ODBCSQLServerTest, testSimpleAccessVector);

View File

@ -64,7 +64,7 @@ ODBCSQLiteTest::~ODBCSQLiteTest()
void ODBCSQLiteTest::testBareboneODBC() void ODBCSQLiteTest::testBareboneODBC()
{ {
std::string tableCreateString = "CREATE TABLE Test " std::string tableCreateString = "CREATE TABLE " + ExecUtil::test_tbl() +
"(First VARCHAR(30)," "(First VARCHAR(30),"
"Second VARCHAR(30)," "Second VARCHAR(30),"
"Third BLOB," "Third BLOB,"
@ -77,7 +77,7 @@ void ODBCSQLiteTest::testBareboneODBC()
executor().bareboneODBCTest(dbConnString(), tableCreateString, SQLExecutor::PB_AT_EXEC, SQLExecutor::DE_MANUAL); executor().bareboneODBCTest(dbConnString(), tableCreateString, SQLExecutor::PB_AT_EXEC, SQLExecutor::DE_MANUAL);
executor().bareboneODBCTest(dbConnString(), tableCreateString, SQLExecutor::PB_AT_EXEC, SQLExecutor::DE_BOUND); executor().bareboneODBCTest(dbConnString(), tableCreateString, SQLExecutor::PB_AT_EXEC, SQLExecutor::DE_BOUND);
tableCreateString = "CREATE TABLE Test " tableCreateString = "CREATE TABLE " + ExecUtil::test_tbl() +
"(First VARCHAR(30)," "(First VARCHAR(30),"
"Second VARCHAR(30)," "Second VARCHAR(30),"
"Third BLOB," "Third BLOB,"
@ -90,7 +90,7 @@ void ODBCSQLiteTest::testBareboneODBC()
executor().bareboneODBCTest(dbConnString(), tableCreateString, SQLExecutor::PB_AT_EXEC, SQLExecutor::DE_MANUAL); executor().bareboneODBCTest(dbConnString(), tableCreateString, SQLExecutor::PB_AT_EXEC, SQLExecutor::DE_MANUAL);
executor().bareboneODBCTest(dbConnString(), tableCreateString, SQLExecutor::PB_AT_EXEC, SQLExecutor::DE_BOUND); executor().bareboneODBCTest(dbConnString(), tableCreateString, SQLExecutor::PB_AT_EXEC, SQLExecutor::DE_BOUND);
tableCreateString = "CREATE TABLE Test " tableCreateString = "CREATE TABLE " + ExecUtil::test_tbl() +
"(First VARCHAR(30)," "(First VARCHAR(30),"
"Second VARCHAR(30)," "Second VARCHAR(30),"
"Third BLOB," "Third BLOB,"
@ -169,8 +169,8 @@ void ODBCSQLiteTest::dropObject(const std::string& type, const std::string& name
void ODBCSQLiteTest::recreateNullableTable() void ODBCSQLiteTest::recreateNullableTable()
{ {
dropObject("TABLE", "NullableTest"); dropObject("TABLE", ExecUtil::nullabletest());
try { *_pSession << "CREATE TABLE NullableTest (EmptyString VARCHAR(30) NULL, EmptyInteger INTEGER NULL, EmptyFloat REAL NULL , EmptyDateTime TIMESTAMP NULL)", now; } try { *_pSession << "CREATE TABLE " << ExecUtil::nullabletest() << " (EmptyString VARCHAR(30) NULL, EmptyInteger INTEGER NULL, EmptyFloat REAL NULL , EmptyDateTime TIMESTAMP NULL)", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonTable()"); }
} }
@ -178,8 +178,8 @@ void ODBCSQLiteTest::recreateNullableTable()
void ODBCSQLiteTest::recreatePersonTable() void ODBCSQLiteTest::recreatePersonTable()
{ {
dropObject("TABLE", "Person"); dropObject("TABLE", ExecUtil::person());
try { session() << "CREATE TABLE Person (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), Age INTEGER)", now; } try { session() << "CREATE TABLE " << ExecUtil::person() << " (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), Age INTEGER)", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonTable()"); }
} }
@ -187,8 +187,8 @@ void ODBCSQLiteTest::recreatePersonTable()
void ODBCSQLiteTest::recreatePersonBLOBTable() void ODBCSQLiteTest::recreatePersonBLOBTable()
{ {
dropObject("TABLE", "Person"); dropObject("TABLE", ExecUtil::person());
try { session() << "CREATE TABLE Person (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), Image BLOB)", now; } try { session() << "CREATE TABLE " << ExecUtil::person() << " (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), Image BLOB)", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonBLOBTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonBLOBTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonBLOBTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonBLOBTable()"); }
} }
@ -196,8 +196,8 @@ void ODBCSQLiteTest::recreatePersonBLOBTable()
void ODBCSQLiteTest::recreatePersonDateTimeTable() void ODBCSQLiteTest::recreatePersonDateTimeTable()
{ {
dropObject("TABLE", "Person"); dropObject("TABLE", ExecUtil::person());
try { session() << "CREATE TABLE Person (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), Born TIMESTAMP)", now; } try { session() << "CREATE TABLE " << ExecUtil::person() << " (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), Born TIMESTAMP)", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonDateTimeTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonDateTimeTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonDateTimeTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonDateTimeTable()"); }
} }
@ -205,8 +205,8 @@ void ODBCSQLiteTest::recreatePersonDateTimeTable()
void ODBCSQLiteTest::recreateIntsTable() void ODBCSQLiteTest::recreateIntsTable()
{ {
dropObject("TABLE", "Strings"); dropObject("TABLE", ExecUtil::strings());
try { session() << "CREATE TABLE Strings (str INTEGER)", now; } try { session() << "CREATE TABLE " << ExecUtil::strings() <<" (str INTEGER)", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateIntsTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateIntsTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateIntsTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateIntsTable()"); }
} }
@ -214,8 +214,8 @@ void ODBCSQLiteTest::recreateIntsTable()
void ODBCSQLiteTest::recreateStringsTable() void ODBCSQLiteTest::recreateStringsTable()
{ {
dropObject("TABLE", "Strings"); dropObject("TABLE", ExecUtil::strings());
try { session() << "CREATE TABLE Strings (str VARCHAR(30))", now; } try { session() << "CREATE TABLE " << ExecUtil::strings() <<" (str VARCHAR(30))", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateStringsTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateStringsTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateStringsTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateStringsTable()"); }
} }
@ -223,8 +223,8 @@ void ODBCSQLiteTest::recreateStringsTable()
void ODBCSQLiteTest::recreateFloatsTable() void ODBCSQLiteTest::recreateFloatsTable()
{ {
dropObject("TABLE", "Strings"); dropObject("TABLE", ExecUtil::strings());
try { session() << "CREATE TABLE Strings (str REAL)", now; } try { session() << "CREATE TABLE " << ExecUtil::strings() <<" (str REAL)", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateFloatsTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateFloatsTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateFloatsTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateFloatsTable()"); }
} }
@ -232,8 +232,8 @@ void ODBCSQLiteTest::recreateFloatsTable()
void ODBCSQLiteTest::recreateTuplesTable() void ODBCSQLiteTest::recreateTuplesTable()
{ {
dropObject("TABLE", "Tuples"); dropObject("TABLE", ExecUtil::tuples());
try { session() << "CREATE TABLE Tuples " try { session() << "CREATE TABLE " << ExecUtil::tuples() <<
"(int0 INTEGER, int1 INTEGER, int2 INTEGER, int3 INTEGER, int4 INTEGER, int5 INTEGER, int6 INTEGER, " "(int0 INTEGER, int1 INTEGER, int2 INTEGER, int3 INTEGER, int4 INTEGER, int5 INTEGER, int6 INTEGER, "
"int7 INTEGER, int8 INTEGER, int9 INTEGER, int10 INTEGER, int11 INTEGER, int12 INTEGER, int13 INTEGER," "int7 INTEGER, int8 INTEGER, int9 INTEGER, int10 INTEGER, int11 INTEGER, int12 INTEGER, int13 INTEGER,"
"int14 INTEGER, int15 INTEGER, int16 INTEGER, int17 INTEGER, int18 INTEGER, int19 INTEGER)", now; } "int14 INTEGER, int15 INTEGER, int16 INTEGER, int17 INTEGER, int18 INTEGER, int19 INTEGER)", now; }
@ -244,8 +244,8 @@ void ODBCSQLiteTest::recreateTuplesTable()
void ODBCSQLiteTest::recreateVectorsTable() void ODBCSQLiteTest::recreateVectorsTable()
{ {
dropObject("TABLE", "Vectors"); dropObject("TABLE", ExecUtil::vectors() );
try { session() << "CREATE TABLE Vectors (int0 INTEGER, flt0 REAL, str0 VARCHAR)", now; } try { session() << "CREATE TABLE " << ExecUtil::vectors() << " (int0 INTEGER, flt0 REAL, str0 VARCHAR)", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateVectorsTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateVectorsTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateVectorsTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateVectorsTable()"); }
} }
@ -253,8 +253,8 @@ void ODBCSQLiteTest::recreateVectorsTable()
void ODBCSQLiteTest::recreateAnysTable() void ODBCSQLiteTest::recreateAnysTable()
{ {
dropObject("TABLE", "Anys"); dropObject("TABLE", ExecUtil::anys() );
try { session() << "CREATE TABLE Anys (int0 INTEGER, flt0 REAL, str0 VARCHAR)", now; } try { session() << "CREATE TABLE " << ExecUtil::anys() << " (int0 INTEGER, flt0 REAL, str0 VARCHAR)", now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateAnysTable()"); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateAnysTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateAnysTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateAnysTable()"); }
} }
@ -262,8 +262,8 @@ void ODBCSQLiteTest::recreateAnysTable()
void ODBCSQLiteTest::recreateNullsTable(const std::string& notNull) void ODBCSQLiteTest::recreateNullsTable(const std::string& notNull)
{ {
dropObject("TABLE", "NullTest"); dropObject("TABLE", ExecUtil::nulltest());
try { session() << format("CREATE TABLE NullTest (i INTEGER %s, r REAL %s, v VARCHAR(30) %s)", try { session() << format("CREATE TABLE %s (i INTEGER %s, r REAL %s, v VARCHAR(30) %s)",ExecUtil::nulltest(),
notNull, notNull,
notNull, notNull,
notNull), now; } notNull), now; }
@ -274,11 +274,11 @@ void ODBCSQLiteTest::recreateNullsTable(const std::string& notNull)
void ODBCSQLiteTest::recreateMiscTable() void ODBCSQLiteTest::recreateMiscTable()
{ {
dropObject("TABLE", "MiscTest"); dropObject("TABLE", ExecUtil::misctest());
try try
{ {
// SQLite fails with BLOB bulk operations // SQLite fails with BLOB bulk operations
session() << "CREATE TABLE MiscTest " session() << "CREATE TABLE "<< ExecUtil::misctest() <<
"(First VARCHAR(30)," "(First VARCHAR(30),"
//"Second BLOB," //"Second BLOB,"
"Third INTEGER," "Third INTEGER,"
@ -291,8 +291,8 @@ void ODBCSQLiteTest::recreateMiscTable()
void ODBCSQLiteTest::recreateLogTable() void ODBCSQLiteTest::recreateLogTable()
{ {
dropObject("TABLE", "T_POCO_LOG"); dropObject("TABLE", ExecUtil::pocolog());;
dropObject("TABLE", "T_POCO_LOG_ARCHIVE"); dropObject("TABLE", ExecUtil::pocolog_a());;
try try
{ {
@ -306,8 +306,8 @@ void ODBCSQLiteTest::recreateLogTable()
"Text VARCHAR," "Text VARCHAR,"
"DateTime DATETIME)"; "DateTime DATETIME)";
session() << sql, "T_POCO_LOG", now; session() << sql, ExecUtil::pocolog(), now;
session() << sql, "T_POCO_LOG_ARCHIVE", now; session() << sql, ExecUtil::pocolog_a(), now;
} catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateLogTable()"); } } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateLogTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateLogTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateLogTable()"); }
@ -326,6 +326,7 @@ CppUnit::Test* ODBCSQLiteTest::suite()
CppUnit_addTest(pSuite, ODBCSQLiteTest, testBareboneODBC); CppUnit_addTest(pSuite, ODBCSQLiteTest, testBareboneODBC);
CppUnit_addTest(pSuite, ODBCSQLiteTest, testZeroRows); CppUnit_addTest(pSuite, ODBCSQLiteTest, testZeroRows);
CppUnit_addTest(pSuite, ODBCSQLiteTest, testSyntaxError);
CppUnit_addTest(pSuite, ODBCSQLiteTest, testSimpleAccess); CppUnit_addTest(pSuite, ODBCSQLiteTest, testSimpleAccess);
CppUnit_addTest(pSuite, ODBCSQLiteTest, testComplexType); CppUnit_addTest(pSuite, ODBCSQLiteTest, testComplexType);
CppUnit_addTest(pSuite, ODBCSQLiteTest, testSimpleAccessVector); CppUnit_addTest(pSuite, ODBCSQLiteTest, testSimpleAccessVector);

View File

@ -22,6 +22,7 @@
#include "Poco/Exception.h" #include "Poco/Exception.h"
#include "Poco/Data/LOB.h" #include "Poco/Data/LOB.h"
#include "Poco/Data/StatementImpl.h" #include "Poco/Data/StatementImpl.h"
#include "Poco/Data/RecordSet.h"
#include "Poco/Data/ODBC/Connector.h" #include "Poco/Data/ODBC/Connector.h"
#include "Poco/Data/ODBC/Utility.h" #include "Poco/Data/ODBC/Utility.h"
#include "Poco/Data/ODBC/Diagnostics.h" #include "Poco/Data/ODBC/Diagnostics.h"
@ -41,6 +42,7 @@ using Poco::Data::ODBC::ODBCException;
using Poco::Data::ODBC::ConnectionException; using Poco::Data::ODBC::ConnectionException;
using Poco::Data::ODBC::StatementException; using Poco::Data::ODBC::StatementException;
using Poco::Data::ODBC::StatementDiagnostics; using Poco::Data::ODBC::StatementDiagnostics;
using Poco::Data::Statement;
using Poco::format; using Poco::format;
using Poco::Tuple; using Poco::Tuple;
using Poco::Any; using Poco::Any;
@ -1029,7 +1031,7 @@ void ODBCTest::testNull()
recreateNullsTable(); recreateNullsTable();
_pSession->setFeature("autoBind", bindValue(i)); _pSession->setFeature("autoBind", bindValue(i));
_pSession->setFeature("autoExtract", bindValue(i+1)); _pSession->setFeature("autoExtract", bindValue(i+1));
_pExecutor->nulls(); _pExecutor->nulls(emptyStringIsSpace());
i += 2; i += 2;
} }
} }
@ -1127,6 +1129,20 @@ void ODBCTest::testMultipleResults()
} }
} }
void ODBCTest::testMultipleResultsNoProj()
{
if (! &session()) fail("Test not available.");
session().setFeature("autoBind", true); // DB2 fails without that
for (int autoE = 0; autoE < 2; ++autoE)
{
recreatePersonTable();
_pSession->setFeature("autoExtract", autoE != 0);
_pExecutor->multipleResultsNoProj("SELECT * FROM " + ExecUtil::person() + " WHERE Age = ?; "
"SELECT Age FROM " + ExecUtil::person() + " WHERE FirstName = ?; "
"SELECT * FROM " + ExecUtil::person() + " WHERE Age = ? OR Age = ? ORDER BY Age;");
}
}
void ODBCTest::testSQLChannel() void ODBCTest::testSQLChannel()
{ {
@ -1219,6 +1235,46 @@ void ODBCTest::testNullable()
} }
} }
void ODBCTest::testNumeric()
{
if (!_pSession) fail("Test not available.");
recreateNumericTable();
std::vector<std::string> vals;
vals.push_back("12345678");
vals.push_back("123456789012.123");
vals.push_back("123456789012345678");
vals.push_back("1234567890.12345678");
vals.push_back("1234567890123456789012");
const std::string sqlStr = std::string("INSERT INTO ") + ExecUtil::numeric_tbl() +
"(id, num8, num16_3, num18, num18_8, num22) VALUES (1, " + str2NumExpr(vals[0],8,0) + " , " + str2NumExpr(vals[1],16,3) + ", " + str2NumExpr(vals[2], 18,0)
+ " , " + str2NumExpr(vals[3], 18, 8) + " , " + str2NumExpr(vals[4], 22, 0) + ")";
session() << sqlStr, now;
for (int i = 0; i < 8;)
{
_pSession->setFeature("autoBind", bindValue(i));
_pSession->setFeature("autoExtract", bindValue(i + 1));
_pExecutor->numericTypes(vals);
i += 2;
}
}
void ODBCTest::testInsertStatReuse()
{
for (int i = 0; i < 8; i += 2)
{
recreatePersonTable();
session().setFeature("autoBind", bindValue(i));
session().setFeature("autoExtract", bindValue(i + 1));
_pExecutor->insertStatReuse();
}
}
void ODBCTest::testUnicode() void ODBCTest::testUnicode()
{ {
@ -1256,6 +1312,28 @@ void ODBCTest::testReconnect()
} }
void ODBCTest::testSyntaxError()
{
try {
session() << "select fro oops", now;
fail("Expected syntax error exception");
}
catch (const StatementException&)
{
}
try {
Statement stat(session());
stat << "select fro oops";
stat.execute();
fail("Expected syntax error exception");
}
catch (const StatementException&)
{
}
}
bool ODBCTest::canConnect(const std::string& driver, bool ODBCTest::canConnect(const std::string& driver,
std::string& dsn, std::string& dsn,
std::string& uid, std::string& uid,
@ -1274,7 +1352,7 @@ bool ODBCTest::canConnect(const std::string& driver,
} }
} }
if (_drivers.end() == itDrv) if ((_drivers.end() == itDrv) && (driver.length() != 0) && (driver[0] != '/'))
{ {
dsn = ""; dsn = "";
uid = ""; uid = "";

View File

@ -141,6 +141,7 @@ public:
virtual void testDynamicAny(); virtual void testDynamicAny();
virtual void testMultipleResults(); virtual void testMultipleResults();
virtual void testMultipleResultsNoProj();
virtual void testSQLChannel(); virtual void testSQLChannel();
virtual void testSQLLogger(); virtual void testSQLLogger();
@ -153,6 +154,9 @@ public:
virtual void testUnicode(); virtual void testUnicode();
virtual void testReconnect(); virtual void testReconnect();
virtual void testNumeric();
virtual void testSyntaxError();
virtual void testInsertStatReuse();
protected: protected:
typedef Poco::Data::ODBC::Utility::DriverMap Drivers; typedef Poco::Data::ODBC::Utility::DriverMap Drivers;
@ -176,6 +180,9 @@ protected:
virtual void recreateMiscTable(); virtual void recreateMiscTable();
virtual void recreateLogTable(); virtual void recreateLogTable();
virtual void recreateUnicodeTable(); virtual void recreateUnicodeTable();
virtual void recreateNumericTable();
virtual bool emptyStringIsSpace() { return false; }
virtual std::string str2NumExpr(const std::string& num, unsigned len, unsigned dec) { return num; }
static SessionPtr init(const std::string& driver, static SessionPtr init(const std::string& driver,
std::string& dsn, std::string& dsn,
@ -264,6 +271,11 @@ inline void ODBCTest::recreateNullableTable()
throw Poco::NotImplementedException("ODBCTest::recreateNullableTable()"); throw Poco::NotImplementedException("ODBCTest::recreateNullableTable()");
} }
inline void ODBCTest::recreateNumericTable()
{
throw Poco::NotImplementedException("ODBCTest::recreateNumericTable()");
}
inline void ODBCTest::recreatePersonTable() inline void ODBCTest::recreatePersonTable()
{ {

View File

@ -12,6 +12,7 @@
#include "ODBCTestSuite.h" #include "ODBCTestSuite.h"
#include "ODBCDB2Test.h" #include "ODBCDB2Test.h"
#include "ODBCSybaseTest.h"
#include "ODBCMySQLTest.h" #include "ODBCMySQLTest.h"
#include "ODBCOracleTest.h" #include "ODBCOracleTest.h"
#include "ODBCPostgreSQLTest.h" #include "ODBCPostgreSQLTest.h"
@ -44,6 +45,7 @@ CppUnit::Test* ODBCTestSuite::suite()
addTest(pSuite, ODBCPostgreSQLTest::suite()); addTest(pSuite, ODBCPostgreSQLTest::suite());
addTest(pSuite, ODBCSQLiteTest::suite()); addTest(pSuite, ODBCSQLiteTest::suite());
addTest(pSuite, ODBCSQLServerTest::suite()); addTest(pSuite, ODBCSQLServerTest::suite());
addTest(pSuite, SybaseODBC::suite());
addTest(pSuite, ODBCDB2Test::suite()); addTest(pSuite, ODBCDB2Test::suite());
// MS Access driver does not support connection status detection // MS Access driver does not support connection status detection
// disabled for the time being // disabled for the time being

File diff suppressed because it is too large Load Diff

View File

@ -73,6 +73,81 @@
using Poco::Data::ODBC::ConnectionException; \ using Poco::Data::ODBC::ConnectionException; \
using Poco::Data::ODBC::StatementException using Poco::Data::ODBC::StatementException
struct ExecUtil
{
static std::string mangleTable(const std::string& name);
static std::string person()
{
return mangleTable("Person");
}
static std::string strings()
{
return mangleTable("Strings");
}
static std::string tuples()
{
return mangleTable("Tuples");
}
static std::string vectors()
{
return mangleTable("Vectors");
}
static std::string anys()
{
return mangleTable("Anys");
}
static std::string nulltest()
{
return mangleTable("NullTest");
}
static std::string misctest()
{
return mangleTable("MiscTest");
}
static std::string nullabletest()
{
return mangleTable("NullableTest");
}
static std::string pocolog()
{
return mangleTable("POCO_LOG");
}
static std::string pocolog_a()
{
return mangleTable("POCO_LOG_A");
}
static std::string stored_func()
{
return mangleTable("storedFunc");
}
static std::string stored_proc()
{
return mangleTable("storedProc");
}
static std::string test_tbl()
{
return mangleTable("Test");
}
static std::string numeric_tbl()
{
return mangleTable("numer_t");
}
};
class SQLExecutor: public CppUnit::TestCase class SQLExecutor: public CppUnit::TestCase
{ {
@ -89,7 +164,7 @@ public:
DE_BOUND DE_BOUND
}; };
SQLExecutor(const std::string& name, Poco::Data::Session* _pSession); SQLExecutor(const std::string& name, Poco::Data::Session* _pSession, const std::string& connInitSql = std::string(), const std::string& schemaName = std::string());
~SQLExecutor(); ~SQLExecutor();
void execute(const std::string& sql); void execute(const std::string& sql);
@ -147,6 +222,8 @@ public:
void limitPrepare(); void limitPrepare();
void limitZero(); void limitZero();
void prepare(); void prepare();
void numericTypes(const std::vector<std::string>& vals);
void insertStatReuse();
template <typename C1, typename C2, typename C3, typename C4, typename C5, typename C6> template <typename C1, typename C2, typename C3, typename C4, typename C5, typename C6>
void doBulkWithBool(Poco::UInt32 size, const std::string& blobPlaceholder="?") void doBulkWithBool(Poco::UInt32 size, const std::string& blobPlaceholder="?")
@ -173,7 +250,7 @@ public:
try try
{ {
session() << session() <<
Poco::format("INSERT INTO MiscTest VALUES (?,%s,?,?,?,?)", blobPlaceholder), Poco::format("INSERT INTO %s VALUES (?,%s,?,?,?,?)", ExecUtil::misctest(), blobPlaceholder),
use(strings), use(strings),
use(blobs), use(blobs),
use(ints), use(ints),
@ -183,14 +260,14 @@ public:
} catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
try { session() << "DELETE FROM MiscTest", now; } try { session() << "DELETE FROM "<< ExecUtil::misctest(), now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
try try
{ {
session() << session() <<
Poco::format("INSERT INTO MiscTest VALUES (?,%s,?,?,?,?)", blobPlaceholder), Poco::format("INSERT INTO %s VALUES (?,%s,?,?,?,?)", ExecUtil::misctest(), blobPlaceholder),
use(strings, bulk), use(strings, bulk),
use(blobs, bulk), use(blobs, bulk),
use(ints, bulk), use(ints, bulk),
@ -209,7 +286,7 @@ public:
try try
{ {
session() << "SELECT * FROM MiscTest ORDER BY Third", session() << "SELECT * FROM "<< ExecUtil::misctest() <<" ORDER BY Third",
into(strings), into(strings),
into(blobs), into(blobs),
into(ints), into(ints),
@ -239,14 +316,14 @@ public:
try try
{ {
session() << "SELECT First FROM MiscTest", into(ints, bulk(size)), limit(size+1), now; session() << "SELECT First FROM "<< ExecUtil::misctest(), into(ints, bulk(size)), limit(size+1), now;
fail ("must fail"); fail ("must fail");
} }
catch(Poco::InvalidArgumentException&){ } catch(Poco::InvalidArgumentException&){ }
try try
{ {
session() << "SELECT First FROM MiscTest", into(ints), bulk(size), now; session() << "SELECT First FROM "<< ExecUtil::misctest(), into(ints), bulk(size), now;
fail ("must fail"); fail ("must fail");
} }
catch(Poco::InvalidAccessException&){ } catch(Poco::InvalidAccessException&){ }
@ -263,7 +340,7 @@ public:
try try
{ {
session() << "SELECT First, Second, Third, Fourth, Fifth, Sixth FROM MiscTest ORDER BY Third", session() << "SELECT First, Second, Third, Fourth, Fifth, Sixth FROM "<< ExecUtil::misctest() <<" ORDER BY Third",
into(strings, bulk), into(strings, bulk),
into(blobs, bulk(size)), into(blobs, bulk(size)),
into(ints, bulk(size)), into(ints, bulk(size)),
@ -313,7 +390,7 @@ public:
try try
{ {
session() << "INSERT INTO MiscTest VALUES (?,?,?,?,?)", session() << "INSERT INTO "<< ExecUtil::misctest() <<" VALUES (?,?,?,?,?)",
use(strings), use(strings),
use(blobs), use(blobs),
use(ints), use(ints),
@ -322,13 +399,13 @@ public:
} catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
try { session() << "DELETE FROM MiscTest", now; } try { session() << "DELETE FROM "<< ExecUtil::misctest(), now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
try try
{ {
session() << "INSERT INTO MiscTest VALUES (?,?,?,?,?)", session() << "INSERT INTO "<< ExecUtil::misctest() <<" VALUES (?,?,?,?,?)",
use(strings, bulk), use(strings, bulk),
use(blobs, bulk), use(blobs, bulk),
use(ints, bulk), use(ints, bulk),
@ -345,7 +422,7 @@ public:
try try
{ {
session() << "SELECT * FROM MiscTest ORDER BY First", session() << "SELECT * FROM "<< ExecUtil::misctest() <<" ORDER BY First",
into(strings), into(strings),
into(blobs), into(blobs),
into(ints), into(ints),
@ -372,14 +449,14 @@ public:
try try
{ {
session() << "SELECT First FROM MiscTest", into(ints, bulk(size)), limit(size+1), now; session() << "SELECT First FROM "<< ExecUtil::misctest(), into(ints, bulk(size)), limit(size+1), now;
fail ("must fail"); fail ("must fail");
} }
catch(Poco::InvalidArgumentException&){ } catch(Poco::InvalidArgumentException&){ }
try try
{ {
session() << "SELECT First FROM MiscTest", into(ints), bulk(size), now; session() << "SELECT First FROM "<< ExecUtil::misctest(), into(ints), bulk(size), now;
fail ("must fail"); fail ("must fail");
} }
catch(Poco::InvalidAccessException&){ } catch(Poco::InvalidAccessException&){ }
@ -392,7 +469,7 @@ public:
try try
{ {
session() << "SELECT * FROM MiscTest ORDER BY First", session() << "SELECT * FROM "<< ExecUtil::misctest() <<" ORDER BY First",
into(strings, bulk(size)), into(strings, bulk(size)),
into(blobs, bulk(size)), into(blobs, bulk(size)),
into(ints, bulk(size)), into(ints, bulk(size)),
@ -435,6 +512,17 @@ public:
void singleSelect(); void singleSelect();
void emptyDB(); void emptyDB();
void assertImpl(bool condition, const std::string& conditionExpression, long lineNumber, const std::string& fileName)
{
assertImplementation(condition, conditionExpression, lineNumber, fileName);
}
void failImpl(const std::string& message, long lineNumber, const std::string& fileName)
{
fail(message, lineNumber, fileName);
}
void blob(int bigSize = 1024, const std::string& blobPlaceholder = "?"); void blob(int bigSize = 1024, const std::string& blobPlaceholder = "?");
template <typename C1, typename C2> template <typename C1, typename C2>
@ -448,16 +536,16 @@ public:
C1 address(size, "Address"); C1 address(size, "Address");
C2 img(size, CLOB("0123456789", 10)); C2 img(size, CLOB("0123456789", 10));
int count = 0; int count = 0;
try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(lastName), use(firstName), use(address), use(img), now; } try { session() << "INSERT INTO " << ExecUtil::person() << " VALUES (?,?,?,?)", use(lastName), use(firstName), use(address), use(img), now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
try { session() << "SELECT COUNT(*) FROM Person", into(count), now; } try { session() << "SELECT COUNT(*) FROM " << ExecUtil::person(), into(count), now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
assert (count == size); assert (count == size);
C2 res; C2 res;
try { session() << "SELECT Image FROM Person", into(res), now; } try { session() << "SELECT Image FROM " << ExecUtil::person(), into(res), now; }
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
assert (res.size() == img.size()); assert (res.size() == img.size());
@ -476,13 +564,13 @@ public:
void internalExtraction(); void internalExtraction();
void filter(const std::string& query = void filter(const std::string& query =
"SELECT * FROM Vectors ORDER BY int0 ASC", "SELECT * FROM " + ExecUtil::vectors() + " ORDER BY i0 ASC",
const std::string& intFldName = "int0"); const std::string& intFldName = "i0");
void internalBulkExtraction(); void internalBulkExtraction();
void internalBulkExtractionUTF16(); void internalBulkExtractionUTF16();
void internalStorageType(); void internalStorageType();
void nulls(); void nulls(bool emptyStrIsSpace = false);
void notNulls(const std::string& sqlState = "23502"); void notNulls(const std::string& sqlState = "23502");
void rowIterator(); void rowIterator();
void stdVectorBool(); void stdVectorBool();
@ -493,9 +581,11 @@ public:
void dynamicAny(); void dynamicAny();
void multipleResults(const std::string& sql = void multipleResults(const std::string& sql =
"SELECT * FROM Person WHERE Age = ?; " "SELECT * FROM " + ExecUtil::person() + " WHERE Age = ?; "
"SELECT Age FROM Person WHERE FirstName = 'Bart'; " "SELECT Age FROM " + ExecUtil::person() +" WHERE FirstName = 'Bart'; "
"SELECT * FROM Person WHERE Age = ? OR Age = ? ORDER BY Age;"); "SELECT * FROM " + ExecUtil::person() + " WHERE Age = ? OR Age = ? ORDER BY Age;");
void multipleResultsNoProj(const std::string& sql);
void sqlChannel(const std::string& connect); void sqlChannel(const std::string& connect);
void sqlLogger(const std::string& connect); void sqlLogger(const std::string& connect);
@ -514,9 +604,12 @@ private:
static const std::string MULTI_SELECT; static const std::string MULTI_SELECT;
void setTransactionIsolation(Poco::Data::Session& session, Poco::UInt32 ti); void setTransactionIsolation(Poco::Data::Session& session, Poco::UInt32 ti);
std::string schemaTable(const std::string& tblName) const;
Poco::Data::Session& session(); Poco::Data::Session& session();
Poco::Data::Session* _pSession; Poco::Data::Session* _pSession;
std::string _connInitSql;
std::string _schemaName;
}; };
@ -527,4 +620,10 @@ inline Poco::Data::Session& SQLExecutor::session()
} }
inline std::string SQLExecutor::schemaTable(const std::string& tblName) const
{
return _schemaName.empty() ? tblName : _schemaName + "." + tblName;
}
#endif // SQLExecutor_INCLUDED #endif // SQLExecutor_INCLUDED

View File

@ -43,72 +43,72 @@ public:
~Binder(); ~Binder();
/// Destroys the Binder. /// Destroys the Binder.
void bind(std::size_t pos, const Poco::Int8 &val, Direction dir); void bind(std::size_t pos, const Poco::Int8 &val, Direction dir, const WhenNullCb& nullCb);
/// Binds an Int8. /// Binds an Int8.
void bind(std::size_t pos, const Poco::UInt8 &val, Direction dir); void bind(std::size_t pos, const Poco::UInt8 &val, Direction dir, const WhenNullCb& nullCb);
/// Binds an UInt8. /// Binds an UInt8.
void bind(std::size_t pos, const Poco::Int16 &val, Direction dir); void bind(std::size_t pos, const Poco::Int16 &val, Direction dir, const WhenNullCb& nullCb);
/// Binds an Int16. /// Binds an Int16.
void bind(std::size_t pos, const Poco::UInt16 &val, Direction dir); void bind(std::size_t pos, const Poco::UInt16 &val, Direction dir, const WhenNullCb& nullCb);
/// Binds an UInt16. /// Binds an UInt16.
void bind(std::size_t pos, const Poco::Int32 &val, Direction dir); void bind(std::size_t pos, const Poco::Int32 &val, Direction dir, const WhenNullCb& nullCb);
/// Binds an Int32. /// Binds an Int32.
void bind(std::size_t pos, const Poco::UInt32 &val, Direction dir); void bind(std::size_t pos, const Poco::UInt32 &val, Direction dir, const WhenNullCb& nullCb);
/// Binds an UInt32. /// Binds an UInt32.
void bind(std::size_t pos, const Poco::Int64 &val, Direction dir); void bind(std::size_t pos, const Poco::Int64 &val, Direction dir, const WhenNullCb& nullCb);
/// Binds an Int64. /// Binds an Int64.
void bind(std::size_t pos, const Poco::UInt64 &val, Direction dir); void bind(std::size_t pos, const Poco::UInt64 &val, Direction dir, const WhenNullCb& nullCb);
/// Binds an UInt64. /// Binds an UInt64.
#ifndef POCO_LONG_IS_64_BIT #ifndef POCO_LONG_IS_64_BIT
void bind(std::size_t pos, const long &val, Direction dir); void bind(std::size_t pos, const long &val, Direction dir, const WhenNullCb& nullCb);
/// Binds a long /// Binds a long
void bind(std::size_t pos, const unsigned long &val, Direction dir); void bind(std::size_t pos, const unsigned long &val, Direction dir, const WhenNullCb& nullCb);
/// Binds an unsigned long /// Binds an unsigned long
#endif #endif
void bind(std::size_t pos, const bool &val, Direction dir); void bind(std::size_t pos, const bool &val, Direction dir, const WhenNullCb& nullCb);
/// Binds a boolean. /// Binds a boolean.
void bind(std::size_t pos, const float &val, Direction dir); void bind(std::size_t pos, const float &val, Direction dir, const WhenNullCb& nullCb);
/// Binds a float. /// Binds a float.
void bind(std::size_t pos, const double &val, Direction dir); void bind(std::size_t pos, const double &val, Direction dir, const WhenNullCb& nullCb);
/// Binds a double. /// Binds a double.
void bind(std::size_t pos, const char &val, Direction dir); void bind(std::size_t pos, const char &val, Direction dir, const WhenNullCb& nullCb);
/// Binds a single character. /// Binds a single character.
void bind(std::size_t pos, const char* const &pVal, Direction dir); void bind(std::size_t pos, const char* const &pVal, Direction dir, const WhenNullCb& nullCb);
/// Binds a const char ptr. /// Binds a const char ptr.
void bind(std::size_t pos, const std::string& val, Direction dir); void bind(std::size_t pos, const std::string& val, Direction dir, const WhenNullCb& nullCb);
/// Binds a string. /// Binds a string.
void bind(std::size_t pos, const Poco::Data::BLOB& val, Direction dir); void bind(std::size_t pos, const Poco::Data::BLOB& val, Direction dir, const WhenNullCb& nullCb);
/// Binds a BLOB. /// Binds a BLOB.
void bind(std::size_t pos, const Poco::Data::CLOB& val, Direction dir); void bind(std::size_t pos, const Poco::Data::CLOB& val, Direction dir, const WhenNullCb& nullCb);
/// Binds a CLOB. /// Binds a CLOB.
void bind(std::size_t pos, const Date& val, Direction dir); void bind(std::size_t pos, const Date& val, Direction dir, const WhenNullCb& nullCb);
/// Binds a Date. /// Binds a Date.
void bind(std::size_t pos, const Time& val, Direction dir); void bind(std::size_t pos, const Time& val, Direction dir, const WhenNullCb& nullCb);
/// Binds a Time. /// Binds a Time.
void bind(std::size_t pos, const DateTime& val, Direction dir); void bind(std::size_t pos, const DateTime& val, Direction dir, const WhenNullCb& nullCb);
/// Binds a DateTime. /// Binds a DateTime.
void bind(std::size_t pos, const NullData& val, Direction dir); void bind(std::size_t pos, const NullData& val, Direction dir, const std::type_info& bindType);
/// Binds a null. /// Binds a null.
private: private:
@ -117,7 +117,7 @@ private:
/// if error has occurred. /// if error has occurred.
template <typename T> template <typename T>
void bindLOB(std::size_t pos, const Poco::Data::LOB<T>& val, Direction dir) void bindLOB(std::size_t pos, const Poco::Data::LOB<T>& val, Direction dir, const WhenNullCb& nullCb)
{ {
// convert a blob to a an unsigned char* array // convert a blob to a an unsigned char* array
const T* pData = reinterpret_cast<const T*>(val.rawContent()); const T* pData = reinterpret_cast<const T*>(val.rawContent());
@ -134,85 +134,85 @@ private:
// //
// inlines // inlines
// //
inline void Binder::bind(std::size_t pos, const Poco::Int8 &val, Direction dir) inline void Binder::bind(std::size_t pos, const Poco::Int8 &val, Direction dir, const WhenNullCb& nullCb)
{ {
Poco::Int32 tmp = val; Poco::Int32 tmp = val;
bind(pos, tmp, dir); bind(pos, tmp, dir, nullCb);
} }
inline void Binder::bind(std::size_t pos, const Poco::UInt8 &val, Direction dir) inline void Binder::bind(std::size_t pos, const Poco::UInt8 &val, Direction dir, const WhenNullCb& nullCb)
{ {
Poco::Int32 tmp = val; Poco::Int32 tmp = val;
bind(pos, tmp, dir); bind(pos, tmp, dir, nullCb);
} }
inline void Binder::bind(std::size_t pos, const Poco::Int16 &val, Direction dir) inline void Binder::bind(std::size_t pos, const Poco::Int16 &val, Direction dir, const WhenNullCb& nullCb)
{ {
Poco::Int32 tmp = val; Poco::Int32 tmp = val;
bind(pos, tmp, dir); bind(pos, tmp, dir, nullCb);
} }
inline void Binder::bind(std::size_t pos, const Poco::UInt16 &val, Direction dir) inline void Binder::bind(std::size_t pos, const Poco::UInt16 &val, Direction dir, const WhenNullCb& nullCb)
{ {
Poco::Int32 tmp = val; Poco::Int32 tmp = val;
bind(pos, tmp, dir); bind(pos, tmp, dir, nullCb);
} }
inline void Binder::bind(std::size_t pos, const Poco::UInt32 &val, Direction dir) inline void Binder::bind(std::size_t pos, const Poco::UInt32 &val, Direction dir, const WhenNullCb& nullCb)
{ {
Poco::Int32 tmp = static_cast<Poco::Int32>(val); Poco::Int32 tmp = static_cast<Poco::Int32>(val);
bind(pos, tmp, dir); bind(pos, tmp, dir, nullCb);
} }
inline void Binder::bind(std::size_t pos, const Poco::UInt64 &val, Direction dir) inline void Binder::bind(std::size_t pos, const Poco::UInt64 &val, Direction dir, const WhenNullCb& nullCb)
{ {
Poco::Int64 tmp = static_cast<Poco::Int64>(val); Poco::Int64 tmp = static_cast<Poco::Int64>(val);
bind(pos, tmp, dir); bind(pos, tmp, dir, nullCb);
} }
inline void Binder::bind(std::size_t pos, const bool &val, Direction dir) inline void Binder::bind(std::size_t pos, const bool &val, Direction dir, const WhenNullCb& nullCb)
{ {
Poco::Int32 tmp = (val ? 1 : 0); Poco::Int32 tmp = (val ? 1 : 0);
bind(pos, tmp, dir); bind(pos, tmp, dir, nullCb);
} }
inline void Binder::bind(std::size_t pos, const float &val, Direction dir) inline void Binder::bind(std::size_t pos, const float &val, Direction dir, const WhenNullCb& nullCb)
{ {
double tmp = val; double tmp = val;
bind(pos, tmp, dir); bind(pos, tmp, dir, nullCb);
} }
inline void Binder::bind(std::size_t pos, const char &val, Direction dir) inline void Binder::bind(std::size_t pos, const char &val, Direction dir, const WhenNullCb& nullCb)
{ {
Poco::Int32 tmp = val; Poco::Int32 tmp = val;
bind(pos, tmp, dir); bind(pos, tmp, dir, nullCb);
} }
inline void Binder::bind(std::size_t pos, const char* const &pVal, Direction dir) inline void Binder::bind(std::size_t pos, const char* const &pVal, Direction dir, const WhenNullCb& nullCb)
{ {
std::string val(pVal); std::string val(pVal);
bind(pos, val, dir); bind(pos, val, dir, nullCb);
} }
inline void Binder::bind(std::size_t pos, const Poco::Data::BLOB& val, Direction dir) inline void Binder::bind(std::size_t pos, const Poco::Data::BLOB& val, Direction dir, const WhenNullCb& nullCb)
{ {
bindLOB<Poco::Data::BLOB::ValueType>(pos, val, dir); bindLOB<Poco::Data::BLOB::ValueType>(pos, val, dir, nullCb);
} }
inline void Binder::bind(std::size_t pos, const Poco::Data::CLOB& val, Direction dir) inline void Binder::bind(std::size_t pos, const Poco::Data::CLOB& val, Direction dir, const WhenNullCb& nullCb)
{ {
bindLOB<Poco::Data::CLOB::ValueType>(pos, val, dir); bindLOB<Poco::Data::CLOB::ValueType>(pos, val, dir, nullCb);
} }

View File

@ -60,7 +60,7 @@ protected:
/// All changes are counted, even if they are later undone by a ROLLBACK or ABORT. /// All changes are counted, even if they are later undone by a ROLLBACK or ABORT.
/// Changes associated with creating and dropping tables are not counted. /// Changes associated with creating and dropping tables are not counted.
const MetaColumn& metaColumn(std::size_t pos) const; const MetaColumn& metaColumn(std::size_t pos, std::size_t dataSet) const;
/// Returns column meta data. /// Returns column meta data.
bool hasNext(); bool hasNext();

View File

@ -44,14 +44,14 @@ Binder::~Binder()
} }
void Binder::bind(std::size_t pos, const Poco::Int32 &val, Direction dir) void Binder::bind(std::size_t pos, const Poco::Int32 &val, Direction dir, const WhenNullCb& nullCb)
{ {
int rc = sqlite3_bind_int(_pStmt, (int) pos, val); int rc = sqlite3_bind_int(_pStmt, (int) pos, val);
checkReturn(rc); checkReturn(rc);
} }
void Binder::bind(std::size_t pos, const Poco::Int64 &val, Direction dir) void Binder::bind(std::size_t pos, const Poco::Int64 &val, Direction dir, const WhenNullCb& nullCb)
{ {
int rc = sqlite3_bind_int64(_pStmt, (int) pos, val); int rc = sqlite3_bind_int64(_pStmt, (int) pos, val);
checkReturn(rc); checkReturn(rc);
@ -59,14 +59,14 @@ void Binder::bind(std::size_t pos, const Poco::Int64 &val, Direction dir)
#ifndef POCO_LONG_IS_64_BIT #ifndef POCO_LONG_IS_64_BIT
void Binder::bind(std::size_t pos, const long &val, Direction dir) void Binder::bind(std::size_t pos, const long &val, Direction dir, const WhenNullCb& nullCb)
{ {
long tmp = static_cast<long>(val); long tmp = static_cast<long>(val);
int rc = sqlite3_bind_int(_pStmt, (int) pos, tmp); int rc = sqlite3_bind_int(_pStmt, (int) pos, tmp);
checkReturn(rc); checkReturn(rc);
} }
void Binder::bind(std::size_t pos, const unsigned long &val, Direction dir) void Binder::bind(std::size_t pos, const unsigned long &val, Direction dir, const WhenNullCb& nullCb)
{ {
long tmp = static_cast<long>(val); long tmp = static_cast<long>(val);
int rc = sqlite3_bind_int(_pStmt, (int) pos, tmp); int rc = sqlite3_bind_int(_pStmt, (int) pos, tmp);
@ -75,45 +75,45 @@ void Binder::bind(std::size_t pos, const unsigned long &val, Direction dir)
#endif #endif
void Binder::bind(std::size_t pos, const double &val, Direction dir) void Binder::bind(std::size_t pos, const double &val, Direction dir, const WhenNullCb& nullCb)
{ {
int rc = sqlite3_bind_double(_pStmt, (int) pos, val); int rc = sqlite3_bind_double(_pStmt, (int) pos, val);
checkReturn(rc); checkReturn(rc);
} }
void Binder::bind(std::size_t pos, const std::string& val, Direction dir) void Binder::bind(std::size_t pos, const std::string& val, Direction dir, const WhenNullCb& nullCb)
{ {
int rc = sqlite3_bind_text(_pStmt, (int) pos, val.c_str(), (int) val.size()*sizeof(char), SQLITE_TRANSIENT); int rc = sqlite3_bind_text(_pStmt, (int) pos, val.c_str(), (int) val.size()*sizeof(char), SQLITE_TRANSIENT);
checkReturn(rc); checkReturn(rc);
} }
void Binder::bind(std::size_t pos, const Date& val, Direction dir) void Binder::bind(std::size_t pos, const Date& val, Direction dir, const WhenNullCb& nullCb)
{ {
DateTime dt(val.year(), val.month(), val.day()); DateTime dt(val.year(), val.month(), val.day());
std::string str(DateTimeFormatter::format(dt, Utility::SQLITE_DATE_FORMAT)); std::string str(DateTimeFormatter::format(dt, Utility::SQLITE_DATE_FORMAT));
bind(pos, str, dir); bind(pos, str, dir, nullCb);
} }
void Binder::bind(std::size_t pos, const Time& val, Direction dir) void Binder::bind(std::size_t pos, const Time& val, Direction dir, const WhenNullCb& nullCb)
{ {
DateTime dt; DateTime dt;
dt.assign(dt.year(), dt.month(), dt.day(), val.hour(), val.minute(), val.second()); dt.assign(dt.year(), dt.month(), dt.day(), val.hour(), val.minute(), val.second());
std::string str(DateTimeFormatter::format(dt, Utility::SQLITE_TIME_FORMAT)); std::string str(DateTimeFormatter::format(dt, Utility::SQLITE_TIME_FORMAT));
bind(pos, str, dir); bind(pos, str, dir, nullCb);
} }
void Binder::bind(std::size_t pos, const DateTime& val, Direction dir) void Binder::bind(std::size_t pos, const DateTime& val, Direction dir, const WhenNullCb& nullCb)
{ {
std::string dt(DateTimeFormatter::format(val, DateTimeFormat::ISO8601_FORMAT)); std::string dt(DateTimeFormatter::format(val, DateTimeFormat::ISO8601_FORMAT));
bind(pos, dt, dir); bind(pos, dt, dir, nullCb);
} }
void Binder::bind(std::size_t pos, const NullData&, Direction) void Binder::bind(std::size_t pos, const NullData&, Direction, const std::type_info& bindType)
{ {
sqlite3_bind_null(_pStmt, pos); sqlite3_bind_null(_pStmt, pos);
} }

View File

@ -302,11 +302,10 @@ std::size_t SQLiteStatementImpl::columnsReturned() const
} }
const MetaColumn& SQLiteStatementImpl::metaColumn(std::size_t pos) const const MetaColumn& SQLiteStatementImpl::metaColumn(std::size_t pos, std::size_t dataSet) const
{ {
std::size_t curDataSet = currentDataSet(); poco_assert (pos >= 0 && pos <= _columns[dataSet].size());
poco_assert (pos >= 0 && pos <= _columns[curDataSet].size()); return _columns[dataSet][pos];
return _columns[curDataSet][pos];
} }

View File

@ -39,24 +39,86 @@ namespace Poco {
namespace Data { namespace Data {
typedef NullType NullData; enum NullData
{
NULL_GENERIC = Poco::NULL_GENERIC,
DATA_NULL_INTEGER = 1,
DATA_NULL_STRING = 2,
DATA_NULL_DATE = 3,
DATA_NULL_TIME = 4,
DATA_NULL_DATETIME = 5,
DATA_NULL_BLOB = 6,
DATA_NULL_FLOAT = 7
};
struct NullValue
{
NullValue()
{}
template <typename T>
operator Poco::Nullable<T>() const
{
return Poco::Nullable<T>();
}
template <typename T>
static NullData nullCode()
{
return Data::NULL_GENERIC;
}
};
namespace Keywords { namespace Keywords {
static const NullValue null;
static const NullData null = NULL_GENERIC;
} // namespace Keywords } // namespace Keywords
template <typename T>
inline bool operator==(const NullValue& nv, const Nullable<T>& n)
{
return n.isNull();
}
template <typename T>
inline bool operator!=(const NullValue& nv, const Nullable<T>& n)
{
return !n.isNull();
}
class Data_API AbstractBinder class Data_API AbstractBinder
/// Interface for Binding data types to placeholders. /// Interface for Binding data types to placeholders.
{ {
public: public:
typedef SharedPtr<AbstractBinder> Ptr; typedef SharedPtr<AbstractBinder> Ptr;
struct WhenNullCb
{
WhenNullCb() :_func(NULL)
{}
inline bool defined() const
{
return (_func != NULL);
}
inline void onNull()
{
if (_func) _func(_data);
}
protected:
void* _data;
void (*_func)(void*);
};
enum Direction enum Direction
/// Binding direction for a parameter. /// Binding direction for a parameter.
{ {
@ -71,7 +133,7 @@ public:
virtual ~AbstractBinder(); virtual ~AbstractBinder();
/// Destroys the AbstractBinder. /// Destroys the AbstractBinder.
virtual void bind(std::size_t pos, const Poco::Int8& val, Direction dir = PD_IN) = 0; virtual void bind(std::size_t pos, const Poco::Int8& val, Direction dir = PD_IN, const WhenNullCb& nullCb = WhenNullCb()) = 0;
/// Binds an Int8. /// Binds an Int8.
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::vector<Poco::Int8>& val, Direction dir = PD_IN);
@ -83,7 +145,7 @@ public:
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::list<Poco::Int8>& val, Direction dir = PD_IN);
/// Binds an Int8 list. /// Binds an Int8 list.
virtual void bind(std::size_t pos, const Poco::UInt8& val, Direction dir = PD_IN) = 0; virtual void bind(std::size_t pos, const Poco::UInt8& val, Direction dir = PD_IN, const WhenNullCb& nullCb = WhenNullCb()) = 0;
/// Binds an UInt8. /// Binds an UInt8.
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::vector<Poco::UInt8>& val, Direction dir = PD_IN);
@ -95,7 +157,7 @@ public:
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::list<Poco::UInt8>& val, Direction dir = PD_IN);
/// Binds an UInt8 list. /// Binds an UInt8 list.
virtual void bind(std::size_t pos, const Poco::Int16& val, Direction dir = PD_IN) = 0; virtual void bind(std::size_t pos, const Poco::Int16& val, Direction dir = PD_IN, const WhenNullCb& nullCb = WhenNullCb()) = 0;
/// Binds an Int16. /// Binds an Int16.
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::vector<Poco::Int16>& val, Direction dir = PD_IN);
@ -107,7 +169,7 @@ public:
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::list<Poco::Int16>& val, Direction dir = PD_IN);
/// Binds an Int16 list. /// Binds an Int16 list.
virtual void bind(std::size_t pos, const Poco::UInt16& val, Direction dir = PD_IN) = 0; virtual void bind(std::size_t pos, const Poco::UInt16& val, Direction dir = PD_IN, const WhenNullCb& nullCb = WhenNullCb()) = 0;
/// Binds an UInt16. /// Binds an UInt16.
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::vector<Poco::UInt16>& val, Direction dir = PD_IN);
@ -119,7 +181,7 @@ public:
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::list<Poco::UInt16>& val, Direction dir = PD_IN);
/// Binds an UInt16 list. /// Binds an UInt16 list.
virtual void bind(std::size_t pos, const Poco::Int32& val, Direction dir = PD_IN) = 0; virtual void bind(std::size_t pos, const Poco::Int32& val, Direction dir = PD_IN, const WhenNullCb& nullCb = WhenNullCb()) = 0;
/// Binds an Int32. /// Binds an Int32.
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::vector<Poco::Int32>& val, Direction dir = PD_IN);
@ -131,7 +193,7 @@ public:
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::list<Poco::Int32>& val, Direction dir = PD_IN);
/// Binds an Int32 list. /// Binds an Int32 list.
virtual void bind(std::size_t pos, const Poco::UInt32& val, Direction dir = PD_IN) = 0; virtual void bind(std::size_t pos, const Poco::UInt32& val, Direction dir = PD_IN, const WhenNullCb& nullCb = WhenNullCb()) = 0;
/// Binds an UInt32. /// Binds an UInt32.
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::vector<Poco::UInt32>& val, Direction dir = PD_IN);
@ -143,7 +205,7 @@ public:
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::list<Poco::UInt32>& val, Direction dir = PD_IN);
/// Binds an UInt32 list. /// Binds an UInt32 list.
virtual void bind(std::size_t pos, const Poco::Int64& val, Direction dir = PD_IN) = 0; virtual void bind(std::size_t pos, const Poco::Int64& val, Direction dir = PD_IN, const WhenNullCb& nullCb = WhenNullCb()) = 0;
/// Binds an Int64. /// Binds an Int64.
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::vector<Poco::Int64>& val, Direction dir = PD_IN);
@ -155,7 +217,7 @@ public:
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::list<Poco::Int64>& val, Direction dir = PD_IN);
/// Binds an Int64 list. /// Binds an Int64 list.
virtual void bind(std::size_t pos, const Poco::UInt64& val, Direction dir = PD_IN) = 0; virtual void bind(std::size_t pos, const Poco::UInt64& val, Direction dir = PD_IN, const WhenNullCb& nullCb = WhenNullCb()) = 0;
/// Binds an UInt64. /// Binds an UInt64.
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::vector<Poco::UInt64>& val, Direction dir = PD_IN);
@ -168,11 +230,11 @@ public:
/// Binds an UInt64 list. /// Binds an UInt64 list.
#ifndef POCO_LONG_IS_64_BIT #ifndef POCO_LONG_IS_64_BIT
virtual void bind(std::size_t pos, const long& val, Direction dir = PD_IN) = 0; virtual void bind(std::size_t pos, const long& val, Direction dir = PD_IN, const WhenNullCb& nullCb = WhenNullCb()) = 0;
/// Binds a long. /// Binds a long.
virtual void bind(std::size_t pos, const unsigned long& val, Direction dir = PD_IN) = 0; virtual void bind(std::size_t pos, const unsigned long& val, Direction dir = PD_IN, const WhenNullCb& nullCb = WhenNullCb()) = 0;
/// Binds an unsigned long. /// Binds an unsiged long.
virtual void bind(std::size_t pos, const std::vector<long>& val, Direction dir = PD_IN); virtual void bind(std::size_t pos, const std::vector<long>& val, Direction dir = PD_IN);
/// Binds a long vector. /// Binds a long vector.
@ -184,7 +246,7 @@ public:
/// Binds a long list. /// Binds a long list.
#endif #endif
virtual void bind(std::size_t pos, const bool& val, Direction dir = PD_IN) = 0; virtual void bind(std::size_t pos, const bool& val, Direction dir = PD_IN, const WhenNullCb& nullCb = WhenNullCb()) = 0;
/// Binds a boolean. /// Binds a boolean.
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::vector<bool>& val, Direction dir = PD_IN);
@ -196,7 +258,7 @@ public:
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::list<bool>& val, Direction dir = PD_IN);
/// Binds a boolean list. /// Binds a boolean list.
virtual void bind(std::size_t pos, const float& val, Direction dir = PD_IN) = 0; virtual void bind(std::size_t pos, const float& val, Direction dir = PD_IN, const WhenNullCb& nullCb = WhenNullCb()) = 0;
/// Binds a float. /// Binds a float.
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::vector<float>& val, Direction dir = PD_IN);
@ -208,7 +270,7 @@ public:
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::list<float>& val, Direction dir = PD_IN);
/// Binds a float list. /// Binds a float list.
virtual void bind(std::size_t pos, const double& val, Direction dir = PD_IN) = 0; virtual void bind(std::size_t pos, const double& val, Direction dir = PD_IN, const WhenNullCb& nullCb = WhenNullCb()) = 0;
/// Binds a double. /// Binds a double.
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::vector<double>& val, Direction dir = PD_IN);
@ -220,7 +282,7 @@ public:
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::list<double>& val, Direction dir = PD_IN);
/// Binds a double list. /// Binds a double list.
virtual void bind(std::size_t pos, const char& val, Direction dir = PD_IN) = 0; virtual void bind(std::size_t pos, const char& val, Direction dir = PD_IN, const WhenNullCb& nullCb = WhenNullCb()) = 0;
/// Binds a single character. /// Binds a single character.
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::vector<char>& val, Direction dir = PD_IN);
@ -232,10 +294,10 @@ public:
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::list<char>& val, Direction dir = PD_IN);
/// Binds a character list. /// Binds a character list.
virtual void bind(std::size_t pos, const char* const& pVal, Direction dir = PD_IN) = 0; virtual void bind(std::size_t pos, const char* const& pVal, Direction dir = PD_IN, const WhenNullCb& nullCb = WhenNullCb()) = 0;
/// Binds a const char ptr. /// Binds a const char ptr.
virtual void bind(std::size_t pos, const std::string& val, Direction dir = PD_IN) = 0; virtual void bind(std::size_t pos, const std::string& val, Direction dir = PD_IN, const WhenNullCb& nullCb = WhenNullCb()) = 0;
/// Binds a string. /// Binds a string.
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::vector<std::string>& val, Direction dir = PD_IN);
@ -247,7 +309,7 @@ public:
virtual void bind(std::size_t pos, const std::list<std::string>& val, Direction dir = PD_IN); virtual void bind(std::size_t pos, const std::list<std::string>& val, Direction dir = PD_IN);
/// Binds a string list. /// Binds a string list.
virtual void bind(std::size_t pos, const UTF16String& val, Direction dir = PD_IN); virtual void bind(std::size_t pos, const UTF16String& val, Direction dir = PD_IN, const WhenNullCb& nullCb = WhenNullCb());
/// Binds a UTF-16 Unicode string. /// Binds a UTF-16 Unicode string.
virtual void bind(std::size_t pos, const std::vector<UTF16String>& val, Direction dir = PD_IN); virtual void bind(std::size_t pos, const std::vector<UTF16String>& val, Direction dir = PD_IN);
@ -259,10 +321,10 @@ public:
virtual void bind(std::size_t pos, const std::list<UTF16String>& val, Direction dir = PD_IN); virtual void bind(std::size_t pos, const std::list<UTF16String>& val, Direction dir = PD_IN);
/// Binds a UTF-16 Unicode string list. /// Binds a UTF-16 Unicode string list.
virtual void bind(std::size_t pos, const BLOB& val, Direction dir = PD_IN) = 0; virtual void bind(std::size_t pos, const BLOB& val, Direction dir = PD_IN, const WhenNullCb& nullCb = WhenNullCb()) = 0;
/// Binds a BLOB. /// Binds a BLOB.
virtual void bind(std::size_t pos, const CLOB& val, Direction dir = PD_IN) = 0; virtual void bind(std::size_t pos, const CLOB& val, Direction dir = PD_IN, const WhenNullCb& nullCb = WhenNullCb()) = 0;
/// Binds a CLOB. /// Binds a CLOB.
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::vector<BLOB>& val, Direction dir = PD_IN);
@ -283,7 +345,7 @@ public:
virtual void bind(std::size_t pos, const std::list<CLOB>& val, Direction dir = PD_IN); virtual void bind(std::size_t pos, const std::list<CLOB>& val, Direction dir = PD_IN);
/// Binds a CLOB list. /// Binds a CLOB list.
virtual void bind(std::size_t pos, const DateTime& val, Direction dir = PD_IN) = 0; virtual void bind(std::size_t pos, const DateTime& val, Direction dir = PD_IN, const WhenNullCb& nullCb = WhenNullCb()) = 0;
/// Binds a DateTime. /// Binds a DateTime.
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::vector<DateTime>& val, Direction dir = PD_IN);
@ -295,7 +357,7 @@ public:
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::list<DateTime>& val, Direction dir = PD_IN);
/// Binds a DateTime list. /// Binds a DateTime list.
virtual void bind(std::size_t pos, const Date& val, Direction dir = PD_IN) = 0; virtual void bind(std::size_t pos, const Date& val, Direction dir = PD_IN, const WhenNullCb& nullCb = WhenNullCb()) = 0;
/// Binds a Date. /// Binds a Date.
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::vector<Date>& val, Direction dir = PD_IN);
@ -307,7 +369,7 @@ public:
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::list<Date>& val, Direction dir = PD_IN);
/// Binds a Date list. /// Binds a Date list.
virtual void bind(std::size_t pos, const Time& val, Direction dir = PD_IN) = 0; virtual void bind(std::size_t pos, const Time& val, Direction dir = PD_IN, const WhenNullCb& nullCb = WhenNullCb()) = 0;
/// Binds a Time. /// Binds a Time.
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::vector<Time>& val, Direction dir = PD_IN);
@ -319,22 +381,22 @@ public:
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::list<Time>& val, Direction dir = PD_IN);
/// Binds a Time list. /// Binds a Time list.
virtual void bind(std::size_t pos, const NullData& val, Direction dir = PD_IN) = 0; virtual void bind(std::size_t pos, const NullData& val, Direction dir = PD_IN, const std::type_info& bindType = typeid(void)) = 0;
/// Binds a null. /// Binds a null.
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::vector<NullData>& val, Direction dir = PD_IN, const std::type_info& bindElemType = typeid(void));
/// Binds a null vector. /// Binds a null vector.
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::deque<NullData>& val, Direction dir = PD_IN, const std::type_info& bindElemType = typeid(void));
/// Binds a null deque. /// Binds a null deque.
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::list<NullData>& val, Direction dir = PD_IN, const std::type_info& bindElemType = typeid(void));
/// Binds a null list. /// Binds a null list.
void bind(std::size_t pos, const Any& val, Direction dir = PD_IN); void bind(std::size_t pos, const Any& val, Direction dir = PD_IN, const WhenNullCb& nullCb = WhenNullCb());
/// Binds an Any. /// Binds an Any.
void bind(std::size_t pos, const Poco::Dynamic::Var& val, Direction dir = PD_IN); void bind(std::size_t pos, const Poco::Dynamic::Var& val, Direction dir = PD_IN, const WhenNullCb& nullCb = WhenNullCb());
/// Binds a Var. /// Binds a Var.
virtual void reset(); virtual void reset();

View File

@ -1401,6 +1401,13 @@ inline AbstractBinding::Ptr use(const NullData& t, const std::string& name = "")
return new Binding<NullData>(const_cast<NullData&>(t), name, AbstractBinding::PD_IN); return new Binding<NullData>(const_cast<NullData&>(t), name, AbstractBinding::PD_IN);
} }
inline AbstractBinding::Ptr use(const NullValue& t, const std::string& name = "")
/// NullData overload.
{
return use(NullValue::nullCode<void>(), name);
}
template <typename T> template <typename T>
inline AbstractBinding::Ptr useRef(T& t, const std::string& name = "") inline AbstractBinding::Ptr useRef(T& t, const std::string& name = "")

View File

@ -39,6 +39,43 @@ namespace Poco {
namespace Data { namespace Data {
template <typename CollTp, typename ElemTp = typename CollTp::value_type>
struct DefaultInitializer
{
static void appendElem(CollTp& coll, const ElemTp& defVal)
{
coll.push_back(defVal);
}
};
template <typename CollTp>
struct DefaultInitializer<CollTp, CLOB>
{
static void appendElem(CollTp& coll, const CLOB& defVal)
{
CLOB v(defVal.rawContent(), defVal.size());
coll.push_back(v);
}
};
template <typename CollTp>
struct DefaultInitializer<CollTp, BLOB>
{
static void appendElem(CollTp& coll, const BLOB& defVal)
{
BLOB v(defVal.rawContent(), defVal.size());
coll.push_back(v);
}
};
template <typename CollTp>
inline void appendElem(CollTp& coll, const typename CollTp::value_type& defVal)
{
DefaultInitializer<CollTp, typename CollTp::value_type>::appendElem(coll, defVal);
}
template <class T> template <class T>
class Extraction: public AbstractExtraction class Extraction: public AbstractExtraction
/// Concrete Data Type specific extraction of values from a query result set. /// Concrete Data Type specific extraction of values from a query result set.
@ -190,7 +227,7 @@ public:
std::size_t extract(std::size_t pos) std::size_t extract(std::size_t pos)
{ {
AbstractExtractor::Ptr pExt = getExtractor(); AbstractExtractor::Ptr pExt = getExtractor();
_rResult.push_back(_default); appendElem(_rResult, _default);
TypeHandler<T>::extract(pos, _rResult.back(), _default, pExt); TypeHandler<T>::extract(pos, _rResult.back(), _default, pExt);
_nulls.push_back(isValueNull(_rResult.back(), pExt->isNull(pos))); _nulls.push_back(isValueNull(_rResult.back(), pExt->isNull(pos)));
return 1u; return 1u;
@ -372,7 +409,7 @@ public:
std::size_t extract(std::size_t pos) std::size_t extract(std::size_t pos)
{ {
AbstractExtractor::Ptr pExt = getExtractor(); AbstractExtractor::Ptr pExt = getExtractor();
_rResult.push_back(_default); appendElem(_rResult, _default);
TypeHandler<T>::extract(pos, _rResult.back(), _default, pExt); TypeHandler<T>::extract(pos, _rResult.back(), _default, pExt);
_nulls.push_back(isValueNull(_rResult.back(), pExt->isNull(pos))); _nulls.push_back(isValueNull(_rResult.back(), pExt->isNull(pos)));
return 1u; return 1u;
@ -462,7 +499,7 @@ public:
std::size_t extract(std::size_t pos) std::size_t extract(std::size_t pos)
{ {
AbstractExtractor::Ptr pExt = getExtractor(); AbstractExtractor::Ptr pExt = getExtractor();
_rResult.push_back(_default); appendElem(_rResult, _default);
TypeHandler<T>::extract(pos, _rResult.back(), _default, pExt); TypeHandler<T>::extract(pos, _rResult.back(), _default, pExt);
_nulls.push_back(isValueNull(_rResult.back(), pExt->isNull(pos))); _nulls.push_back(isValueNull(_rResult.back(), pExt->isNull(pos)));
return 1u; return 1u;

View File

@ -32,26 +32,28 @@ class Data_API Position
/// indicate the recordset position in batch SQL statements. /// indicate the recordset position in batch SQL statements.
{ {
public: public:
Position(Poco::UInt32 value); typedef Poco::UInt32 PositionType;
Position(PositionType value);
/// Creates the Position. /// Creates the Position.
~Position(); ~Position();
/// Destroys the Position. /// Destroys the Position.
Poco::UInt32 value() const; PositionType value() const;
/// Returns the position value. /// Returns the position value.
private: private:
Position(); Position();
Poco::UInt32 _value; PositionType _value;
}; };
/// ///
/// inlines /// inlines
/// ///
inline Poco::UInt32 Position::value() const inline Position::PositionType Position::value() const
{ {
return _value; return _value;
} }

View File

@ -190,6 +190,10 @@ public:
/// Returns reference to row at position pos. /// Returns reference to row at position pos.
/// Rows are lazy-created and cached. /// Rows are lazy-created and cached.
template <class T>
const T& value(std::size_t col) const;
/// Returns the reference to data value at [col] location.
template <class T> template <class T>
const T& value(std::size_t col, std::size_t dataRow, bool useFilter = true) const const T& value(std::size_t col, std::size_t dataRow, bool useFilter = true) const
/// Returns the reference to data value at [col, row] location. /// Returns the reference to data value at [col, row] location.
@ -315,16 +319,16 @@ public:
/// Returns true if there is at least one row in the RecordSet, /// Returns true if there is at least one row in the RecordSet,
/// false otherwise. /// false otherwise.
Poco::Dynamic::Var value(const std::string& name); Poco::Dynamic::Var value(const std::string& name) const;
/// Returns the value in the named column of the current row. /// Returns the value in the named column of the current row.
Poco::Dynamic::Var value(std::size_t index); Poco::Dynamic::Var value(std::size_t index) const;
/// Returns the value in the given column of the current row. /// Returns the value in the given column of the current row.
Poco::Dynamic::Var operator [] (const std::string& name); Poco::Dynamic::Var operator [] (const std::string& name) const;
/// Returns the value in the named column of the current row. /// Returns the value in the named column of the current row.
Poco::Dynamic::Var operator [] (std::size_t index); Poco::Dynamic::Var operator [] (std::size_t index) const;
/// Returns the value in the named column of the current row. /// Returns the value in the named column of the current row.
MetaColumn::ColumnDataType columnType(std::size_t pos) const; MetaColumn::ColumnDataType columnType(std::size_t pos) const;
@ -353,6 +357,9 @@ public:
bool isNull(const std::string& name) const; bool isNull(const std::string& name) const;
/// Returns true if column value of the current row is null. /// Returns true if column value of the current row is null.
bool isNull(std::size_t& colNo) const;
/// Returns true if column value of the current row is null.
std::ostream& copyNames(std::ostream& os) const; std::ostream& copyNames(std::ostream& os) const;
/// Copies the column names to the target output stream. /// Copies the column names to the target output stream.
/// Copied string is formatted by the current RowFormatter. /// Copied string is formatted by the current RowFormatter.
@ -457,6 +464,8 @@ private:
} }
} }
size_t storageRowCount() const;
bool isAllowed(std::size_t row) const; bool isAllowed(std::size_t row) const;
/// Returns true if the specified row is allowed by the /// Returns true if the specified row is allowed by the
/// currently active filter. /// currently active filter.
@ -530,29 +539,35 @@ inline Statement& RecordSet::operator = (const Statement& stmt)
} }
inline Poco::Dynamic::Var RecordSet::value(const std::string& name) inline Poco::Dynamic::Var RecordSet::value(const std::string& name) const
{ {
return value(name, _currentRow); return value(name, _currentRow);
} }
inline Poco::Dynamic::Var RecordSet::value(std::size_t index) inline Poco::Dynamic::Var RecordSet::value(std::size_t index) const
{ {
return value(index, _currentRow); return value(index, _currentRow);
} }
inline Poco::Dynamic::Var RecordSet::operator [] (const std::string& name) inline Poco::Dynamic::Var RecordSet::operator [] (const std::string& name) const
{ {
return value(name, _currentRow); return value(name, _currentRow);
} }
inline Poco::Dynamic::Var RecordSet::operator [] (std::size_t index) inline Poco::Dynamic::Var RecordSet::operator [] (std::size_t index) const
{ {
return value(index, _currentRow); return value(index, _currentRow);
} }
template <class T>
inline const T& RecordSet::value(std::size_t col) const
{
return value<T>(col, _currentRow);
}
inline MetaColumn::ColumnDataType RecordSet::columnType(std::size_t pos)const inline MetaColumn::ColumnDataType RecordSet::columnType(std::size_t pos)const
{ {
@ -602,6 +617,11 @@ inline bool RecordSet::isNull(const std::string& name) const
} }
inline bool RecordSet::isNull(std::size_t& colNo) const
{
return isNull(colNo, _currentRow);
}
inline RecordSet::ConstIterator& RecordSet::begin() const inline RecordSet::ConstIterator& RecordSet::begin() const
{ {
return *_pBegin; return *_pBegin;
@ -638,6 +658,11 @@ inline void RecordSet::formatNames() const
} }
inline size_t RecordSet::storageRowCount() const
{
return impl()->rowsExtracted();
}
/* TODO /* TODO
namespace Keywords { namespace Keywords {

View File

@ -104,6 +104,15 @@ public:
Poco::Dynamic::Var& operator [] (const std::string& name); Poco::Dynamic::Var& operator [] (const std::string& name);
/// Returns the reference to data value at named column location. /// Returns the reference to data value at named column location.
const Poco::Dynamic::Var& get(std::size_t col) const;
/// Returns the reference to data value at column location.
const Poco::Dynamic::Var& operator [] (std::size_t col) const;
/// Returns the reference to data value at column location.
const Poco::Dynamic::Var& operator [] (const std::string& name) const;
/// Returns the reference to data value at named column location.
template <typename T> template <typename T>
void append(const std::string& name, const T& val) void append(const std::string& name, const T& val)
/// Appends the value to the row. /// Appends the value to the row.
@ -225,7 +234,7 @@ private:
ValueVec& values(); ValueVec& values();
/// Returns the reference to values vector. /// Returns the reference to values vector.
std::size_t getPosition(const std::string& name); std::size_t getPosition(const std::string& name) const;
bool isEqualSize(const Row& other) const; bool isEqualSize(const Row& other) const;
bool isEqualType(const Row& other) const; bool isEqualType(const Row& other) const;
@ -287,6 +296,18 @@ inline Poco::Dynamic::Var& Row::operator [] (const std::string& name)
} }
inline const Poco::Dynamic::Var& Row::operator [] (std::size_t col) const
{
return get(col);
}
inline const Poco::Dynamic::Var& Row::operator [] (const std::string& name) const
{
return get(getPosition(name));
}
inline const RowFormatter& Row::getFormatter() const inline const RowFormatter& Row::getFormatter() const
{ {
return *_pFormatter; return *_pFormatter;

View File

@ -365,10 +365,18 @@ public:
/// Returns false if the current data set index points to the last /// Returns false if the current data set index points to the last
/// data set. Otherwise, it returns true. /// data set. Otherwise, it returns true.
std::size_t firstDataSet();
/// Activates the first data set
std::size_t currentDataSet() const;
/// Returns the current data set.
void setRowFormatter(RowFormatter::Ptr pRowFormatter); void setRowFormatter(RowFormatter::Ptr pRowFormatter);
/// Sets the row formatter for this statement. /// Sets the row formatter for this statement.
/// Statement takes the ownership of the formatter. /// Statement takes the ownership of the formatter.
void insertHint();
/// Tells the statement that it is an sinsert one
protected: protected:
typedef StatementImpl::Ptr ImplPtr; typedef StatementImpl::Ptr ImplPtr;
@ -670,7 +678,7 @@ inline const AbstractExtractionVec& Statement::extractions() const
inline const MetaColumn& Statement::metaColumn(std::size_t pos) const inline const MetaColumn& Statement::metaColumn(std::size_t pos) const
{ {
return _pImpl->metaColumn(pos); return _pImpl->metaColumn(pos, _pImpl->currentDataSet());
} }
@ -770,6 +778,19 @@ inline bool Statement::isBulkExtraction() const
} }
inline std::size_t Statement::firstDataSet()
{
_pImpl->firstDataSet();
return 0;
}
inline std::size_t Statement::currentDataSet() const
{
return _pImpl->currentDataSet();
}
inline bool Statement::isAsync() const inline bool Statement::isAsync() const
{ {
return _async; return _async;
@ -789,6 +810,11 @@ inline const RowFormatter::Ptr& Statement::getRowFormatter()
} }
inline void Statement::insertHint()
{
_pImpl->insertHint();
}
inline void swap(Statement& s1, Statement& s2) inline void swap(Statement& s1, Statement& s2)
{ {
s1.swap(s2); s1.swap(s2);

View File

@ -44,6 +44,8 @@ namespace Poco {
namespace Data { namespace Data {
class RecordSet;
class Data_API StatementImpl class Data_API StatementImpl
/// StatementImpl interface that subclasses must implement to define database dependent query execution. /// StatementImpl interface that subclasses must implement to define database dependent query execution.
/// ///
@ -157,7 +159,13 @@ public:
std::size_t dataSetCount() const; std::size_t dataSetCount() const;
/// Returns the number of data sets associated with the statement. /// Returns the number of data sets associated with the statement.
std::size_t currentDataSet() const;
/// Returns the current data set.
protected: protected:
virtual void insertHint();
/// Hints the implementation that it is an insert statement
virtual std::size_t columnsReturned() const = 0; virtual std::size_t columnsReturned() const = 0;
/// Returns number of columns returned by query. /// Returns number of columns returned by query.
@ -169,7 +177,7 @@ protected:
/// some ODBC drivers when this function is called after a select statement /// some ODBC drivers when this function is called after a select statement
/// execution). /// execution).
virtual const MetaColumn& metaColumn(std::size_t pos) const = 0; virtual const MetaColumn& metaColumn(std::size_t pos, size_t dataSet) const = 0;
/// Returns column meta data. /// Returns column meta data.
const MetaColumn& metaColumn(const std::string& name) const; const MetaColumn& metaColumn(const std::string& name) const;
@ -252,6 +260,9 @@ protected:
/// - std::vector /// - std::vector
/// - std::list /// - std::list
void makeExtractors(std::size_t count, const Position& position);
/// Create extractors for the specified dataset
SessionImpl& session(); SessionImpl& session();
/// Returns session associated with this statement. /// Returns session associated with this statement.
@ -284,9 +295,6 @@ protected:
/// When connector-specific behavior is desired, it should be overriden /// When connector-specific behavior is desired, it should be overriden
/// by the statement implementation. /// by the statement implementation.
std::size_t currentDataSet() const;
/// Returns the current data set.
std::size_t activateNextDataSet(); std::size_t activateNextDataSet();
/// Returns the next data set index, or throws NoDataException if the last /// Returns the next data set index, or throws NoDataException if the last
/// data set was reached. /// data set was reached.
@ -295,10 +303,14 @@ protected:
/// Returns the previous data set index, or throws NoDataException if the last /// Returns the previous data set index, or throws NoDataException if the last
/// data set was reached. /// data set was reached.
void firstDataSet();
/// Activate first data set
bool hasMoreDataSets() const; bool hasMoreDataSets() const;
/// Returns true if there are data sets not activated yet. /// Returns true if there are data sets not activated yet.
private: private:
void compile(); void compile();
/// Compiles the statement. /// Compiles the statement.
@ -319,26 +331,26 @@ private:
/// Resets extraction so it can be reused again. /// Resets extraction so it can be reused again.
template <class C> template <class C>
SharedPtr<InternalExtraction<C> > createExtract(const MetaColumn& mc) SharedPtr<InternalExtraction<C> > createExtract(const MetaColumn& mc, size_t position)
{ {
C* pData = new C; C* pData = new C;
Column<C>* pCol = new Column<C>(mc, pData); Column<C>* pCol = new Column<C>(mc, pData);
return new InternalExtraction<C>(*pData, pCol, Poco::UInt32(currentDataSet())); return new InternalExtraction<C>(*pData, pCol, Poco::UInt32(position));
} }
template <class C> template <class C>
SharedPtr<InternalBulkExtraction<C> > createBulkExtract(const MetaColumn& mc) SharedPtr<InternalBulkExtraction<C> > createBulkExtract(const MetaColumn& mc, size_t position)
{ {
C* pData = new C; C* pData = new C;
Column<C>* pCol = new Column<C>(mc, pData); Column<C>* pCol = new Column<C>(mc, pData);
return new InternalBulkExtraction<C>(*pData, return new InternalBulkExtraction<C>(*pData,
pCol, pCol,
static_cast<Poco::UInt32>(getExtractionLimit()), static_cast<Poco::UInt32>(getExtractionLimit()),
Position(static_cast<Poco::UInt32>(currentDataSet()))); Position(static_cast<Poco::UInt32>(position)));
} }
template <class T> template <class T>
void addInternalExtract(const MetaColumn& mc) void addInternalExtract(const MetaColumn& mc, size_t position)
/// Creates and adds the internal extraction. /// Creates and adds the internal extraction.
/// ///
/// The decision about internal extraction container is done /// The decision about internal extraction container is done
@ -370,23 +382,23 @@ private:
if (0 == icompare(DEQUE, storage)) if (0 == icompare(DEQUE, storage))
{ {
if (!isBulkExtraction()) if (!isBulkExtraction())
addExtract(createExtract<std::deque<T> >(mc)); addExtract(createExtract<std::deque<T> >(mc, position));
else else
addExtract(createBulkExtract<std::deque<T> >(mc)); addExtract(createBulkExtract<std::deque<T> >(mc, position));
} }
else if (0 == icompare(VECTOR, storage)) else if (0 == icompare(VECTOR, storage))
{ {
if (!isBulkExtraction()) if (!isBulkExtraction())
addExtract(createExtract<std::vector<T> >(mc)); addExtract(createExtract<std::vector<T> >(mc, position));
else else
addExtract(createBulkExtract<std::vector<T> >(mc)); addExtract(createBulkExtract<std::vector<T> >(mc, position));
} }
else if (0 == icompare(LIST, storage)) else if (0 == icompare(LIST, storage))
{ {
if (!isBulkExtraction()) if (!isBulkExtraction())
addExtract(createExtract<std::list<T> >(mc)); addExtract(createExtract<std::list<T> >(mc, position));
else else
addExtract(createBulkExtract<std::list<T> >(mc)); addExtract(createBulkExtract<std::list<T> >(mc, position));
} }
} }
@ -427,7 +439,7 @@ private:
void formatSQL(std::vector<Any>& arguments); void formatSQL(std::vector<Any>& arguments);
/// Formats the SQL string by filling in placeholders with values from supplied vector. /// Formats the SQL string by filling in placeholders with values from supplied vector.
void assignSubTotal(bool reset); void assignSubTotal(bool reset, size_t firstDs);
StatementImpl(const StatementImpl& stmt); StatementImpl(const StatementImpl& stmt);
StatementImpl& operator = (const StatementImpl& stmt); StatementImpl& operator = (const StatementImpl& stmt);
@ -444,11 +456,13 @@ private:
AbstractBindingVec _bindings; AbstractBindingVec _bindings;
AbstractExtractionVecVec _extractors; AbstractExtractionVecVec _extractors;
std::size_t _curDataSet; std::size_t _curDataSet;
std::size_t _pendingDSNo;
BulkType _bulkBinding; BulkType _bulkBinding;
BulkType _bulkExtraction; BulkType _bulkExtraction;
CountVec _subTotalRowCount; CountVec _subTotalRowCount;
friend class Statement; friend class Statement;
friend class RecordSet;
}; };
@ -627,6 +641,13 @@ inline bool StatementImpl::hasMoreDataSets() const
} }
inline void StatementImpl::firstDataSet()
{
_curDataSet = 0;
_pendingDSNo = 0;
}
} } // namespace Poco::Data } } // namespace Poco::Data

View File

@ -254,6 +254,21 @@ template <typename T>
class TypeHandler<Nullable<T> > class TypeHandler<Nullable<T> >
/// Specialization of type handler for Nullable. /// Specialization of type handler for Nullable.
{ {
class NullHandler : public AbstractBinder::WhenNullCb
{
public:
explicit NullHandler(const Nullable<T>& obj)
{
_data = &const_cast<Nullable<T>&>(obj);
_func = handle;
}
private:
static void handle(void* ptr)
{
reinterpret_cast<Nullable<T>*>(ptr)->clear();
}
};
public: public:
static void bind(std::size_t pos, const Nullable<T>& obj, AbstractBinder::Ptr pBinder, AbstractBinder::Direction dir) static void bind(std::size_t pos, const Nullable<T>& obj, AbstractBinder::Ptr pBinder, AbstractBinder::Direction dir)
@ -261,10 +276,13 @@ public:
poco_assert_dbg (!pBinder.isNull()); poco_assert_dbg (!pBinder.isNull());
if (obj.isNull()) if (obj.isNull())
{ {
pBinder->bind(pos++, Poco::Data::Keywords::null, dir); pBinder->bind(pos++, NullValue::nullCode<T>(), dir, typeid(T));
} }
else else
{ {
if (AbstractBinder::isOutBound(dir))
pBinder->bind(pos++, obj.value(), dir, NullHandler(obj));
else
pBinder->bind(pos++, obj.value(), dir); pBinder->bind(pos++, obj.value(), dir);
} }
} }
@ -274,7 +292,7 @@ public:
poco_assert_dbg (!pPreparator.isNull()); poco_assert_dbg (!pPreparator.isNull());
if (obj.isNull()) if (obj.isNull())
{ {
pPreparator->prepare(pos++, Poco::Data::Keywords::null); pPreparator->prepare(pos++, NullValue::nullCode<T>());
} }
else else
{ {

View File

@ -292,7 +292,7 @@ void AbstractBinder::bind(std::size_t pos, const std::list<std::string>& val, Di
} }
void AbstractBinder::bind(std::size_t pos, const UTF16String& val, Direction dir) void AbstractBinder::bind(std::size_t pos, const UTF16String& val, Direction dir, const WhenNullCb& nullCb)
{ {
throw NotImplementedException("UTF16String binder must be implemented."); throw NotImplementedException("UTF16String binder must be implemented.");
} }
@ -406,120 +406,124 @@ void AbstractBinder::bind(std::size_t pos, const std::list<Time>& val, Direction
} }
void AbstractBinder::bind(std::size_t pos, const std::vector<NullData>& val, Direction dir) void AbstractBinder::bind(std::size_t pos, const std::vector<NullData>& val, Direction dir, const std::type_info& bindElemType)
{ {
throw NotImplementedException("std::vector binder must be implemented."); throw NotImplementedException("std::vector binder must be implemented.");
} }
void AbstractBinder::bind(std::size_t pos, const std::deque<NullData>& val, Direction dir) void AbstractBinder::bind(std::size_t pos, const std::deque<NullData>& val, Direction dir, const std::type_info& bindElemType)
{ {
throw NotImplementedException("std::deque binder must be implemented."); throw NotImplementedException("std::deque binder must be implemented.");
} }
void AbstractBinder::bind(std::size_t pos, const std::list<NullData>& val, Direction dir) void AbstractBinder::bind(std::size_t pos, const std::list<NullData>& val, Direction dir, const std::type_info& bindElemType)
{ {
throw NotImplementedException("std::list binder must be implemented."); throw NotImplementedException("std::list binder must be implemented.");
} }
void AbstractBinder::bind(std::size_t pos, const Any& val, Direction dir) void AbstractBinder::bind(std::size_t pos, const Any& val, Direction dir, const WhenNullCb& nullCb)
{ {
const std::type_info& type = val.type(); const std::type_info& type = val.type();
if(type == typeid(Int32)) if(type == typeid(Int32))
bind(pos, RefAnyCast<Int32>(val), dir); bind(pos, RefAnyCast<Int32>(val), dir, nullCb);
else if(type == typeid(std::string)) else if(type == typeid(std::string))
bind(pos, RefAnyCast<std::string>(val), dir); bind(pos, RefAnyCast<std::string>(val), dir, nullCb);
else if (type == typeid(Poco::UTF16String)) else if (type == typeid(Poco::UTF16String))
bind(pos, RefAnyCast<Poco::UTF16String>(val), dir); bind(pos, RefAnyCast<Poco::UTF16String>(val), dir, nullCb);
else if (type == typeid(bool)) else if (type == typeid(bool))
bind(pos, RefAnyCast<bool>(val), dir); bind(pos, RefAnyCast<bool>(val), dir, nullCb);
else if(type == typeid(char)) else if(type == typeid(char))
bind(pos, RefAnyCast<char>(val), dir); bind(pos, RefAnyCast<char>(val), dir, nullCb);
else if(type == typeid(Int8)) else if(type == typeid(Int8))
bind(pos, RefAnyCast<Int8>(val), dir); bind(pos, RefAnyCast<Int8>(val), dir, nullCb);
else if(type == typeid(UInt8)) else if(type == typeid(UInt8))
bind(pos, RefAnyCast<UInt8>(val), dir); bind(pos, RefAnyCast<UInt8>(val), dir, nullCb);
else if(type == typeid(Int16)) else if(type == typeid(Int16))
bind(pos, RefAnyCast<Int16>(val), dir); bind(pos, RefAnyCast<Int16>(val), dir, nullCb);
else if(type == typeid(UInt16)) else if(type == typeid(UInt16))
bind(pos, RefAnyCast<UInt16>(val), dir); bind(pos, RefAnyCast<UInt16>(val), dir, nullCb);
else if(type == typeid(UInt32)) else if(type == typeid(UInt32))
bind(pos, RefAnyCast<UInt32>(val), dir); bind(pos, RefAnyCast<UInt32>(val), dir, nullCb);
else if(type == typeid(Int64)) else if(type == typeid(Int64))
bind(pos, RefAnyCast<Int64>(val), dir); bind(pos, RefAnyCast<Int64>(val), dir, nullCb);
else if(type == typeid(UInt64)) else if(type == typeid(UInt64))
bind(pos, RefAnyCast<UInt64>(val), dir); bind(pos, RefAnyCast<UInt64>(val), dir, nullCb);
else if(type == typeid(float)) else if(type == typeid(float))
bind(pos, RefAnyCast<float>(val), dir); bind(pos, RefAnyCast<float>(val), dir, nullCb);
else if(type == typeid(double)) else if(type == typeid(double))
bind(pos, RefAnyCast<double>(val), dir); bind(pos, RefAnyCast<double>(val), dir, nullCb);
else if(type == typeid(DateTime)) else if(type == typeid(DateTime))
bind(pos, RefAnyCast<DateTime>(val), dir); bind(pos, RefAnyCast<DateTime>(val), dir, nullCb);
else if(type == typeid(Date)) else if(type == typeid(Date))
bind(pos, RefAnyCast<Date>(val), dir); bind(pos, RefAnyCast<Date>(val), dir, nullCb);
else if(type == typeid(Time)) else if(type == typeid(Time))
bind(pos, RefAnyCast<Time>(val), dir); bind(pos, RefAnyCast<Time>(val), dir, nullCb);
else if(type == typeid(BLOB)) else if(type == typeid(BLOB))
bind(pos, RefAnyCast<BLOB>(val), dir); bind(pos, RefAnyCast<BLOB>(val), dir, nullCb);
else if(type == typeid(void)) else if(type == typeid(void))
bind(pos, Keywords::null, dir); bind(pos, NULL_GENERIC, dir, type);
#ifndef POCO_LONG_IS_64_BIT #ifndef POCO_LONG_IS_64_BIT
else if(type == typeid(long)) else if(type == typeid(long))
bind(pos, RefAnyCast<long>(val), dir); bind(pos, RefAnyCast<long>(val), dir, nullCb);
#endif #endif
else else
throw UnknownTypeException(std::string(val.type().name())); throw UnknownTypeException(std::string(val.type().name()));
} }
void AbstractBinder::bind(std::size_t pos, const Poco::Dynamic::Var& val, Direction dir) void AbstractBinder::bind(std::size_t pos, const Poco::Dynamic::Var& val, Direction dir, const WhenNullCb& nullCb)
{ {
const std::type_info& type = val.type(); const std::type_info& type = val.type();
if(type == typeid(Int32)) if(type == typeid(Int32))
bind(pos, val.extract<Int32>(), dir); bind(pos, val.extract<Int32>(), dir, nullCb);
else if(type == typeid(std::string)) else if(type == typeid(std::string))
bind(pos, val.extract<std::string>(), dir); bind(pos, val.extract<std::string>(), dir, nullCb);
else if (type == typeid(Poco::UTF16String)) else if (type == typeid(Poco::UTF16String))
bind(pos, val.extract<Poco::UTF16String>(), dir); bind(pos, val.extract<Poco::UTF16String>(), dir, nullCb);
else if (type == typeid(bool)) else if (type == typeid(bool))
bind(pos, val.extract<bool>(), dir); bind(pos, val.extract<bool>(), dir, nullCb);
else if(type == typeid(char)) else if(type == typeid(char))
bind(pos, val.extract<char>(), dir); bind(pos, val.extract<char>(), dir, nullCb);
else if(type == typeid(Int8)) else if(type == typeid(Int8))
bind(pos, val.extract<Int8>(), dir); bind(pos, val.extract<Int8>(), dir, nullCb);
else if(type == typeid(UInt8)) else if(type == typeid(UInt8))
bind(pos, val.extract<UInt8>(), dir); bind(pos, val.extract<UInt8>(), dir, nullCb);
else if(type == typeid(Int16)) else if(type == typeid(Int16))
bind(pos, val.extract<Int16>(), dir); bind(pos, val.extract<Int16>(), dir, nullCb);
else if(type == typeid(UInt16)) else if(type == typeid(UInt16))
bind(pos, val.extract<UInt16>(), dir); bind(pos, val.extract<UInt16>(), dir, nullCb);
else if(type == typeid(UInt32)) else if(type == typeid(UInt32))
bind(pos, val.extract<UInt32>(), dir); bind(pos, val.extract<UInt32>(), dir, nullCb);
else if(type == typeid(Int64)) else if(type == typeid(Int64))
bind(pos, val.extract<Int64>(), dir); bind(pos, val.extract<Int64>(), dir, nullCb);
else if(type == typeid(UInt64)) else if(type == typeid(UInt64))
bind(pos, val.extract<UInt64>(), dir); bind(pos, val.extract<UInt64>(), dir, nullCb);
else if(type == typeid(float)) else if(type == typeid(float))
bind(pos, val.extract<float>(), dir); bind(pos, val.extract<float>(), dir, nullCb);
else if(type == typeid(double)) else if(type == typeid(double))
bind(pos, val.extract<double>(), dir); bind(pos, val.extract<double>(), dir, nullCb);
else if(type == typeid(DateTime)) else if(type == typeid(DateTime))
bind(pos, val.extract<DateTime>(), dir); bind(pos, val.extract<DateTime>(), dir, nullCb);
else if(type == typeid(Date)) else if(type == typeid(Date))
bind(pos, val.extract<Date>(), dir); bind(pos, val.extract<Date>(), dir, nullCb);
else if(type == typeid(Time)) else if(type == typeid(Time))
bind(pos, val.extract<Time>(), dir); bind(pos, val.extract<Time>(), dir, nullCb);
else if(type == typeid(BLOB)) else if(type == typeid(BLOB))
bind(pos, val.extract<BLOB>(), dir); bind(pos, val.extract<BLOB>(), dir, nullCb);
else if(type == typeid(void)) else if(type == typeid(void))
bind(pos, Keywords::null, dir); bind(pos, NULL_GENERIC, dir, type);
else if (type == typeid(NullData))
bind(pos, val.extract<NullData>(), dir, type);
else if (type == typeid(NullType))
bind(pos, static_cast<NullData>(val.extract<NullType>()), dir, type);
#ifndef POCO_LONG_IS_64_BIT #ifndef POCO_LONG_IS_64_BIT
else if(type == typeid(long)) else if(type == typeid(long))
bind(pos, val.extract<long>(), dir); bind(pos, val.extract<long>(), dir, nullCb);
#endif #endif
else else
throw UnknownTypeException(std::string(val.type().name())); throw UnknownTypeException(std::string(val.type().name()));

View File

@ -200,8 +200,10 @@ Row& RecordSet::row(std::size_t pos)
std::size_t RecordSet::rowCount() const std::size_t RecordSet::rowCount() const
{ {
if (0 == extractions().size() && 0 == columnsExtracted())
return 0;
poco_assert (extractions().size()); poco_assert (extractions().size());
std::size_t rc = subTotalRowCount(); std::size_t rc = storageRowCount();
if (!isFiltered()) return rc; if (!isFiltered()) return rc;
std::size_t counter = 0; std::size_t counter = 0;
@ -223,7 +225,8 @@ bool RecordSet::isAllowed(std::size_t dataRow) const
bool RecordSet::moveFirst() bool RecordSet::moveFirst()
{ {
if (subTotalRowCount() > 0) const size_t rc = storageRowCount();
if (rc > 0)
{ {
if (!isFiltered()) if (!isFiltered())
{ {
@ -235,7 +238,7 @@ bool RecordSet::moveFirst()
currentRow = 0; currentRow = 0;
while (!isAllowed(currentRow)) while (!isAllowed(currentRow))
{ {
if (currentRow >= subTotalRowCount() - 1) return false; if (currentRow >= rc - 1) return false;
++currentRow; ++currentRow;
} }
@ -251,7 +254,7 @@ bool RecordSet::moveNext()
std::size_t currentRow = _currentRow; std::size_t currentRow = _currentRow;
do do
{ {
if (currentRow >= subTotalRowCount() - 1) return false; if (currentRow >= storageRowCount() -1) return false;
++currentRow; ++currentRow;
} while (isFiltered() && !isAllowed(currentRow)); } while (isFiltered() && !isAllowed(currentRow));
@ -276,10 +279,10 @@ bool RecordSet::movePrevious()
bool RecordSet::moveLast() bool RecordSet::moveLast()
{ {
if (subTotalRowCount() > 0) if (storageRowCount() > 0)
{ {
std::size_t currentRow = _currentRow; std::size_t currentRow = _currentRow;
currentRow = subTotalRowCount() - 1; currentRow = storageRowCount() - 1;
if (!isFiltered()) if (!isFiltered())
{ {
_currentRow = currentRow; _currentRow = currentRow;

View File

@ -94,7 +94,20 @@ Poco::Dynamic::Var& Row::get(std::size_t col)
} }
std::size_t Row::getPosition(const std::string& name) const Poco::Dynamic::Var& Row::get(std::size_t col) const
{
try
{
return _values.at(col);
}
catch (std::out_of_range& re)
{
throw RangeException(re.what());
}
}
std::size_t Row::getPosition(const std::string& name) const
{ {
if (!_pNames) if (!_pNames)
throw NullPointerException(); throw NullPointerException();

View File

@ -69,7 +69,7 @@ void RowIterator::increment() const
if (POSITION_END == _position) if (POSITION_END == _position)
throw RangeException("End of iterator reached."); throw RangeException("End of iterator reached.");
if (_position < _pRecordSet->subTotalRowCount() - 1) if (_position < _pRecordSet->storageRowCount() - 1)
++_position; ++_position;
else else
_position = POSITION_END; _position = POSITION_END;
@ -90,7 +90,7 @@ void RowIterator::decrement() const
if (0 == _position) if (0 == _position)
throw RangeException("Beginning of iterator reached."); throw RangeException("Beginning of iterator reached.");
else if (POSITION_END == _position) else if (POSITION_END == _position)
_position = _pRecordSet->subTotalRowCount() - 1; _position = _pRecordSet->storageRowCount() - 1;
else else
--_position; --_position;
@ -126,15 +126,15 @@ void RowIterator::setPosition(std::size_t pos) const
std::size_t end = pos - _position; std::size_t end = pos - _position;
for (; start < end; ++start) for (; start < end; ++start)
{ {
if (_pRecordSet->subTotalRowCount() != pos) ++pos; if (_pRecordSet->storageRowCount() != pos) ++pos;
else throw RangeException("Invalid position argument."); else throw RangeException("Invalid position argument.");
} }
} }
} }
if (pos < _pRecordSet->subTotalRowCount()) if (pos < _pRecordSet->storageRowCount())
_position = pos; _position = pos;
else if (pos == _pRecordSet->subTotalRowCount()) else if (pos == _pRecordSet->storageRowCount())
_position = POSITION_END; _position = POSITION_END;
else else
throw RangeException("Invalid position argument."); throw RangeException("Invalid position argument.");

View File

@ -52,6 +52,7 @@ StatementImpl::StatementImpl(SessionImpl& rSession):
_storage(STORAGE_UNKNOWN_IMPL), _storage(STORAGE_UNKNOWN_IMPL),
_ostr(), _ostr(),
_curDataSet(0), _curDataSet(0),
_pendingDSNo(0),
_bulkBinding(BULK_UNDEFINED), _bulkBinding(BULK_UNDEFINED),
_bulkExtraction(BULK_UNDEFINED) _bulkExtraction(BULK_UNDEFINED)
{ {
@ -83,6 +84,10 @@ std::size_t StatementImpl::execute(const bool& rReset)
if (_lowerLimit > _extrLimit.value()) if (_lowerLimit > _extrLimit.value())
throw LimitException("Illegal Statement state. Upper limit must not be smaller than the lower limit."); throw LimitException("Illegal Statement state. Upper limit must not be smaller than the lower limit.");
size_t pds = _pendingDSNo;
while (pds > currentDataSet()) activateNextDataSet();
const size_t savedDs = currentDataSet();
do do
{ {
compile(); compile();
@ -92,25 +97,30 @@ std::size_t StatementImpl::execute(const bool& rReset)
lim += executeWithLimit(); lim += executeWithLimit();
} while (canCompile()); } while (canCompile());
// rewind ds back here!!!!
pds = currentDataSet();
while (savedDs < currentDataSet()) activatePreviousDataSet();
_pendingDSNo = pds;
if (_extrLimit.value() == Limit::LIMIT_UNLIMITED) if (_extrLimit.value() == Limit::LIMIT_UNLIMITED)
_state = ST_DONE; _state = ST_DONE;
assignSubTotal(rReset, savedDs);
if (lim < _lowerLimit) if (lim < _lowerLimit)
throw LimitException("Did not receive enough data."); throw LimitException("Did not receive enough data.");
assignSubTotal(rReset);
return lim; return lim;
} }
void StatementImpl::assignSubTotal(bool doReset) void StatementImpl::assignSubTotal(bool doReset, size_t firstDs)
{ {
if (_extractors.size() == _subTotalRowCount.size()) if (_extractors.size() == _subTotalRowCount.size())
{ {
CountVec::iterator it = _subTotalRowCount.begin(); CountVec::iterator it = _subTotalRowCount.begin() + firstDs;
CountVec::iterator end = _subTotalRowCount.end(); CountVec::iterator end = _subTotalRowCount.end();
for (int counter = 0; it != end; ++it, ++counter) for (size_t counter = firstDs; it != end; ++it, ++counter)
{ {
if (_extractors[counter].size()) if (_extractors[counter].size())
{ {
@ -139,7 +149,7 @@ std::size_t StatementImpl::executeWithLimit()
if (!canBind() && (!hasNext() || limit == 0)) if (!canBind() && (!hasNext() || limit == 0))
_state = ST_DONE; _state = ST_DONE;
else if (hasNext() && limit == count && _extrLimit.isHardLimit()) else if (limit == count && _extrLimit.isHardLimit() && hasNext())
throw LimitException("HardLimit reached (retrieved more data than requested)."); throw LimitException("HardLimit reached (retrieved more data than requested).");
else else
_state = ST_PAUSED; _state = ST_PAUSED;
@ -246,10 +256,6 @@ void StatementImpl::setBulkExtraction(const Bulk& b)
void StatementImpl::fixupExtraction() void StatementImpl::fixupExtraction()
{ {
CountVec::iterator sIt = _subTotalRowCount.begin();
CountVec::iterator sEnd = _subTotalRowCount.end();
for (; sIt != sEnd; ++sIt) *sIt = 0;
if (_curDataSet >= _columnsExtracted.size()) if (_curDataSet >= _columnsExtracted.size())
{ {
_columnsExtracted.resize(_curDataSet + 1, 0); _columnsExtracted.resize(_curDataSet + 1, 0);
@ -311,46 +317,54 @@ void StatementImpl::setStorage(const std::string& storage)
void StatementImpl::makeExtractors(std::size_t count) void StatementImpl::makeExtractors(std::size_t count)
{
// type cast is needed when size_t is 64 bit
makeExtractors(count, static_cast<Position::PositionType>(currentDataSet()));
}
void StatementImpl::makeExtractors(std::size_t count, const Position& position)
{ {
for (int i = 0; i < count; ++i) for (int i = 0; i < count; ++i)
{ {
const MetaColumn& mc = metaColumn(i); const MetaColumn& mc = metaColumn(i, position.value());
switch (mc.type()) switch (mc.type())
{ {
case MetaColumn::FDT_BOOL: case MetaColumn::FDT_BOOL:
addInternalExtract<bool>(mc); break; addInternalExtract<bool>(mc, position.value()); break;
case MetaColumn::FDT_INT8: case MetaColumn::FDT_INT8:
addInternalExtract<Int8>(mc); break; addInternalExtract<Int8>(mc, position.value()); break;
case MetaColumn::FDT_UINT8: case MetaColumn::FDT_UINT8:
addInternalExtract<UInt8>(mc); break; addInternalExtract<UInt8>(mc, position.value()); break;
case MetaColumn::FDT_INT16: case MetaColumn::FDT_INT16:
addInternalExtract<Int16>(mc); break; addInternalExtract<Int16>(mc, position.value()); break;
case MetaColumn::FDT_UINT16: case MetaColumn::FDT_UINT16:
addInternalExtract<UInt16>(mc); break; addInternalExtract<UInt16>(mc, position.value()); break;
case MetaColumn::FDT_INT32: case MetaColumn::FDT_INT32:
addInternalExtract<Int32>(mc); break; addInternalExtract<Int32>(mc, position.value()); break;
case MetaColumn::FDT_UINT32: case MetaColumn::FDT_UINT32:
addInternalExtract<UInt32>(mc); break; addInternalExtract<UInt32>(mc, position.value()); break;
case MetaColumn::FDT_INT64: case MetaColumn::FDT_INT64:
addInternalExtract<Int64>(mc); break; addInternalExtract<Int64>(mc, position.value()); break;
case MetaColumn::FDT_UINT64: case MetaColumn::FDT_UINT64:
addInternalExtract<UInt64>(mc); break; addInternalExtract<UInt64>(mc, position.value()); break;
case MetaColumn::FDT_FLOAT: case MetaColumn::FDT_FLOAT:
addInternalExtract<float>(mc); break; addInternalExtract<float>(mc, position.value()); break;
case MetaColumn::FDT_DOUBLE: case MetaColumn::FDT_DOUBLE:
addInternalExtract<double>(mc); break; addInternalExtract<double>(mc, position.value()); break;
case MetaColumn::FDT_STRING: case MetaColumn::FDT_STRING:
addInternalExtract<std::string>(mc); break; addInternalExtract<std::string>(mc, position.value()); break;
case MetaColumn::FDT_WSTRING: case MetaColumn::FDT_WSTRING:
addInternalExtract<Poco::UTF16String>(mc); break; addInternalExtract<Poco::UTF16String>(mc, position.value()); break;
case MetaColumn::FDT_BLOB: case MetaColumn::FDT_BLOB:
addInternalExtract<BLOB>(mc); break; addInternalExtract<BLOB>(mc, position.value()); break;
case MetaColumn::FDT_CLOB:
addInternalExtract<CLOB>(mc, position.value()); break;
case MetaColumn::FDT_DATE: case MetaColumn::FDT_DATE:
addInternalExtract<Date>(mc); break; addInternalExtract<Date>(mc, position.value()); break;
case MetaColumn::FDT_TIME: case MetaColumn::FDT_TIME:
addInternalExtract<Time>(mc); break; addInternalExtract<Time>(mc, position.value()); break;
case MetaColumn::FDT_TIMESTAMP: case MetaColumn::FDT_TIMESTAMP:
addInternalExtract<DateTime>(mc); break; addInternalExtract<DateTime>(mc, position.value()); break;
default: default:
throw Poco::InvalidArgumentException("Data type not supported."); throw Poco::InvalidArgumentException("Data type not supported.");
} }
@ -363,7 +377,7 @@ const MetaColumn& StatementImpl::metaColumn(const std::string& name) const
std::size_t cols = columnsReturned(); std::size_t cols = columnsReturned();
for (std::size_t i = 0; i < cols; ++i) for (std::size_t i = 0; i < cols; ++i)
{ {
const MetaColumn& column = metaColumn(i); const MetaColumn& column = metaColumn(i, currentDataSet());
if (0 == icompare(column.name(), name)) return column; if (0 == icompare(column.name(), name)) return column;
} }
@ -374,7 +388,10 @@ const MetaColumn& StatementImpl::metaColumn(const std::string& name) const
std::size_t StatementImpl::activateNextDataSet() std::size_t StatementImpl::activateNextDataSet()
{ {
if (_curDataSet + 1 < dataSetCount()) if (_curDataSet + 1 < dataSetCount())
return ++_curDataSet; {
_pendingDSNo = ++_curDataSet;
return _curDataSet;
}
else else
throw NoDataException("End of data sets reached."); throw NoDataException("End of data sets reached.");
} }
@ -383,7 +400,10 @@ std::size_t StatementImpl::activateNextDataSet()
std::size_t StatementImpl::activatePreviousDataSet() std::size_t StatementImpl::activatePreviousDataSet()
{ {
if (_curDataSet > 0) if (_curDataSet > 0)
return --_curDataSet; {
_pendingDSNo = --_curDataSet;
return _curDataSet;
}
else else
throw NoDataException("Beginning of data sets reached."); throw NoDataException("Beginning of data sets reached.");
} }
@ -475,4 +495,8 @@ void StatementImpl::formatSQL(std::vector<Any>& arguments)
} }
void StatementImpl::insertHint()
{
}
} } // namespace Poco::Data } } // namespace Poco::Data

View File

@ -129,7 +129,7 @@
<AdditionalIncludeDirectories>..\include;..\..\CppUnit\include;..\..\CppUnit\WinTestRunner\include;..\..\Foundation\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\include;..\..\CppUnit\include;..\..\CppUnit\WinTestRunner\include;..\..\Foundation\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;WINVER=0x0600;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;WINVER=0x0600;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling> <StringPooling>true</StringPooling>
<MinimalRebuild>true</MinimalRebuild> <MinimalRebuild>false</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<BufferSecurityCheck>true</BufferSecurityCheck> <BufferSecurityCheck>true</BufferSecurityCheck>
@ -140,6 +140,7 @@
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
<Link> <Link>
<AdditionalDependencies>CppUnitd.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>CppUnitd.lib;%(AdditionalDependencies)</AdditionalDependencies>
@ -171,6 +172,7 @@
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat/> <DebugInformationFormat/>
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
<Link> <Link>
<AdditionalDependencies>CppUnit.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>CppUnit.lib;%(AdditionalDependencies)</AdditionalDependencies>
@ -189,7 +191,7 @@
<AdditionalIncludeDirectories>..\include;..\..\CppUnit\include;..\..\CppUnit\WinTestRunner\include;..\..\Foundation\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\include;..\..\CppUnit\include;..\..\CppUnit\WinTestRunner\include;..\..\Foundation\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;WINVER=0x0600;POCO_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;WINVER=0x0600;POCO_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling> <StringPooling>true</StringPooling>
<MinimalRebuild>true</MinimalRebuild> <MinimalRebuild>false</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<BufferSecurityCheck>true</BufferSecurityCheck> <BufferSecurityCheck>true</BufferSecurityCheck>
@ -200,6 +202,7 @@
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
<Link> <Link>
<AdditionalDependencies>CppUnitmtd.lib;iphlpapi.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>CppUnitmtd.lib;iphlpapi.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>
@ -231,6 +234,7 @@
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat/> <DebugInformationFormat/>
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
<Link> <Link>
<AdditionalDependencies>CppUnitmt.lib;iphlpapi.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>CppUnitmt.lib;iphlpapi.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>
@ -249,7 +253,7 @@
<AdditionalIncludeDirectories>..\include;..\..\CppUnit\include;..\..\CppUnit\WinTestRunner\include;..\..\Foundation\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\include;..\..\CppUnit\include;..\..\CppUnit\WinTestRunner\include;..\..\Foundation\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;WINVER=0x0600;POCO_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;WINVER=0x0600;POCO_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling> <StringPooling>true</StringPooling>
<MinimalRebuild>true</MinimalRebuild> <MinimalRebuild>false</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<BufferSecurityCheck>true</BufferSecurityCheck> <BufferSecurityCheck>true</BufferSecurityCheck>
@ -260,6 +264,7 @@
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
<Link> <Link>
<AdditionalDependencies>CppUnitmdd.lib;iphlpapi.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>CppUnitmdd.lib;iphlpapi.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>
@ -291,6 +296,7 @@
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat/> <DebugInformationFormat/>
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
<Link> <Link>
<AdditionalDependencies>CppUnitmd.lib;iphlpapi.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>CppUnitmd.lib;iphlpapi.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>

View File

@ -30,119 +30,119 @@ Binder::~Binder()
} }
void Binder::bind(std::size_t pos, const Poco::Int8 &val, Direction dir) void Binder::bind(std::size_t pos, const Poco::Int8 &val, Direction dir, const WhenNullCb& nullCb)
{ {
} }
void Binder::bind(std::size_t pos, const Poco::UInt8 &val, Direction dir) void Binder::bind(std::size_t pos, const Poco::UInt8 &val, Direction dir, const WhenNullCb& nullCb)
{ {
} }
void Binder::bind(std::size_t pos, const Poco::Int16 &val, Direction dir) void Binder::bind(std::size_t pos, const Poco::Int16 &val, Direction dir, const WhenNullCb& nullCb)
{ {
} }
void Binder::bind(std::size_t pos, const Poco::UInt16 &val, Direction dir) void Binder::bind(std::size_t pos, const Poco::UInt16 &val, Direction dir, const WhenNullCb& nullCb)
{ {
} }
void Binder::bind(std::size_t pos, const Poco::Int32 &val, Direction dir) void Binder::bind(std::size_t pos, const Poco::Int32 &val, Direction dir, const WhenNullCb& nullCb)
{ {
} }
void Binder::bind(std::size_t pos, const Poco::UInt32 &val, Direction dir) void Binder::bind(std::size_t pos, const Poco::UInt32 &val, Direction dir, const WhenNullCb& nullCb)
{ {
} }
void Binder::bind(std::size_t pos, const Poco::Int64 &val, Direction dir) void Binder::bind(std::size_t pos, const Poco::Int64 &val, Direction dir, const WhenNullCb& nullCb)
{ {
} }
void Binder::bind(std::size_t pos, const Poco::UInt64 &val, Direction dir) void Binder::bind(std::size_t pos, const Poco::UInt64 &val, Direction dir, const WhenNullCb& nullCb)
{ {
} }
#ifndef POCO_LONG_IS_64_BIT #ifndef POCO_LONG_IS_64_BIT
void Binder::bind(std::size_t pos, const long& val, Direction dir) void Binder::bind(std::size_t pos, const long& val, Direction dir, const WhenNullCb& nullCb)
{ {
} }
void Binder::bind(std::size_t pos, const unsigned long& val, Direction dir) void Binder::bind(std::size_t pos, const unsigned long& val, Direction dir, const WhenNullCb& nullCb)
{ {
} }
#endif #endif
void Binder::bind(std::size_t pos, const bool &val, Direction dir) void Binder::bind(std::size_t pos, const bool &val, Direction dir, const WhenNullCb& nullCb)
{ {
} }
void Binder::bind(std::size_t pos, const float &val, Direction dir) void Binder::bind(std::size_t pos, const float &val, Direction dir, const WhenNullCb& nullCb)
{ {
} }
void Binder::bind(std::size_t pos, const double &val, Direction dir) void Binder::bind(std::size_t pos, const double &val, Direction dir, const WhenNullCb& nullCb)
{ {
} }
void Binder::bind(std::size_t pos, const char &val, Direction dir) void Binder::bind(std::size_t pos, const char &val, Direction dir, const WhenNullCb& nullCb)
{ {
} }
void Binder::bind(std::size_t pos, const char* const &pVal, Direction dir) void Binder::bind(std::size_t pos, const char* const &pVal, Direction dir, const WhenNullCb& nullCb)
{ {
} }
void Binder::bind(std::size_t pos, const std::string& val, Direction dir) void Binder::bind(std::size_t pos, const std::string& val, Direction dir, const WhenNullCb& nullCb)
{ {
} }
void Binder::bind(std::size_t pos, const Poco::UTF16String& val, Direction dir) void Binder::bind(std::size_t pos, const Poco::UTF16String& val, Direction dir, const WhenNullCb& nullCb)
{ {
} }
void Binder::bind(std::size_t pos, const BLOB& val, Direction dir) void Binder::bind(std::size_t pos, const BLOB& val, Direction dir, const WhenNullCb& nullCb)
{ {
} }
void Binder::bind(std::size_t pos, const CLOB& val, Direction dir) void Binder::bind(std::size_t pos, const CLOB& val, Direction dir, const WhenNullCb& nullCb)
{ {
} }
void Binder::bind(std::size_t pos, const Date& val, Direction dir) void Binder::bind(std::size_t pos, const Date& val, Direction dir, const WhenNullCb& nullCb)
{ {
} }
void Binder::bind(std::size_t pos, const Time& val, Direction dir) void Binder::bind(std::size_t pos, const Time& val, Direction dir, const WhenNullCb& nullCb)
{ {
} }
void Binder::bind(std::size_t pos, const DateTime& val, Direction dir) void Binder::bind(std::size_t pos, const DateTime& val, Direction dir, const WhenNullCb& nullCb)
{ {
} }
void Binder::bind(std::size_t pos, const NullData& val, Direction dir) void Binder::bind(std::size_t pos, const NullData& val, Direction dir, const std::type_info& bindType)
{ {
} }

View File

@ -34,75 +34,75 @@ public:
~Binder(); ~Binder();
/// Destroys the Binder. /// Destroys the Binder.
void bind(std::size_t pos, const Poco::Int8 &val, Direction dir); void bind(std::size_t pos, const Poco::Int8 &val, Direction dir, const WhenNullCb& cb);
/// Binds an Int8. /// Binds an Int8.
void bind(std::size_t pos, const Poco::UInt8 &val, Direction dir); void bind(std::size_t pos, const Poco::UInt8 &val, Direction dir, const WhenNullCb& cb);
/// Binds an UInt8. /// Binds an UInt8.
void bind(std::size_t pos, const Poco::Int16 &val, Direction dir); void bind(std::size_t pos, const Poco::Int16 &val, Direction dir, const WhenNullCb& cb);
/// Binds an Int16. /// Binds an Int16.
void bind(std::size_t pos, const Poco::UInt16 &val, Direction dir); void bind(std::size_t pos, const Poco::UInt16 &val, Direction dir, const WhenNullCb& cb);
/// Binds an UInt16. /// Binds an UInt16.
void bind(std::size_t pos, const Poco::Int32 &val, Direction dir); void bind(std::size_t pos, const Poco::Int32 &val, Direction dir, const WhenNullCb& cb);
/// Binds an Int32. /// Binds an Int32.
void bind(std::size_t pos, const Poco::UInt32 &val, Direction dir); void bind(std::size_t pos, const Poco::UInt32 &val, Direction dir, const WhenNullCb& cb);
/// Binds an UInt32. /// Binds an UInt32.
void bind(std::size_t pos, const Poco::Int64 &val, Direction dir); void bind(std::size_t pos, const Poco::Int64 &val, Direction dir, const WhenNullCb& cb);
/// Binds an Int64. /// Binds an Int64.
void bind(std::size_t pos, const Poco::UInt64 &val, Direction dir); void bind(std::size_t pos, const Poco::UInt64 &val, Direction dir, const WhenNullCb& cb);
/// Binds an UInt64. /// Binds an UInt64.
#ifndef POCO_LONG_IS_64_BIT #ifndef POCO_LONG_IS_64_BIT
void bind(std::size_t pos, const long& val, Direction dir); void bind(std::size_t pos, const long& val, Direction dir, const WhenNullCb& cb);
/// Binds a long. /// Binds a long.
void bind(std::size_t pos, const unsigned long& val, Direction dir); void bind(std::size_t pos, const unsigned long& val, Direction dir, const WhenNullCb& cb);
/// Binds an unsigned long. /// Binds an unsigned long.
#endif #endif
void bind(std::size_t pos, const bool &val, Direction dir); void bind(std::size_t pos, const bool &val, Direction dir, const WhenNullCb& cb);
/// Binds a boolean. /// Binds a boolean.
void bind(std::size_t pos, const float &val, Direction dir); void bind(std::size_t pos, const float &val, Direction dir, const WhenNullCb& cb);
/// Binds a float. /// Binds a float.
void bind(std::size_t pos, const double &val, Direction dir); void bind(std::size_t pos, const double &val, Direction dir, const WhenNullCb& cb);
/// Binds a double. /// Binds a double.
void bind(std::size_t pos, const char &val, Direction dir); void bind(std::size_t pos, const char &val, Direction dir, const WhenNullCb& cb);
/// Binds a single character. /// Binds a single character.
void bind(std::size_t pos, const char* const &pVal, Direction dir); void bind(std::size_t pos, const char* const &pVal, Direction dir, const WhenNullCb& cb);
/// Binds a const char ptr. /// Binds a const char ptr.
void bind(std::size_t pos, const std::string& val, Direction dir); void bind(std::size_t pos, const std::string& val, Direction dir, const WhenNullCb& cb);
/// Binds a string. /// Binds a string.
void bind(std::size_t pos, const Poco::UTF16String& val, Direction dir); void bind(std::size_t pos, const Poco::UTF16String& val, Direction dir, const WhenNullCb& cb);
/// Binds a UTF16String. /// Binds a UTF16String.
void bind(std::size_t pos, const BLOB& val, Direction dir); void bind(std::size_t pos, const BLOB& val, Direction dir, const WhenNullCb& cb);
/// Binds a BLOB. /// Binds a BLOB.
void bind(std::size_t pos, const CLOB& val, Direction dir); void bind(std::size_t pos, const CLOB& val, Direction dir, const WhenNullCb& cb);
/// Binds a CLOB. /// Binds a CLOB.
void bind(std::size_t pos, const Date& val, Direction dir); void bind(std::size_t pos, const Date& val, Direction dir, const WhenNullCb& cb);
/// Binds a Date. /// Binds a Date.
void bind(std::size_t pos, const Time& val, Direction dir); void bind(std::size_t pos, const Time& val, Direction dir, const WhenNullCb& cb);
/// Binds a Time. /// Binds a Time.
void bind(std::size_t pos, const DateTime& val, Direction dir); void bind(std::size_t pos, const DateTime& val, Direction dir, const WhenNullCb& cb);
/// Binds a DateTime. /// Binds a DateTime.
void bind(std::size_t pos, const NullData& val, Direction dir); void bind(std::size_t pos, const NullData& val, Direction dir, const std::type_info& bindType);
/// Binds a DateTime. /// Binds a DateTime.
void reset(); void reset();

View File

@ -904,6 +904,11 @@ void DataTest::testRow()
assert (row[3] == 3); assert (row[3] == 3);
assert (row[4] == 4); assert (row[4] == 4);
const Row& cr = row;
assert(cr["field0"] == 0);
assert(cr[0] == 0);
assert(cr.get(0) == 0);
try try
{ {
int i; i = row[5].convert<int>(); // to silence gcc int i; i = row[5].convert<int>(); // to silence gcc

View File

@ -72,7 +72,7 @@ std::size_t TestStatementImpl::columnsReturned() const
} }
const MetaColumn& TestStatementImpl::metaColumn(std::size_t pos) const const MetaColumn& TestStatementImpl::metaColumn(std::size_t pos, std::size_t /*rsPos*/) const
{ {
static MetaColumn c(pos, "", MetaColumn::FDT_BOOL, 0); static MetaColumn c(pos, "", MetaColumn::FDT_BOOL, 0);
return c; return c;

View File

@ -50,7 +50,7 @@ protected:
/// Returns the number of affected rows. /// Returns the number of affected rows.
/// Used to find out the number of rows affected by insert or update. /// Used to find out the number of rows affected by insert or update.
const MetaColumn& metaColumn(std::size_t pos) const; const MetaColumn& metaColumn(std::size_t pos, std::size_t rsPos) const;
/// Returns column meta data. /// Returns column meta data.
bool hasNext(); bool hasNext();

View File

@ -125,7 +125,7 @@
<AdditionalIncludeDirectories>.\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>.\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;Foundation_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;Foundation_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling> <StringPooling>true</StringPooling>
<MinimalRebuild>true</MinimalRebuild> <MinimalRebuild>false</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<BufferSecurityCheck>true</BufferSecurityCheck> <BufferSecurityCheck>true</BufferSecurityCheck>
@ -136,6 +136,7 @@
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
<Link> <Link>
<AdditionalDependencies>ws2_32.lib;iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>ws2_32.lib;iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
@ -215,6 +216,7 @@
<AdditionalIncludeDirectories>.\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>.\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;POCO_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;POCO_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling> <StringPooling>true</StringPooling>
<MinimalRebuild>false</MinimalRebuild>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary> <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<BufferSecurityCheck>false</BufferSecurityCheck> <BufferSecurityCheck>false</BufferSecurityCheck>
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
@ -224,6 +226,7 @@
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat/> <DebugInformationFormat/>
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
<Lib> <Lib>
<OutputFile>..\lib\PocoFoundationmt.lib</OutputFile> <OutputFile>..\lib\PocoFoundationmt.lib</OutputFile>
@ -235,7 +238,7 @@
<AdditionalIncludeDirectories>.\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>.\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;POCO_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;POCO_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling> <StringPooling>true</StringPooling>
<MinimalRebuild>true</MinimalRebuild> <MinimalRebuild>false</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<BufferSecurityCheck>true</BufferSecurityCheck> <BufferSecurityCheck>true</BufferSecurityCheck>
@ -247,6 +250,7 @@
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
<Lib> <Lib>
<OutputFile>..\lib\PocoFoundationmdd.lib</OutputFile> <OutputFile>..\lib\PocoFoundationmdd.lib</OutputFile>

View File

@ -125,7 +125,7 @@
<AdditionalIncludeDirectories>.\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>.\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;Foundation_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;Foundation_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling> <StringPooling>true</StringPooling>
<MinimalRebuild>true</MinimalRebuild> <MinimalRebuild>false</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<BufferSecurityCheck>true</BufferSecurityCheck> <BufferSecurityCheck>true</BufferSecurityCheck>
@ -136,6 +136,7 @@
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
<Link> <Link>
<AdditionalDependencies>iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
@ -168,6 +169,7 @@
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat/> <DebugInformationFormat/>
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
<Link> <Link>
<AdditionalDependencies>iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
@ -200,6 +202,7 @@
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
<Lib> <Lib>
<OutputFile>..\lib64\PocoFoundationmtd.lib</OutputFile> <OutputFile>..\lib64\PocoFoundationmtd.lib</OutputFile>
@ -217,6 +220,7 @@
<StringPooling>true</StringPooling> <StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary> <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<BufferSecurityCheck>false</BufferSecurityCheck> <BufferSecurityCheck>false</BufferSecurityCheck>
<MinimalRebuild>false</MinimalRebuild>
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope> <ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
<RuntimeTypeInfo>true</RuntimeTypeInfo> <RuntimeTypeInfo>true</RuntimeTypeInfo>
@ -224,6 +228,7 @@
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat/> <DebugInformationFormat/>
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
<Lib> <Lib>
<OutputFile>..\lib64\PocoFoundationmt.lib</OutputFile> <OutputFile>..\lib64\PocoFoundationmt.lib</OutputFile>
@ -235,7 +240,7 @@
<AdditionalIncludeDirectories>.\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>.\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;POCO_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;POCO_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling> <StringPooling>true</StringPooling>
<MinimalRebuild>true</MinimalRebuild> <MinimalRebuild>false</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<BufferSecurityCheck>true</BufferSecurityCheck> <BufferSecurityCheck>true</BufferSecurityCheck>
@ -247,6 +252,7 @@
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
<Lib> <Lib>
<OutputFile>..\lib64\PocoFoundationmdd.lib</OutputFile> <OutputFile>..\lib64\PocoFoundationmdd.lib</OutputFile>
@ -271,6 +277,7 @@
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat/> <DebugInformationFormat/>
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
<Lib> <Lib>
<OutputFile>..\lib64\PocoFoundationmd.lib</OutputFile> <OutputFile>..\lib64\PocoFoundationmd.lib</OutputFile>

View File

@ -129,7 +129,7 @@
<AdditionalIncludeDirectories>..\include;..\..\CppUnit\include;..\..\CppUnit\WinTestRunner\include;..\..\Foundation\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\include;..\..\CppUnit\include;..\..\CppUnit\WinTestRunner\include;..\..\Foundation\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;WINVER=0x0600;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;WINVER=0x0600;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling> <StringPooling>true</StringPooling>
<MinimalRebuild>true</MinimalRebuild> <MinimalRebuild>false</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<BufferSecurityCheck>true</BufferSecurityCheck> <BufferSecurityCheck>true</BufferSecurityCheck>
@ -140,6 +140,7 @@
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
<Link> <Link>
<AdditionalDependencies>CppUnitd.lib;iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>CppUnitd.lib;iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
@ -249,7 +250,7 @@
<AdditionalIncludeDirectories>..\include;..\..\CppUnit\include;..\..\CppUnit\WinTestRunner\include;..\..\Foundation\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\include;..\..\CppUnit\include;..\..\CppUnit\WinTestRunner\include;..\..\Foundation\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;WINVER=0x0600;POCO_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;WINVER=0x0600;POCO_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling> <StringPooling>true</StringPooling>
<MinimalRebuild>true</MinimalRebuild> <MinimalRebuild>false</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<BufferSecurityCheck>true</BufferSecurityCheck> <BufferSecurityCheck>true</BufferSecurityCheck>
@ -260,6 +261,7 @@
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
<Link> <Link>
<AdditionalDependencies>CppUnitmdd.lib;iphlpapi.lib;winmm.lib;iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>CppUnitmdd.lib;iphlpapi.lib;winmm.lib;iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
@ -291,6 +293,7 @@
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat /> <DebugInformationFormat />
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
<Link> <Link>
<AdditionalDependencies>CppUnitmd.lib;iphlpapi.lib;winmm.lib;iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>CppUnitmd.lib;iphlpapi.lib;winmm.lib;iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>

View File

@ -129,7 +129,7 @@
<AdditionalIncludeDirectories>..\include;..\..\CppUnit\include;..\..\CppUnit\WinTestRunner\include;..\..\Foundation\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\include;..\..\CppUnit\include;..\..\CppUnit\WinTestRunner\include;..\..\Foundation\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;WINVER=0x0600;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;WINVER=0x0600;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling> <StringPooling>true</StringPooling>
<MinimalRebuild>true</MinimalRebuild> <MinimalRebuild>false</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<BufferSecurityCheck>true</BufferSecurityCheck> <BufferSecurityCheck>true</BufferSecurityCheck>
@ -140,6 +140,7 @@
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
<Link> <Link>
<AdditionalDependencies>CppUnitd.lib;iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>CppUnitd.lib;iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
@ -171,6 +172,7 @@
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat/> <DebugInformationFormat/>
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
<Link> <Link>
<AdditionalDependencies>CppUnit.lib;iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>CppUnit.lib;iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
@ -231,6 +233,7 @@
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat/> <DebugInformationFormat/>
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
<Link> <Link>
<AdditionalDependencies>CppUnitmt.lib;iphlpapi.lib;winmm.lib;iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>CppUnitmt.lib;iphlpapi.lib;winmm.lib;iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
@ -249,7 +252,7 @@
<AdditionalIncludeDirectories>..\include;..\..\CppUnit\include;..\..\CppUnit\WinTestRunner\include;..\..\Foundation\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\include;..\..\CppUnit\include;..\..\CppUnit\WinTestRunner\include;..\..\Foundation\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;WINVER=0x0600;POCO_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;WINVER=0x0600;POCO_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling> <StringPooling>true</StringPooling>
<MinimalRebuild>true</MinimalRebuild> <MinimalRebuild>false</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<BufferSecurityCheck>true</BufferSecurityCheck> <BufferSecurityCheck>true</BufferSecurityCheck>
@ -260,6 +263,7 @@
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
<Link> <Link>
<AdditionalDependencies>CppUnitmdd.lib;iphlpapi.lib;winmm.lib;iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>CppUnitmdd.lib;iphlpapi.lib;winmm.lib;iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
@ -291,6 +295,7 @@
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat/> <DebugInformationFormat/>
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
<Link> <Link>
<AdditionalDependencies>CppUnitmd.lib;iphlpapi.lib;winmm.lib;iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>CppUnitmd.lib;iphlpapi.lib;winmm.lib;iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>

View File

@ -195,8 +195,8 @@ function Process-Input
} }
# NB: this won't work in PowerShell ISE # NB: this won't work in PowerShell ISE
Write-Host "Press Ctrl-C to exit or any other key to continue ..." # Write-Host "Press Ctrl-C to exit or any other key to continue ..."
$x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyUp") # $x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyUp")
} }
} }