List:Commits« Previous MessageNext Message »
From:pharvey Date:July 22 2006 8:29pm
Subject:Connector/ODBC 5 commit: r458 - in trunk/examples/CPP: . ADO
View as plain text  
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="&amp;Compile"
+				CaptureOutputWith="ProcessBuffer"
+				SaveOption="SaveCurrent"
+				RunFromDir="%rw">
+				<Exec/>
+			</Target>
+			<Target
+				Name="Build"
+				MenuCaption="&amp;Build"
+				CaptureOutputWith="ProcessBuffer"
+				SaveOption="SaveWorkspaceFiles"
+				RunFromDir="%rw">
+				<Exec CmdLine="make"/>
+			</Target>
+			<Target
+				Name="Rebuild"
+				MenuCaption="&amp;Rebuild"
+				CaptureOutputWith="ProcessBuffer"
+				SaveOption="SaveWorkspaceFiles"
+				RunFromDir="%rw">
+				<Exec/>
+			</Target>
+			<Target
+				Name="Debug"
+				MenuCaption="&amp;Debug"
+				SaveOption="SaveNone"
+				RunFromDir="%rw">
+				<Exec/>
+			</Target>
+			<Target
+				Name="Execute"
+				MenuCaption="E&amp;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: . ADOpharvey22 Jul