// BDE - (C) Copyright 1995 by Borland International // blobsmpl.c #include "snipit.h" #define NAMELEN 20 // Set name length to 20 characters #define DATELEN 9 // Set date length to 9 characters static const char szTblName[] = "BLOBSMPL"; // Table to create static const char szTblType[] = szPARADOX; // Table Type to use static SNIPFAR FLDDesc fldDesc[] = { { 1, // Field number "First Name", // Field name fldZSTRING, // Field type fldUNKNOWN, // Field dubtype NAMELEN, // Field size ( 1 or 0, // except BLOB or string ) 0, // Decimal places ( 0 ) - // computed 0, // Offset in record ( 0 ) 0, // Length in bytes ( 0 ) 0, // For null bits ( 0 ) fldvNOCHECKS, // Validity checks ( 0 ) fldrREADWRITE // Rights }, { 2, "Middle Name", fldZSTRING, fldUNKNOWN, NAMELEN, 0, 0, 0, 0, fldvNOCHECKS, fldrREADWRITE }, { 3, "Last Name", fldZSTRING, fldUNKNOWN, NAMELEN, 0, 0, 0, 0, fldvNOCHECKS, fldrREADWRITE }, { 4, "DOB", fldDATE, fldUNKNOWN, 0, 0, 0, 0, 0, fldvNOCHECKS, fldrREADWRITE }, { 5, "POB", fldZSTRING, fldUNKNOWN, 20, 0, 0, 0, 0, fldvNOCHECKS, fldrREADWRITE }, { // Note that Memo fields in PARADOX require a // size - this is the amount of the BLOB which // is stored within the actual table as well // as being stored in the .MB file. 6, "General Info", fldBLOB, fldstMEMO, 20, 0, 0, 0, 0, fldvNOCHECKS, fldrREADWRITE } }; // Array of field descriptors static SNIPFAR IDXDesc idxDesc[] = { { // Primary Index "Full Name", // Name 1, // Number { NULL }, // Tag name ( for dBase ) { NULL }, // Optional Format ( BTREE, // HASH, etc ) TRUE, // Primary? TRUE, // Unique? FALSE, // Descending? TRUE, // Maintained? FALSE, // SubSet? FALSE, // Expression index? NULL, // For QBE only 3, // Fields in key 1, // Length in bytes FALSE, // Index out of date? 0, // Key type of expression { 1,2,3 }, // Array of field numbers { 0 }, // Key expression { 0 }, // Key condition FALSE, // Case insensitive 0, // Block size in bytes 0 } }; // Number of fields in the table const unsigned uNumFields = sizeof(fldDesc) / sizeof (fldDesc[0]); // Number of indexes in the table const unsigned uNumIndexes = sizeof(idxDesc) / sizeof(idxDesc[0]); void FillFullRecord(hDBICur, pBYTE); void FillHalfRecord (hDBICur, pBYTE); DBIResult FillFields (hDBICur hCur, pCHAR pszFNAME, pCHAR pszMNAME, pCHAR pszLNAME, UINT16 uMonth, UINT16 uDay, UINT16 uYear, pCHAR pszPOB, pBYTE pRecBuf); void FillString(pCHAR); void FillHalfString (pCHAR); void DispBlob(hDBICur , pBYTE); //===================================================================== // Function: // SimpleBlobIO(); // // Description: // This example shows how to read and write BLOBs. This example // will cover how to access entire BLOB information and sections // of a BLOB. //===================================================================== void SimpleBlobIO (void) { DBIResult rslt; // Value returned from IDAPI functions hDBIDb hDb; // Handle to the database hDBICur hCur; // Handle to the table CURProps TblProps; // Table properties pBYTE pRecBuf = NULL; // Pointer to the record buffer CRTblDesc crTblDsc; // Create Table descriptor BOOL bOverWrite = TRUE; // Overwrite, yes/no flag UINT16 rcdSize; // Size of the record Screen("*** Simple BLOB I/O Example ***\r\n"); BREAK_IN_DEBUGGER(); Screen(" Initializing IDAPI..."); if (InitAndConnect(&hDb) != DBIERR_NONE) { Screen("\r\n*** End of Example ***"); return; } Screen(" Setting the database directory..."); rslt = DbiSetDirectory(hDb, (pCHAR) szTblDirectory); ChkRslt(rslt, "SetDirectory"); // Initialize the table create descriptor. memset(&crTblDsc,0, sizeof(CRTblDesc)); strcpy(crTblDsc.szTblName, szTblName) ; strcpy(crTblDsc.szTblType, szTblType) ; crTblDsc.iFldCount = uNumFields ; crTblDsc.pfldDesc = fldDesc ; crTblDsc.iIdxCount = uNumIndexes ; crTblDsc.pidxDesc = idxDesc ; Screen(" Create the %s table...", szTblName); rslt = DbiCreateTable(hDb, bOverWrite, &crTblDsc); if (ChkRslt(rslt, "CreateTable") != DBIERR_NONE) { CloseDbAndExit(&hDb); Screen("\r\n*** End of Example ***"); return; } rslt = DbiOpenTable(hDb,(pCHAR) szTblName,(pCHAR) szTblType, NULL, NULL, 0, dbiREADWRITE, dbiOPENSHARED, xltFIELD, FALSE, NULL, &hCur); if (ChkRslt(rslt, "OpenTable") != DBIERR_NONE) { CloseDbAndExit(&hDb); Screen("\r\n*** End of Example ***"); return; } // Allocate memory for the record buffer rslt = DbiGetCursorProps(hCur, &TblProps); ChkRslt(rslt, "GetCursorProps"); rcdSize = TblProps.iRecBufSize; pRecBuf = (pBYTE)malloc(sizeof(BYTE) * rcdSize); // Fill the database with a string set in the FillRecord // function. FillFullRecord(hCur, pRecBuf); // Display the BLOB. Screen("\r\n This is the BLOB information in Record #1\r\n"); DispBlob(hCur, pRecBuf); // Create another record and fill it with the same // data. However, change the BLOB info with DbiPutBlob. FillHalfRecord(hCur, pRecBuf); // Display the BLOB. Screen("\r\n This is the BLOB information in Record #2\r\n"); DispBlob(hCur, pRecBuf); // Clean up. free(pRecBuf); Screen("\r\n Close the %s table...", szTblName); rslt = DbiCloseCursor(&hCur); ChkRslt(rslt, "CloseCursor"); Screen(" Delete the %s table...", szTblName); rslt = DbiDeleteTable(hDb, (pCHAR) szTblName, (pCHAR) szTblType); ChkRslt(rslt, "DeleteTable"); Screen(" Close the database and exit IDAPI..."); CloseDbAndExit(&hDb); Screen("\r\n*** End of Example ***"); } //===================================================================== // Function: // FillFullRecord(hCur, pRecBuf); // // Input: hCur - Cursor to Table // pRecBuf - Record Buffer // // Return: Dbi Result // // Desc: This function takes the cursor and fills the record // buffer with pre-assigned values (static values for this // example). It returns an error if we encounter one. // This function makes the code a bit more readable. //===================================================================== void FillFullRecord (hDBICur hCur, pBYTE pRecBuf) { pCHAR pGenInfo; // Buffer to contain the string which is // written to the BLOB field. DBIResult rslt; // Return value from IDAPI functions // Initialize the record buffer before filling it rslt = DbiInitRecord(hCur, pRecBuf); ChkRslt(rslt, "InitRecord"); // Allocate a buffer that is capable of holding a large string. pGenInfo = (pCHAR) malloc(sizeof (CHAR) * 1200); if (pGenInfo == NULL) { return; } // Function will fill the pGeninfo pointer with a string // that is larger than 256 bytes. FillString(pGenInfo); // Fill the fields of the buffer. The fields are filled directly, // but a variable could be used that would hold the string, date or // BLOB information. FillFields(hCur, "Charlie", "L", "Carm", 12, 24, 55, "New York", pRecBuf); // Open the BLOB. To write or read from a BLOB you must open the // BLOB first. All that is needed is the cursor, the record buffer, // the field number and the rights. If the BLOB is opened in // ReadWrite mode, the table must be opened in ReadWrite mode also. rslt = DbiOpenBlob(hCur, pRecBuf, 6, dbiREADWRITE); ChkRslt(rslt, "OpenBlob"); // Put the whole BLOB into the field. rslt = DbiPutBlob(hCur, pRecBuf, 6, 0, (strlen(pGenInfo) + 1), (pBYTE) pGenInfo); ChkRslt(rslt, "PutBlob"); // Append a record to the table. rslt = DbiAppendRecord(hCur, pRecBuf); ChkRslt(rslt, "AppendRecord"); free(pGenInfo); rslt = DbiFreeBlob(hCur, pRecBuf, 6); ChkRslt(rslt, "FreeBlob"); } //===================================================================== // Function: // FillHalfRecord(hCur, pRecBuf); // // Input: hCur - Cursor to Table // pRecBuf - Record Buffer // // Return: Dbi Result // // Desc: This function takes the cursor and fills the record // buffer with pre-assigned values (static values for this // example). It returns an error if we encounter one. // This function makes the code a bit more readable. //===================================================================== void FillHalfRecord (hDBICur hCur, pBYTE pRecBuf) { pCHAR pGenInfo; // Buffer to contain the string which is // written to the BLOB field. UINT16 GenLen; // Length of the string DBIResult rslt; // Return value from IDAPI functions // Initialize the record buffer before filling it. rslt = DbiInitRecord(hCur, pRecBuf); ChkRslt(rslt, "InitRecord"); // Allocate a buffer that is capable of holding a large string. pGenInfo = (pCHAR) malloc(sizeof (CHAR) * 1200); if (pGenInfo == NULL) { return; } // Function will fill the pGeninfo pointer with a string // that is larger than 256 bytes. FillString(pGenInfo); // Fill the fields of the buffer. The fields are filled directly, // but a variable could be used that would hold the string, date or // BLOB information. FillFields(hCur, "Ronald", "P", "Halter", 8, 15, 70, "Chicago", pRecBuf); // Open the BLOB. To write or read from a BLOB you must open the // BLOB first. All that is needed is the cursor, the record buffer, // the field number and the rights. If the BLOB is opened in // ReadWrite mode, the table must be opened in ReadWrite mode also. rslt = DbiOpenBlob(hCur, pRecBuf, 6, dbiREADWRITE); ChkRslt(rslt, "OpenBlob"); // Put the whole BLOB into the field rslt = DbiPutBlob(hCur, pRecBuf, 6, 0, (strlen(pGenInfo) + 1), (pBYTE) pGenInfo); ChkRslt(rslt, "PutBlob"); // Get the length of the present BLOB information before changing // it. GenLen = strlen(pGenInfo); // Clear the pGenINfo Buffer. memset(pGenInfo,0, sizeof(pGenInfo)); // Fill the pGenInfo buffer with a new string. FillHalfString(pGenInfo); // Change half of the present BLOB value by // putting a new string in the second half of the BLOB. // Use the length of the originally inserted BLOB divided // by two to find the halfway point and add one to compensate // for the odd length. rslt = DbiPutBlob(hCur, pRecBuf, 6, (GenLen/2), strlen(pGenInfo), (pBYTE) pGenInfo); ChkRslt(rslt, "PutBlob"); // Append a record to the table. rslt = DbiAppendRecord(hCur, pRecBuf); ChkRslt(rslt, "AppendRecord"); free(pGenInfo); rslt = DbiFreeBlob(hCur, pRecBuf, 6); ChkRslt(rslt, "FreeBlob"); } //===================================================================== // Function: // FillString(pString); // // Input: pString - A string buffer that will be written into by the // function // // Return: None (The input string is modified.) // // Desc: This example fills the input string with a preset string, // which is larger than 256 bytes. //===================================================================== void FillString (pCHAR pString) { strcpy(pString, " This is a test of the BLOB functions. The power of " "a BLOB is that it can contain anything.\r\n" " This is a test of the BLOB functions. The power of " "a BLOB is that it can contain anything.\r\n" " This is a test of the BLOB functions. The power of " "a BLOB is that it can contain anything.\r\n" " This is a test of the BLOB functions. The power of " "a BLOB is that it can contain anything.\r\n" " This is a test of the BLOB functions. The power of " "a BLOB is that it can contain anything.\r\n" " This is a test of the BLOB functions. The power of " "a BLOB is that it can contain anything.\r\n" " This is a test of the BLOB functions. The power of " "a BLOB is that it can contain anything.\r\n" " This is a test of the BLOB functions. The power of " "a BLOB is that it can contain anything.\r\n"); } //===================================================================== // Function: // FillHalfString(pString); // // Input: pString - A string buffer that will be written into by the // function // // Return: None (The input string is modified.) // // Desc: This example fills the input string with a preset string, // which is larger than 256 bytes. The string used is different // from the one used in FillString(). //===================================================================== void FillHalfString (pCHAR pString) { strcpy(pString, " This is line 1 of the BLOB functions. The power of a" " BLOB is that it is dynamic and quick.\r\n" " This is line 2 of the BLOB functions. The power of a" " BLOB is that it is dynamic and quick.\r\n" " This is line 3 of the BLOB functions. The power of a" " BLOB is that it is dynamic and quick.\r\n" " This is line 4 of the BLOB functions. The power of a" " BLOB is that it is dynamic and quick.\r\n"); } //===================================================================== // Function: // DispBlob(hCur, pRecBuf); // // Input: hCur - Table Cursor // pRecBuf - Record Buffer // // Return: None // // Desc: This function displays the BLOB field that is pointed to by // the cursor and which resides in the record buffer. The // function displays the whole BLOB and then half of the BLOB. // It uses DbiGetBlob with and without a range to accomplish // this. //===================================================================== void DispBlob (hDBICur hCur, pBYTE pRecBuf) { UINT32 BlobSize; // Size of the BLOB UINT32 ActualSize; // Actual size of the BLOB as read // from the table pBYTE phBlob = NULL; // Pointer to BLOB data pBYTE phHalfBlob = NULL; // Pointer to BLOB data DBIResult rslt; rslt = DbiInitRecord(hCur, pRecBuf); ChkRslt(rslt, "InitRecord"); // Get the record from the table. rslt = DbiGetRecord(hCur, dbiWRITELOCK, pRecBuf, 0); ChkRslt(rslt, "GetRecord"); // Open the BLOB. The BLOB must be opened before reading from // or writing to it. // This part locks the record in the previous function DbiGetRecord // with the WRITELOCK option. No lock on the BLOB is needed as the // BLOB will not be modified. rslt = DbiOpenBlob(hCur, pRecBuf, 6, dbiREADONLY); ChkRslt(rslt, "OpenBlob"); // Now get the size of the BLOB rslt = DbiGetBlobSize(hCur, pRecBuf, 6, &BlobSize); ChkRslt(rslt, "GetBlobSize"); // Allocate the memory for the BLOB buffer. phBlob = (pBYTE)malloc( sizeof(BYTE) * (UINT16)BlobSize); // Allocate memory for the pHalfBlob buffer phHalfBlob = (pBYTE)malloc(((sizeof(BYTE) * (UINT16)BlobSize)/2)+2); // Initialize the buffers to 0. Cast the Blobsize to UINT16 because // the memset function expects a UINT16. (Assume for the example that // the BLOB is less than 64K in size. memset(phBlob, 0, (UINT16)BlobSize); memset(phHalfBlob, 0, ((UINT16)BlobSize/2)+ 2); // Get the BLOB from the table. rslt = DbiGetBlob(hCur, pRecBuf, 6, 0, BlobSize, phBlob, &ActualSize); ChkRslt(rslt, "GetBlob"); Screen(" This is the whole BLOB Field\r\n"); Screen((pCHAR)phBlob); // Now we are going to get half the BLOB and display that. To get // half the BLOB we start at half the total size (BlobSize/2) and // retrieve the bytes (BlobSize/2). rslt = DbiGetBlob(hCur, pRecBuf, 6, ((BlobSize) / 2), ((BlobSize) / 2), phHalfBlob, &ActualSize); ChkRslt(rslt, "GetBlob"); Screen(" This is half of the BLOB field\r\n"); Screen((pCHAR)phHalfBlob); rslt = DbiFreeBlob(hCur, pRecBuf, 6); ChkRslt(rslt, "FreeBlob"); free(phBlob); free(phHalfBlob); } //===================================================================== // Function: // FillFields(hCur, pszFirst, pszMiddle, pszLast, iMonth, // iDay, iYear, pszPOB, pRecBuf); // // Input: hCur - Cursor handle // pszFirst - First Name // pszMiddle - Middle Name // pszLast - Last Name // iMonth - Month // iDay - Day // iYear - Year // pszPOB - Place of birth // pRecBuf - record buffer // // Return: Result of adding the fields to the record buffer // // Description: // This function will add data to a pre-existing // record buffer. //===================================================================== DBIResult FillFields (hDBICur hCur, pCHAR pszFirst, pCHAR pszMiddle, pCHAR pszLast, UINT16 iMonth, UINT16 iDay, UINT16 iYear, pCHAR pszPOB, pBYTE pRecBuf) { DBIDATE dDate; // Date structure DBIResult rslt; // Return value from IDAPI functions // First Name. rslt = DbiPutField(hCur, 1, pRecBuf, (pBYTE) pszFirst); ChkRslt(rslt, "PutField"); // Middle Name. rslt = DbiPutField(hCur, 2, pRecBuf, (pBYTE) pszMiddle); ChkRslt(rslt, "PutField"); // Last Name. rslt = DbiPutField(hCur, 3, pRecBuf, (pBYTE) pszLast); ChkRslt(rslt, "PutField"); // Date of Birth. rslt = DbiDateEncode(iMonth, iDay, iYear, &dDate); ChkRslt(rslt, "DateEncode"); // If the date is legal we add it to // the fourth field in the record. (Date of Birth) rslt = DbiPutField(hCur, 4, pRecBuf, (pBYTE)&dDate); ChkRslt(rslt, "PutField"); // Place of Birth. rslt = DbiPutField(hCur, 5, pRecBuf, (pBYTE) pszPOB); ChkRslt(rslt, "PutField"); return DBIERR_NONE; }