summaryrefslogtreecommitdiff
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.c657
1 files changed, 397 insertions, 260 deletions
diff --git a/src/interfaces/odbc/results.c b/src/interfaces/odbc/results.c
index af7c8b30f8b..6d20bbaad59 100644
--- a/src/interfaces/odbc/results.c
+++ b/src/interfaces/odbc/results.c
@@ -138,7 +138,7 @@ PGAPI_NumResultCols(
if (stmt->parse_status != STMT_PARSE_FATAL)
{
parse_ok = TRUE;
- *pccol = stmt->nfld;
+ *pccol = SC_get_IRD(stmt)->nfields;
mylog("PARSE: PGAPI_NumResultCols: *pccol = %d\n", *pccol);
}
}
@@ -189,11 +189,12 @@ PGAPI_DescribeCol(
/* gets all the information about a specific column */
StatementClass *stmt = (StatementClass *) hstmt;
ConnectionClass *conn;
+ IRDFields *irdflds;
QResultClass *res;
char *col_name = NULL;
Int4 fieldtype = 0;
- int precision = 0,
- scale = 0;
+ int column_size = 0,
+ decimal_digits = 0;
ConnInfo *ci;
char parse_ok;
char buf[255];
@@ -213,6 +214,7 @@ PGAPI_DescribeCol(
SC_clear_error(stmt);
+ irdflds = SC_get_IRD(stmt);
#if (ODBCVER >= 0x0300)
if (0 == icol) /* bookmark column */
{
@@ -249,11 +251,11 @@ PGAPI_DescribeCol(
parse_statement(stmt);
}
- mylog("PARSE: DescribeCol: icol=%d, stmt=%u, stmt->nfld=%d, stmt->fi=%u\n", icol, stmt, stmt->nfld, stmt->fi);
+ mylog("PARSE: DescribeCol: icol=%d, stmt=%u, stmt->nfld=%d, stmt->fi=%u\n", icol, stmt, irdflds->nfields, irdflds->fi);
- if (stmt->parse_status != STMT_PARSE_FATAL && stmt->fi && stmt->fi[icol])
+ if (stmt->parse_status != STMT_PARSE_FATAL && irdflds->fi && irdflds->fi[icol])
{
- if (icol >= stmt->nfld)
+ if (icol >= irdflds->nfields)
{
stmt->errornumber = STMT_INVALID_COLUMN_NUMBER_ERROR;
stmt->errormsg = "Invalid column number in DescribeCol.";
@@ -262,15 +264,15 @@ PGAPI_DescribeCol(
}
mylog("DescribeCol: getting info for icol=%d\n", icol);
- fieldtype = stmt->fi[icol]->type;
- if (stmt->fi[icol]->alias[0])
- col_name = stmt->fi[icol]->alias;
+ fieldtype = irdflds->fi[icol]->type;
+ if (irdflds->fi[icol]->alias[0])
+ col_name = irdflds->fi[icol]->alias;
else
- col_name = stmt->fi[icol]->name;
- precision = stmt->fi[icol]->precision;
- scale = stmt->fi[icol]->scale;
+ col_name = irdflds->fi[icol]->name;
+ column_size = irdflds->fi[icol]->column_size;
+ decimal_digits = irdflds->fi[icol]->decimal_digits;
- mylog("PARSE: fieldtype=%d, col_name='%s', precision=%d\n", fieldtype, col_name, precision);
+ mylog("PARSE: fieldtype=%d, col_name='%s', column_size=%d\n", fieldtype, col_name, column_size);
if (fieldtype > 0)
parse_ok = TRUE;
}
@@ -310,13 +312,13 @@ PGAPI_DescribeCol(
fieldtype = QR_get_field_type(res, icol);
/* atoi(ci->unknown_sizes) */
- precision = pgtype_precision(stmt, fieldtype, icol, ci->drivers.unknown_sizes);
- scale = pgtype_scale(stmt, fieldtype, icol);
+ column_size = pgtype_column_size(stmt, fieldtype, icol, ci->drivers.unknown_sizes);
+ decimal_digits = pgtype_decimal_digits(stmt, fieldtype, icol);
}
mylog("describeCol: col %d fieldname = '%s'\n", icol, col_name);
mylog("describeCol: col %d fieldtype = %d\n", icol, fieldtype);
- mylog("describeCol: col %d precision = %d\n", icol, precision);
+ mylog("describeCol: col %d column_size = %d\n", icol, column_size);
result = SQL_SUCCESS;
@@ -341,37 +343,37 @@ PGAPI_DescribeCol(
}
/*
- * SQL TYPE
+ * CONCISE(SQL) TYPE
*/
if (pfSqlType)
{
- *pfSqlType = pgtype_to_sqltype(stmt, fieldtype);
+ *pfSqlType = pgtype_to_concise_type(stmt, fieldtype);
mylog("describeCol: col %d *pfSqlType = %d\n", icol, *pfSqlType);
}
/*
- * PRECISION
+ * COLUMN SIZE(PRECISION in 2.x)
*/
if (pcbColDef)
{
- if (precision < 0)
- precision = 0; /* "I dont know" */
+ if (column_size < 0)
+ column_size = 0; /* "I dont know" */
- *pcbColDef = precision;
+ *pcbColDef = column_size;
mylog("describeCol: col %d *pcbColDef = %d\n", icol, *pcbColDef);
}
/*
- * SCALE
+ * DECIMAL DIGITS(SCALE in 2.x)
*/
if (pibScale)
{
- if (scale < 0)
- scale = 0;
+ if (decimal_digits < 0)
+ decimal_digits = 0;
- *pibScale = scale;
+ *pibScale = decimal_digits;
mylog("describeCol: col %d *pibScale = %d\n", icol, *pibScale);
}
@@ -380,7 +382,7 @@ PGAPI_DescribeCol(
*/
if (pfNullable)
{
- *pfNullable = (parse_ok) ? stmt->fi[icol]->nullable : pgtype_nullable(stmt, fieldtype);
+ *pfNullable = (parse_ok) ? irdflds->fi[icol]->nullable : pgtype_nullable(stmt, fieldtype);
mylog("describeCol: col %d *pfNullable = %d\n", icol, *pfNullable);
}
@@ -402,6 +404,7 @@ PGAPI_ColAttributes(
{
static char *func = "PGAPI_ColAttributes";
StatementClass *stmt = (StatementClass *) hstmt;
+ IRDFields *irdflds;
Int4 col_idx, field_type = 0;
ConnectionClass *conn;
ConnInfo *ci;
@@ -414,7 +417,8 @@ PGAPI_ColAttributes(
value = 0;
const FIELD_INFO *fi = NULL;
- mylog("%s: entering..col=%d %d.\n", func, icol, fDescType);
+ mylog("%s: entering..col=%d %d len=%d.\n", func, icol, fDescType,
+ cbDescMax);
if (!stmt)
{
@@ -422,6 +426,9 @@ PGAPI_ColAttributes(
return SQL_INVALID_HANDLE;
}
+ if (pcbDesc)
+ *pcbDesc = 0;
+ irdflds = SC_get_IRD(stmt);
conn = SC_get_conn(stmt);
ci = &(conn->connInfo);
@@ -466,7 +473,7 @@ PGAPI_ColAttributes(
parse_statement(stmt);
}
- cols = stmt->nfld;
+ cols = irdflds->nfields;
/*
* Column Count is a special case. The Column number is ignored
@@ -484,7 +491,7 @@ PGAPI_ColAttributes(
return SQL_SUCCESS;
}
- if (stmt->parse_status != STMT_PARSE_FATAL && stmt->fi && stmt->fi[col_idx])
+ if (stmt->parse_status != STMT_PARSE_FATAL && irdflds->fi && irdflds->fi[col_idx])
{
if (col_idx >= cols)
{
@@ -493,14 +500,14 @@ PGAPI_ColAttributes(
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
- field_type = stmt->fi[col_idx]->type;
+ field_type = irdflds->fi[col_idx]->type;
if (field_type > 0)
parse_ok = TRUE;
}
}
if (parse_ok)
- fi = stmt->fi[col_idx];
+ fi = irdflds->fi[col_idx];
else
{
SC_pre_execute(stmt);
@@ -542,8 +549,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];
+ if (stmt->parse_status != STMT_PARSE_FATAL && irdflds->fi && irdflds->fi[col_idx])
+ fi = irdflds->fi[col_idx];
}
mylog("colAttr: col %d field_type = %d\n", col_idx, field_type);
@@ -587,15 +594,18 @@ inolog("AUTO_INCREMENT=%d\n", value);
#if (ODBCVER >= 0x0300)
case SQL_DESC_NAME:
-#endif /* ODBCVER */
+#else
case SQL_COLUMN_NAME:
+#endif /* ODBCVER */
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);
break;
case SQL_COLUMN_LENGTH:
- value = fi ? fi->length : pgtype_length(stmt, field_type, col_idx, unknown_sizes);
+ value = (fi && fi->length > 0) ? fi->length : pgtype_buffer_length(stmt, field_type, col_idx, unknown_sizes);
+ if (value < 0)
+ value = 0;
mylog("PGAPI_ColAttributes: col %d, length = %d\n", col_idx, value);
break;
@@ -607,8 +617,9 @@ inolog("COLUMN_MONEY=%d\n", value);
#if (ODBCVER >= 0x0300)
case SQL_DESC_NULLABLE:
-#endif /* ODBCVER */
+#else
case SQL_COLUMN_NULLABLE:
+#endif /* ODBCVER */
value = fi ? fi->nullable : pgtype_nullable(stmt, field_type);
inolog("COLUMN_NULLABLE=%d\n", value);
break;
@@ -617,19 +628,23 @@ inolog("COLUMN_NULLABLE=%d\n", value);
p = "";
break;
- case SQL_COLUMN_PRECISION:
- value = fi ? fi->precision : pgtype_precision(stmt, field_type, col_idx, unknown_sizes);
+ case SQL_COLUMN_PRECISION: /* in 2.x */
+ value = (fi && fi->column_size > 0) ? fi->column_size : pgtype_column_size(stmt, field_type, col_idx, unknown_sizes);
+ if (value < 0)
+ value = 0;
- mylog("PGAPI_ColAttributes: col %d, precision = %d\n", col_idx, value);
+ mylog("PGAPI_ColAttributes: col %d, column_size = %d\n", col_idx, value);
break;
case SQL_COLUMN_QUALIFIER_NAME: /* == SQL_DESC_CATALOG_NAME */
p = "";
break;
- case SQL_COLUMN_SCALE:
- value = pgtype_scale(stmt, field_type, col_idx);
+ case SQL_COLUMN_SCALE: /* in 2.x */
+ value = pgtype_decimal_digits(stmt, field_type, col_idx);
inolog("COLUMN_SCALE=%d\n", value);
+ if (value < 0)
+ value = 0;
break;
case SQL_COLUMN_SEARCHABLE: /* SQL_DESC_SEARCHABLE */
@@ -643,7 +658,7 @@ inolog("COLUMN_SCALE=%d\n", value);
break;
case SQL_COLUMN_TYPE: /* == SQL_DESC_CONCISE_TYPE */
- value = pgtype_to_sqltype(stmt, field_type);
+ value = pgtype_to_concise_type(stmt, field_type);
inolog("COLUMN_TYPE=%d\n", value);
break;
@@ -678,46 +693,53 @@ inolog("COLUMN_TYPE=%d\n", value);
mylog("PGAPI_ColAttr: BASE_COLUMN_NAME = '%s'\n", p);
break;
case SQL_DESC_BASE_TABLE_NAME: /* the same as TABLE_NAME ok ? */
- p = fi && (fi->ti) ? fi->ti->name : "";
+ p = (fi && (fi->ti)) ? fi->ti->name : "";
mylog("PGAPI_ColAttr: BASE_TABLE_NAME = '%s'\n", p);
break;
case SQL_DESC_LENGTH: /* different from SQL_COLUMN_LENGTH */
- value = fi ? fi->length : pgtype_length(stmt, field_type, col_idx, unknown_sizes);
+ value = (fi && fi->length > 0) ? fi->length : pgtype_desclength(stmt, field_type, col_idx, unknown_sizes);
+ if (value < 0)
+ value = 0;
mylog("PGAPI_ColAttributes: col %d, length = %d\n", col_idx, value);
break;
case SQL_DESC_OCTET_LENGTH:
- value = fi ? fi->length : pgtype_length(stmt, field_type, col_idx, unknown_sizes);
-
+ value = (fi && fi->length > 0) ? fi->length : pgtype_transfer_octet_length(stmt, field_type, col_idx, unknown_sizes);
+ if (value < 0)
+ value = 0;
mylog("PGAPI_ColAttributes: col %d, octet_length = %d\n", col_idx, value);
break;
case SQL_DESC_PRECISION: /* different from SQL_COLUMN_PRECISION */
- value = fi ? fi->precision : pgtype_precision(stmt, field_type, col_idx, unknown_sizes);
+ value = (fi && fi->column_size > 0) ? fi->column_size : pgtype_precision(stmt, field_type, col_idx, unknown_sizes);
+ if (value < 0)
+ value = 0;
mylog("PGAPI_ColAttributes: col %d, desc_precision = %d\n", col_idx, value);
break;
case SQL_DESC_SCALE: /* different from SQL_COLUMN_SCALE */
value = pgtype_scale(stmt, field_type, col_idx);
+ if (value < 0)
+ value = 0;
break;
case SQL_DESC_LOCAL_TYPE_NAME:
p = pgtype_to_name(stmt, field_type);
break;
case SQL_DESC_TYPE:
- value = pgtype_to_sqltype(stmt, field_type);
- switch (value)
- {
- case SQL_TYPE_DATE:
- case SQL_TYPE_TIME:
- case SQL_TYPE_TIMESTAMP:
- value = SQL_DATETIME;
- break;
- }
+ value = pgtype_to_sqldesctype(stmt, field_type);
+ break;
+ case SQL_DESC_NUM_PREC_RADIX:
+ value = pgtype_radix(stmt, field_type);
break;
case SQL_DESC_LITERAL_PREFIX:
+ p = pgtype_literal_prefix(stmt, field_type);
+ break;
case SQL_DESC_LITERAL_SUFFIX:
- case SQL_DESC_NUM_PREC_RADIX:
+ p = pgtype_literal_suffix(stmt, field_type);
+ break;
case SQL_DESC_UNNAMED:
+ value = (fi && !fi->name[0] && !fi->alias[0]) ? SQL_UNNAMED : SQL_NAMED;
+ break;
#endif /* ODBCVER */
default:
stmt->errornumber = STMT_INVALID_OPTION_IDENTIFIER;
@@ -967,6 +989,7 @@ PGAPI_Fetch(
{
static char *func = "PGAPI_Fetch";
StatementClass *stmt = (StatementClass *) hstmt;
+ ARDFields *opts;
QResultClass *res;
mylog("PGAPI_Fetch: stmt = %u, stmt->result= %u\n", stmt, SC_get_Curres(stmt));
@@ -988,7 +1011,8 @@ PGAPI_Fetch(
}
/* Not allowed to bind a bookmark column when using SQLFetch. */
- if (stmt->bookmark.buffer)
+ opts = SC_get_ARD(stmt);
+ if (opts->bookmark->buffer)
{
stmt->errornumber = STMT_COLNUM_ERROR;
stmt->errormsg = "Not allowed to bind a bookmark column when using PGAPI_Fetch";
@@ -1012,7 +1036,7 @@ PGAPI_Fetch(
return SQL_ERROR;
}
- if (stmt->bindings == NULL)
+ if (opts->bindings == NULL)
{
/* just to avoid a crash if the user insists on calling this */
/* function even if SQL_ExecDirect has reported an Error */
@@ -1040,6 +1064,7 @@ PGAPI_ExtendedFetch(
{
static char *func = "PGAPI_ExtendedFetch";
StatementClass *stmt = (StatementClass *) hstmt;
+ ARDFields *opts;
QResultClass *res;
int num_tuples,
i,
@@ -1078,11 +1103,12 @@ PGAPI_ExtendedFetch(
return SQL_ERROR;
}
+ opts = SC_get_ARD(stmt);
/*
* If a bookmark colunmn is bound but bookmark usage is off, then
* error
*/
- if (stmt->bookmark.buffer && stmt->options.use_bookmarks == SQL_UB_OFF)
+ if (opts->bookmark->buffer && stmt->options.use_bookmarks == SQL_UB_OFF)
{
stmt->errornumber = STMT_COLNUM_ERROR;
stmt->errormsg = "Attempt to retrieve bookmark with bookmark usage disabled";
@@ -1106,7 +1132,7 @@ PGAPI_ExtendedFetch(
return SQL_ERROR;
}
- if (stmt->bindings == NULL)
+ if (opts->bindings == NULL)
{
/* just to avoid a crash if the user insists on calling this */
/* function even if SQL_ExecDirect has reported an Error */
@@ -1118,7 +1144,7 @@ PGAPI_ExtendedFetch(
/* Initialize to no rows fetched */
if (rgfRowStatus)
- for (i = 0; i < stmt->options.rowset_size; i++)
+ for (i = 0; i < opts->rowset_size; i++)
*(rgfRowStatus + i) = SQL_ROW_NOROW;
if (pcrow)
@@ -1144,7 +1170,7 @@ PGAPI_ExtendedFetch(
stmt->rowset_start = 0;
else
- stmt->rowset_start += (save_rowset_size > 0 ? save_rowset_size : stmt->options.rowset_size);
+ stmt->rowset_start += (save_rowset_size > 0 ? save_rowset_size : opts->rowset_size);
mylog("SQL_FETCH_NEXT: num_tuples=%d, currtuple=%d\n", num_tuples, stmt->currTuple);
break;
@@ -1159,22 +1185,22 @@ PGAPI_ExtendedFetch(
*/
if (stmt->rowset_start >= num_tuples)
{
- if (stmt->options.rowset_size > num_tuples)
+ if (opts->rowset_size > num_tuples)
{
stmt->errornumber = STMT_POS_BEFORE_RECORDSET;
stmt->errormsg = "fetch prior from eof and before the beggining";
}
- stmt->rowset_start = num_tuples <= 0 ? 0 : (num_tuples - stmt->options.rowset_size);
+ stmt->rowset_start = num_tuples <= 0 ? 0 : (num_tuples - opts->rowset_size);
}
else
{
- if (stmt->rowset_start < stmt->options.rowset_size)
+ if (stmt->rowset_start < opts->rowset_size)
{
stmt->errormsg = "fetch prior and before the beggining";
stmt->errornumber = STMT_POS_BEFORE_RECORDSET;
}
- stmt->rowset_start -= stmt->options.rowset_size;
+ stmt->rowset_start -= opts->rowset_size;
}
break;
@@ -1187,7 +1213,7 @@ PGAPI_ExtendedFetch(
case SQL_FETCH_LAST:
mylog("SQL_FETCH_LAST: num_tuples=%d, currtuple=%d\n", num_tuples, stmt->currTuple);
- stmt->rowset_start = num_tuples <= 0 ? 0 : (num_tuples - stmt->options.rowset_size);
+ stmt->rowset_start = num_tuples <= 0 ? 0 : (num_tuples - opts->rowset_size);
break;
case SQL_FETCH_ABSOLUTE:
@@ -1255,7 +1281,7 @@ PGAPI_ExtendedFetch(
/* If *new* rowset is prior to result_set, return no data found */
if (stmt->rowset_start < 0)
{
- if (stmt->rowset_start + stmt->options.rowset_size <= 0)
+ if (stmt->rowset_start + opts->rowset_size <= 0)
{
stmt->rowset_start = -1;
return SQL_NO_DATA_FOUND;
@@ -1271,7 +1297,7 @@ PGAPI_ExtendedFetch(
stmt->currTuple = stmt->rowset_start - 1;
/* increment the base row in the tuple cache */
- QR_set_rowset_size(res, stmt->options.rowset_size);
+ QR_set_rowset_size(res, opts->rowset_size);
/* QR_inc_base(res, stmt->last_fetch_count); */
/* Is inc_base right ? */
res->base = stmt->rowset_start;
@@ -1281,7 +1307,7 @@ PGAPI_ExtendedFetch(
mylog("PGAPI_ExtendedFetch: new currTuple = %d\n", stmt->currTuple);
truncated = error = FALSE;
- for (i = 0; i < stmt->options.rowset_size; i++)
+ for (i = 0; i < opts->rowset_size; i++)
{
stmt->bind_row = i; /* set the binding location */
result = SC_fetch(stmt);
@@ -1302,11 +1328,14 @@ PGAPI_ExtendedFetch(
#ifdef DRIVER_CURSOR_IMPLEMENT
else if (res->keyset)
{
- UWORD pstatus = res->keyset[stmt->currTuple].status & KEYSET_INFO_PUBLIC;
+ DWORD currp = stmt->rowset_start + i;
+ UWORD pstatus = res->keyset[currp].status & KEYSET_INFO_PUBLIC;
if (pstatus != 0)
{
rgfRowStatus[i] = pstatus;
- res->keyset[stmt->currTuple].status &= (~KEYSET_INFO_PUBLIC);
+ /* refresh the status */
+ if (SQL_ROW_DELETED != pstatus)
+ res->keyset[currp].status &= (~KEYSET_INFO_PUBLIC);
}
else
rgfRowStatus[i] = SQL_ROW_SUCCESS;
@@ -1314,6 +1343,8 @@ PGAPI_ExtendedFetch(
#endif /* DRIVER_CURSOR_IMPLEMENT */
else
*(rgfRowStatus + i) = SQL_ROW_SUCCESS;
+if (rgfRowStatus[i] != SQL_ROW_SUCCESS)
+inolog("rgfRowStatus[%d]=%d\n", i, rgfRowStatus[i]);
}
}
@@ -1374,39 +1405,35 @@ PGAPI_MoreResults(
/*
* Stuff for updatable cursors.
*/
-static const char *getOidValue(const QResultClass *res, int index)
+static Int2 getNumResultCols(const QResultClass *res)
{
- return QR_get_value_backend_row(res, index, QR_NumResultCols(res) - 1);
+ Int2 res_cols = QR_NumResultCols(res);
+ return res->keyset ? res_cols - 2 : res_cols;
}
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)
+static void KeySetSet(const TupleField *tuple, int num_fields, KeySet *keyset)
{
- 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);
}
+#define LATEST_TUPLE_LOAD 1L
+#define USE_INSERTED_TID (1L << 1)
static QResultClass *
-positioned_load(StatementClass *stmt, BOOL latest, int res_cols, UInt4 oid, const char *tidval)
+positioned_load(StatementClass *stmt, UInt4 flag, UInt4 oid, const char *tidval)
{
QResultClass *qres;
char *selstr;
+ BOOL latest = ((flag & LATEST_TUPLE_LOAD) != 0);
UInt4 len;
len = strlen(stmt->load_statement);
@@ -1419,6 +1446,12 @@ positioned_load(StatementClass *stmt, BOOL latest, int res_cols, UInt4 oid, cons
else
sprintf(selstr, "%s where ctid = '%s' and oid = %u", stmt->load_statement, tidval, oid);
}
+ else if ((flag & USE_INSERTED_TID) != 0)
+ {
+ len += 50;
+ selstr = malloc(len);
+ sprintf(selstr, "%s where ctid = currtid(0, '(,)') and oid = %u", stmt->load_statement, oid);
+ }
else
{
len += 20;
@@ -1428,23 +1461,24 @@ positioned_load(StatementClass *stmt, BOOL latest, int res_cols, UInt4 oid, cons
mylog("selstr=%s\n", selstr);
qres = CC_send_query(SC_get_conn(stmt), selstr, NULL, CLEAR_RESULT_ON_ABORT);
-free(selstr);
+ free(selstr);
return qres;
}
RETCODE SQL_API
-SC_pos_reload(StatementClass *stmt, UWORD irow, UWORD *count)
+SC_pos_reload(StatementClass *stmt, UWORD irow, UDWORD global_ridx, UWORD *count)
{
int i,
res_cols;
- UWORD rcnt, global_ridx, offset;
+ UWORD rcnt, offset;
UInt4 oid, blocknum;
QResultClass *res,
*qres;
+ IRDFields *irdflds = SC_get_IRD(stmt);
RETCODE ret = SQL_ERROR;
char tidval[32];
- mylog("positioned load fi=%x ti=%x\n", stmt->fi, stmt->ti);
+ mylog("positioned load fi=%x ti=%x\n", irdflds->fi, stmt->ti);
rcnt = 0;
if (count)
*count = 0;
@@ -1452,23 +1486,18 @@ SC_pos_reload(StatementClass *stmt, UWORD irow, UWORD *count)
return SQL_ERROR;
if (!stmt->ti)
parse_statement(stmt); /* not preferable */
- if (!stmt->ti || stmt->ntab != 1)
+ if (!stmt->updatable)
{
stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;
return SQL_ERROR;
}
global_ridx = irow + stmt->rowset_start;
- res_cols = QR_NumResultCols(res);
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 = getTidValue(res, global_ridx);*/
- res_cols -= 2;
- if (qres = positioned_load(stmt, TRUE, res_cols, oid, tidval), qres)
+ res_cols = getNumResultCols(res);
+ if (qres = positioned_load(stmt, LATEST_TUPLE_LOAD, oid, tidval), qres)
{
TupleField *tupleo, *tuplen;
@@ -1476,9 +1505,18 @@ SC_pos_reload(StatementClass *stmt, UWORD irow, UWORD *count)
tupleo = res->backend_tuples + res->num_fields * global_ridx;
if (rcnt == 1)
{
+ int effective_fields = res_cols;
+
QR_set_position(qres, 0);
tuplen = qres->tupleField;
- for (i = 0; i < res->num_fields; i++)
+ if (res->keyset)
+ {
+ if (SQL_CURSOR_KEYSET_DRIVEN == stmt->options.cursor_type &&
+ strcmp(tuplen[qres->num_fields - 2].value, tidval))
+ res->keyset[global_ridx].status |= SQL_ROW_UPDATED;
+ KeySetSet(tuplen, qres->num_fields, res->keyset + global_ridx);
+ }
+ for (i = 0; i < effective_fields; i++)
{
if (tupleo[i].value)
free(tupleo[i].value);
@@ -1487,13 +1525,6 @@ 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
@@ -1503,10 +1534,7 @@ SC_pos_reload(StatementClass *stmt, UWORD irow, UWORD *count)
ret = SQL_SUCCESS_WITH_INFO;
if (stmt->options.cursor_type == SQL_CURSOR_KEYSET_DRIVEN)
{
- if (tupleo[res_cols + 1].value)
- free(tupleo[res_cols + 1].value);
- tupleo[res_cols + 1].value = NULL;
- tupleo[res_cols + 1].len = 0;
+ res->keyset[global_ridx].oid = 0;
res->keyset[global_ridx].status |= SQL_ROW_DELETED;
}
}
@@ -1520,24 +1548,23 @@ SC_pos_reload(StatementClass *stmt, UWORD irow, UWORD *count)
}
RETCODE SQL_API
-SC_pos_newload(StatementClass *stmt, UInt4 oid, const char *tidval)
+SC_pos_newload(StatementClass *stmt, UInt4 oid, BOOL tidRef)
{
int i;
- QResultClass *res,
- *qres;
+ QResultClass *res, *qres;
RETCODE ret = SQL_ERROR;
- mylog("positioned new fi=%x ti=%x\n", stmt->fi, stmt->ti);
+ mylog("positioned new ti=%x\n", stmt->ti);
if (!(res = SC_get_Curres(stmt)))
return SQL_ERROR;
if (!stmt->ti)
parse_statement(stmt); /* not preferable */
- if (!stmt->ti || stmt->ntab != 1)
+ if (!stmt->updatable)
{
stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;
return SQL_ERROR;
}
- if (qres = positioned_load(stmt, TRUE, QR_NumResultCols(res) - 2, oid, tidval), qres)
+ if (qres = positioned_load(stmt, tidRef ? USE_INSERTED_TID : 0, oid, NULL), qres)
{
TupleField *tupleo, *tuplen;
int count = QR_get_num_tuples(qres);
@@ -1545,6 +1572,8 @@ SC_pos_newload(StatementClass *stmt, UInt4 oid, const char *tidval)
QR_set_position(qres, 0);
if (count == 1)
{
+ int effective_fields = res->num_fields;
+
tuplen = qres->tupleField;
if (res->fcount >= res->count_allocated)
{
@@ -1569,22 +1598,29 @@ SC_pos_newload(StatementClass *stmt, UInt4 oid, const char *tidval)
res->count_allocated = tuple_size;
}
tupleo = res->backend_tuples + res->num_fields * res->fcount;
- for (i = 0; i < res->num_fields; i++)
+ KeySetSet(tuplen, qres->num_fields, res->keyset + res->fcount);
+ for (i = 0; i < effective_fields; i++)
{
tupleo[i].len = tuplen[i].len;
tuplen[i].len = 0;
tupleo[i].value = tuplen[i].value;
tuplen[i].value = NULL;
}
- KeySetSet(res, res->fcount);
+ for (; i < res->num_fields; i++)
+ {
+ tupleo[i].len = 0;
+ tupleo[i].value = NULL;
+ }
res->fcount++;
ret = SQL_SUCCESS;
}
+ else if (0 == count)
+ ret = SQL_NO_DATA_FOUND;
else
{
stmt->errornumber = STMT_ROW_VERSION_CHANGED;
- stmt->errormsg = "the content was changed before updation";
- ret = SQL_SUCCESS_WITH_INFO;
+ stmt->errormsg = "the driver cound't identify inserted rows";
+ ret = SQL_ERROR;
}
QR_Destructor(qres);
/* stmt->currTuple = stmt->rowset_start + irow; */
@@ -1593,7 +1629,7 @@ SC_pos_newload(StatementClass *stmt, UInt4 oid, const char *tidval)
}
static RETCODE SQL_API
-irow_update(RETCODE ret, StatementClass *stmt, StatementClass *ustmt, UWORD irow)
+irow_update(RETCODE ret, StatementClass *stmt, StatementClass *ustmt, UWORD irow, UDWORD global_ridx)
{
if (ret != SQL_ERROR)
{
@@ -1604,18 +1640,17 @@ irow_update(RETCODE ret, StatementClass *stmt, StatementClass *ustmt, UWORD irow
sscanf(cmdstr, "UPDATE %d", &updcnt) == 1)
{
if (updcnt == 1)
- SC_pos_reload(stmt, irow, (UWORD *) 0);
+ SC_pos_reload(stmt, irow, global_ridx, (UWORD *) 0);
else if (updcnt == 0)
{
stmt->errornumber = STMT_ROW_VERSION_CHANGED;
stmt->errormsg = "the content was changed before updation";
ret = SQL_ERROR;
if (stmt->options.cursor_type == SQL_CURSOR_KEYSET_DRIVEN)
- SC_pos_reload(stmt, irow, (UWORD *) 0);
+ SC_pos_reload(stmt, irow, global_ridx, (UWORD *) 0);
}
else
ret = SQL_ERROR;
- stmt->currTuple = stmt->rowset_start + irow;
}
else
ret = SQL_ERROR;
@@ -1627,62 +1662,60 @@ irow_update(RETCODE ret, StatementClass *stmt, StatementClass *ustmt, UWORD irow
}
return ret;
}
-RETCODE SQL_API
+RETCODE
SC_pos_update(StatementClass *stmt,
- UWORD irow)
+ UWORD irow, UDWORD global_ridx)
{
int i,
- res_cols,
num_cols,
upd_cols;
- UWORD global_ridx;
QResultClass *res;
- BindInfoClass *bindings = stmt->bindings;
+ ARDFields *opts = SC_get_ARD(stmt);
+ IRDFields *irdflds = SC_get_IRD(stmt);
+ BindInfoClass *bindings = opts->bindings;
+ FIELD_INFO **fi = SC_get_IRD(stmt)->fi;
char updstr[4096];
RETCODE ret;
UInt4 oid, offset, blocknum;
UInt2 pgoffset;
- Int4 *used;
+ Int4 *used, bind_size = opts->bind_size;
- mylog("POS UPDATE %d+%d fi=%x ti=%x\n", irow, SC_get_Curres(stmt)->base, stmt->fi, stmt->ti);
+ mylog("POS UPDATE %d+%d fi=%x ti=%x\n", irow, SC_get_Curres(stmt)->base,fi, stmt->ti);
if (!(res = SC_get_Curres(stmt)))
return SQL_ERROR;
if (!stmt->ti)
parse_statement(stmt); /* not preferable */
- if (!stmt->ti || stmt->ntab != 1)
+ if (!stmt->updatable)
{
stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;
return SQL_ERROR;
}
- global_ridx = irow + stmt->rowset_start;
- res_cols = QR_NumResultCols(res);
- /*if (!(oidval = getOidValue(res, global_ridx)))*/
if (!(oid = getOid(res, global_ridx)))
{
stmt->errormsg = "The row is already deleted";
return SQL_ERROR;
}
- /*tidval = getTidValue(res, global_ridx);*/
getTid(res, global_ridx, &blocknum, &pgoffset);
sprintf(updstr, "update \"%s\" set", stmt->ti[0]->name);
- num_cols = stmt->nfld;
- if (stmt->options.row_offset_ptr)
- offset = *stmt->options.row_offset_ptr;
- else
- offset = 0;
+ num_cols = irdflds->nfields;
+ offset = opts->row_offset_ptr ? *opts->row_offset_ptr : 0;
for (i = upd_cols = 0; i < num_cols; i++)
{
if (used = bindings[i].used, used != NULL)
{
used += (offset >> 2);
- mylog("%d used=%d\n", i, *used);
- if (*used != SQL_IGNORE)
+ if (bind_size > 0)
+ used += (bind_size * irow / 4);
+ else
+ used += irow;
+ mylog("%d used=%d,%x\n", i, *used, used);
+ if (*used != SQL_IGNORE && fi[i]->updatable)
{
if (upd_cols)
- sprintf(updstr, "%s, \"%s\" = ?", updstr, stmt->fi[i]->name);
+ sprintf(updstr, "%s, \"%s\" = ?", updstr, fi[i]->name);
else
- sprintf(updstr, "%s \"%s\" = ?", updstr, stmt->fi[i]->name);
+ sprintf(updstr, "%s \"%s\" = ?", updstr, fi[i]->name);
upd_cols++;
}
}
@@ -1695,6 +1728,7 @@ SC_pos_update(StatementClass *stmt,
int j;
int res_cols = QR_NumResultCols(res);
StatementClass *qstmt;
+ APDFields *apdopts;
/*sprintf(updstr, "%s where ctid = '%s' and oid = %s", updstr,
tidval, oidval);*/
@@ -1704,21 +1738,26 @@ SC_pos_update(StatementClass *stmt,
if (PGAPI_AllocStmt(SC_get_conn(stmt), &hstmt) != SQL_SUCCESS)
return SQL_ERROR;
qstmt = (StatementClass *) hstmt;
- qstmt->options.param_bind_type = stmt->options.bind_size;
- qstmt->options.param_offset_ptr = stmt->options.row_offset_ptr;
+ apdopts = SC_get_APD(qstmt);
+ apdopts->param_bind_type = opts->bind_size;
+ apdopts->param_offset_ptr = opts->row_offset_ptr;
for (i = j = 0; i < num_cols; i++)
{
if (used = bindings[i].used, used != NULL)
{
used += (offset >> 2);
+ if (bind_size > 0)
+ used += (bind_size * irow / 4);
+ else
+ used += irow;
mylog("%d used=%d\n", i, *used);
- if (*used != SQL_IGNORE)
+ if (*used != SQL_IGNORE && fi[i]->updatable)
{
PGAPI_BindParameter(hstmt, (SQLUSMALLINT) ++j,
SQL_PARAM_INPUT, bindings[i].returntype,
- pgtype_to_sqltype(stmt, QR_get_field_type(res, i)),
+ pgtype_to_concise_type(stmt, QR_get_field_type(res, i)),
QR_get_fieldsize(res, i),
- (SQLSMALLINT) stmt->fi[i]->precision,
+ (SQLSMALLINT) fi[i]->decimal_digits,
bindings[i].buffer,
bindings[i].buflen,
bindings[i].used);
@@ -1739,55 +1778,61 @@ SC_pos_update(StatementClass *stmt,
stmt->errormsg = "SetPos with data_at_exec not yet supported";
ret = SQL_ERROR;
}
- ret = irow_update(ret, stmt, qstmt, irow);
+ ret = irow_update(ret, stmt, qstmt, irow, global_ridx);
PGAPI_FreeStmt(hstmt, SQL_DROP);
}
else
+ {
ret = SQL_SUCCESS_WITH_INFO;
+ stmt->errormsg = "update list null";
+ }
if (SQL_SUCCESS == ret && res->keyset)
- res->keyset[global_ridx].status |= (SQL_ROW_UPDATED | DRV_SELF_UPDATED);
+ {
+ if (CC_is_in_trans(SC_get_conn(stmt)))
+ res->keyset[global_ridx].status |= (SQL_ROW_UPDATED | CURS_SELF_UPDATING);
+ else
+ res->keyset[global_ridx].status |= (SQL_ROW_UPDATED | CURS_SELF_UPDATED);
+ }
#if (ODBCVER >= 0x0300)
- if (stmt->options.rowStatusArray)
+ if (irdflds->rowStatusArray)
{
switch (ret)
{
case SQL_SUCCESS:
- stmt->options.rowStatusArray[irow] = SQL_ROW_UPDATED;
+ irdflds->rowStatusArray[irow] = SQL_ROW_UPDATED;
break;
default:
- stmt->options.rowStatusArray[irow] = ret;
+ irdflds->rowStatusArray[irow] = ret;
}
}
#endif /* ODBCVER */
return ret;
}
-RETCODE SQL_API
+RETCODE
SC_pos_delete(StatementClass *stmt,
- UWORD irow)
+ UWORD irow, UDWORD global_ridx)
{
- int res_cols;
- UWORD global_ridx, offset;
+ UWORD offset;
QResultClass *res, *qres;
- BindInfoClass *bindings = stmt->bindings;
+ ARDFields *opts = SC_get_ARD(stmt);
+ IRDFields *irdflds = SC_get_IRD(stmt);
+ BindInfoClass *bindings = opts->bindings;
char dltstr[4096];
RETCODE ret;
/*const char *oidval;*/
UInt4 oid, blocknum;
- mylog("POS DELETE fi=%x ti=%x\n", stmt->fi, stmt->ti);
+ mylog("POS DELETE ti=%x\n", stmt->ti);
if (!(res = SC_get_Curres(stmt)))
return SQL_ERROR;
if (!stmt->ti)
parse_statement(stmt); /* not preferable */
- if (!stmt->ti || stmt->ntab != 1)
+ if (!stmt->updatable)
{
stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;
return SQL_ERROR;
}
- res_cols = QR_NumResultCols(res);
- global_ridx = irow + stmt->rowset_start;
- /* if (!(oidval = getOidValue(res, global_ridx)))*/
if (!(oid = getOid(res, global_ridx)))
{
stmt->errormsg = "The row is already deleted";
@@ -1810,18 +1855,17 @@ SC_pos_delete(StatementClass *stmt,
sscanf(cmdstr, "DELETE %d", &dltcnt) == 1)
{
if (dltcnt == 1)
- SC_pos_reload(stmt, irow, (UWORD *) 0);
+ SC_pos_reload(stmt, irow, global_ridx, (UWORD *) 0);
else if (dltcnt == 0)
{
stmt->errornumber = STMT_ROW_VERSION_CHANGED;
stmt->errormsg = "the content was changed before deletion";
ret = SQL_ERROR;
if (stmt->options.cursor_type == SQL_CURSOR_KEYSET_DRIVEN)
- SC_pos_reload(stmt, irow, (UWORD *) 0);
+ SC_pos_reload(stmt, irow, global_ridx, (UWORD *) 0);
}
else
ret = SQL_ERROR;
- stmt->currTuple = stmt->rowset_start + irow;
}
else
ret = SQL_ERROR;
@@ -1836,17 +1880,22 @@ 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 (CC_is_in_trans(SC_get_conn(stmt)))
+ res->keyset[global_ridx].status |= (SQL_ROW_DELETED | CURS_SELF_DELETING);
+ else
+ res->keyset[global_ridx].status |= (SQL_ROW_DELETED | CURS_SELF_DELETED);
+ }
#if (ODBCVER >= 0x0300)
- if (stmt->options.rowStatusArray)
+ if (irdflds->rowStatusArray)
{
switch (ret)
{
case SQL_SUCCESS:
- stmt->options.rowStatusArray[irow] = SQL_ROW_DELETED;
+ irdflds->rowStatusArray[irow] = SQL_ROW_DELETED;
break;
default:
- stmt->options.rowStatusArray[irow] = ret;
+ irdflds->rowStatusArray[irow] = ret;
}
}
#endif /* ODBCVER */
@@ -1858,24 +1907,42 @@ irow_insert(RETCODE ret, StatementClass *stmt, StatementClass *istmt, int addpos
{
if (ret != SQL_ERROR)
{
- int addcnt;
+ int addcnt;
UInt4 oid;
- const char *cmdstr = QR_get_command(SC_get_Curres(istmt));
+ ARDFields *opts = SC_get_ARD(stmt);
+ QResultClass *ires = SC_get_Curres(istmt);
+ const char *cmdstr;
+ cmdstr = QR_get_command((ires->next ? ires->next : ires));
if (cmdstr &&
sscanf(cmdstr, "INSERT %u %d", &oid, &addcnt) == 2 &&
addcnt == 1)
{
- SC_pos_newload(stmt, oid, NULL);
- if (stmt->bookmark.buffer)
+ ConnectionClass *conn = SC_get_conn(stmt);
+ RETCODE qret;
+
+ qret = SQL_NO_DATA_FOUND;
+ if (PG_VERSION_GE(conn, 7.2))
+ {
+ qret = SC_pos_newload(stmt, oid, TRUE);
+ if (SQL_ERROR == qret)
+ return qret;
+ }
+ if (SQL_NO_DATA_FOUND == qret)
+ {
+ qret = SC_pos_newload(stmt, oid, FALSE);
+ if (SQL_ERROR == qret)
+ return qret;
+ }
+ if (opts->bookmark->buffer)
{
char buf[32];
- UInt4 offset = stmt->options.row_offset_ptr ? *stmt->options.row_offset_ptr : 0;
+ UInt4 offset = opts->row_offset_ptr ? *opts->row_offset_ptr : 0;
sprintf(buf, "%ld", addpos + 1);
copy_and_convert_field(stmt, 0, buf,
- SQL_C_ULONG, stmt->bookmark.buffer + offset,
- 0, stmt->bookmark.used ? stmt->bookmark.used
+ SQL_C_ULONG, opts->bookmark->buffer + offset,
+ 0, opts->bookmark->used ? opts->bookmark->used
+ (offset >> 2) : NULL);
}
}
@@ -1887,7 +1954,7 @@ irow_insert(RETCODE ret, StatementClass *stmt, StatementClass *istmt, int addpos
}
return ret;
}
-RETCODE SQL_API
+RETCODE
SC_pos_add(StatementClass *stmt,
UWORD irow)
{
@@ -1896,51 +1963,62 @@ SC_pos_add(StatementClass *stmt,
i;
HSTMT hstmt;
StatementClass *qstmt;
+ ConnectionClass *conn;
QResultClass *res;
- BindInfoClass *bindings = stmt->bindings;
+ ARDFields *opts = SC_get_ARD(stmt);
+ IRDFields *irdflds = SC_get_IRD(stmt);
+ APDFields *apdopts;
+ BindInfoClass *bindings = opts->bindings;
+ FIELD_INFO **fi = SC_get_IRD(stmt)->fi;
char addstr[4096];
RETCODE ret;
UInt4 offset;
- Int4 *used;
+ Int4 *used, bind_size = opts->bind_size;
- mylog("POS ADD fi=%x ti=%x\n", stmt->fi, stmt->ti);
+ mylog("POS ADD fi=%x ti=%x\n", fi, stmt->ti);
if (!(res = SC_get_Curres(stmt)))
return SQL_ERROR;
if (!stmt->ti)
parse_statement(stmt); /* not preferable */
- if (!stmt->ti || stmt->ntab != 1)
+ if (!stmt->updatable)
{
stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;
return SQL_ERROR;
}
- num_cols = stmt->nfld;
+ num_cols = irdflds->nfields;
+ conn = SC_get_conn(stmt);
sprintf(addstr, "insert into \"%s\" (", stmt->ti[0]->name);
if (PGAPI_AllocStmt(SC_get_conn(stmt), &hstmt) != SQL_SUCCESS)
return SQL_ERROR;
- if (stmt->options.row_offset_ptr)
- offset = *stmt->options.row_offset_ptr;
+ if (opts->row_offset_ptr)
+ offset = *opts->row_offset_ptr;
else
offset = 0;
qstmt = (StatementClass *) hstmt;
- qstmt->options.param_bind_type = stmt->options.bind_size;
- qstmt->options.param_offset_ptr = stmt->options.row_offset_ptr;
+ apdopts = SC_get_APD(qstmt);
+ apdopts->param_bind_type = opts->bind_size;
+ apdopts->param_offset_ptr = opts->row_offset_ptr;
for (i = add_cols = 0; i < num_cols; i++)
{
if (used = bindings[i].used, used != NULL)
{
used += (offset >> 2);
+ if (bind_size > 0)
+ used += (bind_size * irow / 4);
+ else
+ used += irow;
mylog("%d used=%d\n", i, *used);
- if (*used != SQL_IGNORE)
+ if (*used != SQL_IGNORE && fi[i]->updatable)
{
if (add_cols)
- sprintf(addstr, "%s, \"%s\"", addstr, stmt->fi[i]->name);
+ sprintf(addstr, "%s, \"%s\"", addstr, fi[i]->name);
else
- sprintf(addstr, "%s\"%s\"", addstr, stmt->fi[i]->name);
+ sprintf(addstr, "%s\"%s\"", addstr, fi[i]->name);
PGAPI_BindParameter(hstmt, (SQLUSMALLINT) ++add_cols,
SQL_PARAM_INPUT, bindings[i].returntype,
- pgtype_to_sqltype(stmt, QR_get_field_type(res, i)),
+ pgtype_to_concise_type(stmt, QR_get_field_type(res, i)),
QR_get_fieldsize(res, i),
- (SQLSMALLINT) stmt->fi[i]->precision,
+ (SQLSMALLINT) fi[i]->decimal_digits,
bindings[i].buffer,
bindings[i].buflen,
bindings[i].used);
@@ -1983,20 +2061,28 @@ SC_pos_add(StatementClass *stmt,
stmt->bind_row = brow_save;
}
else
+ {
ret = SQL_SUCCESS_WITH_INFO;
+ stmt->errormsg = "insert list null";
+ }
PGAPI_FreeStmt(hstmt, SQL_DROP);
if (SQL_SUCCESS == ret && res->keyset)
- res->keyset[res->fcount - 1].status |= DRV_SELF_ADDED;
+ {
+ if (CC_is_in_trans(conn))
+ res->keyset[res->fcount - 1].status |= (SQL_ROW_ADDED | CURS_SELF_ADDING);
+ else
+ res->keyset[res->fcount - 1].status |= (SQL_ROW_ADDED | CURS_SELF_ADDED);
+ }
#if (ODBCVER >= 0x0300)
- if (stmt->options.rowStatusArray)
+ if (irdflds->rowStatusArray)
{
switch (ret)
{
case SQL_SUCCESS:
- stmt->options.rowStatusArray[irow] = SQL_ROW_ADDED;
+ irdflds->rowStatusArray[irow] = SQL_ROW_ADDED;
break;
default:
- stmt->options.rowStatusArray[irow] = ret;
+ irdflds->rowStatusArray[irow] = ret;
}
}
#endif /* ODBCVER */
@@ -2009,6 +2095,47 @@ SC_pos_add(StatementClass *stmt,
*/
#endif /* DRIVER_CURSOR_IMPLEMENT */
+RETCODE
+SC_pos_refresh(StatementClass *stmt, UWORD irow , UDWORD global_ridx)
+{
+ RETCODE ret;
+#if (ODBCVER >= 0x0300)
+ IRDFields *irdflds = SC_get_IRD(stmt);
+#endif /* ODBCVER */
+ /* save the last_fetch_count */
+ int last_fetch = stmt->last_fetch_count;
+ int bind_save = stmt->bind_row;
+
+#ifdef DRIVER_CURSOR_IMPLEMENT
+ if (stmt->options.cursor_type == SQL_CURSOR_KEYSET_DRIVEN)
+ SC_pos_reload(stmt, irow, global_ridx, (UWORD *) 0);
+#endif /* DRIVER_CURSOR_IMPLEMENT */
+ stmt->bind_row = irow;
+ ret = SC_fetch(stmt);
+ /* restore the last_fetch_count */
+ stmt->last_fetch_count = last_fetch;
+ stmt->bind_row = bind_save;
+#if (ODBCVER >= 0x0300)
+ if (irdflds->rowStatusArray)
+ {
+ switch (ret)
+ {
+ case SQL_ERROR:
+ irdflds->rowStatusArray[irow] = SQL_ROW_ERROR;
+ break;
+ case SQL_SUCCESS:
+ irdflds->rowStatusArray[irow] = SQL_ROW_SUCCESS;
+ break;
+ default:
+ irdflds->rowStatusArray[irow] = ret;
+ break;
+ }
+ }
+#endif /* ODBCVER */
+
+ return SQL_SUCCESS;
+}
+
/*
* This positions the cursor within a rowset, that was positioned using SQLExtendedFetch.
* This will be useful (so far) only when using SQLGetData after SQLExtendedFetch.
@@ -2023,10 +2150,13 @@ PGAPI_SetPos(
static char *func = "PGAPI_SetPos";
RETCODE ret;
StatementClass *stmt = (StatementClass *) hstmt;
+ ConnectionClass *conn = SC_get_conn(stmt);
QResultClass *res;
- int num_cols,
- i;
- BindInfoClass *bindings = stmt->bindings;
+ int num_cols, i, start_row, end_row, processed;
+ ARDFields *opts;
+ BindInfoClass *bindings;
+ UDWORD global_ridx, fcount;
+ BOOL auto_commit_needed = FALSE;
if (!stmt)
{
@@ -2034,6 +2164,8 @@ PGAPI_SetPos(
return SQL_INVALID_HANDLE;
}
+ opts = SC_get_ARD(stmt);
+ bindings = opts->bindings;
#ifdef DRIVER_CURSOR_IMPLEMENT
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)
@@ -2055,12 +2187,9 @@ PGAPI_SetPos(
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
- num_cols = QR_NumResultCols(res);
if (irow == 0) /* bulk operation */
{
- int processed;
-
if (SQL_POSITION == fOption)
{
stmt->errornumber = STMT_ROW_OUT_OF_RANGE;
@@ -2068,78 +2197,86 @@ PGAPI_SetPos(
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;
+ start_row = 0;
+ end_row = opts->rowset_size - 1;
}
-
- if (irow > stmt->last_fetch_count)
+ else
{
- stmt->errornumber = STMT_ROW_OUT_OF_RANGE;
- stmt->errormsg = "Row value out of range";
- SC_log_error(func, "", stmt);
- return SQL_ERROR;
+ if (irow > stmt->last_fetch_count)
+ {
+ stmt->errornumber = STMT_ROW_OUT_OF_RANGE;
+ stmt->errormsg = "Row value out of range";
+ SC_log_error(func, "", stmt);
+ return SQL_ERROR;
+ }
+ start_row = end_row = irow - 1;
}
- irow--;
-
+ num_cols = QR_NumResultCols(res);
+ /* Reset for SQLGetData */
+ if (bindings)
+ for (i = 0; i < num_cols; i++)
+ bindings[i].data_left = -1;
+ ret = SQL_SUCCESS;
+ fcount = res->fcount;
#ifdef DRIVER_CURSOR_IMPLEMENT
switch (fOption)
{
case SQL_UPDATE:
- return SC_pos_update(stmt, irow);
case SQL_DELETE:
- return SC_pos_delete(stmt, irow);
case SQL_ADD:
- return SC_pos_add(stmt, irow);
+ if (auto_commit_needed = CC_is_in_autocommit(conn), auto_commit_needed)
+ PGAPI_SetConnectOption(conn, SQL_AUTOCOMMIT, SQL_AUTOCOMMIT_OFF);
+ break;
}
#endif /* DRIVER_CURSOR_IMPLEMENT */
- /* Reset for SQLGetData */
- for (i = 0; i < num_cols; i++)
- bindings[i].data_left = -1;
-
- if (fOption == SQL_REFRESH)
+ for (i = start_row, processed = 0; i <= end_row; i++)
{
- /* save the last_fetch_count */
- int last_fetch = stmt->last_fetch_count;
- int bind_save = stmt->bind_row;
-
+#if (ODBCVER >= 0x0300)
+ if (0 != irow || !opts->row_operation_ptr || opts->row_operation_ptr[i] == SQL_ROW_PROCEED)
+ {
+#endif /* ODBCVER */
+ global_ridx = i + stmt->rowset_start;
+ switch (fOption)
+ {
#ifdef DRIVER_CURSOR_IMPLEMENT
- if (stmt->options.cursor_type == SQL_CURSOR_KEYSET_DRIVEN)
- SC_pos_reload(stmt, irow, (UWORD *) 0);
+ case SQL_UPDATE:
+ ret = SC_pos_update(stmt, (UWORD) i, global_ridx);
+ break;
+ case SQL_DELETE:
+ ret = SC_pos_delete(stmt, (UWORD) i, global_ridx);
+ break;
+ case SQL_ADD:
+ ret = SC_pos_add(stmt, (UWORD) i);
+ break;
#endif /* DRIVER_CURSOR_IMPLEMENT */
- stmt->currTuple = stmt->rowset_start + irow - 1;
- stmt->bind_row = irow;
- SC_fetch(stmt);
- /* restore the last_fetch_count */
- stmt->last_fetch_count = last_fetch;
- stmt->bind_row = bind_save;
+ case SQL_REFRESH:
+ ret = SC_pos_refresh(stmt, (UWORD) i, global_ridx);
+ break;
+ }
+ processed++;
+ if (SQL_ERROR == ret)
+ break;
+#if (ODBCVER >= 0x0300)
+ }
+#endif /* ODBCVER */
}
- else
- stmt->currTuple = stmt->rowset_start + irow;
- QR_set_position(res, irow);
-
- return SQL_SUCCESS;
+ if (SQL_ERROR == ret)
+ res->fcount = fcount; /* restore the count */
+ if (auto_commit_needed)
+ PGAPI_SetConnectOption(conn, SQL_AUTOCOMMIT, SQL_AUTOCOMMIT_ON);
+ if (irow > 0)
+ {
+ if (SQL_ADD != fOption) /* for SQLGetData */
+ {
+ stmt->currTuple = stmt->rowset_start + irow - 1;
+ QR_set_position(res, irow - 1);
+ }
+ }
+ else if (SC_get_IRD(stmt)->rowsFetched)
+ *SC_get_IRD(stmt)->rowsFetched = processed;
+inolog("rowset=%d processed=%d ret=%d\n", opts->rowset_size, processed, ret);
+ return ret;
}