MDAC 2.5 SDK - ADO


 

AppendChunk and GetChunk Methods Example (VC++)

See Also

This example uses the AppendChunk and GetChunk methods to fill an image field with data from another record.

#import "C:\Program Files\Common Files\System\ADO\msado15.dll" \
    no_namespace rename("EOF", "EndOfFile")

#define ChunkSize   100

#include <ole2.h>
#include <stdio.h>
#include "conio.h"
#include "malloc.h"
#include "AppendChunkX.h"

//Function declarations
inline void TESTHR(HRESULT x) {if FAILED(x) _com_issue_error(x);};
void AppendChunkX(void);
void PrintProviderError(_ConnectionPtr pConnection);

///////////////////////////////////////////////////////////
//                                                       //
//      Main Function                                    //
//                                                       //
///////////////////////////////////////////////////////////
void main()
{
    if(FAILED(::CoInitialize(NULL)))
        return;

    AppendChunkX();

    ::CoUninitialize();
}

///////////////////////////////////////////////////////////
//                                                       //
//      AppendChunkX Function                            //
//                                                       //
///////////////////////////////////////////////////////////
void  AppendChunkX(void)
{
    // Define ADO object pointers.
    // Initialize pointers on define.
    // These are in the ADODB::  namespace.
    _RecordsetPtr pRstPubInfo = NULL;
    _ConnectionPtr pConnection = NULL;

    //Define other variables
    //Interface Pointer declared.(VC++ Extensions)   
    IADORecordBinding   *picRs = NULL;  
    CPubInfoRs pubrs;          //C++ class object   

    HRESULT hr = S_OK;
    _bstr_t strCnn("Provider=sqloledb;Data Source=srv;"
        "Initial Catalog=Pubs;User Id=sa;Password=;");

    _bstr_t strMessage,strPubID,strPRInfo;
    _variant_t varChunk;
    long lngOffSet,lngLogoSize;
    char pubId[50];
    lngOffSet = 0;    

    UCHAR chData;
    CHAR ch;
    SAFEARRAY FAR *psa;
    SAFEARRAYBOUND rgsabound[1];
    rgsabound[0].lLbound = 0;
    rgsabound[0].cElements = ChunkSize;

    try
    {
        //Open a Connection.
        TESTHR(pConnection.CreateInstance(__uuidof(Connection)));
        TESTHR(pConnection->Open(strCnn,"","",NULL));

        TESTHR(hr= pRstPubInfo.CreateInstance(__uuidof(Recordset)));  

        pRstPubInfo->CursorType = adOpenKeyset;
        pRstPubInfo->LockType = adLockOptimistic;

        TESTHR(pRstPubInfo->Open("pub_info",
            _variant_t((IDispatch*)pConnection,true),
            adOpenKeyset,adLockOptimistic,adCmdTable));

        //Open an IADORecordBinding interface pointer which we'll use 
        //for Binding Recordset to a class    
        TESTHR(pRstPubInfo->QueryInterface(
            __uuidof(IADORecordBinding),(LPVOID*)&picRs));

        //Bind the Recordset to a C++ Class here    
        TESTHR(picRs->BindToRecordset(&pubrs));

        //Display the available logos here
        strMessage = "Available logos are: " + (_bstr_t)"\n\n";
        printf(strMessage);
        int Counter = 0;
        while(!(pRstPubInfo->EndOfFile))
        { 
            printf("\n%s",pubrs.m_sz_pubid);
            printf("\n%s",strtok(pubrs.m_sz_prinfo,","));

            //Display 5 records at a time and wait for user to continue.
            if (++Counter >= 5)
            {
                Counter = 0;
                printf("\nPress any key to continue...");
                getch();
            }
            pRstPubInfo->MoveNext(); 
        }

        //Prompt For a Logo to Copy
        printf("\nEnter the ID of a logo to copy: ");
        scanf("%s",pubId);
        strPubID = pubId;

        //Copy the logo to a variable in chunks
        pRstPubInfo->Filter = "pub_id = '"  + strPubID + "'";
        lngLogoSize = pRstPubInfo->Fields->Item["logo"]->ActualSize;

        //Create a safe array to store the array of BYTES  
        rgsabound[0].cElements = lngLogoSize;
        psa = SafeArrayCreate(VT_UI1,1,rgsabound);

        long index1 = 0;
        while(lngOffSet < lngLogoSize)
        {
            varChunk = pRstPubInfo->Fields->
                        Item["logo"]->GetChunk(ChunkSize);

            //Copy the data only up to the Actual Size of Field.  
            for(long index=0;index<=(ChunkSize-1);index++)
            {
                hr= SafeArrayGetElement(varChunk.parray,&index,&chData);
                if(SUCCEEDED(hr))
                {
                    //Take BYTE by BYTE and advance Memory Location
                    TESTHR(SafeArrayPutElement(psa,&index1,&chData));
                    index1++;
                }
                else
                    break;
            }
            lngOffSet = lngOffSet + ChunkSize;
        }
        lngOffSet = 0;

        printf("Enter a new Pub Id: ");
        scanf("%s",pubrs.m_sz_pubid);
        strPubID = pubrs.m_sz_pubid;

        printf("Enter descriptive text: " );
        scanf("%c",&ch);
        gets(pubrs.m_sz_prinfo);

        // Temporarily add new publisher to table to avoid error due  
        // to foreign key constraint.
        pConnection->Execute("INSERT publishers(pub_id) VALUES('" + 
            strPubID + "')",NULL,adCmdText);
        
        pRstPubInfo->AddNew();
        pRstPubInfo->Fields->GetItem("pub_id")->PutValue(strPubID);
        pRstPubInfo->Fields->GetItem("pr_info")->
            PutValue(pubrs.m_sz_prinfo);

        //Assign the Safe array  to a variant. 
        varChunk.vt = VT_ARRAY|VT_UI1;
        varChunk.parray = psa;
        hr = pRstPubInfo->Fields->GetItem("logo")->
                AppendChunk(varChunk); 

        //Update the table 
        pRstPubInfo->Update();

        lngLogoSize = pRstPubInfo->Fields->Item["logo"]->ActualSize;

        //Show the newly added record.
        printf("New Record : %s\nDescription : %s\nLogo Size : %s\n",
            pubrs.m_sz_pubid,
            pubrs.m_sz_prinfo,(LPCSTR)(_bstr_t)pRstPubInfo->Fields->
            Item["logo"]->ActualSize);

        //Delete new records because this is demonstration.
        pConnection->Execute("DELETE FROM PUB_INFO WHERE pub_id = '"
                        + strPubID +"'",NULL,adCmdText);

        pConnection->Execute("DELETE FROM publishers WHERE pub_id = '"
                        + strPubID +"'",NULL,adCmdText);

        pRstPubInfo->Close();
        pConnection->Close();
    }
    catch(_com_error &e)
    {
        // Notify the user of errors if any.
        _bstr_t bstrSource(e.Source());
        _bstr_t bstrDescription(e.Description());

        PrintProviderError(pConnection);
        printf("Source : %s \n Description : %s\n",
                (LPCSTR)bstrSource,(LPCSTR)bstrDescription);
    }
}

///////////////////////////////////////////////////////////
//                                                       //
//      PrintProviderError Function                      //
//                                                       //
///////////////////////////////////////////////////////////

void PrintProviderError(_ConnectionPtr pConnection)
{
    // Print Provider Errors from Connection object.
    // pErr is a record object in the Connection's Error collection.
    ErrorPtr  pErr   = NULL;
    long      nCount = 0;    
    long      i      = 0;

    if( (pConnection->Errors->Count) > 0)
    {
        nCount = pConnection->Errors->Count;
        // Collection ranges from 0 to nCount -1.
        for(i = 0; i < nCount; i++)
        {
            pErr = pConnection->Errors->GetItem(i);
            printf("\t Error number: %x\t%s", pErr->Number,
                (LPCSTR) pErr->Description);
        }
    }
}

AppendChunkX.h:

#include "icrsint.h"

//This Class extracts pubid,prinfo.

class CPubInfoRs : public CADORecordBinding
{
    BEGIN_ADO_BINDING(CPubInfoRs)

    ADO_VARIABLE_LENGTH_ENTRY2(1, adVarChar, m_sz_pubid, 
         sizeof(m_sz_pubid), l_pubid, TRUE)

    ADO_VARIABLE_LENGTH_ENTRY2(3, adVarChar, m_sz_prinfo, 
         sizeof(m_sz_prinfo), l_prinfo, TRUE)

    END_ADO_BINDING()

public:
    CHAR   m_sz_pubid[10];
    ULONG  l_pubid;
    CHAR   m_sz_prinfo[200];
    ULONG l_prinfo;    

};