Added:
trunk/examples/CPP/ADO/
trunk/examples/CPP/ADO/5.gif
trunk/examples/CPP/ADO/ADO.pro
trunk/examples/CPP/ADO/exampleADO.vpj
trunk/examples/CPP/ADO/main.cpp
Removed:
trunk/examples/CPP/7/
Log:
Added: trunk/examples/CPP/ADO/5.gif
===================================================================
(Binary files differ)
Property changes on: trunk/examples/CPP/ADO/5.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/examples/CPP/ADO/ADO.pro
===================================================================
--- trunk/examples/CPP/ADO/ADO.pro 2006-07-22 18:26:17 UTC (rev 457)
+++ trunk/examples/CPP/ADO/ADO.pro 2006-07-22 18:29:27 UTC (rev 458)
@@ -0,0 +1,32 @@
+# #########################################################
+#
+# \brief
+#
+# #########################################################
+
+# #########################################################
+# COMMON
+# #########################################################
+TEMPLATE = app
+TARGET = ADO
+DESTDIR = ./
+CONFIG += console
+include( ../common.pri )
+include( ../config.pri )
+include( ../defines.pri )
+include( ../odbc.pri )
+
+# #########################################################
+# WIN
+# #########################################################
+win32 {
+ LIBS += user32.lib
+}
+
+# #########################################################
+# FILES
+# #########################################################
+HEADERS =
+SOURCES = \
+ main.cpp
+
Added: trunk/examples/CPP/ADO/exampleADO.vpj
===================================================================
--- trunk/examples/CPP/ADO/exampleADO.vpj 2006-07-22 18:26:17 UTC (rev 457)
+++ trunk/examples/CPP/ADO/exampleADO.vpj 2006-07-22 18:29:27 UTC (rev 458)
@@ -0,0 +1,73 @@
+<!DOCTYPE Project SYSTEM "http://www.slickedit.com/dtd/vse/10.0/vpj.dtd">
+<Project
+ Version="10.0"
+ VendorName="SlickEdit"
+ WorkingDir=".">
+ <Config
+ Name="Release"
+ OutputFile=""
+ CompilerConfigName="Latest Version">
+ <Menu>
+ <Target
+ Name="Compile"
+ MenuCaption="&Compile"
+ CaptureOutputWith="ProcessBuffer"
+ SaveOption="SaveCurrent"
+ RunFromDir="%rw">
+ <Exec/>
+ </Target>
+ <Target
+ Name="Build"
+ MenuCaption="&Build"
+ CaptureOutputWith="ProcessBuffer"
+ SaveOption="SaveWorkspaceFiles"
+ RunFromDir="%rw">
+ <Exec CmdLine="make"/>
+ </Target>
+ <Target
+ Name="Rebuild"
+ MenuCaption="&Rebuild"
+ CaptureOutputWith="ProcessBuffer"
+ SaveOption="SaveWorkspaceFiles"
+ RunFromDir="%rw">
+ <Exec/>
+ </Target>
+ <Target
+ Name="Debug"
+ MenuCaption="&Debug"
+ SaveOption="SaveNone"
+ RunFromDir="%rw">
+ <Exec/>
+ </Target>
+ <Target
+ Name="Execute"
+ MenuCaption="E&xecute"
+ SaveOption="SaveNone"
+ RunFromDir="%rw">
+ <Exec CmdLine='"exampleADO.exe"'/>
+ </Target>
+ </Menu>
+ </Config>
+ <Files>
+ <Folder
+ Name="Source Files"
+ Filters="*.c;*.C;*.cc;*.cpp;*.cp;*.cxx;*.prg;*.pas;*.dpr;*.asm;*.s;*.bas;*.java;*.cs;*.sc;*.e;*.cob;*.html;*.rc;*.tcl;*.py;*.pl">
+ <F N="main.cpp"/>
+ </Folder>
+ <Folder
+ Name="Header Files"
+ Filters="*.h;*.H;*.hh;*.hpp;*.hxx;*.inc;*.sh;*.cpy;*.if">
+ </Folder>
+ <Folder
+ Name="Resource Files"
+ Filters="*.ico;*.cur;*.dlg"/>
+ <Folder
+ Name="Bitmaps"
+ Filters="*.bmp"/>
+ <Folder
+ Name="Other Files"
+ Filters="">
+ <F N="ADO.pro"/>
+ </Folder>
+ </Files>
+</Project>
Added: trunk/examples/CPP/ADO/main.cpp
===================================================================
--- trunk/examples/CPP/ADO/main.cpp 2006-07-22 18:26:17 UTC (rev 457)
+++ trunk/examples/CPP/ADO/main.cpp 2006-07-22 18:29:27 UTC (rev 458)
@@ -0,0 +1,555 @@
+/*!
+ \file main.cpp
+ \author Peter Harvey <pharvey@stripped>
+ Copyright MySQL AB 2004-2006 Released under GPL.
+ \version Connector/ODBC v5
+ \date 2006
+ \brief Demonstrates ADO in use via C++.
+
+ It is probably safe to say that ADO is seldom used via C++ while ADO is
often used by
+ Visual Basic. The result is that it can sometimes be very difficult to
find information
+ on how to do some things with ADO in C++. For example; sending binary
'down the pipe'
+ via CreateParameter.
+
+ This file has been created in the hope that it may answer questions by
those wishing
+ to 'go down this path'.
+
+ \note Before using this code you will want to;
+ - create the tbAdo table (see code comments later in this file)
+ - create the insAdo stored procedure (see code comments later in this
file)
+ - create a DSN (to tbAdo and insAdo) - for MyODBC you may want to use
following options;
+ - allow big results
+ - use compressed protocol
+ - alter the connection information in the code below
+ - BINARY_FILENAME must exist in current dir when prg exec
+
+ \warning Do not use this in a production environment or in any environment where
you may suffer
+ grief if things go horribly wrong. Use at your own risk.
+*/
+#include <oledb.h>
+#include <msdadc.h>
+#include <msdaguid.h>
+
+#include <ole2.h>
+#include <stdio.h>
+#include <io.h>
+#include <fcntl.h>
+#include <sys\stat.h>
+
+/*!
+ \note
+
+ Import ADO.
+
+ We can avoid using the full path if LIBPATH environment variable includes
+ the path to msado<VERSION>.dll.
+*/
+/*
+#import "msado15.dll" \
+ no_namespace rename("EOF", "EndOfFile")
+*/
+#import "C:\Program Files\Common Files\System\ado\msado15.dll" \
+ no_namespace \
+ rename( "EOF", "EndOfFile")
+
+// handle a HRESULT return type
+inline void TESTHR( HRESULT x ) { if FAILED(x) _com_issue_error(x); };
+
+// global connect
+_ConnectionPtr pConnection = NULL;
+char *pszConnectionString = "ado2";
+char *pszUserID = "root";
+char *pszPassword = "pharvey";
+
+// sample data
+UCHAR pDataText[] = "12345678901234567890123456789012345678901234567890";
+int nDataLengthText = 10; // data truncation errors if this is larger than strlen
pDataText or size of column
+
+#define BINARY_FILENAME "5.gif"
+UCHAR * pDataBinary = NULL;
+long nDataLengthBinary = 0;
+
+/*!
+ \brief Print the providers errors.
+*/
+void doPrintProviderError( const char *pszFileName, int nLine, const char *pszFunction,
_ConnectionPtr pConnection )
+{
+ ErrorPtr pErr = NULL;
+
+ // do we have errors?
+ if ( pConnection->Errors->Count > 0 )
+ {
+ long nCount = pConnection->Errors->Count;
+
+ // for each error - print error
+ for ( long n = 0; n < nCount; n++ )
+ {
+ pErr = pConnection->Errors->GetItem( n );
+ printf( "[%s][%d][%s] ERROR: %x\t%s\n", pszFileName, nLine, pszFunction,
pErr->Number, (LPCSTR)pErr->Description );
+ }
+ }
+}
+
+/*!
+ \brief Print COM error.
+*/
+void doPrintComError( const char *pszFileName, int nLine, const char *pszFunction,
_com_error &e )
+{
+ _bstr_t bstrSource( e.Source() );
+ _bstr_t bstrDescription( e.Description() );
+
+ printf( "[%s][%d][%s] ERROR:\n", pszFileName, nLine, pszFunction );
+ printf( "\tCode = %08lx\n", e.Error() );
+ wprintf( L"\tCode meaning = %s\n", e.ErrorMessage() );
+ printf( "\tSource = %s\n", (LPCSTR)bstrSource );
+ printf( "\tDescription = %s\n", (LPCSTR)bstrDescription );
+}
+
+/*!
+ \brief Print record-set.
+
+ This prints all data in the record-set in a generic fashion.
+*/
+bool doPrintRecordset( _RecordsetPtr pRecordset )
+{
+ /* field names */
+ for ( long nField = 0; nField < pRecordset->Fields->Count; nField++ )
+ {
+ if ( !nField )
+ printf( "|" );
+ printf( "%s %d |", (LPCSTR)(pRecordset->Fields->GetItem( nField
)->Name), pRecordset->Fields->Item[nField]->Type );
+ }
+ printf( "\n" );
+
+ /* rows */
+ while ( !pRecordset->EndOfFile )
+ {
+ wprintf( pRecordset->GetString( adClipString, 1, "|", "\n", "<NULL>" )
);
+// pRecordset->MoveNext();
+ }
+
+ return true;
+}
+
+/*!
+ \brief Connect.
+
+ This will connect to the data source.
+*/
+bool doConnect()
+{
+ try
+ {
+ TESTHR( pConnection.CreateInstance( __uuidof( Connection ) ) );
+ pConnection->Open( pszConnectionString, pszUserID, pszPassword,
adConnectUnspecified );
+ printf( "[%s][%d] state: %d\n", __FILE__, __LINE__, pConnection->State );
+ }
+ catch ( _com_error &e )
+ {
+ doPrintProviderError( __FILE__, __LINE__, __FUNCTION__, pConnection );
+ doPrintComError( __FILE__, __LINE__, __FUNCTION__, e );
+ return false;
+ }
+
+ return true;
+}
+
+/*!
+ \brief Print all data in tbAdo.
+*/
+bool doSelect()
+{
+ _CommandPtr pCommand = NULL;
+ _ParameterPtr pParameter = NULL;
+ _RecordsetPtr pRecordset = NULL;
+
+ try
+ {
+ TESTHR( pCommand.CreateInstance( __uuidof( Command ) ) );
+ pCommand->ActiveConnection = pConnection;
+ pCommand->CommandText = "SELECT * FROM tbAdo";
+ pCommand->CommandType = adCmdText;
+
+ pRecordset = pCommand->Execute( NULL, NULL, adCmdText );
+
+ doPrintRecordset( pRecordset );
+ }
+ catch ( _com_error &e )
+ {
+ doPrintProviderError( __FILE__, __LINE__, __FUNCTION__, pConnection );
+ doPrintComError( __FILE__, __LINE__, __FUNCTION__, e );
+ return false;
+ }
+
+
+ return true;
+}
+
+/*!
+ \brief Use CreateParameter on an INSERT statement.
+
+ This will show CreateParameter in use on an INSERT statement
+ with a variety of column data types.
+
+ \note Needs the following table to work...
+
+ MSSQL
+ -----
+ CREATE TABLE `tbAdo`
+ (
+ `bin` VARBINARY(1024),
+ `txt` TEXT,
+ `n` INTEGER,
+ `vc` VARCHAR(50)
+ )
+
+ MySQL
+ -----
+ CREATE TABLE `tbAdo`
+ (
+ `bin` VARBINARY(1024),
+ `txt` TEXT,
+ `n` INTEGER UNSIGNED,
+ `vc` VARCHAR(50)
+ )
+ ENGINE = InnoDB;
+*/
+bool doCreateParameterInsert()
+{
+ _CommandPtr pCommand = NULL;
+ _ParameterPtr pParameter = NULL;
+ VARIANT variant1;
+ VARIANT variant2;
+ VARIANT variant3;
+ VARIANT variant4;
+
+ SAFEARRAY FAR * pArrayBinary;
+ SAFEARRAYBOUND arrayBoundBinary[1];
+
+ SAFEARRAY FAR * pArrayText;
+ SAFEARRAYBOUND arrayBoundText[1];
+
+ try
+ {
+ // our INSERT statement
+ TESTHR( pCommand.CreateInstance( __uuidof( Command ) ) );
+ pCommand->ActiveConnection = pConnection;
+ pCommand->CommandText = "INSERT INTO tbAdo VALUES( ?, ?, ?, ? )";
+ pCommand->CommandType = adCmdText;
+
+ // BINARY
+ {
+ // init a SAFEARRAY
+ void *pSafeArrayDataRef = NULL;
+
+ arrayBoundBinary[0].lLbound = 0;
+ arrayBoundBinary[0].cElements = nDataLengthBinary;
+
+ pArrayBinary = SafeArrayCreate( VT_UI1, 1, arrayBoundBinary );
+
+ SafeArrayAccessData( pArrayBinary, &pSafeArrayDataRef );
+ memcpy( pSafeArrayDataRef, pDataBinary, nDataLengthBinary );
+ SafeArrayUnaccessData( pArrayBinary );
+
+ // init VARIANT with our safearray
+ variant1.vt = VT_ARRAY|VT_UI1;
+ variant1.parray = pArrayBinary;
+
+ // init bound parameter with our variant
+ pParameter = pCommand->CreateParameter( "bin", adBinary,
adParamInput, nDataLengthBinary, variant1 );
+ pCommand->Parameters->Append( pParameter );
+ }
+
+ // TEXT
+ {
+ // init a SAFEARRAY
+ void *pSafeArrayDataRef = NULL;
+
+ arrayBoundText[0].lLbound = 0;
+ arrayBoundText[0].cElements = nDataLengthText;
+
+ pArrayText = SafeArrayCreate( VT_UI1, 1, arrayBoundText );
+
+ SafeArrayAccessData( pArrayText, &pSafeArrayDataRef );
+ memcpy( pSafeArrayDataRef, pDataText, nDataLengthText );
+ SafeArrayUnaccessData( pArrayText );
+
+ // init VARIANT with our safearray
+ variant2.vt = VT_ARRAY|VT_UI1;
+ variant2.parray = pArrayText;
+
+ // init bound parameter with our variant
+ pParameter = pCommand->CreateParameter( "txt", adLongVarChar,
adParamInput, nDataLengthText, variant2 );
+ pCommand->Parameters->Append( pParameter );
+ }
+
+ // INTEGER
+ variant3.vt = VT_I2;
+ variant3.iVal = 1867;
+ pParameter = pCommand->CreateParameter( "n", adInteger, adParamInput,
sizeof(int), variant3 );
+ pCommand->Parameters->Append( pParameter );
+
+ // VARCHAR
+ variant4.vt = VT_BSTR;
+ variant4.bstrVal = _bstr_t( "test" );
+ pParameter = pCommand->CreateParameter( "vc", adChar, adParamInput, 5,
variant4 );
+ pCommand->Parameters->Append( pParameter );
+
+ // execute statement
+ pCommand->Execute( NULL, NULL, adCmdText );
+
+// SafeArrayDestroy( variant4 );
+ }
+ catch ( _com_error &e )
+ {
+ doPrintProviderError( __FILE__, __LINE__, __FUNCTION__, pConnection );
+ doPrintComError( __FILE__, __LINE__, __FUNCTION__, e );
+ return false;
+ }
+
+
+ return true;
+}
+
+/*!
+ \brief Use CreateParameter on a stored procedure.
+
+ This shows CreateParameter in use on a stored procedure with a variety of
+ column data types.
+
+ \note This needs the following stored procedure to work...
+
+ MSSQL
+ ------
+ CREATE PROCEDURE insAdo @bin VARBINARY(1024), @txt TEXT, @n INT, @vc
VARCHAR(50) AS
+ INSERT INTO tbAdo VALUES( @bin, @txt, @n, @vc )
+
+ MySQL
+ -----
+ CREATE PROCEDURE `northwind`.`insAdo` ( IN bin VARBINARY(1024), IN txt TEXT,
IN n INT, IN vc VARCHAR(50) )
+ BEGIN
+ INSERT INTO tbAdo VALUES( @bin, @txt, @n, @vc );
+ END
+
+*/
+bool doCreateParameterProcedure()
+{
+ _CommandPtr pCommand = NULL;
+ _ParameterPtr pParameter = NULL;
+ VARIANT variant1;
+ VARIANT variant2;
+ VARIANT variant3;
+ VARIANT variant4;
+
+ SAFEARRAY FAR * pArrayBinary;
+ SAFEARRAYBOUND arrayBoundBinary[1];
+
+ SAFEARRAY FAR * pArrayText;
+ SAFEARRAYBOUND arrayBoundText[1];
+
+ try
+ {
+ // our stored procedure statement
+ TESTHR( pCommand.CreateInstance( __uuidof( Command ) ) );
+ pCommand->ActiveConnection = pConnection;
+ pCommand->CommandText = "insAdo";
+ pCommand->CommandType = adCmdStoredProc;
+
+ // BINARY
+ {
+ // init a SAFEARRAY
+ void *pSafeArrayDataRef = NULL;
+
+ arrayBoundBinary[0].lLbound = 0;
+ arrayBoundBinary[0].cElements = nDataLengthBinary;
+
+ pArrayBinary = SafeArrayCreate( VT_UI1, 1, arrayBoundBinary );
+
+ SafeArrayAccessData( pArrayBinary, &pSafeArrayDataRef );
+ memcpy( pSafeArrayDataRef, pDataBinary, nDataLengthBinary );
+ SafeArrayUnaccessData( pArrayBinary );
+
+ // init VARIANT with our safearray
+ variant1.vt = VT_ARRAY|VT_UI1;
+ variant1.parray = pArrayBinary;
+
+ // init bound parameter with our variant
+ pParameter = pCommand->CreateParameter( "bin", adBinary,
adParamInput, nDataLengthBinary, variant1 );
+ pCommand->Parameters->Append( pParameter );
+ }
+
+ // TEXT
+ {
+ // init a SAFEARRAY
+ void *pSafeArrayDataRef = NULL;
+
+ arrayBoundText[0].lLbound = 0;
+ arrayBoundText[0].cElements = nDataLengthText;
+
+ pArrayText = SafeArrayCreate( VT_UI1, 1, arrayBoundText );
+
+ SafeArrayAccessData( pArrayText, &pSafeArrayDataRef );
+ memcpy( pSafeArrayDataRef, pDataText, nDataLengthText );
+ SafeArrayUnaccessData( pArrayText );
+
+ // init VARIANT with our safearray
+ variant2.vt = VT_ARRAY|VT_UI1;
+ variant2.parray = pArrayBinary;
+
+ // init bound parameter with our variant
+ pParameter = pCommand->CreateParameter( "txt", adChar, adParamInput,
nDataLengthText, variant2 );
+ pCommand->Parameters->Append( pParameter );
+ }
+
+ // INTEGER
+ variant3.vt = VT_I2;
+ variant3.iVal = 1867;
+ pParameter = pCommand->CreateParameter( "n", adInteger, adParamInput,
sizeof(int), variant3 );
+ pCommand->Parameters->Append( pParameter );
+
+ // VARCHAR
+ variant4.vt = VT_BSTR;
+ variant4.bstrVal = _bstr_t( "test" );
+ pParameter = pCommand->CreateParameter( "vc", adChar, adParamInput, 5,
variant4 );
+ pCommand->Parameters->Append( pParameter );
+
+ // execute statement
+ pCommand->Execute( NULL, NULL, adCmdStoredProc );
+
+// SafeArrayDestroy( variant4 );
+ }
+ catch ( _com_error &e )
+ {
+ doPrintProviderError( __FILE__, __LINE__, __FUNCTION__, pConnection );
+ doPrintComError( __FILE__, __LINE__, __FUNCTION__, e );
+ return false;
+ }
+
+ return true;
+}
+
+
+/*!
+ \brief Disconnect.
+
+ This will disconnect from the data source.
+*/
+bool doDisconnect()
+{
+ try
+ {
+ pConnection->Close();
+ printf( "[%s][%d] state: %d\n", __FILE__, __LINE__, pConnection->State );
+ }
+ catch ( _com_error &e )
+ {
+ doPrintProviderError( __FILE__, __LINE__, __FUNCTION__, pConnection );
+ doPrintComError( __FILE__, __LINE__, __FUNCTION__, e );
+ return false;
+ }
+
+ return true;
+}
+
+/*!
+ \brief Loads a file into memory.
+
+ Loads contents of file (pszFileName) into buffer (ppData).
+
+ \note
+ This takes care of allocating buffer at ppData but caller must
+ free it when done.
+
+ \param pszFileName File to be loaded. It must exist.
+ \param ppData Place to return the pointer to the file data.
+ \param pnDataLength Place to return the number of bytes loaded from the
+ file. The buffer size at ppData may be this size OR
+ larger.
+
+ \return bool
+
+ \retval false Something went wrong. Error message was sent to stdout.
+ \retval true Success.
+*/
+bool doLoadFile( const char *pszFileName, UCHAR **ppData, long *pnDataLength )
+{
+ bool bReturn = false;
+
+ int nFile = open( pszFileName, _O_RDONLY, _S_IREAD );
+ if ( nFile == -1 )
+ {
+ printf( "[%s][%d][%s] ERROR: Failed to open (%s)\n", __FILE__, __LINE__,
__FUNCTION__, pszFileName );
+ return false;
+ }
+
+ *pnDataLength = _filelength( nFile );
+ if ( *pnDataLength < 1 )
+ {
+ printf( "[%s][%d][%s] ERROR: Failed to get file length for (%s)\n", __FILE__,
__LINE__, __FUNCTION__, pszFileName );
+ goto doLoadFileExit1;
+ }
+
+ *ppData = (UCHAR*)malloc( *pnDataLength );
+ if ( *ppData == NULL )
+ {
+ printf( "[%s][%d][%s] ERROR: Failed to malloc %ld bytes\n", __FILE__, __LINE__,
__FUNCTION__, *pnDataLength );
+ goto doLoadFileExit2;
+ }
+
+ int nReadTotal = 0;
+ int nRead = 0;
+ do
+ {
+ nRead = read( nFile, *ppData, *pnDataLength );
+ nReadTotal += nRead;
+ } while ( nRead );
+
+ if ( (long)nReadTotal != *pnDataLength )
+ printf( "[%s][%d][%s] INFO: Allocated %ld and read %d into it.\n", __FILE__,
__LINE__, __FUNCTION__, *pnDataLength, nReadTotal );
+
+ bReturn = true;
+ goto doLoadFileExit1;
+
+doLoadFileExit2:
+ free( *ppData );
+
+doLoadFileExit1:
+ close( nFile );
+
+ return bReturn;
+}
+
+/*!
+ \brief main
+
+ This is the 'main' entry point to this program - it all starts here.
+
+ \todo We need to do a better job of cleaning up after our processing.
+*/
+void main()
+{
+ /*!
+ \note
+ */
+ if ( FAILED( ::CoInitialize( NULL ) ) )
+ return;
+
+ /* get some example binary data */
+ if ( !doLoadFile( BINARY_FILENAME, &pDataBinary, &nDataLengthBinary ) )
+ return;
+
+ /* do it */
+ if ( doConnect() )
+ {
+ doCreateParameterInsert();
+ doCreateParameterProcedure();
+ doSelect();
+ doDisconnect();
+ }
+
+ /*!
+ \note
+ */
+ ::CoUninitialize();
+}
+
| Thread |
|---|
| • Connector/ODBC 5 commit: r458 - in trunk/examples/CPP: . ADO | pharvey | 22 Jul |