From 2d9bed5c977d557523a8ab7f2010c14dd50e73c3 Mon Sep 17 00:00:00 2001 From: Dave Page Date: Mon, 31 Oct 2005 19:57:06 +0000 Subject: [PATCH] Initial fix for Declare/Fetch option [Anoop, Sivakumar and Vaidhy @ Pervasive] --- connection.c | 4 ++++ results.c | 40 +++++++++++++++++++++++---------- statement.c | 63 ++++++++++++++++++++++++++++++++++++++++++++-------- statement.h | 1 + 4 files changed, 87 insertions(+), 21 deletions(-) diff --git a/connection.c b/connection.c index 753f63a..1ec2986 100644 --- a/connection.c +++ b/connection.c @@ -1925,6 +1925,10 @@ CC_mapping(ConnectionClass *self, PGresult *pgres,QResultClass *qres) CI_set_field_info(qres->fields, i, PQfname(pgres,i), typid, (Int2)typlen, atttypmod); } + if (qres->manual_tuples) + { + TL_Destructor(qres->manual_tuples); + } qres->manual_tuples = TL_Constructor(num_attributes); qres->manual_tuples->num_tuples = (Int4)num_tuples; for(i=0;i < num_tuples;i++) diff --git a/results.c b/results.c index ed61f88..903796e 100644 --- a/results.c +++ b/results.c @@ -842,24 +842,37 @@ inolog("GetData Column 0 is type %d not of type SQL_C_BOOKMARK", fCType); return SQL_ERROR; } } - - if (stmt->manual_result || !SC_is_fetchcursor(stmt)) + if (stmt->manual_result) { - /* make sure we're positioned on a valid row */ - num_rows = QR_get_num_total_tuples(res); - if ((stmt->currTuple < 0) || - (stmt->currTuple >= num_rows)) + if(!SC_is_fetchcursor(stmt)) { - SC_set_error(stmt, STMT_INVALID_CURSOR_STATE_ERROR, "Not positioned on a valid row for GetData."); - SC_log_error(func, "", stmt); - return SQL_ERROR; + /* make sure we're positioned on a valid row */ + num_rows = QR_get_num_total_tuples(res); + if ((stmt->currTuple < 0) || + (stmt->currTuple >= num_rows)) + { + SC_set_error(stmt, STMT_INVALID_CURSOR_STATE_ERROR, "Not positioned on a valid row for GetData."); + SC_log_error(func, "", stmt); + return SQL_ERROR; + } + } + else + { + if (stmt->currTuple < 0) + { + SC_set_error(stmt, STMT_INVALID_CURSOR_STATE_ERROR, "Not positioned on a valid row for GetData."); + SC_log_error(func, "", stmt); + return SQL_ERROR; + } } - mylog(" num_rows = %d\n", num_rows); if (!get_bookmark) { if (stmt->manual_result) - value = QR_get_value_manual(res, stmt->currTuple, icol); + if(SC_is_fetchcursor(stmt)) + value = QR_get_value_manual(res, (stmt->currTuple % stmt->hdbc->connInfo.drivers.fetch_max), icol); + else + value = QR_get_value_manual(res, stmt->currTuple, icol); else { Int4 curt = GIdx2ResultIdx(stmt->currTuple, stmt, res); @@ -1405,9 +1418,12 @@ PGAPI_ExtendedFetch( * Handle Declare Fetch style specially because the end is not really * the end... */ - if (SC_is_fetchcursor(stmt) && !stmt->manual_result) + if (SC_is_fetchcursor(stmt) ) { + if(!stmt->manual_result) + { return SQL_NO_DATA_FOUND; + } } else { diff --git a/statement.c b/statement.c index cf83c47..53a5262 100644 --- a/statement.c +++ b/statement.c @@ -167,6 +167,8 @@ PGAPI_FreeStmt(HSTMT hstmt, /* Free any cursors and discard any result info */ if (res = SC_get_Result(stmt), res) { + if(SC_is_fetchcursor(stmt)) + SC_set_handle(stmt,res); QR_Destructor(res); SC_set_Result(stmt, NULL); } @@ -204,6 +206,19 @@ PGAPI_FreeStmt(HSTMT hstmt, } +/* + * For Declare/Fetch, setting the parameters to close the cursor. + */ +void +SC_set_handle(StatementClass *self,QResultClass *res) +{ + res->conn = self->hdbc; + if(!res->cursor) + res->cursor = malloc(sizeof(self->cursor_name)); + strcpy(res->cursor,self->cursor_name); +} + + /* * StatementClass implementation */ @@ -608,6 +623,8 @@ SC_recycle_statement(StatementClass *self) /* Free any cursors */ if (res = SC_get_Result(self), res) { + if(SC_is_fetchcursor(self)) + SC_set_handle(self,res); QR_Destructor(res); SC_set_Result(self, NULL); } @@ -894,6 +911,10 @@ SC_fetch(StatementClass *self) lf; Oid type; char *value; + char fetch[128]; + + QueryInfo qi; + UDWORD qflag = 0; ColumnInfoClass *coli; BindInfoClass *bookmark; @@ -903,19 +924,42 @@ SC_fetch(StatementClass *self) self->last_fetch_count = self->last_fetch_count_include_ommitted = 0; coli = QR_get_fields(res); /* the column info */ + /* Issue the fetch query here in case of declare fetch for subsequent rows */ + if (SC_is_fetchcursor(self) && ((self->currTuple % ci->drivers.fetch_max) >= QR_get_num_total_tuples(res) - 1)) + { + qi.result_in = NULL; + qi.cursor = self->cursor_name; + qi.row_size = ci->drivers.fetch_max; + sprintf(fetch, "fetch %d in %s",ci->drivers.fetch_max , self->cursor_name); + res = CC_send_query(self->hdbc, fetch, &qi, qflag); + SC_set_Result(self,res); + } + mylog("manual_result = %d, use_declarefetch = %d\n", self->manual_result, ci->drivers.use_declarefetch); - if (self->manual_result || !SC_is_fetchcursor(self)) + if (self->manual_result) { - if (self->currTuple >= QR_get_num_total_tuples(res) - 1 || - (self->options.maxRows > 0 && self->currTuple == self->options.maxRows - 1)) + if(!SC_is_fetchcursor(self)) { - /* - * if at the end of the tuples, return "no data found" and set - * the cursor past the end of the result set - */ - self->currTuple = QR_get_num_total_tuples(res); - return SQL_NO_DATA_FOUND; + if (self->currTuple >= QR_get_num_total_tuples(res) - 1 || + (self->options.maxRows > 0 && self->currTuple == self->options.maxRows - 1)) + { + /* + * if at the end of the tuples, return "no data found" and set + * the cursor past the end of the result set + */ + self->currTuple = QR_get_num_total_tuples(res); + return SQL_NO_DATA_FOUND; + } + } + else + { + if ((((self->currTuple + 1) % ci->drivers.fetch_max) >= QR_get_num_total_tuples(res)) && + QR_get_num_total_tuples(res) < ci->drivers.fetch_max) + { + self->currTuple = QR_get_num_total_tuples(res); + return SQL_NO_DATA_FOUND; + } } mylog("**** SC_fetch: manual_result\n"); @@ -940,6 +984,7 @@ SC_fetch(StatementClass *self) return SQL_ERROR; } } + #ifdef DRIVER_CURSOR_IMPLEMENT if (res->haskeyset) { diff --git a/statement.h b/statement.h index c51305e..a246c4f 100644 --- a/statement.h +++ b/statement.h @@ -306,6 +306,7 @@ struct StatementClass_ #endif /* WIN_MULTITHREAD_SUPPORT */ /* Statement prototypes */ StatementClass *SC_Constructor(void); +void SC_set_handle(StatementClass *self,QResultClass *res); void InitializeStatementOptions(StatementOptions *opt); char SC_Destructor(StatementClass *self); BOOL SC_opencheck(StatementClass *self, const char *func); -- 2.39.5