[unixODBC-dev] quiktest.c patch

Eric Sharkey sharkey at netrics.com
Thu Feb 24 16:59:15 GMT 2005


I now have quiktest.c (modified) running on my driver and reporting zero
errors.  (Yay!)  I'm attaching the patch relative to the version in
unixODBC 2.2.10 needed to get the test to run on my driver.

None of this is specific to my driver.  It's all general bugs in the
test.  However, the patch at *** 1783,1789 **** only fixes the bug
for SQL_IDENTIFIER_CASE=SQL_IC_LOWER drivers, but it shouldn't
make it any worse for other driver types.


The patch at *** 4773,4800 **** allows the test to be more accepting
of what drivers return from a call to SQLGetDescField().  The docs say:

  SQL_NO_DATA is returned if RecNumber is greater than the current
  number of descriptor records.

and also defines the error condition:

  HY091 Invalid descriptor field identifier 
        FieldIdentifier was undefined for the DescriptorHandle.

and then in the comments says:

  When an application calls SQLGetDescField to retrieve the value
  of a field that is undefined for a particular descriptor type,
  the function returns SQL_SUCCESS but the value returned for the
  field is undefined.

I find this to be confusing and inconsistent.   The test as originally
written assumes SQL_NO_DATA will be returned for RecNumber > the
number of records even if the field identifier is bogus for the handle,
and that SQL_ERROR HY091 will be returned for a valid RecNumber
and undefined FieldIdentifier.  I see nothing in the docs which
mandate this behavior and have modified it to accept either SQL_NO_DATA
or SQL_ERROR HY091 when both the RecNumber is too high and the
field is invalid.  The test, as modified, is still inconsistent with 
the comment saying SQL_SUCCESS will be returned for undefined fields.

The rest should be pretty straight forward.

Eric

-------------- next part --------------
*** quiktest.c.orig	Thu Feb 24 10:49:23 2005
--- quiktest.c	Thu Feb 24 11:25:25 2005
***************
*** 312,318 ****
  	SQL_DESC_LENGTH,                                        TEXT("SQL_DESC_LENGTH"),                                        FALSE,  DESC_ALL,               DESC_MOST,      DESC_NONE,      23,                                                             0,                                              sizeof(SQLUINTEGER),    SQL_IS_UINTEGER,
  	SQL_DESC_LITERAL_PREFIX,                        TEXT("SQL_DESC_LITERAL_PREFIX"),                        FALSE,  DESC_IRD,               DESC_NONE,      DESC_NONE,      (SQLINTEGER)szParamName,                0,                                              sizeof(SQLCHAR),                0,
  	SQL_DESC_LITERAL_SUFFIX,                        TEXT("SQL_DESC_LITERAL_SUFFIX"),                        FALSE,  DESC_IRD,               DESC_NONE,      DESC_NONE,      (SQLINTEGER)szParamName,                0,                                              sizeof(SQLCHAR),                0,
! 	SQL_DESC_LOCAL_TYPE_NAME,                       TEXT("SQL_DESC_LOCAL_TYPE_NAME"),                       FALSE,  DESC_IRD,               DESC_NONE,      DESC_NONE,      (SQLINTEGER)szParamName,                0,                                              sizeof(SQLCHAR),                0,
  	SQL_DESC_NAME,                                          TEXT("SQL_DESC_NAME"),                                          FALSE,  DESC_ID,                DESC_IPD,       DESC_NONE,      (SQLINTEGER)szParamName,                0,                                              sizeof(SQLCHAR),                0,
  	SQL_DESC_NULLABLE,                                      TEXT("SQL_DESC_NULLABLE"),                                      FALSE,  DESC_ID,                DESC_NONE,      DESC_NONE,      0,                                                              0,                                              sizeof(SQLSMALLINT),    SQL_IS_SMALLINT,
  	SQL_DESC_OCTET_LENGTH,                          TEXT("SQL_DESC_OCTET_LENGTH"),                          FALSE,  DESC_ALL,               DESC_MOST,      DESC_NONE,      sizeof(tsval),                                  0,                                              sizeof(SQLINTEGER),             SQL_IS_INTEGER,
--- 312,318 ----
  	SQL_DESC_LENGTH,                                        TEXT("SQL_DESC_LENGTH"),                                        FALSE,  DESC_ALL,               DESC_MOST,      DESC_NONE,      23,                                                             0,                                              sizeof(SQLUINTEGER),    SQL_IS_UINTEGER,
  	SQL_DESC_LITERAL_PREFIX,                        TEXT("SQL_DESC_LITERAL_PREFIX"),                        FALSE,  DESC_IRD,               DESC_NONE,      DESC_NONE,      (SQLINTEGER)szParamName,                0,                                              sizeof(SQLCHAR),                0,
  	SQL_DESC_LITERAL_SUFFIX,                        TEXT("SQL_DESC_LITERAL_SUFFIX"),                        FALSE,  DESC_IRD,               DESC_NONE,      DESC_NONE,      (SQLINTEGER)szParamName,                0,                                              sizeof(SQLCHAR),                0,
! 	SQL_DESC_LOCAL_TYPE_NAME,                       TEXT("SQL_DESC_LOCAL_TYPE_NAME"),                       FALSE,  DESC_ID,                DESC_NONE,      DESC_NONE,      (SQLINTEGER)szParamName,                0,                                              sizeof(SQLCHAR),                0,
  	SQL_DESC_NAME,                                          TEXT("SQL_DESC_NAME"),                                          FALSE,  DESC_ID,                DESC_IPD,       DESC_NONE,      (SQLINTEGER)szParamName,                0,                                              sizeof(SQLCHAR),                0,
  	SQL_DESC_NULLABLE,                                      TEXT("SQL_DESC_NULLABLE"),                                      FALSE,  DESC_ID,                DESC_NONE,      DESC_NONE,      0,                                                              0,                                              sizeof(SQLSMALLINT),    SQL_IS_SMALLINT,
  	SQL_DESC_OCTET_LENGTH,                          TEXT("SQL_DESC_OCTET_LENGTH"),                          FALSE,  DESC_ALL,               DESC_MOST,      DESC_NONE,      sizeof(tsval),                                  0,                                              sizeof(SQLINTEGER),             SQL_IS_INTEGER,
***************
*** 1440,1447 ****
  			{
  				switch(fHandleType)
  				{
! 				case SQL_HANDLE_DBC:
! 				case SQL_HANDLE_STMT:
  					if (_tcscmp((LPTSTR)rgbValue,szDataSourceName))
  						sprintf(szBuff,TEXT("\t\t\tSQL_DIAG_SERVER_NAME\tReceived: %s\tExpected: %s"),(LPTSTR)rgbValue,szDataSourceName);
  					break;
--- 1440,1448 ----
  			{
  				switch(fHandleType)
  				{
!                                 /* Driver manager errors won't necessarily return a server name, so we only check
!                                    this for errors that go through to the driver (the descriptor handle error) */
! 				case SQL_HANDLE_DESC:
  					if (_tcscmp((LPTSTR)rgbValue,szDataSourceName))
  						sprintf(szBuff,TEXT("\t\t\tSQL_DIAG_SERVER_NAME\tReceived: %s\tExpected: %s"),(LPTSTR)rgbValue,szDataSourceName);
  					break;
***************
*** 1774,1779 ****
--- 1775,1784 ----
  	if(rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
  		RETCHECK(SQL_SUCCESS, rc,szSQLGETINFO);
  
+         //Zero means unlimited or unknown, assume 128
+         if (cTableName==0)
+           cTableName=128;
+ 
  	rc = SQLGetInfo(hdbc, SQL_QUALIFIER_NAME_SEPARATOR, 
  		lpqt->buf, sizeof(lpqt->buf), NULL);
  	if(rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
***************
*** 1783,1789 ****
  		cTableName -= 4;
  	
  	_sntprintf(lpqt->szTableName, min(cTableName, MAX_TABLE_NAME-1),
! 				TEXT("Q%s"), szTime);
  
  } //SetTableName()
  
--- 1788,1794 ----
  		cTableName -= 4;
  	
  	_sntprintf(lpqt->szTableName, min(cTableName, MAX_TABLE_NAME-1),
! 				TEXT("q%s"), szTime);
  
  } //SetTableName()
  
***************
*** 1849,1854 ****
--- 1854,1861 ----
  		sizeof cFieldName, NULL);
  	RETCHECK(SQL_SUCCESS, rc,szSQLGETINFO);
  
+         cMaxRowSize = 0;
+ 
  	rc = SQLGetInfo(hdbc, SQL_MAX_ROW_SIZE, &cMaxRowSize,
  		sizeof cMaxRowSize, NULL);
  	/* don't check for SQL_SUCCES here, it's a 2.0 function.  If it's successful
***************
*** 1858,1864 ****
  	
  /* TO DO: add checks in here for dos file types GetInfo SQL_QUALIFIER_NAME_SEPARATER */
  
! 	if(cFieldName > MAX_FIELD - 1)
  		cFieldName = MAX_FIELD - 1;
  
  	if(cFieldName < PREFIX_SIZE)
--- 1865,1871 ----
  	
  /* TO DO: add checks in here for dos file types GetInfo SQL_QUALIFIER_NAME_SEPARATER */
  
! 	if((cFieldName > MAX_FIELD - 1)||(cFieldName==0))
  		cFieldName = MAX_FIELD - 1;
  
  	if(cFieldName < PREFIX_SIZE)
***************
*** 2859,2865 ****
  
  	RETCHECK(SQL_NO_DATA_FOUND, rc, szSQLFETCH);
  
! 	if(ind != cTypes + 1)
  		DISPLAYERROR(szSQLFETCH, TEXT("Incorrect number of result rows"));
  
  	rc = SQLFreeStmt(hstmt, SQL_CLOSE);
--- 2866,2872 ----
  
  	RETCHECK(SQL_NO_DATA_FOUND, rc, szSQLFETCH);
  
! 	if(ind != guwRowCount)
  		DISPLAYERROR(szSQLFETCH, TEXT("Incorrect number of result rows"));
  
  	rc = SQLFreeStmt(hstmt, SQL_CLOSE);
***************
*** 3366,3372 ****
  
  		RETCHECK(SQL_NO_DATA_FOUND, rc,szSQLFETCH);
  
! 		if(i != cTypes)
  			DISPLAYERROR(TEXT("'LIKE' query"),TEXT("incorrect number of result rows"));
  
  		}
--- 3373,3379 ----
  
  		RETCHECK(SQL_NO_DATA_FOUND, rc,szSQLFETCH);
  
! 		if(i != guwRowCount)
  			DISPLAYERROR(TEXT("'LIKE' query"),TEXT("incorrect number of result rows"));
  
  		}
***************
*** 3418,3424 ****
  	DWORD           dwLen=0;
  	SWORD           fSqlType;
  	SDWORD  cbValue=0;
! 	UWORD           iTableCol,row,iCol,uwRowSetSize;
  	CHAR           szQuery[MAX_STRING_SIZE], szColName[SMALLBUFF];
  	CHAR*  rgbValue = NULL;
  	DSTRUCT*        rgData = NULL;
--- 3425,3431 ----
  	DWORD           dwLen=0;
  	SWORD           fSqlType;
  	SDWORD  cbValue=0;
! 	UWORD           iTableCol,row,iCol,uwRowSetSize,ExpectedRows;
  	CHAR           szQuery[MAX_STRING_SIZE], szColName[SMALLBUFF];
  	CHAR*  rgbValue = NULL;
  	DSTRUCT*        rgData = NULL;
***************
*** 3491,3504 ****
  		RETCHECK(SQL_SUCCESS_WITH_INFO, rc, szSQLEXECDIRECT);
  		goto abortxfetch;
  	}
! 	iCol=0;
! 	do      {
! 		iCol++;
  		rc=SQLDescribeCol(hstmt, iCol, szColName, SMALLBUFF, 
  			NULL, &fSqlType, NULL, NULL, NULL);
  		RETCHECK(SQL_SUCCESS, rc,szSQLDESCRIBECOL);
! 	} while(fSqlType!=SQL_CHAR && iCol<=cTypes);
! 
  	FreeStmt(SQL_CLOSE);
  	if(iCol>cTypes){
  		DISPLAYERROR(szSQLEXTENDEDFETCH, TEXT("\t\t\tSelect-order by  Failed"));
--- 3498,3509 ----
  		RETCHECK(SQL_SUCCESS_WITH_INFO, rc, szSQLEXECDIRECT);
  		goto abortxfetch;
  	}
!         for(iCol=1;iCol<=cTypes;iCol++) {
  		rc=SQLDescribeCol(hstmt, iCol, szColName, SMALLBUFF, 
  			NULL, &fSqlType, NULL, NULL, NULL);
  		RETCHECK(SQL_SUCCESS, rc,szSQLDESCRIBECOL);
!                 if ((fSqlType==SQL_CHAR)||(fSqlType==SQL_VARCHAR)) break;
!         }
  	FreeStmt(SQL_CLOSE);
  	if(iCol>cTypes){
  		DISPLAYERROR(szSQLEXTENDEDFETCH, TEXT("\t\t\tSelect-order by  Failed"));
***************
*** 3555,3562 ****
  		goto abortxfetch;
  	}
   
! 	// Need to change this loop if number of rows in table < uwRowSetSize
! 	for (row=0; row<uwRowSetSize; row++)
  	{
  		SWORD iResultSetCol=0;
  		if (SQL_SUCCESS != (rc = SQLFetch(hstmt))){
--- 3560,3571 ----
  		goto abortxfetch;
  	}
   
!         if (uwRowSetSize>guwRowCount) {
!         	ExpectedRows=guwRowCount;
!         } else {
!         	ExpectedRows=uwRowSetSize;
!         }
! 	for (row=0; row<ExpectedRows; row++)
  	{
  		SWORD iResultSetCol=0;
  		if (SQL_SUCCESS != (rc = SQLFetch(hstmt))){
***************
*** 3601,3606 ****
--- 3610,3728 ----
  } /* TestExtendedFetch() */
  
  
+ //-----------------------------------------------------------------------
+ //    Function: InsertOneRow
+ //
+ //              Insert one row into the table.
+ //
+ //                      lpqt:                   temp place to hold data genrated
+ //                      rgFields:       hold info about each data type in the dbs
+ //                      cTypes;         the count of data types
+ //                      lpd:                    buffer used for SQLBindParam
+ //                      cSeed;          the seed used to generate data
+ //                      fFreeHsmt:      if the hstmt should be freed      
+ //
+ //              Return TRUE: the insertion was successful
+ //                               FALSE: otherwise
+ //-----------------------------------------------------------------------
+ 										  
+ BOOL   InsertOneRow(QTSTRUCT  *lpqt,FIELDINFO  *rgFields,UWORD cTypes,
+ 										DSTRUCT  *lpd,UWORD cSeed,BOOL fFreeHstmt)
+ {
+ 	RETCODE                         rc;
+ 	UWORD                           w;
+ 	UWORD                           ind;
+ 	LPTSTR                          pch=NULL;
+ 	SQLHDESC                                hdesc;
+    SQLSMALLINT          fParamType = SQL_PARAM_INPUT;
+ 	CHAR                                   szDataItem[150];
+ 
+ 
+ 	//prepare the insert statement
+ 	rc = SQLPrepare(hstmt, szInsertStmt, SQL_NTS);
+ 	RETCHECK(SQL_SUCCESS, rc,szSQLPREPARE);
+ 
+ 	//going through each data type, call SQLBindParam
+ 	for(ind = 0, w = 0; ind < cTypes; ind++) 
+ 	{
+ 
+ 		//make data according to data type description in rgFields[], cSeed is the seed
+ 		pch = qtMakeData(cSeed,ind,&rgFields[ind], szDataItem);
+ 
+ 		//if the data type is READ_ONLY, skip
+ 		if(!pch) 
+ 			continue;
+ 
+ 		//populate the NULL data
+ 		if(*pch) 
+ 		{
+ 			_tcscpy(lpd[w].data, pch);
+ 			lpd[w].cb = SQL_NTS;
+ 		}
+ 		else 
+ 		{
+ 			_tcscpy(lpd[w].data,TEXT(""));
+ 			lpd[w].cb = SQL_NULL_DATA;
+ 		}
+ 
+ 		if (g_f3XDriver && Supported(SQL_API_SQLSETDESCFIELD))
+ //              if (0)  //DEBUG
+ 		{
+ 			//bind the data buffer in lpd[] to each column of the table
+ 			rc = SQLBindParam(hstmt, (SQLSMALLINT)(w+1),SQL_C_CHAR, rgFields[ind].wSQLType,
+ 									rgFields[ind].precision, rgFields[ind].scale,
+ 									&lpd[w].data, &lpd[w].cb);
+ 			RETCHECK(SQL_SUCCESS, rc,szSQLBINDPARAM);
+ 
+ 			if(rc!= SQL_SUCCESS)
+ 				return FALSE;
+ 
+ 			//get the driver parameter descriptor handle
+ 			rc = SQLGetStmtAttr(hstmt,SQL_ATTR_IMP_PARAM_DESC, &hdesc, sizeof(hdesc),NULL);
+ 			RETCHECK(SQL_SUCCESS, rc,szSQLGETSTMTATTR);
+ 			if(rc!= SQL_SUCCESS)
+ 				return FALSE;
+ 
+ 			//set the parameter type field in the descriptor
+ 			rc = SQLSetDescField(hdesc, (SQLSMALLINT)(w+1), SQL_DESC_PARAMETER_TYPE, 
+ 										(PTR)fParamType, sizeof(fParamType));
+ 			RETCHECK(SQL_SUCCESS, rc,szSQLSETDESCFIELD);
+ 
+ 		}
+ 		else
+ 		{
+ 			rc = SQLBindParameter(hstmt, (UWORD)(w+1),SQL_PARAM_INPUT,SQL_C_CHAR, 
+ 							rgFields[ind].wSQLType, rgFields[ind].precision, 
+ 							rgFields[ind].scale,&lpd[w].data, 100, &lpd[w].cb);
+ 				
+ 			RETCHECK(SQL_SUCCESS, rc,szSQLBINDPARAMETER);
+ 
+ 			if(rc!= SQL_SUCCESS)
+ 				return FALSE;
+ 		}
+ 
+ 
+ 		//go on to next column
+ 		w++;
+ 	}
+ 
+ 	// insert a row 
+ 	rc = SQLExecute(hstmt); 
+ 	RETCHECK(SQL_SUCCESS, rc,szSQLEXECUTE);
+ 	if(rc!= SQL_SUCCESS)
+ 		return FALSE;
+ 
+ 	//free the hstmt if required
+ 	if(fFreeHstmt)
+ 	{
+ 		if (FreeStmt(SQL_CLOSE))
+ 			return FALSE;
+ 
+ 	}
+ 
+ 	return TRUE;
+ 
+ }       //InsertOneRow
  
  
  /*------------------------------------------------------------------------------
***************
*** 3634,3639 ****
--- 3756,3769 ----
  						/* cNumResSetCols is set in BuildInsertStmt() */
  	uwRowsetSize = 5;/* uwRowsetSize rows per Rowset */
  
+         while (guwRowCount<2*uwRowsetSize) {
+                 if(!InsertOneRow(lpqt,rgFields,cTypes,lpd,(UWORD)(guwRowCount), TRUE)) {
+ 		   DISPLAYERROR(szQUICKREBIND,TEXT("\t\t\tUnable to insert rows"));
+                    return;
+                 }
+                 guwRowCount++;          
+         }
+ 
  	/* Only col which might not be bound but might not be AutoUpdateable is col 0 */
  	if(!qtMakeData(0, 0, &rgFields[0], szQuery))
  		fCol0Bound = FALSE;
***************
*** 3665,3680 ****
  		RETCHECK(SQL_SUCCESS_WITH_INFO, rc, szSQLEXECDIRECT);
  		goto abortQuikRebind;
  	}
! 	iCol=0;
! 	do      {
! 		iCol++;
! 		rc=SQLDescribeCol(hstmt, iCol, szColName, SMALLBUFF, 
! 			NULL, &fSqlType, NULL, NULL, NULL);
! 		RETCHECK(SQL_SUCCESS, rc,szSQLDESCRIBECOL);
! 	} while(fSqlType!=SQL_CHAR && iCol<=cTypes);
! 
  	FreeStmt(SQL_CLOSE);
! 	if(iCol>=cTypes){
  		DISPLAYERROR(szQUICKREBIND, TEXT("\t\t\tSelect-order by  Failed"));
  		goto abortQuikRebind;
  	}
--- 3795,3808 ----
  		RETCHECK(SQL_SUCCESS_WITH_INFO, rc, szSQLEXECDIRECT);
  		goto abortQuikRebind;
  	}
!         for(iCol=1;iCol<=cTypes;iCol++) {
!                 rc=SQLDescribeCol(hstmt, iCol, szColName, SMALLBUFF,
!                         NULL, &fSqlType, NULL, NULL, NULL);
!                 RETCHECK(SQL_SUCCESS, rc,szSQLDESCRIBECOL);
!                 if ((fSqlType==SQL_CHAR)||(fSqlType==SQL_VARCHAR)) break;
!         }
  	FreeStmt(SQL_CLOSE);
! 	if(iCol>cTypes){
  		DISPLAYERROR(szQUICKREBIND, TEXT("\t\t\tSelect-order by  Failed"));
  		goto abortQuikRebind;
  	}
***************
*** 4773,4800 ****
  		fValidOp=rgDescInfo[iDescField].fSettable;
  	}
  
! 	// If we're reading beyond the last record, expect SQL_NO_DATA.
! 	if (swDescRec > swDescRecCount && DESC_UPDATE_MODE_READ == swUpdateMode)
  	{
! 		sprintf(buf,TEXT("%s: Able to %s descriptor field %s in the %s beyond last record."),
  				pszAPI, szOp, rgDescInfo[iDescField].szDescFieldName, DescTypes[uwDescIndex].szDescName);
! 		ERRSHANDLE(SQL_HANDLE_DESC, hdesc, SQL_NO_DATA, rc, buf);
  	}
  	else
  	{
! 		if (fValidOp & DescTypes[uwDescIndex].uwTypeMask)
  		{
! 			sprintf(buf,TEXT("%s: Unable to %s descriptor field %s in the %s"),
  					pszAPI, szOp, rgDescInfo[iDescField].szDescFieldName, DescTypes[uwDescIndex].szDescName);
! 			ERRSHANDLE(SQL_HANDLE_DESC, hdesc, SQL_SUCCESS, rc, buf);
  		}
  		else
  		{
! 			sprintf(buf,TEXT("%s: Able to %s descriptor field %s in the %s"),
! 					pszAPI, szOp, rgDescInfo[iDescField].szDescFieldName, DescTypes[uwDescIndex].szDescName);
! 			ERRSHANDLE(SQL_HANDLE_DESC, hdesc, SQL_ERROR, rc, buf);
  		}
  	}
  }
  
  //-----------------------------------------------------------------------
--- 4901,4940 ----
  		fValidOp=rgDescInfo[iDescField].fSettable;
  	}
  
! 	if ((fValidOp & DescTypes[uwDescIndex].uwTypeMask)&&swDescRec <= swDescRecCount)
  	{
! 		sprintf(buf,TEXT("%s: Unable to %s descriptor field %s in the %s"),
  				pszAPI, szOp, rgDescInfo[iDescField].szDescFieldName, DescTypes[uwDescIndex].szDescName);
! 		ERRSHANDLE(SQL_HANDLE_DESC, hdesc, SQL_SUCCESS, rc, buf);
  	}
  	else
  	{
! 		// If there are two valid failure modes, don't be picky
! 		if (!(fValidOp & DescTypes[uwDescIndex].uwTypeMask) &&
! 			(swDescRec > swDescRecCount && DESC_UPDATE_MODE_READ == swUpdateMode))
  		{
! 			sprintf(buf,TEXT("%s: Able to %s descriptor field %s in the %s beyond last record."),
  					pszAPI, szOp, rgDescInfo[iDescField].szDescFieldName, DescTypes[uwDescIndex].szDescName);
! 			ERRSHANDLE(SQL_HANDLE_DESC, hdesc, rc==SQL_NO_DATA?SQL_NO_DATA:SQL_ERROR, rc, buf);
  		}
  		else
  		{
! 			// If we're reading beyond the last record, expect SQL_NO_DATA.
! 			if (swDescRec > swDescRecCount && DESC_UPDATE_MODE_READ == swUpdateMode)
! 			{
! 				sprintf(buf,TEXT("%s: Able to %s descriptor field %s in the %s beyond last record."),
! 						pszAPI, szOp, rgDescInfo[iDescField].szDescFieldName, DescTypes[uwDescIndex].szDescName);
! 				ERRSHANDLE(SQL_HANDLE_DESC, hdesc, SQL_NO_DATA, rc, buf);
! 			}
! 			else
! 			{
! 				sprintf(buf,TEXT("%s: Able to %s descriptor field %s in the %s"),
! 						pszAPI, szOp, rgDescInfo[iDescField].szDescFieldName, DescTypes[uwDescIndex].szDescName);
! 				ERRSHANDLE(SQL_HANDLE_DESC, hdesc, SQL_ERROR, rc, buf);
! 			}
  		}
  	}
+ 
  }
  
  //-----------------------------------------------------------------------
***************
*** 6091,6115 ****
  //-----------------------------------------------------------------------
  SWORD   GetRowCnt(QTSTRUCT  *lpqt)
  {
  	SWORD           sRowCnt;
  	RETCODE         rc;
  
  	// free the statment handle for a fresh start
  	FreeStmt(SQL_DROP);
  
  	AllocHstmt();
  
! 	//get row count for the table
! 	sprintf(lpqt->sz,TEXT("select count(*) from %s"), lpqt->szTableName);
! 
! 	rc = SQLExecDirect(hstmt, lpqt->sz, SQL_NTS);
! 	RETCHECK(SQL_SUCCESS, rc,szSQLEXECDIRECT);
  
! 	rc = SQLFetch(hstmt);
! 	RETCHECK(SQL_SUCCESS, rc,szSQLFETCH);
  
! 	rc = SQLGetData(hstmt,1, SQL_C_SSHORT, &sRowCnt, sizeof(sRowCnt), NULL);
! 	RETCHECK(SQL_SUCCESS, rc,szSQLGETDATA);
  
  	FreeStmt(SQL_CLOSE);
  
--- 6231,6284 ----
  //-----------------------------------------------------------------------
  SWORD   GetRowCnt(QTSTRUCT  *lpqt)
  {
+         SQLLEN          lRowCnt;
  	SWORD           sRowCnt;
  	RETCODE         rc;
+         SQLUINTEGER     can_count;
  
  	// free the statment handle for a fresh start
  	FreeStmt(SQL_DROP);
  
  	AllocHstmt();
  
! 	//check if count() is supported
! 	rc = SQLGetInfo(hdbc, SQL_AGGREGATE_FUNCTIONS, &can_count, sizeof(can_count), NULL);
! 	RETCHECK(SQL_SUCCESS, rc,szSQLGETINFO);
  
!         if (rc==SQL_SUCCESS) {
!           can_count&=SQL_AF_COUNT;
!         } else {
!           can_count=0;
!         }
! 
!         if (can_count) {
! 	  //get row count for the table the easy way
! 	  sprintf(lpqt->sz,TEXT("select count(*) from %s"), lpqt->szTableName);
! 
! 	  rc = SQLExecDirect(hstmt, lpqt->sz, SQL_NTS);
! 	  RETCHECK(SQL_SUCCESS, rc,szSQLEXECDIRECT);
! 
! 	  rc = SQLFetch(hstmt);
! 	  RETCHECK(SQL_SUCCESS, rc,szSQLFETCH);
! 
! 	  rc = SQLGetData(hstmt,1, SQL_C_SSHORT, &sRowCnt, sizeof(sRowCnt), NULL);
! 	  RETCHECK(SQL_SUCCESS, rc,szSQLGETDATA);
!         } else {
! 	  //get row count for the table the hard way
! 	  sprintf(lpqt->sz,TEXT("select * from %s"), lpqt->szTableName);
! 
! 	  rc = SQLExecDirect(hstmt, lpqt->sz, SQL_NTS);
! 	  RETCHECK(SQL_SUCCESS, rc,szSQLEXECDIRECT);
! 
!           sRowCnt=0;
! 
! 	  rc = SQLFetch(hstmt);
!           while (rc==SQL_SUCCESS||rc==SQL_SUCCESS_WITH_INFO) {
!             sRowCnt++;
! 	    rc = SQLFetch(hstmt);
!           }
  
!         }
  
  	FreeStmt(SQL_CLOSE);
  
***************
*** 6118,6237 ****
  
  
  //-----------------------------------------------------------------------
- //    Function: InsertOneRow
- //
- //              Insert one row into the table.
- //
- //                      lpqt:                   temp place to hold data genrated
- //                      rgFields:       hold info about each data type in the dbs
- //                      cTypes;         the count of data types
- //                      lpd:                    buffer used for SQLBindParam
- //                      cSeed;          the seed used to generate data
- //                      fFreeHsmt:      if the hstmt should be freed      
- //
- //              Return TRUE: the insertion was successful
- //                               FALSE: otherwise
- //-----------------------------------------------------------------------
- 										  
- BOOL   InsertOneRow(QTSTRUCT  *lpqt,FIELDINFO  *rgFields,UWORD cTypes,
- 										DSTRUCT  *lpd,UWORD cSeed,BOOL fFreeHstmt)
- {
- 	RETCODE                         rc;
- 	UWORD                           w;
- 	UWORD                           ind;
- 	LPTSTR                          pch=NULL;
- 	SQLHDESC                                hdesc;
-    SQLSMALLINT          fParamType = SQL_PARAM_INPUT;
- 	CHAR                                   szDataItem[150];
- 
- 
- 	//prepare the insert statement
- 	rc = SQLPrepare(hstmt, szInsertStmt, SQL_NTS);
- 	RETCHECK(SQL_SUCCESS, rc,szSQLPREPARE);
- 
- 	//going through each data type, call SQLBindParam
- 	for(ind = 0, w = 0; ind < cTypes; ind++) 
- 	{
- 
- 		//make data according to data type description in rgFields[], cSeed is the seed
- 		pch = qtMakeData(cSeed,ind,&rgFields[ind], szDataItem);
- 
- 		//if the data type is READ_ONLY, skip
- 		if(!pch) 
- 			continue;
- 
- 		//populate the NULL data
- 		if(*pch) 
- 		{
- 			_tcscpy(lpd[w].data, pch);
- 			lpd[w].cb = SQL_NTS;
- 		}
- 		else 
- 		{
- 			_tcscpy(lpd[w].data,TEXT(""));
- 			lpd[w].cb = SQL_NULL_DATA;
- 		}
- 
- 		if (g_f3XDriver && Supported(SQL_API_SQLSETDESCFIELD))
- //              if (0)  //DEBUG
- 		{
- 			//bind the data buffer in lpd[] to each column of the table
- 			rc = SQLBindParam(hstmt, (SQLSMALLINT)(w+1),SQL_C_CHAR, rgFields[ind].wSQLType,
- 									rgFields[ind].precision, rgFields[ind].scale,
- 									&lpd[w].data, &lpd[w].cb);
- 			RETCHECK(SQL_SUCCESS, rc,szSQLBINDPARAM);
- 
- 			if(rc!= SQL_SUCCESS)
- 				return FALSE;
- 
- 			//get the driver parameter descriptor handle
- 			rc = SQLGetStmtAttr(hstmt,SQL_ATTR_IMP_PARAM_DESC, &hdesc, sizeof(hdesc),NULL);
- 			RETCHECK(SQL_SUCCESS, rc,szSQLGETSTMTATTR);
- 			if(rc!= SQL_SUCCESS)
- 				return FALSE;
- 
- 			//set the parameter type field in the descriptor
- 			rc = SQLSetDescField(hdesc, (SQLSMALLINT)(w+1), SQL_DESC_PARAMETER_TYPE, 
- 										(PTR)fParamType, sizeof(fParamType));
- 			RETCHECK(SQL_SUCCESS, rc,szSQLSETDESCFIELD);
- 
- 		}
- 		else
- 		{
- 			rc = SQLBindParameter(hstmt, (UWORD)(w+1),SQL_PARAM_INPUT,SQL_C_CHAR, 
- 							rgFields[ind].wSQLType, rgFields[ind].precision, 
- 							rgFields[ind].scale,&lpd[w].data, 100, &lpd[w].cb);
- 				
- 			RETCHECK(SQL_SUCCESS, rc,szSQLBINDPARAMETER);
- 
- 			if(rc!= SQL_SUCCESS)
- 				return FALSE;
- 		}
- 
- 
- 		//go on to next column
- 		w++;
- 	}
- 
- 	// insert a row 
- 	rc = SQLExecute(hstmt); 
- 	RETCHECK(SQL_SUCCESS, rc,szSQLEXECUTE);
- 	if(rc!= SQL_SUCCESS)
- 		return FALSE;
- 
- 	//free the hstmt if required
- 	if(fFreeHstmt)
- 	{
- 		if (FreeStmt(SQL_CLOSE))
- 			return FALSE;
- 
- 	}
- 
- 	return TRUE;
- 
- }       //InsertOneRow
- 
- //-----------------------------------------------------------------------
  //    Function: ExecEndTran
  //
  //              Execute EndTran statement, return the row count of the table
--- 6287,6292 ----


More information about the unixODBC-dev mailing list