Dr. DeeBee(r) ODBC Driver Kit Bronze/Silver Edition Bug Fixes - August 3, 2002 ------------------------------------------------------------------------------ The following bugs have been discovered in the current release of the Dr. DeeBee ODBC Driver Kit - Bronze Edition and Silver Edition ------------------------------------------------------------------------------ 19-04-30 In UTIL.C, search for "case 'A':". Change: case 'A': /* **** CONTROL MAY COME HERE FROM PREVIOUS CASE **** */ ptr++; To: case 'A': /* **** CONTROL MAY COME HERE FROM PREVIOUS CASE **** */ if ((lpTime->hour == 12) || (lpTime->hour == 24)) lpTime->hour -= (12); ptr++; ------------------------------ Previous Posting ----------------------------- 02-08-02 <<<< THIS BUG FIX DOES NOT APPLY TO THE BRONZE EDITION >>>> In PREPARE.C, search for "GlobalPtrHandle(lpstmt->lpKeyInfo)". Change: if (lpstmt->lpKeyInfo != NULL) { GlobalUnlock (GlobalPtrHandle(lpstmt->lpKeyInfo)); GlobalFree (GlobalPtrHandle(lpstmt->lpKeyInfo)); } to: if (lpstmt->lpKeyInfo != NULL) { GlobalUnlock (GlobalPtrHandle(lpstmt->lpKeyInfo)); GlobalFree (GlobalPtrHandle(lpstmt->lpKeyInfo)); lpstmt->lpKeyInfo = NULL; } ------------------------------ Previous Posting ----------------------------- 01-10-23 <<<< THIS BUG FIX IS FOR THE NETWORK EDITION ONLY >>>> In DRDBSVR.C, search for "Send the data and length". Change: /* Send the data and length */ if ((fCType == SQL_C_CHAR) && (cbValue < cbValueMax)) marshallData(lpNetConnection, fCType, rgbValue, cbValue); else if (fCType == SQL_C_CHAR) marshallData(lpNetConnection, fCType, rgbValue, cbValueMax - 1); else marshallData(lpNetConnection, fCType, rgbValue, cbValue); to: /* Send the data and length */ if ((fCType == SQL_C_CHAR) && (cbValue < cbValueMax)) marshallData(lpNetConnection, fCType, rgbValue, cbValue); else if (fCType == SQL_C_CHAR) marshallData(lpNetConnection, fCType, rgbValue, cbValueMax - 1); else if ((fCType == SQL_C_BINARY) && (cbValue <= cbValueMax)) marshallData(lpNetConnection, fCType, rgbValue, cbValue); else if (fCType == SQL_C_BINARY) marshallData(lpNetConnection, fCType, rgbValue, cbValueMax); else marshallData(lpNetConnection, fCType, rgbValue, cbValue); ------------------------------ Previous Posting ----------------------------- 01-03-27 <<<< THIS BUG FIX DOES NOT APPLY TO THE BRONZE EDITION >>>> In EVALUATE.C, search for "Position the current table to the next record". Change: /* No. Position the current table to the next record */ err = ISAMNextRecord(lpSqlNodeTable->node.table.Handle); if ((err == NO_ISAM_ERR) || (err == ISAM_EOF)) lpstmt->fISAMTxnStarted = TRUE; to: /* No. Position the current table to the next record */ err = ISAMNextRecord(lpSqlNodeTable->node.table.Handle); if ((err == NO_ISAM_ERR) || (err == ISAM_EOF)) lpstmt->fISAMTxnStarted = TRUE; fOuterJoinIsNull = FALSE; ------------------------------------------------------------------------------ 01-03-26 <<<< THIS BUG FIX IS FOR THE NETWORK EDITION ONLY >>>> In NETISAM.C, search for "Just copy the value". Change: /* Yes. Just copy the value */ *pcbValue = lpISAMColDef->cbValue; if (lpISAMColDef->cbValue > 0) { to: /* Yes. Just copy the value */ *pcbValue = lpISAMColDef->cbValue; if (lpISAMColDef->cbValue >= 0) { ------------------------------------------------------------------------------ 01-03-15 <<<< THIS BUG FIX IS FOR THE NETWORK EDITION ONLY >>>> In DRDBSVR.C, search for "Send the data and length". Change: /* Send the data and length */ if ((fCType == SQL_C_CHAR) && (cbValue < cbValueMax)) marshallData(lpNetConnection, fCType, rgbValue, cbValue); else if (fCType == SQL_C_CHAR) marshallData(lpNetConnection, fCType, rgbValue, cbValueMax - 1); else marshallData(lpNetConnection, fCType, rgbValue, cbValueMax); to: /* Send the data and length */ if ((fCType == SQL_C_CHAR) && (cbValue < cbValueMax)) marshallData(lpNetConnection, fCType, rgbValue, cbValue); else if (fCType == SQL_C_CHAR) marshallData(lpNetConnection, fCType, rgbValue, cbValueMax - 1); else marshallData(lpNetConnection, fCType, rgbValue, cbValue); ------------------------------------------------------------------------------ 01-03-13 <<<< THIS BUG FIX IS FOR THE NETWORK EDITION ONLY >>>> In NET.C, search for "unmarshallCharArray(lpNetConnection, (UCHAR FAR *)". Change: unmarshallCharArray(lpNetConnection, (UCHAR FAR *)*rgbValue, &cbValue); to: if (cbValue > 0) unmarshallCharArray(lpNetConnection, (UCHAR FAR *)*rgbValue, &cbValue); ------------------------------------------------------------------------------ 01-03-08 <<<< THIS BUG FIX DOES NOT APPLY TO THE BRONZE EDITION >>>> In CONNECT.C, search for "(lpdbc->lpISAM->fTxnCapable != SQL_TC_NONE)". Change: if (lpdbc->lpISAM->fTxnCapable != SQL_TC_NONE) { to: if ((lpdbc->lpISAM != NULL) && (lpdbc->lpISAM->fTxnCapable != SQL_TC_NONE)) { ------------------------------------------------------------------------------ 01-01-15 <<<< THIS BUG FIX IS FOR THE NETWORK EDITION ONLY >>>> In NET.C, search for "((fCType == SQL_C_CHAR) && (cbSize == 0))". Change: if ((cbSize > 0) || ((fCType == SQL_C_CHAR) && (cbSize == 0))) { to: if ((fCType == SQL_C_CHAR) && (cbSize == 0) && (*rgbValue != NULL)) ((UCHAR FAR *)*rgbValue)[0] = '\0'; else if ((cbSize > 0) || ((fCType == SQL_C_CHAR) && (cbSize == 0))) { ------------------------------ Previous Posting ----------------------------- 00-10-24 <<<< THIS BUG FIX IS FOR THE NETWORK EDITION ONLY >>>> In DRDBSVR.C, search for "WSACleanup()". Change: closesocket(tSock); WSACleanup(); to: closesocket(tSock); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - In DRDBSVR.C, search for "netSvrDestroy()". There are three of them. in the one in the main() routine, change: netSvrDestroy(); return 1; to: netSvrDestroy(); WSACleanup(); return 1; ------------------------------------------------------------------------------ 00-10-03 <<<< THIS BUG FIX IS FOR THE NETWORK EDITION ONLY >>>> In DRDBSVR.C, search for "SQL_BIGINT". There are two of these. In both cases, change: case SQL_INTEGER: case SQL_BIGINT: case SQL_REAL: to: case SQL_INTEGER: case SQL_REAL: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - In DRDBSVR.C, search for "SQL_NUMERIC". There are two of these. In both cases, change: case SQL_NUMERIC: to: case SQL_NUMERIC: case SQL_BIGINT: ------------------------------------------------------------------------------ 00-04-11 In SEMANTIC.C, search for "lpSqlNode->node.column.Value = ". The one in the TYPE_NUMERIC case is OK. For the TYPE_CHAR and TYPE_BINARY cases, change: case TYPE_CHAR: lpSqlNode->node.column.Value = AllocateSpace(lplpSql, (SDWORD) (1 + lpSqlNode->sqlPrecision)); if (lpSqlNode->node.column.Value == NO_STRING) return ERR_MEMALLOCFAIL; break; case TYPE_BINARY: lpSqlNode->node.column.Value = AllocateSpace(lplpSql, (SDWORD) (sizeof(SDWORD) + lpSqlNode->sqlPrecision)); if (lpSqlNode->node.column.Value == NO_STRING) return ERR_MEMALLOCFAIL; break; to: case TYPE_CHAR: if (lpSqlNode->sqlPrecision < MAX_CHAR_LITERAL_LENGTH) lpSqlNode->node.column.Value = AllocateSpace(lplpSql, (SDWORD) (1 + lpSqlNode->sqlPrecision)); else lpSqlNode->node.column.Value = AllocateSpace(lplpSql, (SDWORD) (1 + MAX_CHAR_LITERAL_LENGTH)); if (lpSqlNode->node.column.Value == NO_STRING) return ERR_MEMALLOCFAIL; break; case TYPE_BINARY: if (lpSqlNode->sqlPrecision < MAX_BINARY_LITERAL_LENGTH) lpSqlNode->node.column.Value = AllocateSpace(lplpSql, (SDWORD) (sizeof(SDWORD) + lpSqlNode->sqlPrecision)); else lpSqlNode->node.column.Value = AllocateSpace(lplpSql, (SDWORD) (sizeof(SDWORD) + MAX_BINARY_LITERAL_LENGTH)); if (lpSqlNode->node.column.Value == NO_STRING) return ERR_MEMALLOCFAIL; break; ------------------------------------------------------------------------------ 00-04-10 In BCD.C, search for "(cDecimalDigits != 0)". Change: if (cDecimalDigits != 0) { ... } to: if (cDecimalDigits != 0) { ... } /* Remove leading zeros */ while (*lpszResult == '0') s_lstrcpy(lpszResult, lpszResult+1); ------------------------------------------------------------------------------ 00-04-07 In ISAM.C, search for "&(SQLTypes[i])". Change: lpSQLType = &(SQLTypes[i]); to: lpSQLType = &(lpISAMTableDef->lpISAM->SQLTypes[i]); Note: If you re-wrote ISAMGetColumnType(), you may not need to do this ------------------------------ Previous Posting ----------------------------- 00-03-27 <<<< THIS BUG FIX IS FOR THE NETWORK EDITION ONLY >>>> In DRDBSVR.C, search for "Allocate newBuf". Change: /* Allocate newBuf */ h = GlobalAlloc (GMEM_MOVEABLE, numOpaques*sizeof(void*)); to: /* Allocate newBuf */ h = GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT,numOpaques*sizeof(void*)); ------------------------------------------------------------------------------ 00-03-21 <<<< THIS BUG FIX IS FOR THE NETWORK EDITION ONLY >>>> In NET.C, search for "s_lstrlen(rgbValue) + 1". Change: cbValue = s_lstrlen(rgbValue) + 1; to: cbValue = s_lstrlen(rgbValue); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - In NET.C, search for "if (cbSize > 0) {". Change: if (cbSize > 0) { to: if ((cbSize > 0) || ((fCType == SQL_C_CHAR) && (cbSize == 0))) { - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - In NET.C, search for "GlobalAlloc (GMEM_MOVEABLE, cbValue)". Change: h = GlobalAlloc (GMEM_MOVEABLE, cbValue); to: if (fCType == SQL_C_CHAR) h = GlobalAlloc (GMEM_MOVEABLE, cbValue+1); else h = GlobalAlloc (GMEM_MOVEABLE, cbValue); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - In NET.C, search for "unmarshallCharArray(lpNetConnection, (UCHAR FAR *)". Change: unmarshallCharArray(lpNetConnection, (UCHAR FAR *)*rgbValue, &cbValue); to: unmarshallCharArray(lpNetConnection, (UCHAR FAR *)*rgbValue, &cbValue); ((UCHAR FAR *)*rgbValue)[cbValue] = '\0'; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - In DRDBSVR.C, search for "lpISAMColDef->cbValue+1". There are two of these. In both cases, change: if (fCType == SQL_C_CHAR) marshallData(lpNetConnection, fCType, szValue, lpISAMColDef->cbValue+1); else marshallData(lpNetConnection, fCType, szValue, lpISAMColDef->cbValue); to: marshallData(lpNetConnection, fCType, szValue, lpISAMColDef->cbValue); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - In DRDBSVR.C, search for "Send the data and length". Change: /* Send the data and length */ if ((fCType == SQL_C_CHAR) && (cbValue < cbValueMax)) marshallData(lpNetConnection, fCType, rgbValue, cbValue+1); else marshallData(lpNetConnection, fCType, rgbValue, cbValueMax); to: /* Send the data and length */ if ((fCType == SQL_C_CHAR) && (cbValue < cbValueMax)) marshallData(lpNetConnection, fCType, rgbValue, cbValue); else if (fCType == SQL_C_CHAR) marshallData(lpNetConnection, fCType, rgbValue, cbValueMax - 1); else marshallData(lpNetConnection, fCType, rgbValue, cbValueMax); ------------------------------------------------------------------------------ 00-03-16 <<<< THIS BUG FIX IS FOR THE NETWORK EDITION ONLY >>>> In DRDBSVR.C, search for "lpISAMColDef->cbValue >= sizeof(szValue)". There are two of them. Change both of the from else if (lpISAMColDef->cbValue >= sizeof(szValue)) to: else if (lpISAMColDef->cbValue >= (SDWORD) sizeof(szValue)) ----------------------------------------------------------------------------- 00-03-10 In EVALUATE.C: Search for "case NODE_TYPE_NULL:". In the one place the code looks like this: case NODE_TYPE_NULL: lpSqlNode->sqlIsNull = TRUE; break; change it to: case NODE_TYPE_NULL: if (lpSqlNode->sqlDataType == TYPE_NUMERIC) lpSqlNode->value.String = ""; lpSqlNode->sqlIsNull = TRUE; break; ------------------------------ Previous Posting ----------------------------- 99-12-16 In PARSE.H, search for "AllocateSpace". Change: STRINGIDX INTFUNC AllocateSpace(LPSQLTREE FAR *, SWORD); to: STRINGIDX INTFUNC AllocateSpace(LPSQLTREE FAR *, SDWORD); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - In PARSE.C, search for "INTFUNC AllocateSpace". Change: STRINGIDX INTFUNC AllocateSpace(LPSQLTREE FAR *lplpSql, SWORD cbSize) to: STRINGIDX INTFUNC AllocateSpace(LPSQLTREE FAR *lplpSql, SDWORD cbSize) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - In SEMANTIC.C, search for "lpSqlNode->node.column.Value = AllocateSpace". There are three of these. In the one for TYPE_CHAR case, change: case TYPE_CHAR: lpSqlNode->node.column.Value = AllocateSpace(lplpSql, (SWORD) (1 + lpSqlNode->sqlPrecision)); to: case TYPE_CHAR: lpSqlNode->node.column.Value = AllocateSpace(lplpSql, (SDWORD) (1 + lpSqlNode->sqlPrecision)); In the one for TYPE_BINARY case, change: case TYPE_BINARY: lpSqlNode->node.column.Value = AllocateSpace(lplpSql, (SWORD) (sizeof(SDWORD) + lpSqlNode->sqlPrecision)); to: case TYPE_BINARY: lpSqlNode->node.column.Value = AllocateSpace(lplpSql, (SDWORD) (sizeof(SDWORD) + lpSqlNode->sqlPrecision)); ------------------------------------------------------------------------------ 99-10-05 <<<< THIS BUG FIX DOES NOT APPLY TO THE BRONZE EDITION >>>> In EVALUATE.C, search for "/* Rewind the tables */". Change: /* Rewind the tables */ to: /* Rewind the tables */ if (lpSqlNode->node.select.Sortfile != HFILE_ERROR) { _lclose(lpSqlNode->node.select.Sortfile); lpSqlNode->node.select.Sortfile = HFILE_ERROR; lpSqlNode->node.select.ReturningDistinct = FALSE; DeleteFile((LPCSTR) ToString(lpstmt->lpSqlStmt, lpSqlNode->node.select.SortfileName)); s_lstrcpy(ToString(lpstmt->lpSqlStmt, lpSqlNode->node.select.SortfileName), ""); } ------------------------------------------------------------------------------ 99-09-24 <<<< THIS BUG FIX IS FOR THE NETWORK EDITION ONLY >>>> In DRDBSVR.C, search for "CreateThread". There are two of them. In the first instance, change hThread = CreateThread(NULL, 0, handleClientRequests, (LPVOID)childSock, 0, &idThread); to: hThread = CreateThread(NULL, 0, handleClientRequests, (LPVOID)childSock, 0, &idThread); CloseHandle(hThread); In the second instance, change: hThread = CreateThread(NULL, 0, main, NULL, 0, &idThread); if (hThread == NULL) { return GetLastError(); } /* Wait for either thread to finish or mainSocket to become valid */ /* !!! should block not loop... */ while (TRUE) { if (drdeebeesvr_mainSocket != INVALID_SOCKET) { return 0; } if (!GetExitCodeThread(hThread, &exitcode)) { return GetLastError(); } if (exitcode != STILL_ACTIVE) { return -1; } } to: hThread = CreateThread(NULL, 0, main, NULL, 0, &idThread); if (hThread == NULL) { return GetLastError(); } /* Wait for either thread to finish or mainSocket to become valid */ /* !!! should block not loop... */ while (TRUE) { if (drdeebeesvr_mainSocket != INVALID_SOCKET) { CloseHandle(hThread); return 0; } if (!GetExitCodeThread(hThread, &exitcode)) { CloseHandle(hThread); return GetLastError(); } if (exitcode != STILL_ACTIVE) { CloseHandle(hThread); return -1; } } ------------------------------------------------------------------------------ 99-09-19 <<<< THIS BUG FIX DOES NOT APPLY TO THE BRONZE EDITION >>>> In SCALAR.C, search for "switch (lpSqlNodeValue[0]->value.String[0])". Change switch (lpSqlNodeValue[0]->value.String[0]) { to: lpstr1 = lpSqlNodeValue[0]->value.String; if (*lpstr1 == '.') { lpstr1++; while (*lpstr1 == '0') lpstr1++; } switch (*lpstr1) { ------------------------------------------------------------------------------ 99-09-18 <<<< THIS BUG FIX DOES NOT APPLY TO THE BRONZE EDITION >>>> In UTIL.C, search for "if (!s_lstrcmp(szBuffer, "0") && (dbl != 0.0) &&". Change if (!s_lstrcmp(szBuffer, "0") && (dbl != 0.0) && to if ((!s_lstrcmp(szBuffer, "0") || !s_lstrcmp(szBuffer, "-0")) && (dbl != 0.0) && ------------------------------------------------------------------------------ 99-09-15 <<<< THIS BUG FIX DOES NOT APPLY TO THE BRONZE EDITION >>>> In EVALUATE.C, search for "/* Rewind the other tables */". Change } /* Rewind the other tables */ to: } else fOuterJoinIsNull = FALSE; /* Rewind the other tables */ ------------------------------------------------------------------------------ 99-09-11 <<<< THIS BUG FIX DOES NOT APPLY TO THE BRONZE EDITION >>>> In the bug fix designated by 99-09-10 (immediately below). The bug fix was incorrect. Instead of: if (sw1 < sw2) sw2 = sw1; it should be if (sw1 < sw2) sw2 = sw1 + 1; ------------------------------ Previous Posting ----------------------------- 99-09-10 <<<< THIS BUG FIX DOES NOT APPLY TO THE BRONZE EDITION >>>> In SCALAR.C, search for "if (sw1 < sw2)". There are two of these, look for the one in the SCALAR_SUBSTRING case (the second one of the two). Change if (sw1 < sw2) { s_lstrcpy(lpstmt->szError, lpScalarFunc->name); return ERR_SCALARBADARG; } to: if (sw1 < sw2) sw2 = sw1; ------------------------------------------------------------------------------ 99-07-29 <<<< THIS BUG FIX DOES NOT APPLY TO THE BRONZE EDITION >>>> In SCALAR.C, search for "floor(lpSqlNodeValue[0]->value.Double * power)". There will be two of them. In both cases, change: lpSqlNode->value.Double = floor(lpSqlNodeValue[0]->value.Double * power) / power; to: dbl = floor(lpSqlNodeValue[0]->value.Double * power); if ((dbl < 0.0) && (dbl != lpSqlNodeValue[0]->value.Double * power)) dbl += (1.0); lpSqlNode->value.Double = dbl / power; In SCALAR.C, search for "dbl = floor(dbl * power) / power". Change: dbl = floor(dbl * power) / power; to: dblOriginal = dbl; dbl = floor(dbl * power); if ((dbl < 0.0) && (dblOriginal != dbl * power)) dbl += (1.0); dbl /= (power); (you will also have to add the declaration "double dblOriginal;") ------------------------------------------------------------------------------ 99-07-28 <<<< THIS BUG FIX DOES NOT APPLY TO THE BRONZE EDITION >>>> In SCALAR.C, search for "(lpSqlNode->value.String[0] != '-')". Change: if (fFractionalPart && (lpSqlNode->value.String[0] != '-')) { to: if (fFractionalPart && (lpstr1[0] != '-')) { Search for "(lpSqlNode->value.String[0] == '-')". Change: if (fFractionalPart && (lpSqlNode->value.String[0] == '-')) { to: if (fFractionalPart && (lpstr1[0] == '-')) { ------------------------------------------------------------------------------ 99-07-27 <<<< THIS BUG FIX DOES NOT APPLY TO THE BRONZE EDITION >>>> In EVALUATE.C, search for "No. Return result". Change: /* No. Return result */ lpSqlNode->sqlIsNull = FALSE; to: /* No. Return result */ err = ERR_SUCCESS; lpSqlNode->sqlIsNull = FALSE; ------------------------------------------------------------------------------ 99-07-09 <<<< THIS BUG FIX DOES NOT APPLY TO THE BRONZE EDITION >>>> In PREPARE.C, search for "End the transaction if need be". Remove: /* End the transaction if need be */ if ((lpstmt->fStmtType == STMT_TYPE_SELECT) && (lpstmt->lpdbc->lpISAM->fTxnCapable != SQL_TC_NONE) && lpstmt->lpdbc->fAutoCommitTxn) { err = SQLTransact(SQL_NULL_HENV, (HDBC)lpstmt->lpdbc, SQL_COMMIT); if ((err != SQL_SUCCESS) && (err != SQL_SUCCESS_WITH_INFO)) { lpstmt->errcode = lpstmt->lpdbc->errcode; s_lstrcpy(lpstmt->szISAMError, lpstmt->lpdbc->szISAMError); return err; } } ------------------------------------------------------------------------------ 99-05-05 <<<< THIS BUG FIX DOES NOT APPLY TO THE BRONZE EDITION >>>> In EVALUATE.C, search for "Is a sort needed?". Change: /* Is a sort needed? */ to: /* Is a sort needed? */ if (lpSqlNode->node.select.Sortfile != HFILE_ERROR) { _lclose(lpSqlNode->node.select.Sortfile); lpSqlNode->node.select.Sortfile = HFILE_ERROR; lpSqlNode->node.select.ReturningDistinct = FALSE; DeleteFile((LPCSTR) ToString(lpstmt->lpSqlStmt, lpSqlNode->node.select.SortfileName)); s_lstrcpy(ToString(lpstmt->lpSqlStmt, lpSqlNode->node.select.SortfileName), ""); } ------------------------------------------------------------------------------ 99-05-05 <<<< THIS BUG FIX ONLY APPLIES TO THE BRONZE EDITION >>>> In EVALUATE.C, search for "Is a sort needed?". Change: /* Is a sort needed? */ to: /* Is a sort needed? */ if (lpstmt->hfSortfile != HFILE_ERROR) { _lclose(lpstmt->hfSortfile); lpstmt->hfSortfile = HFILE_ERROR; lpstmt->fReturnDistinct = FALSE; DeleteFile(lpstmt->szSortfile); lstrcpy(lpstmt->szSortfile, ""); } ------------------------------ Previous Posting ----------------------------- 99-03-17 <<<< THIS BUG FIX DOES NOT APPLY TO THE BRONZE EDITION >>>> In SCALAR.C, search for "UCHAR soundex_table[26];". Change: UCHAR soundex_table[26]; to: UCHAR soundex_table[27]; ------------------------------------------------------------------------------ 99-03-16 <<<< THIS BUG FIX DOES NOT APPLY TO THE BRONZE EDITION >>>> In SCALAR.C, search for "soundex(str1, sdex1);". Change: soundex(str1, sdex1); to: sdex1[0] = '\0'; sdex1[1] = '\0'; sdex1[2] = '\0'; sdex1[3] = '\0'; sdex1[4] = '\0'; sdex2[0] = '\0'; sdex2[1] = '\0'; sdex2[2] = '\0'; sdex2[3] = '\0'; sdex2[4] = '\0'; soundex(str1, sdex1); ------------------------------------------------------------------------------ 99-03-17 <<<< THIS BUG ONLY APPLIES TO THE NEWORK EDITION >>>> In NET.C, replace the implementation of marshallBufResize() with the following: BOOL marshallBufResize(LPNETCONNECTION lpNetConnection, size_t cbSize, BOOL preserveData) /* Resizes the marshall buffer associated with the NetConnection. */ /* If 'preserveData' is FALSE, the buffer indexes (cbInUse & cbCurr) */ /* are set back to 0; otherwise they are unchanged. */ /* If 'preserveData' is TRUE then cbSize may not be smaller than */ /* the current marshall buffer size, and the new buffer size will be */ /* rounded up to the next multiple of MARSHALLBUF_CHUNKSIZE. */ /* (May or may not do actual memory reallocation, depending on */ /* whether the requested size is smaller or larger than the */ /* minimum buffer size and/or the current buffer size.) */ { int state; enum tagState { AllSmall = 0 ,NeedToGrow = 1 ,NeedToShrink = 2 ,NeedToAdjust = 3 }; /* Make sure the buf is not null */ if (lpNetConnection->mb.lpBuf == NULL) { lpNetConnection->mb.lpBuf = lpNetConnection->mb.lpDefBuf; lpNetConnection->mb.cbSize = MARSHALLBUF_DEFSIZE; marshallBufZero(lpNetConnection); } /* Return FALSE if neg. size requested, or preserve & shrink requested */ if (cbSize < 0) return FALSE; if (!preserveData) marshallBufZero(lpNetConnection); else { if (cbSize < lpNetConnection->mb.cbSize) return FALSE; } state = 0; if (cbSize > MARSHALLBUF_DEFSIZE) state |= (1); if (lpNetConnection->mb.cbSize > MARSHALLBUF_DEFSIZE) state |= (2); /* Strategy: always keep the DEFSIZE buffer. */ /* if it's too small, put it in the back pocket & allocate a big one */ /* toss the big one & reclaim the DEFSIZE one when done */ switch (state) { case AllSmall: break; case NeedToShrink: /* Restore the backup buffer */ marshallBufFree(lpNetConnection); lpNetConnection->mb.lpBuf = lpNetConnection->mb.lpDefBuf; lpNetConnection->mb.cbSize = MARSHALLBUF_DEFSIZE; break; case NeedToAdjust: if (cbSize < lpNetConnection->mb.cbSize) { /* Shrinking... */ /* If curr size is within chunk of requested, don't reallocate */ if (cbSize + MARSHALLBUF_CHUNKSIZE > lpNetConnection->mb.cbSize) break; } /* *** DROP INTO THE NEXT CASE *** */ case NeedToGrow: /* *** CONTROL MAY GET HERE FROM PREVIOUS CASE *** */ /* Round up cbSize to the next full MARSHALLBUF_CHUNKSIZE */ cbSize = (cbSize + MARSHALLBUF_CHUNKSIZE -1) & ~(MARSHALLBUF_CHUNKSIZE-1); if (cbSize != lpNetConnection->mb.cbSize) { /* not staying the same */ if (preserveData) marshallBufReAlloc(lpNetConnection, cbSize);/* Never shrink */ else marshallBufAlloc(lpNetConnection, cbSize); } break; } if ((lpNetConnection->mb.lpBuf == NULL) || (lpNetConnection->mb.cbSize == 0)) return FALSE; return TRUE; } ------------------------------------------------------------------------------ 99-02-25 <<<< THIS BUG FIX DOES NOT APPLY TO THE BRONZE EDITION >>>> In EVALUATE.C, search for "Yes. Use a record of all nulls" (make sure the one you find starts with the word "Yes"). Change: /* Yes. Use a record of all nulls */ err = ERR_SUCCESS; lpSqlNodeTable->node.table.AllNull = TRUE; fOuterJoinIsNull = TRUE; to: /* Yes. No data if already tried all null record */ if (lpSqlNodeTable->node.table.AllNull) return ERR_NODATAFOUND; /* Use a record of all nulls */ err = ERR_SUCCESS; lpSqlNodeTable->node.table.AllNull = TRUE; fOuterJoinIsNull = TRUE; ------------------------------------------------------------------------------ 99-02-17 <<<< THIS BUG FIX DOES NOT APPLY TO THE BRONZE EDITION >>>> In EVALUATE.C, search for "Try to fetch a row". Change: /* Try to fetch a row */ if (err == ERR_SUCCESS) { err = FetchRow(lpstmt, lpSqlNodeSelect); if ((err != ERR_SUCCESS) && (err != ERR_NODATAFOUND)) return err; } /* Return result */ lpSqlNode->sqlIsNull = FALSE; if (err == ERR_NODATAFOUND) lpSqlNode->value.Double = FALSE; else lpSqlNode->value.Double = TRUE; to: /* Try to fetch a row */ if (err == ERR_SUCCESS) { err = FetchRow(lpstmt, lpSqlNodeSelect); if ((err != ERR_SUCCESS) && (err != ERR_NODATAFOUND)) return err; } /* Return result */ lpSqlNode->sqlIsNull = FALSE; if (err == ERR_NODATAFOUND) { lpSqlNode->value.Double = FALSE; err = ERR_SUCCESS; } else lpSqlNode->value.Double = TRUE; ------------------------------------------------------------------------------ 99-02-06 In SEMANTIC.C, search for "Yes. Add this sort column to the count" (make sure the one you find starts with the word "Yes"). Change: /* Yes. Add this sort column to the count */ count++; to: /* Yes. Add this sort column to the count */ if (count != 0) s_lstrcat(szSortDirective, ","); count++; Assuming you applied the patch dated 98-07-30, about 35 lines down change /* Put direction of the key column in the sort directive */ s_lstrcat(szSortDirective, "A"); if (lpSqlNodeValues->node.values.Next != NO_SQLNODE) s_lstrcat(szSortDirective, ","); back to what is was originally: /* Put direction of the key column in the sort directive */ s_lstrcat(szSortDirective, "A"); ------------------------------------------------------------------------------ 99-02-04 In OPTMIZE.C, search for "Can we optimize the sort". Change: /* Can we optimize the sort by pushing the sorting down to the */ /* ISAM level? */ if ((idxSortcolumns == NO_SQLNODE) && (lpSqlNode->node.select.Groupbycolumns == NO_SQLNODE) && (!lpSqlNode->node.select.ImplicitGroupby) && (!lpSqlNode->node.select.Distinct)) { to: /* Can we optimize the sort by pushing the sorting down to the */ /* ISAM level? */ if ((idxSortcolumns == NO_SQLNODE) && (tableSequenceNumber == 1) && (lpSqlNode->node.select.Groupbycolumns == NO_SQLNODE) && (!lpSqlNode->node.select.ImplicitGroupby) && (!lpSqlNode->node.select.Distinct)) { ------------------------------------------------------------------------------ 99-01-18 <<<< THIS BUG FIX DOES NOT APPLY TO THE BRONZE EDITION >>>> In SEMANTIC.C, search for "lpSqlNodeColumn->node.column.Table =". There are three of these in SEMANTIC.C, change the third one (the one in SemanticCheck()). Change: lpSqlNodeColumn->node.column.Table = lpSqlNode->node.insert.Table; to: lpSqlNode = ToNode(*lplpSql, idxNode); lpSqlNodeColumn->node.column.Table = lpSqlNode->node.insert.Table; ------------------------------------------------------------------------------ 99-01-07 <<<< THIS BUG FIX DOES NOT APPLY TO THE BRONZE EDITION >>>> In INFO.C, search for "SQL_SUBQUERIES". Change: case SQL_SUBQUERIES: case SQL_UNION: *(SDWORD FAR *)rgbInfoValue = 0; if (pcbInfoValue != NULL) *pcbInfoValue = 4; break; to: case SQL_UNION: *(SDWORD FAR *)rgbInfoValue = 0; if (pcbInfoValue != NULL) *pcbInfoValue = 4; break; case SQL_SUBQUERIES: *(SDWORD FAR *)rgbInfoValue = SQL_SQ_COMPARISON | SQL_SQ_EXISTS | SQL_SQ_IN | SQL_SQ_QUANTIFIED | SQL_SQ_CORRELATED_SUBQUERIES; if (pcbInfoValue != NULL) *pcbInfoValue = 4; break; ------------------------------ Previous Posting ----------------------------- 98-12-08 <<<< THIS BUG FIX DOES NOT APPLY TO THE BRONZE EDITION >>>> In SEMANTIC.C, search for "Check the list of tables". After /* Check the list of tables */ err = SemanticCheck(lpstmt, lplpSql, lpSqlNode->node.select.Tables, FALSE, fCaseSensitive, NO_SQLNODE, idxNode); if (err != ERR_SUCCESS) return err; add: lpSqlNode = ToNode(*lplpSql, idxNode); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - In SEMANTIC.C, search for "Check the WHERE clause". After /* Check the WHERE clause */ err = SemanticCheck(lpstmt, lplpSql, lpSqlNode->node.select.Predicate, FALSE, fCaseSensitive, NO_SQLNODE, idxNode); if (err != ERR_SUCCESS) return err; add: lpSqlNode = ToNode(*lplpSql, idxNode); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - In SEMANTIC.C, search for "Check the HAVING clause". After /* Check the HAVING clause */ err = SemanticCheck(lpstmt, lplpSql, lpSqlNode->node.select.Having, fIsGroupby, fCaseSensitive, NO_SQLNODE, idxNode); if (err != ERR_SUCCESS) return err; add: lpSqlNode = ToNode(*lplpSql, idxNode); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - In SEMANTIC.C, search for "SemanticCheck(lpstmt, lplpSql, lpSqlNode->node.boolean.Left". After err = SemanticCheck(lpstmt, lplpSql, lpSqlNode->node.boolean.Left, fIsGroupby, fCaseSensitive, idxNodeTableOuterJoinFromTables, idxEnclosingStatement); if (err != ERR_SUCCESS) return err; add: lpSqlNode = ToNode(*lplpSql, idxNode); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - In SEMANTIC.C, search for "SemanticCheck(lpstmt, lplpSql, lpSqlNode->node.tables.Table". After err = SemanticCheck(lpstmt, lplpSql, lpSqlNode->node.tables.Table, fIsGroupby, fCaseSensitive, idxNodeTableOuterJoinFromTables, idxEnclosingStatement); if (err != ERR_SUCCESS) return err; add: lpSqlNode = ToNode(*lplpSql, idxNode); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - In SEMANTIC.C, search for "SemanticCheck(lpstmt, lplpSql, lpSqlNode->node.tables.Next". After err = SemanticCheck(lpstmt, lplpSql, lpSqlNode->node.tables.Next, fIsGroupby, fCaseSensitive, idxNodeTableOuterJoinFromTables, idxEnclosingStatement); if (err != ERR_SUCCESS) return err; add: lpSqlNode = ToNode(*lplpSql, idxNode); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - In SEMANTIC.C, search for "SemanticCheck(lpstmt, lplpSql, lpSqlNode->node.comparison.Left". After err = SemanticCheck(lpstmt, lplpSql, lpSqlNode->node.comparison.Left, fIsGroupby, fCaseSensitive, idxNodeTableOuterJoinFromTables, idxEnclosingStatement); if (err != ERR_SUCCESS) return err; add: lpSqlNode = ToNode(*lplpSql, idxNode); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - In SEMANTIC.C, search for "SemanticCheck(lpstmt, lplpSql, lpSqlNode->node.comparison.Right". After err = SemanticCheck(lpstmt, lplpSql, lpSqlNode->node.comparison.Right, fIsGroupby, fCaseSensitive, idxNodeTableOuterJoinFromTables, idxEnclosingStatement); if (err != ERR_SUCCESS) return err; add: lpSqlNode = ToNode(*lplpSql, idxNode); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - In SEMANTIC.C, search for "Semantic check the right node". Change /* Semantic check the right node on next iteration of the loop */ lpSqlNode = ToNode(*lplpSql, lpSqlNode->node.boolean.Right); to: /* Semantic check the right node on next iteration of the loop */ idxNode = lpSqlNode->node.boolean.Right; lpSqlNode = ToNode(*lplpSql, idxNode); ------------------------------------------------------------------------------ 98-11-23 In SEMANTIC.C, search for "Recalculate these pointers". Change /* Recalculate these pointers since the Alloc above */ /* may have moved them */ lpSqlNodeColumnGroupby = ToNode(*lplpSql, lpSqlNodeGroupbycolumns->node.groupbycolumns.Column); to: /* Recalculate these pointers since the Alloc above */ /* may have moved them */ lpSqlNodeGroupbycolumns = ToNode(*lplpSql, idxGroupbycolumns); lpSqlNodeColumnGroupby = ToNode(*lplpSql, lpSqlNodeGroupbycolumns->node.groupbycolumns.Column); ------------------------------------------------------------------------------ 98-11-17 <<<< THIS BUG FIX DOES NOT APPLY TO THE BRONZE EDITION >>>> In PARSE.C, search for GetKeyword(lpstmt, lplpszSqlStr, pcbSqlStr, "VALUES" Change: /* Make sure keyword is given */ err = GetKeyword(lpstmt, lplpszSqlStr, pcbSqlStr, "VALUES", lpszToken); if (err != ERR_SUCCESS) return err; /* Error if no starting '(' */ err = GetSymbol(lpstmt, lplpszSqlStr, pcbSqlStr, "(", lpszToken); if (err != ERR_SUCCESS) return err; /* Sub-select? */ old_lpszSqlStr = *lplpszSqlStr; old_cbSqlStr = *pcbSqlStr; err = GetKeyword(lpstmt, lplpszSqlStr, pcbSqlStr, "SELECT", lpszToken); if (err != ERR_SUCCESS) { /* No. Get the value list */ *lplpszSqlStr = old_lpszSqlStr; *pcbSqlStr = old_cbSqlStr; err = ParseValuelist(lpstmt, lplpszSqlStr, pcbSqlStr, lplpSql, lpIdxValues, lpszToken); if (err != ERR_SUCCESS) return err; } else { /* Yes. Get SELECT */ err = ParseSelect(lpstmt, lplpszSqlStr, pcbSqlStr, lplpSql, lpIdxValues, lpszToken); if (err != ERR_SUCCESS) return err; } /* Error if no ending ')' */ err = GetSymbol(lpstmt, lplpszSqlStr, pcbSqlStr, ")", lpszToken); if (err != ERR_SUCCESS) return err; to: /* Sub-select? */ old_lpszSqlStr = *lplpszSqlStr; old_cbSqlStr = *pcbSqlStr; err = GetKeyword(lpstmt, lplpszSqlStr, pcbSqlStr, "SELECT", lpszToken); if (err != ERR_SUCCESS) { /* No. Make sure keyword is given */ *lplpszSqlStr = old_lpszSqlStr; *pcbSqlStr = old_cbSqlStr; err = GetKeyword(lpstmt, lplpszSqlStr, pcbSqlStr, "VALUES", lpszToken); if (err != ERR_SUCCESS) return err; /* Error if no starting '(' */ err = GetSymbol(lpstmt, lplpszSqlStr, pcbSqlStr, "(", lpszToken); if (err != ERR_SUCCESS) return err; /* Get the value list */ err = ParseValuelist(lpstmt, lplpszSqlStr, pcbSqlStr, lplpSql, lpIdxValues, lpszToken); if (err != ERR_SUCCESS) return err; /* Error if no ending ')' */ err = GetSymbol(lpstmt, lplpszSqlStr, pcbSqlStr, ")", lpszToken); if (err != ERR_SUCCESS) return err; } else { /* Yes. Get SELECT */ err = ParseSelect(lpstmt, lplpszSqlStr, pcbSqlStr, lplpSql, lpIdxValues, lpszToken); if (err != ERR_SUCCESS) return err; } ------------------------------------------------------------------------------ 98-11-12 <<<< THIS BUG FIX DOES NOT APPLY TO THE BRONZE EDITION >>>> In SEMANTIC.C, search for "Check the value list". After: /* Check the value list */ err = SemanticCheck(lpstmt, lplpSql, lpSqlNode->node.insert.Values, fIsGroupby, fCaseSensitive, idxNodeTableOuterJoinFromTables, idxNode); if (err != ERR_SUCCESS) return err; add: lpSqlNode = ToNode(*lplpSql, idxNode); ------------------------------------------------------------------------------ 98-10-13 <<<< THIS BUG FIX DOES NOT APPLY TO THE BRONZE EDITION >>>> In SCALAR.C, search for "(MONTHS_PER_YEAR * (ts2.tm_year - ts.tm_year)))" After: lpSqlNode->value.Double = ((ts2.tm_mon - ts.tm_mon) + (MONTHS_PER_YEAR * (ts2.tm_year - ts.tm_year))) / 3; add: break; ------------------------------------------------------------------------------ 98-09-22 <<<< THIS BUG FIX DOES NOT APPLY TO THE BRONZE EDITION >>>> In PARSE.C search for "if (!s_lstrcmpi(lpszToken, "*"))". Replace: if (!s_lstrcmpi(lpszToken, "*")) with if ((!s_lstrcmpi(lpszToken, "*")) && ((*pcbSqlStr == 0) || (*(*lplpszSqlStr) != ')'))) ------------------------------ Previous Posting ----------------------------- 98-09-16 <<<< THIS BUG FIX DOES NOT APPLY TO THE BRONZE EDITION >>>> In SCALAR.C, search for "lng = (long)", replace: lng = (long) lpSqlNodeValue[0]->value.Double; _fmemcpy(BINARY_DATA(lpSqlNode->value.Binary), &shrt, sizeof(long)); with lng = (long) lpSqlNodeValue[0]->value.Double; _fmemcpy(BINARY_DATA(lpSqlNode->value.Binary), &lng, sizeof(long)); ------------------------------------------------------------------------------ 98-07-30 In SEMANTIC.C, search for "/* Put direction of the key column in the sort directive */". You will see this twice in the file. At the second occurrence, replace: /* Put direction of the key column in the sort directive */ s_lstrcat(szSortDirective, "A"); break; with: /* Put direction of the key column in the sort directive */ s_lstrcat(szSortDirective, "A"); if (lpSqlNodeValues->node.values.Next != NO_SQLNODE) s_lstrcat(szSortDirective, ","); break; About 40 lines down, you will see /* Go to next sort column */ idxValues = lpSqlNodeValues->node.values.Next; if (idxValues != NO_SQLNODE) s_lstrcat(szSortDirective, ","); replace this with: /* Go to next sort column */ idxValues = lpSqlNodeValues->node.values.Next; ------------------------------ Previous Posting ----------------------------- 98-07-13 <<<< THIS BUG FIX IS FOR THE SILVER EDITION ONLY >>>> In SCALAR.C, search for "lpTo = BINARY_DATA(lpSqlNode->value.Binary);". Replace: lpTo = BINARY_DATA(lpSqlNode->value.Binary); with lpTo = lpSqlNode->value.String; ------------------------------------------------------------------------------ 98-06-29 In EVALUATE.C, search for "return 1;". Replace: return -1; else if (leftTimestamp.fraction < rightTimestamp.fraction) return 1; with return 1; else if (leftTimestamp.fraction < rightTimestamp.fraction) return -1; ------------------------------ Previous Posting ----------------------------- 98-05-22 <<<< THIS BUG FIX DOES NOT APPLY TO THE BRONZE EDITION >>>> In PARSE.C, search for "Is an index being created?". Replace: /* Is an index being created? */ old_lpszSqlStr = *lplpszSqlStr; old_cbSqlStr = *pcbSqlStr; err = GetKeyword(lpstmt, lplpszSqlStr, pcbSqlStr, "INDEX", lpszToken); if (err == ERR_SUCCESS) { /* Yes. Unique index? */ old_lpszSqlStr = *lplpszSqlStr; old_cbSqlStr = *pcbSqlStr; err = GetKeyword(lpstmt, lplpszSqlStr, pcbSqlStr, "UNIQUE", lpszToken); if (err == ERR_SUCCESS) { fUnique = TRUE; } else { *lplpszSqlStr = old_lpszSqlStr; *pcbSqlStr = old_cbSqlStr; fUnique = FALSE; } /* Get index name */ with old_lpszSqlStr = *lplpszSqlStr; old_cbSqlStr = *pcbSqlStr; err = GetKeyword(lpstmt, lplpszSqlStr, pcbSqlStr, "UNIQUE", lpszToken); if (err == ERR_SUCCESS) fUnique = TRUE; else { *lplpszSqlStr = old_lpszSqlStr; *pcbSqlStr = old_cbSqlStr; fUnique = FALSE; } /* Is an index being created? */ old_lpszSqlStr = *lplpszSqlStr; old_cbSqlStr = *pcbSqlStr; err = GetKeyword(lpstmt, lplpszSqlStr, pcbSqlStr, "INDEX", lpszToken); if (err == ERR_SUCCESS) { /* Get index name */ In PARSE.C, search for "Make sure a table is being created". Replace: /* No. Make sure a table is being created */ *lplpszSqlStr = old_lpszSqlStr; *pcbSqlStr = old_cbSqlStr; err = GetKeyword(lpstmt, lplpszSqlStr, pcbSqlStr, "TABLE", lpszToken); if (err != ERR_SUCCESS) return err; with /* No. Make sure a table is being created */ *lplpszSqlStr = old_lpszSqlStr; *pcbSqlStr = old_cbSqlStr; err = GetKeyword(lpstmt, lplpszSqlStr, pcbSqlStr, "TABLE", lpszToken); if (err != ERR_SUCCESS) return err; /* Error if UNIQUE specified */ if (fUnique) { s_lstrcpy(lpstmt->szError, "UNIQUE"); return ERR_EXPECTEDOTHER; } ------------------------------------------------------------------------------ 98-05-06 <<<< THIS BUG FIX ONLY APPLIES TO YOU HAVE A MODULE CALLED SORT.C >>>> <<<< If you don't have a SORT.C, don't worry, you don't need it. >>>> <<<< Earlier editions of the driver kit used the OptTech sort >>>> <<<< instead. The OptTech sort performs better than ours, but it >>>> <<<< doesn't come with source code. Our SORT.C module does not >>>> <<<< implement all the OptTech functionality (it only implements >>>> <<<< the stuff we use). >>>> In SORT.C, search for "if (outputCounter > 0)". Replace: if (outputCounter > 0) { if (_llseek(hfile, ((UDWORD) (nextOutputBunch - 1)) * ((UDWORD) (sortData->recordSize * bunchSize)), 0) == HFILE_ERROR) { GlobalUnlock(hBetaBuffer); GlobalFree(hBetaBuffer); GlobalUnlock(hAlphaBuffer); GlobalFree(hAlphaBuffer); return ERR_SORT; } with if (_llseek(hfile, ((UDWORD) (nextOutputBunch - 1)) * ((UDWORD) (sortData->recordSize * bunchSize)), 0) == HFILE_ERROR) { GlobalUnlock(hBetaBuffer); GlobalFree(hBetaBuffer); GlobalUnlock(hAlphaBuffer); GlobalFree(hAlphaBuffer); return ERR_SORT; } if (outputCounter > 0) { In SORT.C, search for "if (betaCounter > 0)". Replace: /* Any more records in the beta buffer? */ if (betaCounter > 0) { /* Yes. Write them out */ if (_llseek(hfile, (recordCount - (UDWORD) betaCounter) * ((UDWORD) sortData->recordSize), 0) == HFILE_ERROR) { GlobalUnlock(hBetaBuffer); GlobalFree(hBetaBuffer); GlobalUnlock(hAlphaBuffer); GlobalFree(hAlphaBuffer); return ERR_SORT; } with /* Any more records in the beta buffer? */ if (betaCounter > 0) { In SORT.C, search for "if (alphaCounter > 0)". Replace: /* Any more records in the alpha buffer? */ if (alphaCounter > 0) { /* Yes. Write them out */ if (_llseek(hfile, (recordCount - (UDWORD) alphaCounter) * ((UDWORD) sortData->recordSize), 0) == HFILE_ERROR) { GlobalUnlock(hBetaBuffer); GlobalFree(hBetaBuffer); GlobalUnlock(hAlphaBuffer); GlobalFree(hAlphaBuffer); return ERR_SORT; } with /* Any more records in the alpha buffer? */ if (alphaCounter > 0) { ------------------------------------------------------------------------------ 98-01-20 In RESULTS.C, search for "lpstmt->cbOffset += (cbValueMax-1);". Replace: /* Fix the offset */ if (cbValue >= cbValueMax) { if (fCType == SQL_C_CHAR) lpstmt->cbOffset += (cbValueMax-1); else lpstmt->cbOffset += (cbValueMax); } else if (cbValue > 0) lpstmt->cbOffset += (cbValue); with: /* Fix the offset */ if (cbValue >= cbValueMax) { if (fCType == SQL_C_CHAR) { if (cbValueMax > 0) lpstmt->cbOffset += (cbValueMax-1); } else lpstmt->cbOffset += (cbValueMax); } else if (cbValue > 0) lpstmt->cbOffset += (cbValue); In RESULTS.C, search for "lpstmt->cbOffset += (cbValueMax-1);". Replace: /* Fix the offset */ if (cbValue >= cbValueMax) lpstmt->cbOffset += (cbValueMax-1); else if (cbValue > 0) lpstmt->cbOffset += (cbValue); with: /* Fix the offset */ if (cbValue >= cbValueMax) { if (cbValueMax > 0) lpstmt->cbOffset += (cbValueMax-1); } else if (cbValue > 0) lpstmt->cbOffset += (cbValue); ------------------------------------------------------------------------------ 98-01-16 In RESULTS.C, search for "So far no column read". Replace: /* So far no column read */ lpstmt->icol = NO_COLUMN; lpstmt->cbOffset = 0; /* Get the bound columns */ errcode = ERR_SUCCESS; for (lpBound = lpstmt->lpBound; lpBound != NULL; lpBound = lpBound->lpNext) { rc = SQLGetData(hstmt, lpBound->icol, lpBound->fCType, lpBound->rgbValue, lpBound->cbValueMax, lpBound->pcbValue); if (rc == SQL_SUCCESS_WITH_INFO) errcode = lpstmt->errcode; else if (rc != SQL_SUCCESS) return rc; } with: /* Get the bound columns */ errcode = ERR_SUCCESS; for (lpBound = lpstmt->lpBound; lpBound != NULL; lpBound = lpBound->lpNext) { rc = SQLGetData(hstmt, lpBound->icol, lpBound->fCType, lpBound->rgbValue, lpBound->cbValueMax, lpBound->pcbValue); if (rc == SQL_SUCCESS_WITH_INFO) errcode = lpstmt->errcode; else if (rc != SQL_SUCCESS) return rc; } /* So far no column read */ lpstmt->icol = NO_COLUMN; lpstmt->cbOffset = 0; ------------------------------------------------------------------------------ 97-12-30 <<<< THIS BUG FIX ONLY APPLIES TO YOU HAVE A MODULE CALLED SORT.C >>>> <<<< If you don't have a SORT.C, don't worry, you don't need it. >>>> <<<< Earlier editions of the driver kit used the OptTech sort >>>> <<<< instead. The OptTech sort performs better than ours, but it >>>> <<<< doesn't come with source code. Our SORT.C module does not >>>> <<<< implement all the OptTech functionality (it only implements >>>> <<<< the stuff we use). >>>> In SORT.C, search for "UWORD recordStart". Replace: UWORD recordStart; with UDWORD recordStart; ------------------------------------------------------------------------------ 97-11-28 In UTIL.C, search for "#define UPPER(c)". Replace: #define UPPER(c) ((((c) < 'a') && ((c) > 'z')) ? (c) : (((c) - 'a') + 'A')) with #define UPPER(c) ((((c) < 'a') || ((c) > 'z')) ? (c) : (((c) - 'a') + 'A')) ------------------------------------------------------------------------------ 97-11-07 In CONNECT.C, search for "ISAMOpen(szDatabase, szDSN". Replace: err = ISAMOpen(szDatabase, szDSN, szUsername, szPassword, &(lpdbc->lpISAM), lpdbc->szISAMError); with err = ISAMOpen(szDatabase, lpdbc->szDSN, szUsername, szPassword, &(lpdbc->lpISAM), lpdbc->szISAMError); ------------------------------ Previous Posting ----------------------------- 97-10-03 <<<< THIS BUG FIX DOES NOT APPLY TO THE BRONZE EDITION >>>> In SCALAR.C, in the InternalEvaluateScalar routine, search for the SCALAR_LOCATE case. Remove the code: if (s_lstrlen(lpstr2) == 0) { s_lstrcpy(lpstmt->szError, lpScalarFunc->name); return ERR_SCALARBADARG; } In SCALAR.C, in the InternalEvaluateScalar routine, search for the SCALAR_LOCATE_START case. Change: if ((s_lstrlen(lpstr2) == 0) || (sw3 <= 0)) { to: if (sw3 <= 0) { ------------------------------------------------------------------------------ 97-09-19 <<<< THIS BUG FIX ONLY APPLIES TO YOU HAVE A MODULE CALLED SORT.C >>>> <<<< If you don't have a SORT.C, don't worry, you don't need it. >>>> <<<< Earlier editions of the driver kit used the OptTech sort >>>> <<<< instead. The OptTech sort performs better than ours, but it >>>> <<<< doesn't come with source code. Our SORT.C module does not >>>> <<<< implement all the OptTech functionality (it only implements >>>> <<<< the stuff we use). >>>> In SORT.C, search for "Any more records in the beta buffer?". Change: /* Any more records in the beta buffer? */ if (betaCounter > 0) { /* Yes. Write them out */ if (_llseek(hfile, ((UDWORD) betaCounter) * ((UDWORD) sortData->recordSize), 2) == HFILE_ERROR) { to: /* Any more records in the beta buffer? */ if (betaCounter > 0) { /* Yes. Write them out */ if (_llseek(hfile, (recordCount - (UDWORD) betaCounter) * ((UDWORD) sortData->recordSize), 0) == HFILE_ERROR) { In SORT.C, search for "if (_lwrite(hfile, betaBuffer,". Change: if (_lwrite(hfile, betaBuffer, (UINT) (sortData->recordSize * betaCounter)) != (UINT) (sortData->recordSize * betaCounter)) { to: if (_lwrite(hfile, betaRecord, (UINT) (sortData->recordSize * betaCounter)) != (UINT) (sortData->recordSize * betaCounter)) { In SORT.C, search for "Any more records in the alpha buffer?". Change: /* Any more records in the alpha buffer? */ if (alphaCounter > 0) { /* Yes. Write them out */ if (_llseek(hfile, ((UDWORD) alphaCounter) * ((UDWORD) sortData->recordSize), 2) == HFILE_ERROR) { to: /* Any more records in the alpha buffer? */ if (alphaCounter > 0) { /* Yes. Write them out */ if (_llseek(hfile, (recordCount - (UDWORD) alphaCounter) * ((UDWORD) sortData->recordSize), 0) == HFILE_ERROR) { In SORT.C, search for "if (_lwrite(hfile, alphaBuffer,". Change: if (_lwrite(hfile, alphaBuffer, (UINT) (sortData->recordSize * alphaCounter)) != (UINT) (sortData->recordSize * alphaCounter)) { to: if (_lwrite(hfile, alphaRecord, (UINT) (sortData->recordSize * alphaCounter)) != (UINT) (sortData->recordSize * alphaCounter)) { ------------------------------------------------------------------------------ 97-09-08 <<<< THIS BUG FIX DOES NOT APPLY TO THE BRONZE EDITION >>>> In ISAM.H, search for "typedef UDWORD ISAMBOOKMARK;". Change: typedef UDWORD ISAMBOOKMARK; to: typedef UDWORD ISAMBOOKMARK; #define NULL_BOOKMARK 0xFFFFFFFF In EVALUATE.C, search for "Position to that record". Change: /* Position to that record */ err = ISAMPosition(lpSqlNodeTable->node.table.Handle, bookmark); if (err != NO_ISAM_ERR) { ISAMGetErrorMessage(lpstmt->lpdbc->lpISAM, lpstmt->szISAMError); return err; } lpstmt->fISAMTxnStarted = TRUE; to: /* Position to that record */ if (bookmark == NULL_BOOKMARK) lpSqlNodeTable->node.table.AllNull = TRUE; else { lpSqlNodeTable->node.table.AllNull = FALSE; err = ISAMPosition(lpSqlNodeTable->node.table.Handle, bookmark); if (err != NO_ISAM_ERR) { ISAMGetErrorMessage(lpstmt->lpdbc->lpISAM, lpstmt->szISAMError); return err; } lpstmt->fISAMTxnStarted = TRUE; } In EVALUATE.C, search again for "Position to that record". Change: /* Position to that record */ err = ISAMPosition(lpSqlNodeTable->node.table.Handle, bookmark); if (err != NO_ISAM_ERR) { ISAMGetErrorMessage(lpstmt->lpdbc->lpISAM, lpstmt->szISAMError); _lclose_buffer(hfSortfile); DeleteFile((LPCSTR) szFilename); return err; } lpstmt->fISAMTxnStarted = TRUE; to: /* Position to that record */ if (bookmark == NULL_BOOKMARK) lpSqlNodeTable->node.table.AllNull = TRUE; else { lpSqlNodeTable->node.table.AllNull = FALSE; err = ISAMPosition(lpSqlNodeTable->node.table.Handle, bookmark); if (err != NO_ISAM_ERR) { ISAMGetErrorMessage(lpstmt->lpdbc->lpISAM, lpstmt->szISAMError); _lclose_buffer(hfSortfile); DeleteFile((LPCSTR) szFilename); return err; } lpstmt->fISAMTxnStarted = TRUE; } In EVALUATE.C, search for "Get bookmark of current record". Change: /* Get bookmark of current record */ err = ISAMGetBookmark(lpSqlNodeTable->node.table.Handle, &bookmark); if (err != ERR_SUCCESS) { ISAMGetErrorMessage(lpstmt->lpdbc->lpISAM, lpstmt->szISAMError); _lclose_buffer(hfSortfile); DeleteFile((LPCSTR) szFilename); return err; } lpstmt->fISAMTxnStarted = TRUE; to: /* Get bookmark of current record */ if (lpSqlNodeTable->node.table.AllNull) bookmark = NULL_BOOKMARK; else { err = ISAMGetBookmark(lpSqlNodeTable->node.table.Handle, &bookmark); if (err != ERR_SUCCESS) { ISAMGetErrorMessage(lpstmt->lpdbc->lpISAM, lpstmt->szISAMError); _lclose_buffer(hfSortfile); DeleteFile((LPCSTR) szFilename); return err; } lpstmt->fISAMTxnStarted = TRUE; } In EVALUATE.C, search again for "Get bookmark of current record". Change: /* Get bookmark of current record */ err = ISAMGetBookmark(lpSqlNodeTable->node.table.Handle, &bookmark); if (err != ERR_SUCCESS) { ISAMGetErrorMessage(lpstmt->lpdbc->lpISAM, lpstmt->szISAMError); _lclose(hfSortfile); DeleteFile((LPCSTR) szFilename); return err; } lpstmt->fISAMTxnStarted = TRUE; to: /* Get bookmark of current record */ if (lpSqlNodeTable->node.table.AllNull) bookmark = NULL_BOOKMARK; else { err = ISAMGetBookmark(lpSqlNodeTable->node.table.Handle, &bookmark); if (err != ERR_SUCCESS) { ISAMGetErrorMessage(lpstmt->lpdbc->lpISAM, lpstmt->szISAMError); _lclose(hfSortfile); DeleteFile((LPCSTR) szFilename); return err; } lpstmt->fISAMTxnStarted = TRUE; } ------------------------------------------------------------------------------ 97-08-15 In BCD.C, search for "lpszRight[idxDecimalRight] = '\0';". Change: lpszRight[idxDecimalRight] = '\0'; to: if (lpszRight[idxDecimalRight] != '\0') lpszRight[idxDecimalRight] = '\0'; In BCD.C, search for "lpszRight[idxDecimalRight] = cRight;". Change: lpszRight[idxDecimalRight] = cRight; to: if (lpszRight[idxDecimalRight] != cRight) lpszRight[idxDecimalRight] = cRight; ------------------------------------------------------------------------------ 97-08-14 In SEMANTIC.C, search for ERR_INVALIDINSVAL. Change case NODE_TYPE_AGGREGATE: return ERR_INVALIDINSVAL; to: case NODE_TYPE_AGGREGATE: case NODE_TYPE_COLUMN: return ERR_INVALIDINSVAL; In SEMANTIC.C, search for ERR_INVALIDINVAL (not ERR_INVALIDINSVAL). Change: case NODE_TYPE_AGGREGATE: return ERR_INVALIDINVAL; to: case NODE_TYPE_AGGREGATE: case NODE_TYPE_COLUMN: return ERR_INVALIDINVAL; ------------------------------------------------------------------------------ 97-08-07 <<<< THIS BUG FIX DOES NOT APPLY TO THE BRONZE EDITION >>>> In SCALAR.C, search for "SCALAR_SIN" four times. At the fourth location, change: case SCALAR_SIN: lpSqlNode->value.Double = log10(lpSqlNodeValue[0]->value.Double); break; to: case SCALAR_SIN: lpSqlNode->value.Double = sin(lpSqlNodeValue[0]->value.Double); break; ------------------------------------------------------------------------------ 97-08-05 In EVALUATE.C, search for "Remove trailing blanks if need be". Change /* Remove trailing blanks if need be */ if ((lpSqlNode->sqlDataType == SQL_VARCHAR) || (lpSqlNode->sqlDataType == SQL_LONGVARCHAR)) { to: /* Remove trailing blanks if need be */ if ((lpSqlNode->sqlSqlType == SQL_VARCHAR) || (lpSqlNode->sqlSqlType == SQL_LONGVARCHAR)) { ------------------------------------------------------------------------------ 97-07-20 In PREPARE.C, search for SQLFreeStmt and then search for cRowCount (in the SQL_CLOSE case). Remove the line: lpstmt->cRowCount = -1; ------------------------------ Previous Posting ----------------------------- 97-06-25 <<<< THIS BUG FIX IS FOR THE NETWORK EDITION ONLY >>>> In NETISAM.C, search for "LoadString(s_hModule, opRetVal". Change: LoadString(s_hModule, opRetVal, (LPSTR) lpszErrorMessage, MAX_ERROR_LENGTH+1); to: if (opRetVal != ISAM_NETERROR) unmarshallString(lpNetConnection, lpszErrorMessage); else LoadString(s_hModule, opRetVal, (LPSTR) lpszErrorMessage, MAX_ERROR_LENGTH+1); In DRDBDVR.C, search for "LoadString(s_hModule, opRetVal". Remove the following line of code: LoadString(s_hModule, opRetVal, (LPSTR) szErrorMsg, MAX_ERROR_LENGTH+1); ------------------------------------------------------------------------------ 97-05-21 In UTIL.C, search for "February". Change: case 2: /* February */ if ((((lpDate->year + 300) / 400) * 400) == (lpDate->year + 300)) { to: case 2: /* February */ if (((lpDate->year / 400) * 400) == lpDate->year) { Then, search for "February" again. Change: case 2: /* February */ if ((((lpTimestamp->year + 300) / 400) * 400) == (lpTimestamp->year + 300)) { to: case 2: /* February */ if (((lpTimestamp->year / 400) * 400) == lpTimestamp->year) { ------------------------------------------------------------------------------ 97-05-19 <<<< THIS BUG FIX IS FOR THE SILVER EDITION ONLY >>>> In EVALUATE.C, serach for "hf->ptr += (count);". Change: hf->ptr += (count); to: hf->ptr += (count); ptr += (count); ------------------------------------------------------------------------------ 97-05-06 <<<< THIS BUG FIX IS FOR THE NETWORK EDITION ONLY >>>> In DRDBSVR.C, search for "Send the data and length". Change: /* Send the data and length */ if ((fCType == SQL_C_CHAR) && (cbValue < cbValueMax)) marshallData(lpNetConnection, fCType, rgbValue, cbValue+1); else marshallData(lpNetConnection, fCType, rgbValue, cbValue); to: /* Send the data and length */ if ((fCType == SQL_C_CHAR) && (cbValue < cbValueMax)) marshallData(lpNetConnection, fCType, rgbValue, cbValue+1); else marshallData(lpNetConnection, fCType, rgbValue, cbValueMax); (note the change from cbValue to cbValueMax on the last line) ------------------------------------------------------------------------------ 97-05-03 In TRACE.C, search for "lpTimestamp->fraction". Change: wsprintf((LPSTR) str, "%4d-%02u-%02u %02u:%02u:%02u.%09ul", lpTimestamp->year, lpTimestamp->month, lpTimestamp->day, lpTimestamp->hour, lpTimestamp->minute, lpTimestamp->second, lpTimestamp->fraction); to: wsprintf((LPSTR) str, "%4d-%02u-%02u %02u:%02u:%02u.%09lu", lpTimestamp->year, lpTimestamp->month, lpTimestamp->day, lpTimestamp->hour, lpTimestamp->minute, lpTimestamp->second, lpTimestamp->fraction); (note the change from 'ul' to 'lu' at the end of the format string) ------------------------------------------------------------------------------ 97-05-02 <<<< THIS BUG FIX IS FOR THE SILVER EDITION ONLY >>>> In PARSE.C, search for "*lpDatatype == TYPE_INTEGER;". Change: *lpDatatype == TYPE_INTEGER; to: *lpDatatype = TYPE_INTEGER; In PARSE.C, search for "datatype = SQL_DOUBLE;". Change: datatype = SQL_DOUBLE; to: datatype = TYPE_DOUBLE; ----------------------------------------------------------------------------- <<<< BUG FIXES BELOW THIS LINE APPLY TO THE BRONZE EDITION ONLY >>>> <<<< THESE BUG FIXES HAVE BEEN INTEGRATED INTO THE SILVER EDITION >>>> ------------------------------ Previous Posting ----------------------------- 97-05-01 <<<< THIS BUG FIX ONLY APPLIES TO YOU HAVE A MODULE CALLED SORT.C >>>> <<<< If you don't have a SORT.C, don't worry, you don't need it. >>>> <<<< Earlier editions of the driver kit used the OptTech sort >>>> <<<< instead. The OptTech sort performs better than ours, but it >>>> <<<< doesn't come with source code. Our SORT.C module does not >>>> <<<< implement all the OptTech functionality (it only implements >>>> <<<< the stuff we use). >>>> In SORT.C, search for "_fmemcmp". Note: "_fmemcmp" appears four times in SORT.C, we only care about the first two of the three that are in SortKeyCompare(). For the first two "_fmemcmp" in SortKeyCompare() (but not the third), change: compare = _fmemcmp(leftValuePtr, rightValuePtr, keyComponent->length); to: for (leftDecimalPos = 0; leftDecimalPos < keyComponent->length; leftDecimalPos++) { if ((*leftValuePtr == '.') || (*leftValuePtr == ' ')) break; leftValuePtr++; } for (rightDecimalPos = 0; rightDecimalPos < keyComponent->length; rightDecimalPos++) { if ((*rightValuePtr == '.') || (*rightValuePtr == ' ')) break; rightValuePtr++; } if (leftDecimalPos > rightDecimalPos) compare = 1; else if (leftDecimalPos < rightDecimalPos) compare = -1; else { leftValuePtr = leftRecordPtr + keyComponent->offset; rightValuePtr = rightRecordPtr + keyComponent->offset; compare = _fmemcmp(leftValuePtr, rightValuePtr, keyComponent->length); } You will also need to declare some new local variables in the SortKeyCompare() function: UWORD leftDecimalPos; UWORD rightDecimalPos; ------------------------------------------------------------------------------ 97-04-28 <<<< THIS BUG FIX IS FOR THE NETWORK EDITION ONLY >>>> In NET.C search for "cbValue = (size_t) cbSize;". Change: cbValue = (size_t) cbSize; if (cbValue > 0) { sizeof (ISAM) to: cbValue = (size_t) cbSize; if (cbSize > 0) { sizeof (ISAM) ------------------------------------------------------------------------------ 97-04-13 In UTIL.C, search for "fTruncated = DoubleToChar(flt". Change: fTruncated = DoubleToChar(flt, rgbValueOut, cbValueOutMax); to: fTruncated = DoubleToChar(flt, rgbValueOut, cbValueOutMax); if (fTruncated) ((LPSTR) rgbValueOut)[cbValueOutMax-1] = '\0'; In UTIL.C, search for "fTruncated = DoubleToChar(dbl". Change: fTruncated = DoubleToChar(dbl, rgbValueOut, cbValueOutMax); to: fTruncated = DoubleToChar(dbl, rgbValueOut, cbValueOutMax); if (fTruncated) ((LPSTR) rgbValueOut)[cbValueOutMax-1] = '\0'; ------------------------------------------------------------------------------ 97-04-10 In PARSE.C, search for "if (foundDecimalPoint) {". Change: if (foundDecimalPoint) { *lpTo = '\0'; lstrcpy(lpstmt->szError, lpToken); return ERR_MALFORMEDNUMBER; } to: if (foundDecimalPoint) { *lpTo = '\0'; lstrcpy(lpstmt->szError, lpToken); return ERR_MALFORMEDNUMBER; } foundDecimalPoint = TRUE; ------------------------------------------------------------------------------ 97-04-10 In SQLTYPE.C, change: #include "sql.h" to: #define ODBCVER 0x0210 #include "sql.h" ------------------------------ Previous Posting ----------------------------- 97-04-06 In DRDBDR.H, change: #include to: #define ODBCVER 0x0210 #include ------------------------------------------------------------------------------ 97-04-06 In DBASE.H, change: #include to: #define ODBCVER 0x0210 #include ------------------------------------------------------------------------------ 97-03-29 In CONNECT.C, search for "Return the connections string". Change: /* Return the connections string */ to: /* Put a dummy Server name on the connection string */ /* A bug in Jet 3.0 expects a non-empty server keyword */ /* from all ODBC drivers, shows up in DSN-less connections. */ lstrcat(szConnStr, ";SERVER=NotTheServer"); /* Return the connections string */ ------------------------------------------------------------------------------ 97-03-12 <<<< THIS BUG FIX IS FOR THE NETWORK EDITION ONLY >>>> In NET.C search for "(ISAM)". Change: sizeof (ISAM) to: sizeof (NETCONNECTION) ------------------------------------------------------------------------------ 97-03-10 <<<< THIS BUG FIX IS FOR THE NETWORK EDITION ONLY >>>> In NET.C, in the unmarshallData() routine, change this declaration: UDWORD cbSize; to: SDWORD cbSize; ------------------------------------------------------------------------------ 97-02-21 In BCD.C, search for "cDecimalDigits != 0". Change: if (cDecimalDigits != 0) { to: if (cDecimalDigits != 0) { while (lstrlen(lpszResult) < cDecimalDigits) { _fmemmove(lpszResult + 1, lpszResult, lstrlen(lpszResult)+1); lpszResult[0] = '0'; } ------------------------------------------------------------------------------ 97-02-07 In SQLTYPE.C, remove #define WINVER 0x0300 ------------------------------------------------------------------------------ 97-02-07 In DRDBDR.H, remove #define WINVER 0x0300 ------------------------------ Previous Posting ----------------------------- 97-01-29 In CONNECT.C, search for "SQL_CLOSE". Change: rc = SQLFreeStmt((HSTMT) lpdbc->lpstmts, SQL_CLOSE); to: rc = SQLFreeStmt((HSTMT) lpstmt, SQL_CLOSE); ------------------------------------------------------------------------------ 97-01-28 In PARSE.C, search for "lstrlen(lpszToken) > 10". Change: if ((lstrlen(lpszToken) > 10) && (scale == NO_SCALE)) { to: if ((lstrlen(lpszToken) >= 10) && (scale == NO_SCALE)) { ------------------------------------------------------------------------------ 97-01-21 In UTIL.C, search for "lstrcat(szTemplate, "ul");". Change: lstrcat(szTemplate, "ul"); to: lstrcat(szTemplate, "lu"); ------------------------------ Previous Posting ----------------------------- 96-12-19 In EVALAUTE.C, search for "result.node.comparison.Operator". It occurs twice in the file. The first one is OK. Change the second one from: result.node.comparison.Operator = OP_LT; to: result.node.comparison.Operator = OP_GT; ------------------------------------------------------------------------------ 96-11-07 In PARSE.C, search for "(scale == NO_SCALE)". Change: if (scale == NO_SCALE) { to: if ((lstrlen(lpszToken) > 10) && (scale == NO_SCALE)) { scale = 0; } if (scale == NO_SCALE) { ------------------------------------------------------------------------------ 96-11-01 In PREPARE.C, search for "wsprintf". Change: wsprintf(szCursorname, "CUR%05d", i); to: wsprintf(szCursorname, "CUR%05d", (SWORD) i); ------------------------------ Previous Posting ----------------------------- 96-10-31 In EVALUATE.C, search for "remove duplicate bookmarks". Change: /* Sort the file and remove duplicate bookmarks */ wsprintf(szSortDirective, "S(%d,%d,W,A)DUPO(Bd,%d,%d)F(FIX,%d)", to: /* Sort the file and remove duplicate bookmarks */ wsprintf(szSortDirective, "S(%d,%d,W,A)DUPO(B%d,%d,%d)F(FIX,%d)", (note the extra '%' after 'DUPO(B') ------------------------------------------------------------------------------ 96-10-30 <<<< THIS BUG FIX IS FOR THE NETWORK EDITION ONLY >>>> In NET.C, search for "len = (size_t) ntohl(netLen);". Change: ret = recv(lpNetConnection->socket, (char*) &netLen, sizeof(ULONG), 0); if ((ret == SOCKET_ERROR) || (ret != sizeof(ULONG))) return ISAM_NETERROR; len = (size_t) ntohl(netLen); to: UCHAR netLenBuf[sizeof(ULONG)]; len = sizeof(ULONG); lpBuf = netLenBuf; while (len) { ret = recv(lpNetConnection->socket, lpBuf, len, 0); if ((ret == SOCKET_ERROR) || (ret == 0)) return ISAM_NETERROR; lpBuf += (size_t) ret; if (len < (size_t) ret) return ISAM_NETERROR; len -= ((size_t) ret); } _fmemcpy((PTR)&netLen, netLenBuf, sizeof(ULONG)); len = (size_t) ntohl(netLen); ------------------------------ Previous Posting ----------------------------- 96-10-21 In ISAM.C, search for "Clear trailing blanks". Change: /* No. Clear trailing blanks */ i = lstrlen(szBuffer); while ((i != 0) && (szBuffer[i] == ' ')) { szBuffer[i] = '\0'; i--; } to: /* No. Clear trailing blanks */ i = lstrlen(szBuffer); while ((i != 0) && (szBuffer[i-1] == ' ')) { szBuffer[i-1] = '\0'; i--; } ------------------------------------------------------------------------------ 96-10-11 In UTIL.C, search for and change (this occurs in two places): ((LPSTR) lpstr)[cbValueMax-1] = '\0'; to: ((LPSTR) rgbValue)[cbValueMax-1] = '\0'; ------------------------------------------------------------------------------ 96-10-10 Bug fixes for all Bronze Editions sold prior to October 10, 1996 are available by upgrading to the newest code base. Current Bronze Edition licensees can get this upgrade by contacting SYWARE, Inc. at +1-617-497-1300. ------------------------------------------------------------------------------