Dr. DeeBee(r) ODBC Driver Kit Gold Edition - Bug Fixes - January 18, 2016 ------------------------------------------------------------------------------ The following bugs have been discovered in the current release of the Dr. DeeBee ODBC Driver Kit - Gold Edition ------------------------------------------------------------------------------ 21-06-24 In SCALAR.C, search for "STINY_LOW_D, STINY_LOW_D". Change: err = CharToDouble(lpSqlNodeValue[0]->value.String, s_lstrlen(lpSqlNodeValue[0]->value.String), TRUE, STINY_LOW_D, STINY_LOW_D, &(lpSqlNode->value.Double)); To: err = CharToDouble(lpSqlNodeValue[0]->value.String, s_lstrlen(lpSqlNodeValue[0]->value.String), TRUE, STINY_LOW_D, STINY_HIGH_D, &(lpSqlNode->value.Double)); ------------------------------------------------------------------------------ 21-06-23 In SCALAR.C, search for "lpSqlNode->value.Double = *((char far *)". Change: lpSqlNode->value.Double = *((char far *) BINARY_DATA(lpSqlNodeValue[0]->value.Binary)); if ((lpSqlNode->value.Double < BIT_LOW_D) || (lpSqlNode->value.Double > BIT_HIGH_D)) return ERR_OUTOFRANGE; To: lpSqlNode->value.Double = *((char far *) BINARY_DATA(lpSqlNodeValue[0]->value.Binary)); if ((lpSqlNode->value.Double < STINY_LOW_D) || (lpSqlNode->value.Double > STINY_HIGH_D)) return ERR_OUTOFRANGE; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - In SCALAR.C, search for "lpSqlNode->value.Double = *((short far *)". Change: lpSqlNode->value.Double = *((short far *) BINARY_DATA(lpSqlNodeValue[0]->value.Binary)); if ((lpSqlNode->value.Double < BIT_LOW_D) || (lpSqlNode->value.Double > BIT_HIGH_D)) return ERR_OUTOFRANGE; To: lpSqlNode->value.Double = *((short far *) BINARY_DATA(lpSqlNodeValue[0]->value.Binary)); if ((lpSqlNode->value.Double < SSHORT_LOW_D) || (lpSqlNode->value.Double > SSHORT_HIGH_D)) return ERR_OUTOFRANGE; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - In SCALAR.C, search for "lpSqlNode->value.Double = *((long far *)". Change: lpSqlNode->value.Double = *((long far *) BINARY_DATA(lpSqlNodeValue[0]->value.Binary)); if ((lpSqlNode->value.Double < BIT_LOW_D) || (lpSqlNode->value.Double > BIT_HIGH_D)) return ERR_OUTOFRANGE; To: lpSqlNode->value.Double = *((long far *) BINARY_DATA(lpSqlNodeValue[0]->value.Binary)); if ((lpSqlNode->value.Double < SLONG_LOW_D) || (lpSqlNode->value.Double > SLONG_HIGH_D)) return ERR_OUTOFRANGE; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - In SCALAR.C, search for "lpSqlNode->value.Double = *((float far *)". Change: lpSqlNode->value.Double = *((float far *) BINARY_DATA(lpSqlNodeValue[0]->value.Binary)); if ((lpSqlNode->value.Double < BIT_LOW_D) || (lpSqlNode->value.Double > BIT_HIGH_D)) return ERR_OUTOFRANGE; To: lpSqlNode->value.Double = *((float far *) BINARY_DATA(lpSqlNodeValue[0]->value.Binary)); if ((lpSqlNode->value.Double < FLOAT_LOW_D) || (lpSqlNode->value.Double > FLOAT_HIGH_D)) return ERR_OUTOFRANGE; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - In SCALAR.C, search for "lpSqlNode->value.Double = *((double far *)". Change: lpSqlNode->value.Double = *((double far *) BINARY_DATA(lpSqlNodeValue[0]->value.Binary)); if ((lpSqlNode->value.Double < BIT_LOW_D) || (lpSqlNode->value.Double > BIT_HIGH_D)) return ERR_OUTOFRANGE; To: lpSqlNode->value.Double = *((double far *) BINARY_DATA(lpSqlNodeValue[0]->value.Binary)); if ((lpSqlNode->value.Double < DOUBLE_LOW_D) || (lpSqlNode->value.Double > DOUBLE_HIGH_D)) return ERR_OUTOFRANGE; ------------------------------ Previous Posting ----------------------------- 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++; ------------------------------------------------------------------------------ 17-11-16 In PREPARE.C, search for "if (lpstmt->DescIRD.lpcRowCount != NULL)". There are three of these. In only the first case, change: if (lpstmt->DescIRD.lpcRowCount != NULL) *(lpstmt->DescIRD.lpcRowCount) = -1; To: lpstmt->DescIRD.lpcRowCount = NULL; ------------------------------ Previous Posting ----------------------------- 16-01-18 In ODBC30.C, search for "*((SDWORD FAR *) rgbValue) = 3;". There are two of these. In both cases, change: *((SDWORD FAR *) rgbValue) = 3; To: *((SWORD FAR *) rgbValue) = 3; ------------------------------ Previous Posting ----------------------------- 11-01-10 <<<< THIS BUG FIX IS FOR THE NETWORK EDITION ONLY >>>> In NETISAM.C, Search for "unmarshallString(lpNetConnection, lpszErrorMessage)". There are four of these in NETISAM.C. Find the one that looks like this: if (opRetVal != ISAM_NETERROR) unmarshallString(lpNetConnection, lpszErrorMessage); else LoadString(s_hModule, opRetVal, (LPSTR) lpszErrorMessage, MAX_ERROR_LENGTH+1); unmarshallString(lpNetConnection, lpszErrorMessage); netDisconnect(lpNetConnection); and change it to: if (opRetVal != ISAM_NETERROR) unmarshallString(lpNetConnection, lpszErrorMessage); else LoadString(s_hModule, opRetVal, (LPSTR) lpszErrorMessage, MAX_ERROR_LENGTH+1); netDisconnect(lpNetConnection); ------------------------------ Previous Posting ----------------------------- 11-01-05 <<<< THIS BUG FIX IS FOR THE NETWORK EDITION ONLY >>>> In DRDBSVR.C, Search for "INTFUNC netSvr_ISAMGetData". After the declarations, you will see: if ((lpISAMTableDef = unmarshallTableDef(lpNetConnection)) == NULL) { opRetVal = ISAM_NETISAM; marshallBufClear(lpNetConnection); marshallWord(lpNetConnection, opRetVal); } change this to: if ((lpISAMTableDef = unmarshallTableDef(lpNetConnection)) == NULL) { opRetVal = ISAM_NETISAM; marshallBufClear(lpNetConnection); marshallWord(lpNetConnection, opRetVal); return; } ------------------------------ Previous Posting ----------------------------- 11-01-03 <<<< THIS BUG FIX IS FOR THE NETWORK EDITION ONLY >>>> In DRDBSVR.C, Search for "Unmarshall ISAM opaque handle & statement". Change: /* Unmarshall ISAM opaque handle & statement */ unmarshallOpaque(lpNetConnection, &netISAM); if (netISAM != lpNetConnection->socket) { opRetVal = ISAM_NETISAM; } to /* Unmarshall ISAM opaque handle & statement */ unmarshallOpaque(lpNetConnection, &netISAM); if (netISAM != lpNetConnection->socket) { opRetVal = ISAM_NETISAM; marshallBufClear(lpNetConnection); marshallWord(lpNetConnection, opRetVal); return; } ------------------------------ Previous Posting ----------------------------- 10-12-07 In DRDBDR.H, Search for "Error Codes". Change: /***************************************************************************/ /* Error codes (also used as string ids in the resource file) */ to /***************************************************************************/ /* Memory allocation */ #ifdef __cplusplus #ifdef GlobalPtrHandle #undef GlobalPtrHandle #endif #define GlobalAlloc DRDB_GlobalAlloc #define GlobalLock DRDB_GlobalLock #define GlobalReAlloc DRDB_GlobalReAlloc #define GlobalPtrHandle DRDB_GlobalPtrHandle #define GlobalUnlock DRDB_GlobalUnlock #define GlobalFree DRDB_GlobalFree HGLOBAL DRDB_GlobalAlloc(int flags, int size); PTR DRDB_GlobalLock(HGLOBAL hGlobal); HGLOBAL DRDB_GlobalReAlloc(HGLOBAL hGlobal, int size, int flags); HGLOBAL DRDB_GlobalPtrHandle(PTR ptr); void DRDB_GlobalUnlock(HGLOBAL hGlobal); void DRDB_GlobalFree(HGLOBAL hGlobal); #endif /***************************************************************************/ /* Error codes (also used as string ids in the resource file) */ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - At the end of UTIL.C, append: #ifdef __cplusplus /***************************************************************************/ HGLOBAL DRDB_GlobalAlloc(int flags, int size) { char *ptr; ptr = new char[size + sizeof(long)]; *((long *) ptr) = size; ptr += sizeof(long); return (HGLOBAL) ptr; } /***************************************************************************/ PTR DRDB_GlobalLock(HGLOBAL hGlobal) { return (PTR) hGlobal; } /***************************************************************************/ HGLOBAL DRDB_GlobalReAlloc(HGLOBAL hGlobal, int size, int flags) { char *ptrOld; char *ptrNew; long oldSize; ptrOld = (char *) hGlobal; oldSize = *((long *) (ptrOld - sizeof(long))); ptrNew = new char[size + 4]; *((long *) ptrNew) = size; ptrNew += sizeof(long); if (oldSize > size) oldSize = size; _fmemcpy(ptrNew, ptrOld, oldSize); delete (ptrOld - sizeof(long)); return (HGLOBAL) ptrNew; } /***************************************************************************/ HGLOBAL DRDB_GlobalPtrHandle(PTR ptr) { return (HGLOBAL) ptr; } /***************************************************************************/ void DRDB_GlobalUnlock(HGLOBAL hGlobal) { return; } /***************************************************************************/ void DRDB_GlobalFree(HGLOBAL hGlobal) { char *ptr; ptr = (char *) hGlobal; ptr -= (sizeof(long)); delete ptr; return; } /***************************************************************************/ #endif /***************************************************************************/ ------------------------------ Previous Posting ----------------------------- 09-09-25 In CATALOG.C, search for "RETCODE SQL_API SQLTables". Change: /***************************************************************************/ RETCODE SQL_API SQLTables ( to: /***************************************************************************/ BOOL INTFUNC IsTableOnList( UCHAR FAR *szTableType, SWORD cbTableType) { UCHAR FAR *lpStart; UCHAR FAR *lpEnd; UCHAR cEndChar; /* Get length of list of table types */ if (cbTableType == SQL_NTS) cbTableType = s_lstrlen(szTableType); /* Remove leading blanks */ while ((cbTableType > 0) && (*szTableType == ' ')) { szTableType++; cbTableType--; } /* If no list given, TABLE is considered to be on the list */ if (cbTableType == 0) return TRUE; /* Look for TABLE on the list */ while (cbTableType != 0) { /* Quoted value? */ if (*szTableType == '\'') cEndChar = '\''; else cEndChar = ','; /* Skip past starting quote, if any */ if (cEndChar == '\'') { szTableType++; cbTableType--; } /* Remember the start of the value */ lpStart = szTableType; /* Find end of the value */ lpEnd = szTableType; while ((cbTableType > 0) && (*szTableType != cEndChar)) { lpEnd = szTableType; szTableType++; cbTableType--; } /* Is this the TABLE entry? */ if ((lpEnd - lpStart + 1 == 5) && (( *lpStart == 'T') || ( *lpStart == 't')) && ((*(lpStart + 1) == 'A') || (*(lpStart + 1) == 'a')) && ((*(lpStart + 2) == 'B') || (*(lpStart + 2) == 'b')) && ((*(lpStart + 3) == 'L') || (*(lpStart + 3) == 'l')) && ((*(lpStart + 4) == 'E') || (*(lpStart + 4) == 'e'))) { /* Yes. Return it */ return TRUE; } /* Remove trailing quote, if any */ if (cEndChar == '\'') { if ((cbTableType > 0) && (*szTableType == '\'')) { szTableType++; cbTableType--; } /* Remove trailing blanks */ while ((cbTableType > 0) && (*szTableType == ' ')) { szTableType++; cbTableType--; } } /* Remove trailing comma */ if ((cbTableType > 0) && (*szTableType == ',')) { szTableType++; cbTableType--; } /* Remove leading blanks */ while ((cbTableType > 0) && (*szTableType == ' ')) { szTableType++; cbTableType--; } } /* TABLE not found */ return FALSE; } /***************************************************************************/ RETCODE SQL_API SQLTables ( - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - In CATALOG.C, search for "So far no tables returned". Change: /* So far no tables returned */ lpstmt->irow = BEFORE_FIRST_ROW; to: /* So far no tables returned */ if (IsTableOnList(szTableType, cbTableType)) lpstmt->irow = BEFORE_FIRST_ROW; else lpstmt->irow = AFTER_LAST_ROW; ------------------------------------------------------------------------------ 09-09-24 Replace COLDEFS.C with http://www.syware.com/download/drdeebee/coldefs.c ------------------------------ Previous Posting ----------------------------- 08-02-25 <<<< THIS BUG FIX IS FOR THE NETWORK EDITION ONLY >>>> In NETISAM.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 NETISAM.C, search for "SQL_NUMERIC". There are two of these. In both cases, change: case SQL_NUMERIC: to: case SQL_NUMERIC: case SQL_BIGINT: ------------------------------ Previous Posting ----------------------------- 07-11-28 In RESULTS.C, search for "COLUMN_ORDINAL_POSITION" Change: case COLUMN_ORDINAL_POSITION: fSqlTypeIn = SQL_INTEGER; rgbValueIn = &(lpstmt->irow); To: case COLUMN_ORDINAL_POSITION: fSqlTypeIn = SQL_INTEGER; udValue = (UDWORD) (lpstmt->irow + 1); rgbValueIn = &udValue; ------------------------------------------------------------------------------ 07-11-27 In ODBC30.C, search for "if (s_lstrcmp(lpdbc->szDSN, " "))" Change: if (s_lstrcmp(lpdbc->szDSN, " ")) To: if ((lpdbc != NULL) && s_lstrcmp(lpdbc->szDSN, " ")) ------------------------------------------------------------------------------ 07-11-26 In SEMANTIC.H, search for "AdjustCType(LPSTMT lpstmt, SWORD fCType)" Change: SWORD INTFUNC AdjustCType(LPSTMT lpstmt, SWORD fCType); to: SWORD INTFUNC AdjustCType(LPDBC lpdbc, SWORD fCType); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - In SEMANTIC.C, search for "AdjustCType(LPSTMT lpstmt, SWORD fCType)" Change: SWORD INTFUNC AdjustCType(LPSTMT lpstmt, SWORD fCType) { if (lpstmt->lpdbc->lpenv->fODBCVer == SQL_OV_ODBC2) { to: SWORD INTFUNC AdjustCType(LPDBC lpdbc, SWORD fCType) { if (lpdbc->lpenv->fODBCVer == SQL_OV_ODBC2) { - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - In RESULTS.C, search for "Save the bound description" Change: /* Save the bound description */ lpBound->fCType = AdjustCType(lpstmt, fCType); To: /* Save the bound description */ lpBound->fCType = AdjustCType(lpstmt->lpdbc, fCType); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - In RESULTS.C, search for "Adjust C Type" Change: /* Adjust C Type */ fCType = AdjustCType(lpstmt, fCType); To: /* Adjust C Type */ fCType = AdjustCType(lpstmt->lpdbc, fCType); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - In ODBC30.C, search for "AdjustCType(lpdescSource->lpstmt". There are six of these. For all six change: AdjustCType(lpdescSource->lpstmt To: AdjustCType(lpdescSource->lpdbc - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - In ODBC30.C, search for "AdjustCType(lpdesc->lpstmt". There are five of these. For all five change: Change: AdjustCType(lpdesc->lpstmt To: AdjustCType(lpdesc->lpdbc ------------------------------ Previous Posting ----------------------------- 05-03-17 In UTIL.C, search for "s_lstrcat(lpChar, szBuffer)" Change: s_lstrcat(lpChar, szBuffer); To: s_lstrcpy(lpChar, szBuffer); ------------------------------ Previous Posting ----------------------------- 03-11-07 In PREPARE.C, search for "lpstmt->lpParameterDesc->lpFirst = lpParameterBookmark;" Change: while (lpstmt->lpParameterDesc->lpFirst != NULL) { lpParameter = lpstmt->lpParameterDesc->lpFirst->lpNext; if (lpstmt->lpParameterDesc->lpFirst->inum == BOOKMARK_COLUMN_ID) lpParameterBookmark = lpstmt->lpParameterDesc->lpFirst; else { GlobalUnlock (GlobalPtrHandle(lpstmt->lpParameterDesc->lpFirst)); GlobalFree (GlobalPtrHandle(lpstmt->lpParameterDesc->lpFirst)); lpstmt->lpParameterDesc->lpFirst = lpParameter; } } lpstmt->lpParameterDesc->lpFirst = lpParameterBookmark; To: while (lpstmt->lpParameterDesc->lpFirst != NULL) { lpParameter = lpstmt->lpParameterDesc->lpFirst->lpNext; if (lpstmt->lpParameterDesc->lpFirst->inum == BOOKMARK_COLUMN_ID) { lpParameterBookmark = lpstmt->lpParameterDesc->lpFirst; lpParameterBookmark->lpNext = NULL; } else { GlobalUnlock (GlobalPtrHandle(lpstmt->lpParameterDesc->lpFirst)); GlobalFree (GlobalPtrHandle(lpstmt->lpParameterDesc->lpFirst)); } lpstmt->lpParameterDesc->lpFirst = lpParameter; } lpstmt->lpParameterDesc->lpFirst = lpParameterBookmark; ------------------------------ Previous Posting ----------------------------- 03-10-22 In ODBC30.C, search for "*((UDWORD FAR *) rgbValue) = SQL_CODE_TIMESTAMP;" Change: if (TIMESTAMP_SCALE > 0) *((UDWORD FAR *) rgbValue) = 20 + TIMESTAMP_SCALE; else *((UDWORD FAR *) rgbValue) = 19; *((UDWORD FAR *) rgbValue) = SQL_CODE_TIMESTAMP; break; to: if (TIMESTAMP_SCALE > 0) *((UDWORD FAR *) rgbValue) = 20 + TIMESTAMP_SCALE; else *((UDWORD FAR *) rgbValue) = 19; break; ------------------------------ Previous Posting ----------------------------- 02-08-03 In EVALUATE.C, search for "lpSqlNodeParameter->node.parameter.BufferSize = cbBuffer". There are two of them. In the first one, change: lpSqlNodeParameter->node.parameter.BufferSize = cbBuffer + sizeof(SDWORD); to: lpSqlNodeParameter->node.parameter.BufferSize = cbBuffer; In the second one, change: lpSqlNodeParameter->node.parameter.BufferSize = cbBuffer + 1; to: lpSqlNodeParameter->node.parameter.BufferSize = cbBuffer; ------------------------------------------------------------------------------ 02-08-02 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; } ------------------------------------------------------------------------------ 02-08-01 In EVALUTATE.C, search for "if (lpSqlNode->sqlDataType == TYPE_NUMERIC)" (this code was put in for bug fix 00-03-10). Change: if (lpSqlNode->sqlDataType == TYPE_NUMERIC) lpSqlNode->value.String = ""; to: if (lpSqlNode->sqlDataType == TYPE_NUMERIC) lpSqlNode->value.String = (LPUSTR) ""; ------------------------------ Previous Posting ----------------------------- 01-11-21 In RESULTS.C, search for "&& (errcode == ERR_DATATRUNCATED)". Change: if ((rc == SQL_SUCCESS) && (errcode == ERR_DATATRUNCATED)) { to: if ((rc == SQL_SUCCESS) && (errcode == ERR_DATATRUNCATED)) { lpstmt->iSetPos = NO_SET_POS; ------------------------------ 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 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 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-04-04 In EVALUATE.C, search for "(lpstmt->fUseBookmarks != SQL_UB_OFF)". Change: if (((lpstmt->fCursorType != SQL_SCROLL_FORWARD_ONLY) || (lpstmt->fUseBookmarks != SQL_UB_OFF)) && (!fSortFileCreated) && (!fSubSelect)) { to: if ((lpstmt->fCursorType != SQL_SCROLL_FORWARD_ONLY) && (!fSortFileCreated) && (!fSubSelect)) { ------------------------------------------------------------------------------ 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; ------------------------------------------------------------------------------ 00-03-01 In EVALUATE.C, search for "*((double FAR *) lpAggregateValue) += (1.0);". Change: case AGG_COUNT: *((double FAR *) lpAggregateValue) += (1.0); break; to: case AGG_COUNT: *((double FAR *) lpAggregateValue) += (*((double FAR *) lpValue)); break; ------------------------------------------------------------------------------ 00-02-03 In UTIL.C, search for "(*lpszValue >= '6')". Change: if ((*lpszValue >= '6') && (val >= 1844674407370955160)) { if (!fFoundDecimalPoint) { if (lpNumeric->scale == -128) return ERR_OUTOFRANGE; (lpNumeric->scale)--; } fTruncated = TRUE; } else if (val >= 1844674407370955161) { to: if ((*lpszValue >= '6') && (val >= 1844674407370955161)) { if (!fFoundDecimalPoint) { if (lpNumeric->scale == -128) return ERR_OUTOFRANGE; (lpNumeric->scale)--; } fTruncated = TRUE; } else if (val >= 1844674407370955160) { ------------------------------ 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-12-15 In DRDBDR.H, search for "#define MAX_PATHNAME_SIZE 127". Change: #define MAX_PATHNAME_SIZE 127 to #define MAX_PATHNAME_SIZE MAX_PATH - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - If you are still using DBASE.H, in DBASE.H, search for "#define DBASE_MAX_PATHNAME_SIZE 127". Change: #define DBASE_MAX_PATHNAME_SIZE 127 to: #define DBASE_MAX_PATHNAME_SIZE MAX_PATH ------------------------------------------------------------------------------ 99-10-12 In CATALOG.C, search for "p = ptr + s_lstrlen(p)". Change: for (p = ptr + s_lstrlen(p); p >= ptr; p = (LPUSTR) AnsiPrev((LPSTR) ptr, (LPSTR) p)) *(p+1) = *p; *ptr = '\\'; to: p = ptr + s_lstrlen(ptr); while (TRUE) { *(p+1) = *p; if (p == ptr) break; p = (LPUSTR) AnsiPrev((LPSTR) ptr, (LPSTR) p); } *ptr = '\\'; ------------------------------------------------------------------------------ 99-10-05 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-20 In PARSE.H, search for "OuterJoinPredicate". Change SQLNODEIDX OuterJoinPredicate; /* BOOLEAN, COMPARISON, */ /* NO_SQLNODE */ to: SQLNODEIDX OuterJoinPredicate; /* BOOLEAN, COMPARISON, */ /* NO_SQLNODE */ BOOL InnerJoin; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - In PARSE.C, search for "(LPUSTR) "INDEX"," (note the double quotes around the word INDEX). Change: (LPUSTR) "INDEX", to: (LPUSTR) "INDEX", (LPUSTR) "INNER", - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - In PARSE.C, search for "OuterJoinPredicate = NO_SQLNODE". Change: lpSqlNode->node.table.OuterJoinPredicate = NO_SQLNODE; to: lpSqlNode->node.table.OuterJoinPredicate = NO_SQLNODE; lpSqlNode->node.table.InnerJoin = TRUE; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - In PARSE.C, search for "INTFUNC ParseOJ". Replace the entire function with: RETCODE INTFUNC ParseOJ(LPSTMT lpstmt, LPUSTR FAR *lplpszSqlStr, SDWORD FAR *pcbSqlStr, LPSQLTREE FAR *lplpSql, BOOL fMustBeInnerJoin, SQLNODEIDX FAR *lpIdxLeft, SQLNODEIDX FAR *lpIdxRight, LPUSTR lpszToken) /* Retrives an outer join from the input stream and creates two */ /* NODE_TYPE_TABLES nodes which are linked together. */ /* */ /* inneroj := tableref INNER JOIN tableref ON boolean | */ /* tableref INNER JOIN inneroj ON boolean | */ /* */ /* oj := tableref LEFT OUTER JOIN tableref ON boolean | */ /* tableref LEFT OUTER JOIN oj ON boolean | */ /* ( inneroj ) INNER JOIN tableref ON boolean | */ /* ( inneroj ) INNER JOIN inneroj ON boolean */ /* inneroj */ { RETCODE err; SQLNODEIDX idxTableLeft; SQLNODEIDX idxTableRight; SQLNODEIDX idxTablesLastOneOnLeftSide; SQLNODEIDX idxTablesRight; SQLNODEIDX idxPredicate; LPSQLNODE lpSqlNode; LPUSTR old_lpszSqlStr; SDWORD old_cbSqlStr; BOOL fInnerJoin; /* Is there a starting parenthesis? */ old_lpszSqlStr = *lplpszSqlStr; old_cbSqlStr = *pcbSqlStr; err = GetSymbol(lpstmt, lplpszSqlStr, pcbSqlStr, "(", lpszToken); if (err != ERR_SUCCESS) { /* No. Get left table */ *lplpszSqlStr = old_lpszSqlStr; *pcbSqlStr = old_cbSqlStr; err = ParseTableref(lpstmt, lplpszSqlStr, pcbSqlStr, lplpSql, &idxTableLeft, lpszToken); if (err != ERR_SUCCESS) return err; /* Create the TABLES node for the left table */ idxTablesLastOneOnLeftSide = AllocateNode(lplpSql, NODE_TYPE_TABLES); if (idxTablesLastOneOnLeftSide == NO_SQLNODE) return ERR_MEMALLOCFAIL; lpSqlNode = ToNode(*lplpSql, idxTablesLastOneOnLeftSide); lpSqlNode->node.tables.Table = idxTableLeft; lpSqlNode->node.tables.Next = NO_SQLNODE; *lpIdxLeft = idxTablesLastOneOnLeftSide; } else { /* Yes. If there is a parenthesis, then only inner joins allowed */ fMustBeInnerJoin = TRUE; /* Get the join inside the parentheis */ err = ParseOJ(lpstmt, lplpszSqlStr, pcbSqlStr, lplpSql, fMustBeInnerJoin, lpIdxLeft, &idxTablesLastOneOnLeftSide, lpszToken); if (err != ERR_SUCCESS) return err; /* Get the closing parenthesis */ err = GetSymbol(lpstmt, lplpszSqlStr, pcbSqlStr, ")", lpszToken); if (err != ERR_SUCCESS) return err; } /* Get INNER or LEFT OUTER JOIN keywords */ err = GetKeyword(lpstmt, lplpszSqlStr, pcbSqlStr, NULL, lpszToken); if (err != ERR_SUCCESS) return err; if (!s_lstrcmpi("LEFT", lpszToken)) { err = GetKeyword(lpstmt, lplpszSqlStr, pcbSqlStr, "OUTER", lpszToken); if (err != ERR_SUCCESS) return err; fInnerJoin = FALSE; } else if (!s_lstrcmpi("INNER", lpszToken)) { fInnerJoin = TRUE; } else { s_lstrcpy(lpstmt->szError, "LEFT, INNER"); return ERR_EXPECTEDOTHER; } err = GetKeyword(lpstmt, lplpszSqlStr, pcbSqlStr, "JOIN", lpszToken); if (err != ERR_SUCCESS) return err; if (!fInnerJoin && fMustBeInnerJoin) { s_lstrcpy(lpstmt->szError, "INNER"); return ERR_EXPECTEDOTHER; } /* Get nested outer join */ old_lpszSqlStr = *lplpszSqlStr; old_cbSqlStr = *pcbSqlStr; err = ParseOJ(lpstmt, lplpszSqlStr, pcbSqlStr, lplpSql, fMustBeInnerJoin, &idxTablesRight, lpIdxRight, lpszToken); if (err == ERR_SUCCESS) { lpSqlNode = ToNode(*lplpSql, idxTablesRight); idxTableRight = lpSqlNode->node.tables.Table; } else { /* Not a nested outer join. Just get right table */ *lplpszSqlStr = old_lpszSqlStr; *pcbSqlStr = old_cbSqlStr; err = ParseTableref(lpstmt, lplpszSqlStr, pcbSqlStr, lplpSql, &idxTableRight, lpszToken); if (err != ERR_SUCCESS) return err; /* Create the TABLES node for the right table */ idxTablesRight = AllocateNode(lplpSql, NODE_TYPE_TABLES); if (idxTablesRight == NO_SQLNODE) return ERR_MEMALLOCFAIL; lpSqlNode = ToNode(*lplpSql, idxTablesRight); lpSqlNode->node.tables.Table = idxTableRight; lpSqlNode->node.tables.Next = NO_SQLNODE; *lpIdxRight = idxTablesRight; } /* Get ON keyword */ err = GetKeyword(lpstmt, lplpszSqlStr, pcbSqlStr, "ON", lpszToken); if (err != ERR_SUCCESS) return err; /* Get condition */ err = ParseBoolean(lpstmt, lplpszSqlStr, pcbSqlStr, lplpSql, &idxPredicate, lpszToken); if (err != ERR_SUCCESS) return err; /* Link the list of tables together */ lpSqlNode = ToNode(*lplpSql, idxTablesLastOneOnLeftSide); lpSqlNode->node.tables.Next = idxTablesRight; /* Put in outer join information into the right table node */ lpSqlNode = ToNode(*lplpSql, idxTableRight); lpSqlNode->node.table.OuterJoinFromTables = *lpIdxLeft; lpSqlNode->node.table.OuterJoinPredicate = idxPredicate; lpSqlNode->node.table.InnerJoin = fInnerJoin; return ERR_SUCCESS; } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - In PARSE.C, search for "Get outer join tables and condition". Change: /* Get outer join tables and condition */ err = ParseOJ(lpstmt, lplpszSqlStr, pcbSqlStr, lplpSql, lpIdxLeft, lpIdxRight, lpszToken); with: /* Get outer join tables and condition */ err = ParseOJ(lpstmt, lplpszSqlStr, pcbSqlStr, lplpSql, FALSE, lpIdxLeft, lpIdxRight, lpszToken); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - In OPTIMIZE.C, search for "OuterJoinPredicate != NO_SQLNODE". Change: if (lpSqlNodeTable->node.table.OuterJoinPredicate != NO_SQLNODE) break; to: if ((lpSqlNodeTable->node.table.OuterJoinPredicate != NO_SQLNODE) && !(lpSqlNodeTable->node.table.InnerJoin)) break; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - In EVALUATE.C, search for "Is this table the right side of an outer join". Change: /* Yes. Is this table the right side of an outer join */ if (lpSqlNodeTable->node.table.OuterJoinPredicate == NO_SQLNODE) { to: /* Yes. Is this table the right side of an outer join */ if ((lpSqlNodeTable->node.table.OuterJoinPredicate == NO_SQLNODE) || lpSqlNodeTable->node.table.InnerJoin) { - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - In EVALUATE.C, search for "If not an outer join, error". Change: /* End of table. If not an outer join, error */ if (lpSqlNode->node.table.OuterJoinPredicate == NO_SQLNODE) return ERR_NODATAFOUND; to: /* End of table. If not an outer join, error */ if ((lpSqlNode->node.table.OuterJoinPredicate == NO_SQLNODE) || lpSqlNode->node.table.InnerJoin) return ERR_NODATAFOUND; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - In INFO.C, search for "SQL_OJ_CAPABILITIES". Change: case SQL_OJ_CAPABILITIES: *(SDWORD FAR *)rgbInfoValue = SQL_OJ_LEFT | SQL_OJ_NESTED | SQL_OJ_NOT_ORDERED | SQL_OJ_ALL_COMPARISON_OPS; to: case SQL_OJ_CAPABILITIES: *(SDWORD FAR *)rgbInfoValue = SQL_OJ_LEFT | SQL_OJ_INNER | SQL_OJ_NESTED | SQL_OJ_NOT_ORDERED | SQL_OJ_ALL_COMPARISON_OPS; ------------------------------------------------------------------------------ 99-09-19 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 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-17 In EVALUATE.C, search for "if (lpSqlNodeExpression == NULL)". Change /* Put inthe null flag */ if (lpSqlNodeExpression == NULL) to: /* Put inthe null flag */ if (lpSqlNodeAggregate->node.aggregate.Operator == AGG_COUNT) cNullFlag = NOT_NULL_FLAG; else if (lpSqlNodeExpression == NULL) ------------------------------------------------------------------------------ 99-09-15 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 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 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-08-31 In SEMANTIC.C, search for "Check the ORDER BY columns". Change } } lpSqlNode = ToNode(*lplpSql, idxNode); } /* Check the ORDER BY columns */ to: } lpSqlNode = ToNode(*lplpSql, idxNode); } } /* Check the ORDER BY columns */ ------------------------------------------------------------------------------ 99-08-30 In RESULTS.C, search for "ODBCGetData". There are five of them (four calls to the function and one is the function itself). On the fifth one, change: rc = ODBCGetData(hstmt, lpBound->inum, lpBound->fCType, lpBound->rgbValue, lpBound->cbValueMax, lpBound->pcbValue, lpBound->pcbValueIndicator, 0); to: rc = ODBCGetData(hstmt, lpBound->inum, lpBound->fCType, lpBound->rgbValue, lpBound->cbValueMax, lpBound->pcbValue, lpBound->pcbValueIndicator, *(lpstmt->lpBoundDesc->pcbOffset)); ------------------------------------------------------------------------------ 99-07-29 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 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 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 In PREPARE.C, search for "End the transaction if need be". Change: /* End the transaction if need be */ if ((lpstmt->fStmtType == STMT_TYPE_SELECT) && (lpstmt->lpdbc->lpISAM->fTxnCapable != SQL_TC_NONE) && lpstmt->lpdbc->fAutoCommitTxn) { to: /* End the transaction if need be */ if ((lpstmt->fStmtType == STMT_TYPE_SELECT) && (lpstmt->fConcurrency != SQL_CONCUR_READ_ONLY) && (lpstmt->lpdbc->lpISAM->fTxnCapable != SQL_TC_NONE) && lpstmt->lpdbc->fAutoCommitTxn) { ------------------------------------------------------------------------------ 99-06-01 In ODBC30.C, search for "szSqlState != NULL". Change: if (szSqlState != NULL) { rc = SQLGetDiagField(HandleType, Handle, iRow, SQL_DIAG_SQLSTATE, szSqlState, SQL_SQLSTATE_SIZE, NULL); to if (szSqlState != NULL) { rc = SQLGetDiagField(HandleType, Handle, iRow, SQL_DIAG_SQLSTATE, szSqlState, SQL_SQLSTATE_SIZE+1, NULL); ------------------------------------------------------------------------------ 99-05-05 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), ""); } ------------------------------ Previous Posting ----------------------------- 99-03-17 In SCALAR.C, search for "UCHAR soundex_table[26];". Change: UCHAR soundex_table[26]; to: UCHAR soundex_table[27]; ------------------------------------------------------------------------------ 99-03-16 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-15 <<<< 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 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 In EVALUATE.C, search for "Try to fetch a row". Change: /* Try to fetch a row */ if (err == ERR_SUCCESS) { err = FetchRow(lpstmt, lpSqlNodeSelect, SQL_FETCH_NEXT, 0); 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, SQL_FETCH_NEXT, 0); 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-12 In ODBC30.C, search for "SQLGetConnectOption". There are two of them. In both cases, change: rc = SQLGetConnectOption(hdbc, (UWORD) fAttribute, rgbValue); to: rc = SQLGetConnectOption(hdbc, (UWORD) fAttribute, rgbValue); break; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - In ODBC30.C, search for "SQL_CURSOR_STATIC". Change: case SQL_CURSOR_STATIC: default: lpstmt->errcode = ERR_INTERNAL; return SQL_ERROR; } } if (pcbValue != NULL) *pcbValue = 4; to: case SQL_CURSOR_STATIC: default: lpstmt->errcode = ERR_INTERNAL; return SQL_ERROR; } } if (pcbValue != NULL) *pcbValue = 4; break; ------------------------------------------------------------------------------ 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 In SEMANTIC.C, search for "lpSqlNodeColumn->node.column.Table =". There are four of these in SEMANTIC.C, change the fourth 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-06 In EVALUATE.C, search for "fSortFileCreated = TRUE". This occurs four times. In all four places, change: fSortFileCreated = TRUE; to: if (lpSqlNode->node.select.Sortfile != HFILE_ERROR) fSortFileCreated = TRUE; ------------------------------------------------------------------------------ 98-12-23 In CONNECT.C, search for "lpProc = MakeProcInstance". Change: lpProc = MakeProcInstance((FARPROC) dlgDirectory, s_hModule); to: lpProc = (DLGPROC) MakeProcInstance((FARPROC) dlgDirectory, s_hModule); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - In DLL.C, search for "s_hModule = hInst;". Change: s_hModule = hInst; to: s_hModule = (HINSTANCE) hInst; In DLL.C, search for "s_hModule = hModule;". Change: s_hModule = hModule; to: s_hModule = (HINSTANCE) hModule; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - In ODBC30.C, search for "lstrcpy(szError". Change: lstrcpy(szError, (LPSTR) szTemplate + 2 * (SQL_SQLSTATE_SIZE + 1)); to: s_lstrcpy(szError, (LPSTR) szTemplate + 2 * (SQL_SQLSTATE_SIZE + 1)); In ODBC30.C, search for "lpdesc->pcbOffset = rgbValue;". Change: lpdesc->pcbOffset = rgbValue; to: lpdesc->pcbOffset = (SDWORD FAR *) rgbValue; In ODBC30.C, search for "lpstmt->lpParameterDesc->pcbOffset = rgbValue;". Change: lpstmt->lpParameterDesc->pcbOffset = rgbValue; to: lpstmt->lpParameterDesc->pcbOffset = (SDWORD FAR *) rgbValue; In ODBC30.C, search for "lpstmt->lpBoundDesc->pcbOffset = rgbValue;". Change: lpstmt->lpBoundDesc->pcbOffset = rgbValue; to: lpstmt->lpBoundDesc->pcbOffset = (SDWORD FAR *) rgbValue; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - In RESULTS.C, search for "Reopen rowset file for writing". Change: /* Reopen rowset file for writing */ _lclose(lpSqlNode->node.select.Sortfile); lpSqlNode->node.select.Sortfile = _lopen( to: /* Reopen rowset file for writing */ _lclose(lpSqlNode->node.select.Sortfile); lpSqlNode->node.select.Sortfile = _lopen((LPSTR) In RESULTS.C, search for "Reopen rowset file for reading". Change: /* Reopen rowset file for reading */ _lclose(lpSqlNode->node.select.Sortfile); lpSqlNode->node.select.Sortfile = _lopen( to: /* Reopen rowset file for reading */ _lclose(lpSqlNode->node.select.Sortfile); lpSqlNode->node.select.Sortfile = _lopen((LPSTR) In RESULTS.C, search for "lstrcpy(szError". Change: lstrcpy(szError, (LPSTR) szTemplate + 2 * (SQL_SQLSTATE_SIZE + 1)); to: s_lstrcpy(szError, (LPSTR) szTemplate + 2 * (SQL_SQLSTATE_SIZE + 1)); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - In SETUP.C, search for "lpProc = MakeProcInstance". This occurs in two places. In both places change: lpProc = MakeProcInstance((FARPROC) dlgSetup, s_hModule); to: lpProc = (DLGPROC) MakeProcInstance((FARPROC) dlgSetup, s_hModule); ------------------------------ Previous Posting ----------------------------- 98-12-08 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 "SemanticCheck(lpstmt, lplpSql, lpSqlNode->node.comparison.Right2". After err = SemanticCheck(lpstmt, lplpSql, lpSqlNode->node.comparison.Right2, 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-27 In EVALUATE.C, search for "fCType[cRestrict] = SQL_C_BINARY;". There are two occurances of this. Change the first one from: case TYPE_TIMESTAMP: fCType[cRestrict] = SQL_C_BINARY; to: case TYPE_TIMESTAMP: fCType[cRestrict] = SQL_C_TIMESTAMP; ------------------------------------------------------------------------------ 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-20 In EVALUATE.C, search for "fCType == SQL_C_DEFAULT". Change if (fCType == SQL_C_DEFAULT) { switch (lpSqlNodeParameter->sqlSqlType) { case SQL_CHAR: case SQL_VARCHAR: case SQL_LONGVARCHAR: fCType = SQL_C_CHAR; break; case SQL_BIGINT: #if (ODBCVER < 0x0300) fCType = SQL_C_CHAR; #else lpSqlType = NULL; for (i = 0; i < (SDWORD) lpstmt->lpdbc->lpISAM->cSQLTypes; i++) { if (lpstmt->lpdbc->lpISAM->SQLTypes[i].type==SQL_BIGINT) { lpSqlType = &(lpstmt->lpdbc->lpISAM->SQLTypes[i]); break; } } if (lpSqlType == NULL) fCType = SQL_C_SBIGINT; else if (lpSqlType->unsignedAttribute == TRUE) fCType = SQL_C_UBIGINT; else fCType = SQL_C_SBIGINT; #endif break; case SQL_DECIMAL: case SQL_NUMERIC: #if (ODBCVER < 0x0300) fCType = SQL_C_CHAR; #else fCType = SQL_C_NUMERIC; #endif break; to: if (fCType == SQL_C_DEFAULT) { switch (lpSqlNodeParameter->sqlSqlType) { case SQL_CHAR: case SQL_VARCHAR: case SQL_LONGVARCHAR: case SQL_BIGINT: case SQL_DECIMAL: case SQL_NUMERIC: fCType = SQL_C_CHAR; break; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - In PREPARE.C, search for "fCType == SQL_C_DEFAULT". Change if (fCType == SQL_C_DEFAULT) { switch (fSqlType) { case SQL_CHAR: case SQL_VARCHAR: case SQL_LONGVARCHAR: fCType = SQL_C_CHAR; break; case SQL_BIGINT: #if (ODBCVER < 0x0300) fCType = SQL_C_CHAR; #else lpSqlType = NULL; for (i = 0; i < lpstmt->lpdbc->lpISAM->cSQLTypes; i++) { if (lpstmt->lpdbc->lpISAM->SQLTypes[i].type == SQL_BIGINT) { lpSqlType = &(lpstmt->lpdbc->lpISAM->SQLTypes[i]); break; } } if (lpSqlType == NULL) fCType = SQL_C_SBIGINT; else if (lpSqlType->unsignedAttribute == TRUE) fCType = SQL_C_UBIGINT; else fCType = SQL_C_SBIGINT; #endif break; case SQL_DECIMAL: case SQL_NUMERIC: #if (ODBCVER < 0x0300) fCType = SQL_C_CHAR; #else fCType = SQL_C_NUMERIC; #endif break; to: if (fCType == SQL_C_DEFAULT) { switch (fSqlType) { case SQL_CHAR: case SQL_VARCHAR: case SQL_LONGVARCHAR: case SQL_BIGINT: case SQL_DECIMAL: case SQL_NUMERIC: fCType = SQL_C_CHAR; break; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - In RESULTS.C, search for "sizeof(NUMERIC)". Change #if (ODBCVER < 0x0300) *pfDesc = lpSqlNode->sqlPrecision + 2; #else *pfDesc = sizeof(NUMERIC); #endif to: *pfDesc = lpSqlNode->sqlPrecision + 2; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - In RESULTS.C, search for "sizeof(BIGINT)". Change #if (ODBCVER < 0x0300) if (lpSqlType->unsignedAttribute == TRUE) *pfDesc = lpSqlNode->sqlPrecision; else *pfDesc = lpSqlNode->sqlPrecision + 1; #else *pfDesc = sizeof(BIGINT); #endif break; to: if (lpSqlType->unsignedAttribute == TRUE) *pfDesc = lpSqlNode->sqlPrecision; else *pfDesc = lpSqlNode->sqlPrecision + 1; break; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - In RESULTS.C, search for "sizeof(NUMERIC)". Change #if (ODBCVER < 0x0300) udValue = lpstmt->lpISAMTableDef-> lpColumnDef[lpstmt->irow].cbPrecision + 2; #else udValue = sizeof(NUMERIC); #endif to: udValue = lpstmt->lpISAMTableDef-> lpColumnDef[lpstmt->irow].cbPrecision + 2; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - In RESULTS.C, search for "sizeof(BIGINT)". Change #if (ODBCVER < 0x0300) if (lpSqlType->unsignedAttribute == TRUE) udValue = lpstmt->lpISAMTableDef-> lpColumnDef[lpstmt->irow].cbPrecision; else udValue = lpstmt->lpISAMTableDef-> lpColumnDef[lpstmt->irow].cbPrecision + 1; #else udValue = sizeof(BIGINT); #endif to: if (lpSqlType->unsignedAttribute == TRUE) udValue = lpstmt->lpISAMTableDef-> lpColumnDef[lpstmt->irow].cbPrecision; else udValue = lpstmt->lpISAMTableDef-> lpColumnDef[lpstmt->irow].cbPrecision + 1; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - In RESULTS.C, search for "sizeof(NUMERIC)". Change #if (ODBCVER < 0x0300) udValue = lpstmt->lpISAMTableDef-> lpColumnDef[index].cbPrecision + 2; #else udValue = sizeof(NUMERIC); #endif to: udValue = lpstmt->lpISAMTableDef-> lpColumnDef[index].cbPrecision + 2; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - In RESULTS.C, search for "sizeof(BIGINT)". Change #if (ODBCVER < 0x0300) if (lpSqlType->unsignedAttribute == TRUE) udValue = lpstmt->lpISAMTableDef-> lpColumnDef[index].cbPrecision; else udValue = lpstmt->lpISAMTableDef-> lpColumnDef[index].cbPrecision + 1; #else udValue = sizeof(BIGINT); #endif to: if (lpSqlType->unsignedAttribute == TRUE) udValue = lpstmt->lpISAMTableDef-> lpColumnDef[index].cbPrecision; else udValue = lpstmt->lpISAMTableDef-> lpColumnDef[index].cbPrecision + 1; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - In RESULTS.C, search for "fCType = SQL_C_UBIGINT;". Change case SQL_CHAR: case SQL_VARCHAR: case SQL_LONGVARCHAR: fCType = SQL_C_CHAR; break; case SQL_BIGINT: #if (ODBCVER < 0x0300) fCType = SQL_C_CHAR; #else if (lpSqlType->unsignedAttribute == TRUE) fCType = SQL_C_UBIGINT; else fCType = SQL_C_SBIGINT; #endif break; case SQL_DECIMAL: case SQL_NUMERIC: #if (ODBCVER < 0x0300) fCType = SQL_C_CHAR; #else fCType = SQL_C_NUMERIC; #endif break; to: case SQL_CHAR: case SQL_VARCHAR: case SQL_LONGVARCHAR: case SQL_BIGINT: case SQL_DECIMAL: case SQL_NUMERIC: fCType = SQL_C_CHAR; break; ------------------------------------------------------------------------------ 98-11-20 In EVALUATE.C, search for "Does the record satisfy the HAVING clause". change: /* Does the record satisfy the HAVING clause */ if (lpSqlNodeHaving != NULL) { lpSqlNodeSelect->node.select.SortRecord = lpCurrentRecord; to: /* Does the record satisfy the HAVING clause */ if (lpSqlNodeHaving != NULL) { lpSqlNodeSelect->node.select.SortRecord = lpResultRecord; In EVALUATE.C, search for "Does the last record satisfy the HAVING clause" change /* Does the last record satisfy the HAVING clause? */ if (lpSqlNodeHaving != NULL) { lpSqlNodeSelect->node.select.SortRecord = lpCurrentRecord; to: /* Does the last record satisfy the HAVING clause? */ if (lpSqlNodeHaving != NULL) { lpSqlNodeSelect->node.select.SortRecord = lpResultRecord; ------------------------------------------------------------------------------ 98-11-17 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, NULL); 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, NULL); 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 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-11-11 In PARSE.C, search for "Return EXISTS condition". After /* Return EXISTS condition */ op = OP_EXISTS; idxRight = NO_SQLNODE; add: idxRight2 = NO_SQLNODE; ------------------------------------------------------------------------------ 98-10-13 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 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 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; ------------------------------------------------------------------------------