aboutsummaryrefslogtreecommitdiff
path: root/src/interfaces/odbc/results.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/interfaces/odbc/results.c')
-rw-r--r--src/interfaces/odbc/results.c259
1 files changed, 181 insertions, 78 deletions
diff --git a/src/interfaces/odbc/results.c b/src/interfaces/odbc/results.c
index 13f223b7205..af7c8b30f8b 100644
--- a/src/interfaces/odbc/results.c
+++ b/src/interfaces/odbc/results.c
@@ -160,8 +160,7 @@ PGAPI_NumResultCols(
*pccol = QR_NumResultCols(result);
/* updatable cursors */
- if (ci->updatable_cursors &&
- stmt->options.scroll_concurrency != SQL_CONCUR_READ_ONLY)
+ if (result->keyset)
*pccol -= 2;
}
@@ -433,7 +432,7 @@ PGAPI_ColAttributes(
*/
#if (ODBCVER >= 0x0300)
- if (0 == icol) /* bookmark column */
+ if (0 == icol && SQL_DESC_COUNT != fDescType) /* bookmark column */
{
switch (fDescType)
{
@@ -473,7 +472,11 @@ PGAPI_ColAttributes(
* Column Count is a special case. The Column number is ignored
* in this case.
*/
+#if (ODBCVER >= 0x0300)
+ if (fDescType == SQL_DESC_COUNT)
+#else
if (fDescType == SQL_COLUMN_COUNT)
+#endif /* ODBCVER */
{
if (pfDesc)
*pfDesc = cols;
@@ -539,6 +542,8 @@ PGAPI_ColAttributes(
}
field_type = QR_get_field_type(SC_get_Curres(stmt), col_idx);
+ if (stmt->parse_status != STMT_PARSE_FATAL && stmt->fi && stmt->fi[col_idx])
+ fi = stmt->fi[col_idx];
}
mylog("colAttr: col %d field_type = %d\n", col_idx, field_type);
@@ -549,6 +554,7 @@ PGAPI_ColAttributes(
value = pgtype_auto_increment(stmt, field_type);
if (value == -1) /* non-numeric becomes FALSE (ODBC Doc) */
value = FALSE;
+inolog("AUTO_INCREMENT=%d\n", value);
break;
@@ -581,9 +587,8 @@ PGAPI_ColAttributes(
#if (ODBCVER >= 0x0300)
case SQL_DESC_NAME:
-#else
- case SQL_COLUMN_NAME:
#endif /* ODBCVER */
+ case SQL_COLUMN_NAME:
p = fi ? (fi->alias[0] ? fi->alias : fi->name) : QR_get_fieldname(SC_get_Curres(stmt), col_idx);
mylog("PGAPI_ColAttr: COLUMN_NAME = '%s'\n", p);
@@ -597,14 +602,15 @@ PGAPI_ColAttributes(
case SQL_COLUMN_MONEY: /* == SQL_DESC_FIXED_PREC_SCALE */
value = pgtype_money(stmt, field_type);
+inolog("COLUMN_MONEY=%d\n", value);
break;
#if (ODBCVER >= 0x0300)
case SQL_DESC_NULLABLE:
-#else
- case SQL_COLUMN_NULLABLE:
#endif /* ODBCVER */
+ case SQL_COLUMN_NULLABLE:
value = fi ? fi->nullable : pgtype_nullable(stmt, field_type);
+inolog("COLUMN_NULLABLE=%d\n", value);
break;
case SQL_COLUMN_OWNER_NAME: /* == SQL_DESC_SCHEMA_NAME */
@@ -623,6 +629,7 @@ PGAPI_ColAttributes(
case SQL_COLUMN_SCALE:
value = pgtype_scale(stmt, field_type, col_idx);
+inolog("COLUMN_SCALE=%d\n", value);
break;
case SQL_COLUMN_SEARCHABLE: /* SQL_DESC_SEARCHABLE */
@@ -637,6 +644,7 @@ PGAPI_ColAttributes(
case SQL_COLUMN_TYPE: /* == SQL_DESC_CONCISE_TYPE */
value = pgtype_to_sqltype(stmt, field_type);
+inolog("COLUMN_TYPE=%d\n", value);
break;
case SQL_COLUMN_TYPE_NAME: /* == SQL_DESC_TYPE_NAME */
@@ -658,7 +666,7 @@ PGAPI_ColAttributes(
* if (field_type == PG_TYPE_OID) pfDesc = SQL_ATTR_READONLY;
* else
*/
- value = SQL_ATTR_WRITE;
+ value = fi ? (fi->updatable ? SQL_ATTR_WRITE : SQL_ATTR_READONLY) : SQL_ATTR_READWRITE_UNKNOWN;
mylog("PGAPI_ColAttr: UPDATEABLE = %d\n", value);
break;
@@ -1292,9 +1300,17 @@ PGAPI_ExtendedFetch(
if (result == SQL_ERROR)
*(rgfRowStatus + i) = SQL_ROW_ERROR;
#ifdef DRIVER_CURSOR_IMPLEMENT
- /* this should be refined */
- else if (result > 10 && result < 20)
- *(rgfRowStatus + i) = result - 10;
+ else if (res->keyset)
+ {
+ UWORD pstatus = res->keyset[stmt->currTuple].status & KEYSET_INFO_PUBLIC;
+ if (pstatus != 0)
+ {
+ rgfRowStatus[i] = pstatus;
+ res->keyset[stmt->currTuple].status &= (~KEYSET_INFO_PUBLIC);
+ }
+ else
+ rgfRowStatus[i] = SQL_ROW_SUCCESS;
+ }
#endif /* DRIVER_CURSOR_IMPLEMENT */
else
*(rgfRowStatus + i) = SQL_ROW_SUCCESS;
@@ -1347,7 +1363,7 @@ PGAPI_MoreResults(
mylog("%s: entering...\n", func);
if (stmt && (res = SC_get_Curres(stmt)))
- SC_get_Curres(stmt) = res->next;
+ SC_set_Curres(stmt, res->next);
if (SC_get_Curres(stmt))
return SQL_SUCCESS;
return SQL_NO_DATA_FOUND;
@@ -1358,28 +1374,61 @@ PGAPI_MoreResults(
/*
* Stuff for updatable cursors.
*/
+static const char *getOidValue(const QResultClass *res, int index)
+{
+ return QR_get_value_backend_row(res, index, QR_NumResultCols(res) - 1);
+}
+static UInt4 getOid(const QResultClass *res, int index)
+{
+ return res->keyset[index].oid;
+}
+static const char *getTidValue(const QResultClass *res, int index)
+{
+ return QR_get_value_backend_row(res, index, QR_NumResultCols(res) - 2);
+}
+static void getTid(const QResultClass *res, int index, UInt4 *blocknum, UInt2 *offset)
+{
+ *blocknum = res->keyset[index].blocknum;
+ *offset = res->keyset[index].offset;
+}
+static void KeySetSet(const QResultClass *res, int index)
+{
+ int num_fields = res->num_fields;
+ TupleField *tuple = res->backend_tuples + num_fields * index;
+ KeySet *keyset = res->keyset + index;
+
+ sscanf(tuple[num_fields - 2].value, "(%u,%hu)",
+ &keyset->blocknum, &keyset->offset);
+ sscanf(tuple[num_fields - 1].value, "%u", &keyset->oid);
+}
+
static QResultClass *
positioned_load(StatementClass *stmt, BOOL latest, int res_cols, UInt4 oid, const char *tidval)
{
- int i;
QResultClass *qres;
- char selstr[4096];
+ char *selstr;
+ UInt4 len;
- sprintf(selstr, "select");
- for (i = 0; i < res_cols; i++)
- sprintf(selstr, "%s \"%s\",", selstr, stmt->fi[i]->name);
- sprintf(selstr, "%s CTID, OID from \"%s\" where", selstr, stmt->ti[0]->name);
+ len = strlen(stmt->load_statement);
if (tidval)
{
+ len += 100;
+ selstr = malloc(len);
if (latest)
- sprintf(selstr, "%s ctid = currtid2('%s', '%s') and",
- selstr, stmt->ti[0]->name, tidval);
- else
- sprintf(selstr, "%s ctid = '%s' and", selstr, tidval);
+ sprintf(selstr, "%s where ctid = currtid2('%s', '%s') and oid = %u", stmt->load_statement, stmt->ti[0]->name, tidval, oid);
+ else
+ sprintf(selstr, "%s where ctid = '%s' and oid = %u", stmt->load_statement, tidval, oid);
}
- sprintf(selstr, "%s oid = %u", selstr, oid),
- mylog("selstr=%s\n", selstr);
- qres = CC_send_query(SC_get_conn(stmt), selstr, NULL, TRUE);
+ else
+ {
+ len += 20;
+ selstr = malloc(len);
+ sprintf(selstr, "%s where oid = %u", stmt->load_statement, oid);
+ }
+
+ mylog("selstr=%s\n", selstr);
+ qres = CC_send_query(SC_get_conn(stmt), selstr, NULL, CLEAR_RESULT_ON_ABORT);
+free(selstr);
return qres;
}
@@ -1388,14 +1437,12 @@ SC_pos_reload(StatementClass *stmt, UWORD irow, UWORD *count)
{
int i,
res_cols;
- UWORD rcnt,
- global_ridx;
- UInt4 oid;
+ UWORD rcnt, global_ridx, offset;
+ UInt4 oid, blocknum;
QResultClass *res,
*qres;
RETCODE ret = SQL_ERROR;
- char *tidval,
- *oidval;
+ char tidval[32];
mylog("positioned load fi=%x ti=%x\n", stmt->fi, stmt->ti);
rcnt = 0;
@@ -1412,15 +1459,18 @@ SC_pos_reload(StatementClass *stmt, UWORD irow, UWORD *count)
}
global_ridx = irow + stmt->rowset_start;
res_cols = QR_NumResultCols(res);
- if (!(oidval = QR_get_value_backend_row(res, global_ridx, res_cols - 1)))
+ if (!(oid = getOid(res, global_ridx)))
+ return SQL_SUCCESS_WITH_INFO;
+ getTid(res, global_ridx, &blocknum, &offset);
+ sprintf(tidval, "(%u, %u)", blocknum, offset);
+ /*if (!(oidval = getOidValue(res, global_ridx)))
return SQL_SUCCESS_WITH_INFO;
sscanf(oidval, "%u", &oid);
- tidval = QR_get_value_backend_row(res, global_ridx, res_cols - 2);
+ tidval = getTidValue(res, global_ridx);*/
res_cols -= 2;
if (qres = positioned_load(stmt, TRUE, res_cols, oid, tidval), qres)
{
- TupleField *tupleo,
- *tuplen;
+ TupleField *tupleo, *tuplen;
rcnt = QR_get_num_tuples(qres);
tupleo = res->backend_tuples + res->num_fields * global_ridx;
@@ -1437,6 +1487,13 @@ SC_pos_reload(StatementClass *stmt, UWORD irow, UWORD *count)
tupleo[i].value = tuplen[i].value;
tuplen[i].value = NULL;
}
+ if (res->keyset)
+ {
+ if (SQL_CURSOR_KEYSET_DRIVEN == stmt->options.cursor_type &&
+ strcmp(tupleo[res->num_fields - 2].value, tidval))
+ res->keyset[global_ridx].status |= SQL_ROW_UPDATED;
+ KeySetSet(res, global_ridx);
+ }
ret = SQL_SUCCESS;
}
else
@@ -1450,6 +1507,7 @@ SC_pos_reload(StatementClass *stmt, UWORD irow, UWORD *count)
free(tupleo[res_cols + 1].value);
tupleo[res_cols + 1].value = NULL;
tupleo[res_cols + 1].len = 0;
+ res->keyset[global_ridx].status |= SQL_ROW_DELETED;
}
}
QR_Destructor(qres);
@@ -1481,8 +1539,7 @@ SC_pos_newload(StatementClass *stmt, UInt4 oid, const char *tidval)
}
if (qres = positioned_load(stmt, TRUE, QR_NumResultCols(res) - 2, oid, tidval), qres)
{
- TupleField *tupleo,
- *tuplen;
+ TupleField *tupleo, *tuplen;
int count = QR_get_num_tuples(qres);
QR_set_position(qres, 0);
@@ -1507,6 +1564,8 @@ SC_pos_newload(StatementClass *stmt, UInt4 oid, const char *tidval)
QR_Destructor(qres);
return SQL_ERROR;
}
+ if (res->haskeyset)
+ res->keyset = (KeySet *) realloc(res->keyset, sizeof(KeySet) * tuple_size);
res->count_allocated = tuple_size;
}
tupleo = res->backend_tuples + res->num_fields * res->fcount;
@@ -1517,6 +1576,7 @@ SC_pos_newload(StatementClass *stmt, UInt4 oid, const char *tidval)
tupleo[i].value = tuplen[i].value;
tuplen[i].value = NULL;
}
+ KeySetSet(res, res->fcount);
res->fcount++;
ret = SQL_SUCCESS;
}
@@ -1533,12 +1593,12 @@ SC_pos_newload(StatementClass *stmt, UInt4 oid, const char *tidval)
}
static RETCODE SQL_API
-irow_update(RETCODE ret, StatementClass *stmt, UWORD irow)
+irow_update(RETCODE ret, StatementClass *stmt, StatementClass *ustmt, UWORD irow)
{
if (ret != SQL_ERROR)
{
int updcnt;
- const char *cmdstr = QR_get_command(SC_get_Curres(stmt));
+ const char *cmdstr = QR_get_command(SC_get_Curres(ustmt));
if (cmdstr &&
sscanf(cmdstr, "UPDATE %d", &updcnt) == 1)
@@ -1580,9 +1640,8 @@ SC_pos_update(StatementClass *stmt,
BindInfoClass *bindings = stmt->bindings;
char updstr[4096];
RETCODE ret;
- char *tidval,
- *oidval;
- UInt4 offset;
+ UInt4 oid, offset, blocknum;
+ UInt2 pgoffset;
Int4 *used;
mylog("POS UPDATE %d+%d fi=%x ti=%x\n", irow, SC_get_Curres(stmt)->base, stmt->fi, stmt->ti);
@@ -1597,12 +1656,14 @@ SC_pos_update(StatementClass *stmt,
}
global_ridx = irow + stmt->rowset_start;
res_cols = QR_NumResultCols(res);
- if (!(oidval = QR_get_value_backend_row(res, global_ridx, res_cols - 1)))
+ /*if (!(oidval = getOidValue(res, global_ridx)))*/
+ if (!(oid = getOid(res, global_ridx)))
{
stmt->errormsg = "The row is already deleted";
return SQL_ERROR;
}
- tidval = QR_get_value_backend_row(res, global_ridx, res_cols - 2);
+ /*tidval = getTidValue(res, global_ridx);*/
+ getTid(res, global_ridx, &blocknum, &pgoffset);
sprintf(updstr, "update \"%s\" set", stmt->ti[0]->name);
num_cols = stmt->nfld;
@@ -1635,8 +1696,10 @@ SC_pos_update(StatementClass *stmt,
int res_cols = QR_NumResultCols(res);
StatementClass *qstmt;
- sprintf(updstr, "%s where ctid = '%s' and oid = %s", updstr,
- tidval, oidval);
+ /*sprintf(updstr, "%s where ctid = '%s' and oid = %s", updstr,
+ tidval, oidval);*/
+ sprintf(updstr, "%s where ctid = '(%u, %u)' and oid = %u", updstr,
+ blocknum, pgoffset, oid);
mylog("updstr=%s\n", updstr);
if (PGAPI_AllocStmt(SC_get_conn(stmt), &hstmt) != SQL_SUCCESS)
return SQL_ERROR;
@@ -1676,11 +1739,13 @@ SC_pos_update(StatementClass *stmt,
stmt->errormsg = "SetPos with data_at_exec not yet supported";
ret = SQL_ERROR;
}
- ret = irow_update(ret, qstmt, irow);
+ ret = irow_update(ret, stmt, qstmt, irow);
PGAPI_FreeStmt(hstmt, SQL_DROP);
}
else
ret = SQL_SUCCESS_WITH_INFO;
+ if (SQL_SUCCESS == ret && res->keyset)
+ res->keyset[global_ridx].status |= (SQL_ROW_UPDATED | DRV_SELF_UPDATED);
#if (ODBCVER >= 0x0300)
if (stmt->options.rowStatusArray)
{
@@ -1689,9 +1754,8 @@ SC_pos_update(StatementClass *stmt,
case SQL_SUCCESS:
stmt->options.rowStatusArray[irow] = SQL_ROW_UPDATED;
break;
- case SQL_SUCCESS_WITH_INFO:
- stmt->options.rowStatusArray[irow] = SQL_ROW_SUCCESS_WITH_INFO;
- break;
+ default:
+ stmt->options.rowStatusArray[irow] = ret;
}
}
#endif /* ODBCVER */
@@ -1703,13 +1767,13 @@ SC_pos_delete(StatementClass *stmt,
UWORD irow)
{
int res_cols;
- UWORD global_ridx;
- QResultClass *res,
- *qres;
+ UWORD global_ridx, offset;
+ QResultClass *res, *qres;
BindInfoClass *bindings = stmt->bindings;
char dltstr[4096];
RETCODE ret;
- char *oidval;
+ /*const char *oidval;*/
+ UInt4 oid, blocknum;
mylog("POS DELETE fi=%x ti=%x\n", stmt->fi, stmt->ti);
if (!(res = SC_get_Curres(stmt)))
@@ -1723,18 +1787,20 @@ SC_pos_delete(StatementClass *stmt,
}
res_cols = QR_NumResultCols(res);
global_ridx = irow + stmt->rowset_start;
- if (!(oidval = QR_get_value_backend_row(res, global_ridx, res_cols - 1)))
+ /* if (!(oidval = getOidValue(res, global_ridx)))*/
+ if (!(oid = getOid(res, global_ridx)))
{
stmt->errormsg = "The row is already deleted";
return SQL_ERROR;
}
- sprintf(dltstr, "delete from \"%s\" where ctid = '%s' and oid = %s",
- stmt->ti[0]->name,
- QR_get_value_backend_row(SC_get_Curres(stmt), global_ridx, res_cols - 2),
- oidval);
+ getTid(res, global_ridx, &blocknum, &offset);
+ /*sprintf(dltstr, "delete from \"%s\" where ctid = '%s' and oid = %s",*/
+ sprintf(dltstr, "delete from \"%s\" where ctid = '(%u, %u)' and oid = %u",
+ stmt->ti[0]->name, blocknum, offset, oid);
mylog("dltstr=%s\n", dltstr);
- qres = CC_send_query(SC_get_conn(stmt), dltstr, NULL, TRUE);
+ qres = CC_send_query(SC_get_conn(stmt), dltstr, NULL, CLEAR_RESULT_ON_ABORT);
+ ret = SQL_SUCCESS;
if (qres && QR_command_successful(qres))
{
int dltcnt;
@@ -1769,6 +1835,8 @@ SC_pos_delete(StatementClass *stmt,
}
if (qres)
QR_Destructor(qres);
+ if (SQL_SUCCESS == ret && res->keyset)
+ res->keyset[global_ridx].status |= (SQL_ROW_DELETED | DRV_SELF_DELETED);
#if (ODBCVER >= 0x0300)
if (stmt->options.rowStatusArray)
{
@@ -1777,9 +1845,8 @@ SC_pos_delete(StatementClass *stmt,
case SQL_SUCCESS:
stmt->options.rowStatusArray[irow] = SQL_ROW_DELETED;
break;
- case SQL_SUCCESS_WITH_INFO:
- stmt->options.rowStatusArray[irow] = SQL_ROW_SUCCESS_WITH_INFO;
- break;
+ default:
+ stmt->options.rowStatusArray[irow] = ret;
}
}
#endif /* ODBCVER */
@@ -1787,13 +1854,13 @@ SC_pos_delete(StatementClass *stmt,
}
static RETCODE SQL_API
-irow_insert(RETCODE ret, StatementClass *stmt, int addpos)
+irow_insert(RETCODE ret, StatementClass *stmt, StatementClass *istmt, int addpos)
{
if (ret != SQL_ERROR)
{
int addcnt;
UInt4 oid;
- const char *cmdstr = QR_get_command(SC_get_Curres(stmt));
+ const char *cmdstr = QR_get_command(SC_get_Curres(istmt));
if (cmdstr &&
sscanf(cmdstr, "INSERT %u %d", &oid, &addcnt) == 2 &&
@@ -1802,12 +1869,14 @@ irow_insert(RETCODE ret, StatementClass *stmt, int addpos)
SC_pos_newload(stmt, oid, NULL);
if (stmt->bookmark.buffer)
{
- char buf[32];
+ char buf[32];
+ UInt4 offset = stmt->options.row_offset_ptr ? *stmt->options.row_offset_ptr : 0;
- sprintf(buf, "%ld", addpos);
+ sprintf(buf, "%ld", addpos + 1);
copy_and_convert_field(stmt, 0, buf,
- SQL_C_ULONG, stmt->bookmark.buffer,
- 0, stmt->bookmark.used);
+ SQL_C_ULONG, stmt->bookmark.buffer + offset,
+ 0, stmt->bookmark.used ? stmt->bookmark.used
+ + (offset >> 2) : NULL);
}
}
else
@@ -1882,6 +1951,7 @@ SC_pos_add(StatementClass *stmt,
}
if (add_cols > 0)
{
+ int brow_save;
sprintf(addstr, "%s) values (", addstr);
for (i = 0; i < add_cols; i++)
@@ -1907,11 +1977,16 @@ SC_pos_add(StatementClass *stmt,
stmt->errormsg = "SetPos with data_at_exec not yet supported";
ret = SQL_ERROR;
}
- ret = irow_insert(ret, qstmt, res->fcount);
+ brow_save = stmt->bind_row;
+ stmt->bind_row = irow;
+ ret = irow_insert(ret, stmt, qstmt, res->fcount);
+ stmt->bind_row = brow_save;
}
else
ret = SQL_SUCCESS_WITH_INFO;
PGAPI_FreeStmt(hstmt, SQL_DROP);
+ if (SQL_SUCCESS == ret && res->keyset)
+ res->keyset[res->fcount - 1].status |= DRV_SELF_ADDED;
#if (ODBCVER >= 0x0300)
if (stmt->options.rowStatusArray)
{
@@ -1920,9 +1995,8 @@ SC_pos_add(StatementClass *stmt,
case SQL_SUCCESS:
stmt->options.rowStatusArray[irow] = SQL_ROW_ADDED;
break;
- case SQL_SUCCESS_WITH_INFO:
- stmt->options.rowStatusArray[irow] = SQL_ROW_SUCCESS_WITH_INFO;
- break;
+ default:
+ stmt->options.rowStatusArray[irow] = ret;
}
}
#endif /* ODBCVER */
@@ -1947,6 +2021,7 @@ PGAPI_SetPos(
UWORD fLock)
{
static char *func = "PGAPI_SetPos";
+ RETCODE ret;
StatementClass *stmt = (StatementClass *) hstmt;
QResultClass *res;
int num_cols,
@@ -1960,7 +2035,7 @@ PGAPI_SetPos(
}
#ifdef DRIVER_CURSOR_IMPLEMENT
- mylog("SetPos fOption=%d irow=%d lock=%d currt=%d\n", fOption, irow, fLock, stmt->currTuple);
+ mylog("%s fOption=%d irow=%d lock=%d currt=%d\n", func, fOption, irow, fLock, stmt->currTuple);
if (stmt->options.scroll_concurrency != SQL_CONCUR_READ_ONLY)
;
else
@@ -1982,12 +2057,40 @@ PGAPI_SetPos(
}
num_cols = QR_NumResultCols(res);
- if (irow == 0)
+ if (irow == 0) /* bulk operation */
{
- stmt->errornumber = STMT_ROW_OUT_OF_RANGE;
- stmt->errormsg = "Driver does not support Bulk operations.";
- SC_log_error(func, "", stmt);
- return SQL_ERROR;
+ int processed;
+
+ if (SQL_POSITION == fOption)
+ {
+ stmt->errornumber = STMT_ROW_OUT_OF_RANGE;
+ stmt->errormsg = "Bulk Fresh operations not allowed.";
+ SC_log_error(func, "", stmt);
+ return SQL_ERROR;
+ }
+ ret = SQL_SUCCESS;
+ for (i = 0, processed = 0; i < stmt->options.rowset_size; i++)
+ {
+#if (ODBCVER >= 0x0300)
+ if (!stmt->options.row_operation_ptr || stmt->options.row_operation_ptr[i] == SQL_ROW_PROCEED)
+ {
+#endif /* ODBCVER */
+ if (ret = PGAPI_SetPos(hstmt, (UWORD) (i + 1), fOption, fLock), SQL_ERROR == ret)
+ break;
+ processed++;
+#if (ODBCVER >= 0x0300)
+ }
+#endif /* ODBCVER */
+ }
+ if (processed > 0 && SQL_ERROR == ret)
+ {
+ processed++;
+ ret = SQL_SUCCESS_WITH_INFO;
+ stmt->errornumber = STMT_ERROR_IN_ROW;
+ }
+ if (stmt->options.rowsFetched)
+ *stmt->options.rowsFetched = processed;
+ return ret;
}
if (irow > stmt->last_fetch_count)