Re: Problem retrieveing results from bottom to top

"Daniel A. Veiga" <[email protected]>
Newsgroups gmane.comp.db.tds.freetds
Message-ID <[email protected]>
It's true, I get similar results when running under MS-SQL Server
Windows ODBC driver. But there I have the the possibility of avoiding 
the error. Before calling SQLFetchScroll I call SQLGetStmtAttr
(SQL_ATTR_ROW_NUMBER). If the row number is less than the rowset size, 
instead of retrieving the full rowset I retrieve only the number of 
records left. I tried the same under TDS odbc, but SQLGetStmtAttr
(SQL_ATTR_ROW_NUMBER) always returns 0 (unknown) and I find no solution
to the problem.
I modified cursor7 again, where you can see the difference:)
Bye,


                              Daniel




>> Should I have known you were going to make it part of the project I
would have been more carefull with the comments, name of the created
temp table, etc. To tell you the truth I only sent it as part of the
bug report, as it was an easy way of showing that some records are
returned twice.
>> Bye,
>>                                     Daniel
>
> CVS does not mean that are set on stone :)
> I tried with ms odbc and give same results with a small difference.
Overlapping is detected and a warning is returned. Note however that
there is no way to detect how many rows overlapped. It seems that
sp_cursorfetch returns 2 to say success but overlapped.
>
> freddy77
>
>
>> > Daniel A. Veiga wrote:
>> >> I modified one of the cursor test
>> >> programs to show the problem. I attack it to this mail.
>> >
>> > Applied to CVS.  Thanks!
>> >
>> > --jkl
>> >
>> _______________________________________________
>> FreeTDS mailing list
>> [email protected]
>> http://lists.ibiblio.org/mailman/listinfo/freetds
>

_______________________________________________
FreeTDS mailing list
[email protected]
http://lists.ibiblio.org/mailman/listinfo/freetds
cursor7.c (application/octet-stream, 3 KB)
#include "common.h"

/* Test SQLFetchScroll with a non-unitary rowset, using bottom-up direction */

static char software_version[] = "$Id: cursor7.c,v 1.0 2008/06/13 16:08:46 dav Exp $";
static void *no_unused_var_warn[] = { software_version, no_unused_var_warn };

static void Test(void)
{
#define ROWS 5
	struct data_t {
		SQLINTEGER i;
		SQLLEN ind_i;
		char c[20];
		SQLLEN ind_c;
	} data[ROWS];
	SQLUSMALLINT statuses[ROWS];
	SQLULEN num_row;
	SQLULEN RowNumber;

	int i;
	SQLRETURN ErrCode;

	ResetStatement();

	CHK(SQLSetStmtAttr, (Statement, SQL_ATTR_CONCURRENCY, int2ptr(SQL_CONCUR_READ_ONLY), 0));
	CHK(SQLSetStmtAttr, (Statement, SQL_ATTR_CURSOR_TYPE, int2ptr(SQL_CURSOR_STATIC), 0));

	CHK(SQLPrepare, (Statement, (SQLCHAR *) "SELECT c, i FROM #cursor7_test", SQL_NTS));
	CHK(SQLExecute, (Statement));
	CHK(SQLSetStmtAttr, (Statement, SQL_ATTR_ROW_BIND_TYPE, int2ptr(sizeof(data[0])), 0));
	CHK(SQLSetStmtAttr, (Statement, SQL_ATTR_ROW_ARRAY_SIZE, int2ptr(ROWS), 0));
	CHK(SQLSetStmtAttr, (Statement, SQL_ATTR_ROW_STATUS_PTR, statuses, 0));
	CHK(SQLSetStmtAttr, (Statement, SQL_ATTR_ROWS_FETCHED_PTR, &num_row, 0));

	CHK(SQLBindCol, (Statement, 1, SQL_C_CHAR, &data[0].c, sizeof(data[0].c), &data[0].ind_c));
	CHK(SQLBindCol, (Statement, 2, SQL_C_LONG, &data[0].i, sizeof(data[0].i), &data[0].ind_i));
	
	/* Read records from last to first */
	printf("\n\nReading records from last to first:\n");
	ErrCode=SQLFetchScroll(Statement, SQL_FETCH_LAST, -ROWS); 
	while ( (ErrCode==SQL_SUCCESS) || (ErrCode==SQL_SUCCESS_WITH_INFO) )
	    {
		/* Print this set of rows */
		for(i=ROWS-1;i>=0;i--)
		    {
			if (statuses[i]!=SQL_ROW_NOROW)
				printf("\t %d, %s\n", data[i].i, data[i].c);
		    }

		CHK(SQLGetStmtAttr, (Statement, SQL_ROW_NUMBER, (SQLPOINTER)(&RowNumber), sizeof(RowNumber), NULL));
		printf("---> We are in record No: %u\n", RowNumber);

		/* Read next rowset */
		ErrCode=SQLFetchScroll(Statement, SQL_FETCH_RELATIVE, -ROWS);
	    }
	printf("\nRecords 5, 4 and 3 are returned twice!!\n\n");
}

static void Init(void)
{
	int i;
	char sql[128];
	
	printf("\n\nCreating table #cursor7_test with 12 records.\n");

	Command(Statement, "\tCREATE TABLE #cursor7_test (i INT, c VARCHAR(20))");
	for (i = 1; i <= 12; ++i) {
		sprintf(sql, "\tINSERT INTO #cursor7_test(i,c) VALUES(%d, 'a%db%dc%d')", i, i, i, i);
		Command(Statement, sql);
	}

}

int
main(int argc, char *argv[])
{
	unsigned char sqlstate[6];
	unsigned char msg[256];
	SQLRETURN retcode;

	use_odbc_version3 = 1;
	Connect();

	retcode = SQLSetConnectAttr(Connection, SQL_ATTR_CURSOR_TYPE,  (SQLPOINTER) SQL_CURSOR_DYNAMIC, SQL_IS_INTEGER);
	if (retcode != SQL_SUCCESS) {
		CHK(SQLGetDiagRec, (SQL_HANDLE_DBC, Connection, 1, sqlstate, NULL, (SQLCHAR *) msg, sizeof(msg), NULL));
		sqlstate[5] = 0;
		if (strcmp((const char*) sqlstate, "S1092") == 0) {
			printf("Your connection seems to not support cursors, probably you are using wrong protocol version or Sybase\n");
			Disconnect();
			exit(0);
		}
		ODBC_REPORT_ERROR("SQLSetConnectAttr");
	}

	Init();

	Test();

	Disconnect();
	
	return 0;
}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.