in driver/results.cc [1925:2244]
SQLRETURN SQL_API myodbc_single_fetch( SQLHSTMT hstmt,
SQLUSMALLINT fFetchType,
SQLLEN irow,
SQLULEN *pcrow,
SQLUSMALLINT *rgfRowStatus,
my_bool upd_status )
{
SQLULEN rows_to_fetch;
long cur_row, max_row;
SQLRETURN row_res, res;
STMT *stmt= (STMT *) hstmt;
MYSQL_ROW values= 0;
MYSQL_ROW_OFFSET save_position= 0;
SQLULEN dummy_pcrow;
BOOL disconnected= FALSE;
long brow= 0;
try
{
if ( !stmt->result )
return stmt->set_error("24000", "Fetch without a SELECT", 0);
cur_row = stmt->current_row;
if ( !pcrow )
pcrow= &dummy_pcrow;
/* for scrollable cursor("scroller") max_row is max row for currently
fetched part of resultset */
max_row= (long) num_rows(stmt);
stmt->reset_getdata_position();
stmt->current_values= 0; /* For SQLGetData */
switch ( fFetchType )
{
case SQL_FETCH_NEXT:
cur_row= (stmt->current_row < 0 ? 0 :
stmt->current_row + stmt->rows_found_in_set);
break;
case SQL_FETCH_PRIOR:
cur_row= (stmt->current_row <= 0 ? -1 :
(long)(stmt->current_row - stmt->ard->array_size));
break;
case SQL_FETCH_FIRST:
cur_row= 0L;
break;
case SQL_FETCH_LAST:
cur_row = max_row - (long)stmt->ard->array_size;
break;
case SQL_FETCH_ABSOLUTE:
if (irow < 0)
{
/* Fetch from end of result set */
if ( max_row+irow < 0 && -irow <= (long) stmt->ard->array_size )
{
/*
| FetchOffset | > LastResultRow AND
| FetchOffset | <= RowsetSize
*/
cur_row= 0; /* Return from beginning */
}
else
cur_row = max_row + (long)irow; /* Ok if max_row <= -irow */
}
else
cur_row= (long) irow - 1;
break;
case SQL_FETCH_RELATIVE:
cur_row = stmt->current_row + (long)irow;
if (stmt->current_row > 0 && cur_row < 0 &&
(long) - irow <= (long)stmt->ard->array_size)
{
cur_row= 0;
}
break;
case SQL_FETCH_BOOKMARK:
{
if (stmt->stmt_options.bookmark_ptr)
{
DESCREC *arrec;
IS_BOOKMARK_VARIABLE(stmt);
arrec= desc_get_rec(stmt->ard, -1, FALSE);
if (arrec->concise_type == SQL_C_BOOKMARK)
{
brow = (long)(*((SQLLEN *) stmt->stmt_options.bookmark_ptr));
}
else
{
brow= atol((const char*) stmt->stmt_options.bookmark_ptr);
}
}
cur_row = brow + (long)irow;
if (cur_row < 0 && (long)-irow <= (long)stmt->ard->array_size)
{
cur_row= 0;
}
}
break;
default:
return stmt->set_error( MYERR_S1106, "Fetch type out of range", 0);
}
if ( cur_row < 0 )
{
stmt->current_row= -1; /* Before first row */
stmt->rows_found_in_set= 0;
data_seek(stmt, 0L);
stmt->set_error("01S07", "One or more row has error.", 0);
return SQL_SUCCESS_WITH_INFO; //SQL_NO_DATA_FOUND
}
if ( cur_row > max_row )
{
if (scroller_exists(stmt))
{
while (cur_row > (max_row= (long)scroller_move(stmt)));
switch (scroller_prefetch(stmt))
{
case SQL_NO_DATA:
stmt->set_error("01S07", "One or more row has error.", 0);
return SQL_SUCCESS_WITH_INFO; //SQL_NO_DATA_FOUND
case SQL_ERROR: return stmt->set_error(MYERR_S1000,
stmt->dbc->connection_proxy->error(), 0);
}
}
else
{
cur_row= max_row;
}
}
if ( !stmt->result_array && !if_forward_cache(stmt) )
{
/*
If Dynamic, it loses the stmt->end_of_set, so
seek to desired row, might have new data or
might be deleted
*/
if ( stmt->stmt_options.cursor_type != SQL_CURSOR_DYNAMIC &&
cur_row && cur_row == (long)(stmt->current_row +
stmt->rows_found_in_set) )
row_seek(stmt, stmt->end_of_set);
else
data_seek(stmt, cur_row);
}
stmt->current_row= cur_row;
if (scroller_exists(stmt)
|| (if_forward_cache(stmt) && !stmt->result_array))
{
rows_to_fetch= stmt->ard->array_size;
}
else
{
rows_to_fetch= myodbc_min(max_row-cur_row,
(long)stmt->ard->array_size);
}
/* out params has been silently fetched */
if (rows_to_fetch == 0)
{
if (stmt->out_params_state != OPS_UNKNOWN)
{
rows_to_fetch= 1;
}
else
{
*pcrow= 0;
stmt->rows_found_in_set= 0;
if ( upd_status && stmt->ird->rows_processed_ptr )
{
*stmt->ird->rows_processed_ptr= 0;
}
stmt->set_error("01S07", "One or more row has error.", 0);
return SQL_SUCCESS_WITH_INFO; //SQL_NO_DATA_FOUND
}
}
res= SQL_SUCCESS;
{
save_position= row_tell(stmt);
/* - Actual fetching happens here - */
if (!(values = stmt->fetch_row()) )
{
if (scroller_exists(stmt))
{
scroller_move(stmt);
row_res= scroller_prefetch(stmt);
if (row_res != SQL_SUCCESS)
{
goto exitSQLSingleFetch;
}
if ( !(values = stmt->fetch_row()) )
{
goto exitSQLSingleFetch;
}
/* Not sure that is right, but see it better than nothing */
save_position= row_tell(stmt);
}
else
{
goto exitSQLSingleFetch;
}
}
if ( stmt->fix_fields )
{
values= (*stmt->fix_fields)(stmt,values);
}
stmt->current_values= values;
}
if (!stmt->fix_fields)
{
fill_ird_data_lengths(stmt->ird, fetch_lengths(stmt),
stmt->result->field_count);
}
row_res= fill_fetch_buffers(stmt, values, cur_row);
/* For SQL_SUCCESS we need all rows to be SQL_SUCCESS */
if (res != row_res)
{
/* Any successful row makes overall result SQL_SUCCESS_WITH_INFO */
if (SQL_SUCCEEDED(row_res))
{
res= SQL_SUCCESS_WITH_INFO;
}
/* Else error */
else if (cur_row == 0)
{
/* SQL_ERROR only if all rows fail */
res= SQL_ERROR;
}
else
{
res= SQL_SUCCESS_WITH_INFO;
}
}
/* "Fetching" includes buffers filling. I think errors in that
have to affect row status */
if (rgfRowStatus)
{
rgfRowStatus[cur_row]= sqlreturn2row_status(row_res);
}
/*
No need to update rowStatusPtr_ex, it's the same as rgfRowStatus.
*/
if (upd_status && stmt->ird->array_status_ptr)
{
stmt->ird->array_status_ptr[cur_row]= sqlreturn2row_status(row_res);
}
exitSQLSingleFetch:
stmt->rows_found_in_set= 1;
*pcrow= cur_row;
disconnected= is_connection_lost(stmt->dbc->connection_proxy->error_code())
&& handle_connection_error(stmt);
if ( upd_status && stmt->ird->rows_processed_ptr )
{
*stmt->ird->rows_processed_ptr= cur_row;
}
/* It is possible that both rgfRowStatus and array_status_ptr are set
(and upp_status is TRUE) */
if ( rgfRowStatus )
{
rgfRowStatus[cur_row]= disconnected ? SQL_ROW_ERROR : SQL_ROW_NOROW;
}
/*
No need to update rowStatusPtr_ex, it's the same as rgfRowStatus.
*/
if ( upd_status && stmt->ird->array_status_ptr )
{
stmt->ird->array_status_ptr[cur_row]= disconnected? SQL_ROW_ERROR
: SQL_ROW_NOROW;
}
if (SQL_SUCCEEDED(res) && !if_forward_cache(stmt))
{
/* reset result position */
stmt->end_of_set= row_seek(stmt, save_position);
}
if (SQL_SUCCEEDED(res)
&& stmt->rows_found_in_set < stmt->ard->array_size)
{
if (disconnected)
{
return SQL_ERROR;
}
else if (stmt->rows_found_in_set == 0)
{
stmt->set_error("01S07", "One or more row has error.", 0);
return SQL_SUCCESS_WITH_INFO; //SQL_NO_DATA_FOUND
}
}
}
catch(MYERROR &e)
{
res = e.retcode;
}
return res;
}