mirror of
https://github.com/postgres/postgres.git
synced 2025-07-28 23:42:10 +03:00
1) Add rollback functionality to updatable cursors.
2) Implement some options for SQLGetDescField(). 3) Handle *Inifinity* timestamp for SQL_C_CHAR type output. 4) Separate Unicode conversions from common implementations. 5) Improve internal parse_statement() function.
This commit is contained in:
@ -67,8 +67,8 @@ PGAPI_BindParameter(
|
|||||||
opts->parameters[ipar].paramType = fParamType;
|
opts->parameters[ipar].paramType = fParamType;
|
||||||
opts->parameters[ipar].CType = fCType;
|
opts->parameters[ipar].CType = fCType;
|
||||||
opts->parameters[ipar].SQLType = fSqlType;
|
opts->parameters[ipar].SQLType = fSqlType;
|
||||||
opts->parameters[ipar].precision = cbColDef;
|
opts->parameters[ipar].column_size = cbColDef;
|
||||||
opts->parameters[ipar].scale = ibScale;
|
opts->parameters[ipar].decimal_digits = ibScale;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If rebinding a parameter that had data-at-exec stuff in it, then
|
* If rebinding a parameter that had data-at-exec stuff in it, then
|
||||||
@ -276,10 +276,10 @@ PGAPI_DescribeParam(
|
|||||||
*pfSqlType = opts->parameters[ipar].SQLType;
|
*pfSqlType = opts->parameters[ipar].SQLType;
|
||||||
|
|
||||||
if (pcbColDef)
|
if (pcbColDef)
|
||||||
*pcbColDef = opts->parameters[ipar].precision;
|
*pcbColDef = opts->parameters[ipar].column_size;
|
||||||
|
|
||||||
if (pibScale)
|
if (pibScale)
|
||||||
*pibScale = opts->parameters[ipar].scale;
|
*pibScale = opts->parameters[ipar].decimal_digits;
|
||||||
|
|
||||||
if (pfNullable)
|
if (pfNullable)
|
||||||
*pfNullable = pgtype_nullable(stmt, opts->parameters[ipar].paramType);
|
*pfNullable = pgtype_nullable(stmt, opts->parameters[ipar].paramType);
|
||||||
@ -458,8 +458,8 @@ reset_a_parameter_binding(APDFields *self, int ipar)
|
|||||||
self->parameters[ipar].EXEC_buffer = NULL;
|
self->parameters[ipar].EXEC_buffer = NULL;
|
||||||
}
|
}
|
||||||
self->parameters[ipar].SQLType = 0;
|
self->parameters[ipar].SQLType = 0;
|
||||||
self->parameters[ipar].precision = 0;
|
self->parameters[ipar].column_size = 0;
|
||||||
self->parameters[ipar].scale = 0;
|
self->parameters[ipar].decimal_digits = 0;
|
||||||
self->parameters[ipar].data_at_exec = FALSE;
|
self->parameters[ipar].data_at_exec = FALSE;
|
||||||
self->parameters[ipar].lobj_oid = 0;
|
self->parameters[ipar].lobj_oid = 0;
|
||||||
}
|
}
|
||||||
|
@ -40,8 +40,8 @@ struct ParameterInfoClass_
|
|||||||
Int2 paramType;
|
Int2 paramType;
|
||||||
Int2 CType;
|
Int2 CType;
|
||||||
Int2 SQLType;
|
Int2 SQLType;
|
||||||
UInt4 precision;
|
UInt4 column_size;
|
||||||
Int2 scale;
|
Int2 decimal_digits;
|
||||||
Oid lobj_oid;
|
Oid lobj_oid;
|
||||||
Int4 *EXEC_used; /* amount of data OR the oid of the large
|
Int4 *EXEC_used; /* amount of data OR the oid of the large
|
||||||
* object */
|
* object */
|
||||||
|
@ -288,6 +288,7 @@ CC_Constructor()
|
|||||||
rv->pg_version_minor = 0;
|
rv->pg_version_minor = 0;
|
||||||
rv->ms_jet = 0;
|
rv->ms_jet = 0;
|
||||||
rv->unicode = 0;
|
rv->unicode = 0;
|
||||||
|
rv->result_uncommitted = 0;
|
||||||
#ifdef MULTIBYTE
|
#ifdef MULTIBYTE
|
||||||
rv->client_encoding = NULL;
|
rv->client_encoding = NULL;
|
||||||
rv->server_encoding = NULL;
|
rv->server_encoding = NULL;
|
||||||
@ -1110,21 +1111,30 @@ CC_get_error(ConnectionClass *self, int *number, char **message)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void CC_on_commit(ConnectionClass *conn, BOOL set_no_trans)
|
void CC_on_commit(ConnectionClass *conn)
|
||||||
{
|
{
|
||||||
if (CC_is_in_trans(conn))
|
if (CC_is_in_trans(conn))
|
||||||
{
|
{
|
||||||
if (set_no_trans)
|
#ifdef DRIVER_CURSOR_IMPLEMENT
|
||||||
CC_set_no_trans(conn);
|
if (conn->result_uncommitted)
|
||||||
|
ProcessRollback(conn, FALSE);
|
||||||
|
#endif /* DRIVER_CURSOR_IMPLEMENT */
|
||||||
|
CC_set_no_trans(conn);
|
||||||
}
|
}
|
||||||
|
conn->result_uncommitted = 0;
|
||||||
}
|
}
|
||||||
void CC_on_abort(ConnectionClass *conn, BOOL set_no_trans)
|
void CC_on_abort(ConnectionClass *conn, BOOL set_no_trans)
|
||||||
{
|
{
|
||||||
if (CC_is_in_trans(conn))
|
if (CC_is_in_trans(conn))
|
||||||
{
|
{
|
||||||
|
#ifdef DRIVER_CURSOR_IMPLEMENT
|
||||||
|
if (conn->result_uncommitted)
|
||||||
|
ProcessRollback(conn, TRUE);
|
||||||
|
#endif /* DRIVER_CURSOR_IMPLEMENT */
|
||||||
if (set_no_trans)
|
if (set_no_trans)
|
||||||
CC_set_no_trans(conn);
|
CC_set_no_trans(conn);
|
||||||
}
|
}
|
||||||
|
conn->result_uncommitted = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1293,11 +1303,11 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi, UDWORD flag)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (strnicmp(cmdbuffer, "COMMIT", 6) == 0)
|
else if (strnicmp(cmdbuffer, "COMMIT", 6) == 0)
|
||||||
CC_on_commit(self, TRUE);
|
CC_on_commit(self);
|
||||||
else if (strnicmp(cmdbuffer, "ROLLBACK", 8) == 0)
|
else if (strnicmp(cmdbuffer, "ROLLBACK", 8) == 0)
|
||||||
CC_on_abort(self, TRUE);
|
CC_on_abort(self, TRUE);
|
||||||
else if (strnicmp(cmdbuffer, "END", 3) == 0)
|
else if (strnicmp(cmdbuffer, "END", 3) == 0)
|
||||||
CC_on_commit(self, TRUE);
|
CC_on_commit(self);
|
||||||
else if (strnicmp(cmdbuffer, "ABORT", 5) == 0)
|
else if (strnicmp(cmdbuffer, "ABORT", 5) == 0)
|
||||||
CC_on_abort(self, TRUE);
|
CC_on_abort(self, TRUE);
|
||||||
|
|
||||||
|
@ -272,6 +272,7 @@ struct ConnectionClass_
|
|||||||
Int2 pg_version_minor;
|
Int2 pg_version_minor;
|
||||||
char ms_jet;
|
char ms_jet;
|
||||||
char unicode;
|
char unicode;
|
||||||
|
char result_uncommitted;
|
||||||
#ifdef MULTIBYTE
|
#ifdef MULTIBYTE
|
||||||
char *client_encoding;
|
char *client_encoding;
|
||||||
char *server_encoding;
|
char *server_encoding;
|
||||||
@ -318,8 +319,9 @@ void CC_lookup_pg_version(ConnectionClass *conn);
|
|||||||
void CC_initialize_pg_version(ConnectionClass *conn);
|
void CC_initialize_pg_version(ConnectionClass *conn);
|
||||||
void CC_log_error(const char *func, const char *desc, const ConnectionClass *self);
|
void CC_log_error(const char *func, const char *desc, const ConnectionClass *self);
|
||||||
int CC_get_max_query_len(const ConnectionClass *self);
|
int CC_get_max_query_len(const ConnectionClass *self);
|
||||||
void CC_on_commit(ConnectionClass *conn, BOOL set_no_trans);
|
void CC_on_commit(ConnectionClass *conn);
|
||||||
void CC_on_abort(ConnectionClass *conn, BOOL set_no_trans);
|
void CC_on_abort(ConnectionClass *conn, BOOL set_no_trans);
|
||||||
|
void ProcessRollback(ConnectionClass *conn, BOOL undo);
|
||||||
|
|
||||||
/* CC_send_query_options */
|
/* CC_send_query_options */
|
||||||
#define CLEAR_RESULT_ON_ABORT 1L
|
#define CLEAR_RESULT_ON_ABORT 1L
|
||||||
|
@ -265,6 +265,16 @@ stime2timestamp(const SIMPLE_TIME *st, char *str, BOOL bZone, BOOL precision)
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
precstr[0] = '\0';
|
precstr[0] = '\0';
|
||||||
|
if (st->infinity > 0)
|
||||||
|
{
|
||||||
|
strcpy(str, "Infinity");
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
else if (st->infinity < 0)
|
||||||
|
{
|
||||||
|
strcpy(str, "-Infinity");
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
if (precision && st->fr)
|
if (precision && st->fr)
|
||||||
{
|
{
|
||||||
sprintf(precstr, ".%09d", st->fr);
|
sprintf(precstr, ".%09d", st->fr);
|
||||||
@ -447,6 +457,27 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
|
|||||||
case PG_TYPE_DATETIME:
|
case PG_TYPE_DATETIME:
|
||||||
case PG_TYPE_TIMESTAMP:
|
case PG_TYPE_TIMESTAMP:
|
||||||
st.fr = 0;
|
st.fr = 0;
|
||||||
|
st.infinity = 0;
|
||||||
|
if (strnicmp(value, "infinity", 8) == 0)
|
||||||
|
{
|
||||||
|
st.infinity = 1;
|
||||||
|
st.m = 12;
|
||||||
|
st.d = 31;
|
||||||
|
st.y = 9999;
|
||||||
|
st.hh = 24;
|
||||||
|
st.mm = 0;
|
||||||
|
st.ss = 0;
|
||||||
|
}
|
||||||
|
if (strnicmp(value, "-infinity", 9) == 0)
|
||||||
|
{
|
||||||
|
st.infinity = -1;
|
||||||
|
st.m = 0;
|
||||||
|
st.d = 0;
|
||||||
|
st.y = 0;
|
||||||
|
st.hh = 0;
|
||||||
|
st.mm = 0;
|
||||||
|
st.ss = 0;
|
||||||
|
}
|
||||||
if (strnicmp(value, "invalid", 7) != 0)
|
if (strnicmp(value, "invalid", 7) != 0)
|
||||||
{
|
{
|
||||||
BOOL bZone = (field_type != PG_TYPE_TIMESTAMP_NO_TMZONE && PG_VERSION_GE(SC_get_conn(stmt), 7.2));
|
BOOL bZone = (field_type != PG_TYPE_TIMESTAMP_NO_TMZONE && PG_VERSION_GE(SC_get_conn(stmt), 7.2));
|
||||||
@ -2495,7 +2526,7 @@ convert_money(const char *s, char *sout, size_t soutmax)
|
|||||||
* It does not zero out SIMPLE_TIME in case it is desired to initialize it with a value
|
* It does not zero out SIMPLE_TIME in case it is desired to initialize it with a value
|
||||||
*/
|
*/
|
||||||
char
|
char
|
||||||
parse_datetime(char *buf, SIMPLE_TIME *st)
|
parse_datetime(const char *buf, SIMPLE_TIME *st)
|
||||||
{
|
{
|
||||||
int y,
|
int y,
|
||||||
m,
|
m,
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
int infinity;
|
||||||
int m;
|
int m;
|
||||||
int d;
|
int d;
|
||||||
int y;
|
int y;
|
||||||
@ -42,7 +43,7 @@ int copy_statement_with_parameters(StatementClass *stmt);
|
|||||||
int convert_escape(const char *value, StatementClass *stmt,
|
int convert_escape(const char *value, StatementClass *stmt,
|
||||||
int *npos, int *stsize, const char **val_resume);
|
int *npos, int *stsize, const char **val_resume);
|
||||||
BOOL convert_money(const char *s, char *sout, size_t soutmax);
|
BOOL convert_money(const char *s, char *sout, size_t soutmax);
|
||||||
char parse_datetime(char *buf, SIMPLE_TIME *st);
|
char parse_datetime(const char *buf, SIMPLE_TIME *st);
|
||||||
int convert_linefeeds(const char *s, char *dst, size_t max, BOOL convlf, BOOL *changed);
|
int convert_linefeeds(const char *s, char *dst, size_t max, BOOL convlf, BOOL *changed);
|
||||||
int convert_special_chars(const char *si, char *dst, int used, BOOL convlf,int ccsc);
|
int convert_special_chars(const char *si, char *dst, int used, BOOL convlf,int ccsc);
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
*
|
*
|
||||||
* Comments: See "notice.txt" for copyright and license information.
|
* Comments: See "notice.txt" for copyright and license information.
|
||||||
*
|
*
|
||||||
* $Id: descriptor.h,v 1.1 2002/03/28 08:08:02 inoue Exp $
|
* $Id: descriptor.h,v 1.2 2002/04/01 03:01:14 inoue Exp $
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -92,5 +92,8 @@ void IRDFields_free(IRDFields *self);
|
|||||||
void IPDFields_free(IPDFields *self);
|
void IPDFields_free(IPDFields *self);
|
||||||
void ARD_unbind_cols(ARDFields *self, BOOL freeall);
|
void ARD_unbind_cols(ARDFields *self, BOOL freeall);
|
||||||
void APD_free_params(APDFields *self, char option);
|
void APD_free_params(APDFields *self, char option);
|
||||||
|
#if (ODBCVER >= 0x0300)
|
||||||
|
void Desc_set_error(SQLHDESC hdesc, int errornumber, const char * errormsg);
|
||||||
|
#endif /* ODBCVER */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -235,7 +235,8 @@ SQLGetDiagField(SQLSMALLINT HandleType, SQLHANDLE Handle,
|
|||||||
SQLSMALLINT *StringLength)
|
SQLSMALLINT *StringLength)
|
||||||
{
|
{
|
||||||
mylog("[[SQLGetDiagField]] Handle=(%u,%x) Rec=%d Id=%d\n", HandleType, Handle, RecNumber, DiagIdentifier);
|
mylog("[[SQLGetDiagField]] Handle=(%u,%x) Rec=%d Id=%d\n", HandleType, Handle, RecNumber, DiagIdentifier);
|
||||||
return SQL_ERROR;
|
return PGAPI_GetDiagField(HandleType, Handle, RecNumber, DiagIdentifier,
|
||||||
|
DiagInfo, BufferLength, StringLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* SQLError -> SQLDiagRec */
|
/* SQLError -> SQLDiagRec */
|
||||||
|
@ -89,10 +89,25 @@ SQLSetDescFieldW(SQLHDESC DescriptorHandle, SQLSMALLINT RecNumber,
|
|||||||
mylog("[SQLSetDescFieldW]");
|
mylog("[SQLSetDescFieldW]");
|
||||||
if (BufferLength > 0)
|
if (BufferLength > 0)
|
||||||
{
|
{
|
||||||
uval = ucs2_to_utf8(Value, BufferLength / 2, &vallen);
|
switch (FieldIdentifier)
|
||||||
val_alloced = TRUE;
|
{
|
||||||
|
case SQL_DESC_BASE_COLUMN_NAME:
|
||||||
|
case SQL_DESC_BASE_TABLE_NAME:
|
||||||
|
case SQL_DESC_CATALOG_NAME:
|
||||||
|
case SQL_DESC_LABEL:
|
||||||
|
case SQL_DESC_LITERAL_PREFIX:
|
||||||
|
case SQL_DESC_LITERAL_SUFFIX:
|
||||||
|
case SQL_DESC_LOCAL_TYPE_NAME:
|
||||||
|
case SQL_DESC_NAME:
|
||||||
|
case SQL_DESC_SCHEMA_NAME:
|
||||||
|
case SQL_DESC_TABLE_NAME:
|
||||||
|
case SQL_DESC_TYPE_NAME:
|
||||||
|
uval = ucs2_to_utf8(Value, BufferLength / 2, &vallen);
|
||||||
|
val_alloced = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
if (!val_alloced)
|
||||||
{
|
{
|
||||||
uval = Value;
|
uval = Value;
|
||||||
vallen = BufferLength;
|
vallen = BufferLength;
|
||||||
@ -109,11 +124,49 @@ SQLGetDescFieldW(SQLHDESC hdesc, SQLSMALLINT iRecord, SQLSMALLINT iField,
|
|||||||
SQLINTEGER *pcbValue)
|
SQLINTEGER *pcbValue)
|
||||||
{
|
{
|
||||||
RETCODE ret;
|
RETCODE ret;
|
||||||
char *qstr = NULL, *mtxt = NULL;
|
BOOL alloced = FALSE;
|
||||||
|
SQLINTEGER blen, bMax, *pcbV;
|
||||||
|
char *rgbV = NULL;
|
||||||
|
|
||||||
mylog("[SQLGetDescFieldW]");
|
mylog("[SQLGetDescFieldW]");
|
||||||
ret = PGAPI_GetDescField(hdesc, iRecord, iField, rgbValue,
|
switch (iField)
|
||||||
cbValueMax, pcbValue);
|
{
|
||||||
|
case SQL_DESC_BASE_COLUMN_NAME:
|
||||||
|
case SQL_DESC_BASE_TABLE_NAME:
|
||||||
|
case SQL_DESC_CATALOG_NAME:
|
||||||
|
case SQL_DESC_LABEL:
|
||||||
|
case SQL_DESC_LITERAL_PREFIX:
|
||||||
|
case SQL_DESC_LITERAL_SUFFIX:
|
||||||
|
case SQL_DESC_LOCAL_TYPE_NAME:
|
||||||
|
case SQL_DESC_NAME:
|
||||||
|
case SQL_DESC_SCHEMA_NAME:
|
||||||
|
case SQL_DESC_TABLE_NAME:
|
||||||
|
case SQL_DESC_TYPE_NAME:
|
||||||
|
alloced = TRUE;
|
||||||
|
bMax = cbValueMax * 3 / 2;
|
||||||
|
rgbV = malloc(bMax + 1);
|
||||||
|
pcbV = &blen;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
rgbV = rgbValue;
|
||||||
|
bMax = cbValueMax;
|
||||||
|
pcbV = pcbValue;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ret = PGAPI_GetDescField(hdesc, iRecord, iField, rgbV, bMax, pcbV);
|
||||||
|
if (alloced)
|
||||||
|
{
|
||||||
|
blen = utf8_to_ucs2(rgbV, blen, (SQLWCHAR *) rgbValue, cbValueMax / 2);
|
||||||
|
if (SQL_SUCCESS == ret && blen * 2 > cbValueMax)
|
||||||
|
{
|
||||||
|
ret = SQL_SUCCESS_WITH_INFO;
|
||||||
|
Desc_set_error(hdesc, STMT_TRUNCATED, "The buffer was too small for the rgbDesc.");
|
||||||
|
}
|
||||||
|
if (pcbValue)
|
||||||
|
*pcbValue = blen * 2;
|
||||||
|
free(rgbV);
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -171,6 +224,9 @@ RETCODE SQL_API SQLColAttributeW(
|
|||||||
SQLINTEGER *pfDesc)
|
SQLINTEGER *pfDesc)
|
||||||
{
|
{
|
||||||
RETCODE ret;
|
RETCODE ret;
|
||||||
|
BOOL alloced = FALSE;
|
||||||
|
SQLSMALLINT *rgbL, blen, bMax;
|
||||||
|
char *rgbD = NULL;
|
||||||
|
|
||||||
mylog("[SQLColAttributeW]");
|
mylog("[SQLColAttributeW]");
|
||||||
switch (fDescType)
|
switch (fDescType)
|
||||||
@ -187,11 +243,35 @@ RETCODE SQL_API SQLColAttributeW(
|
|||||||
case SQL_DESC_TABLE_NAME:
|
case SQL_DESC_TABLE_NAME:
|
||||||
case SQL_DESC_TYPE_NAME:
|
case SQL_DESC_TYPE_NAME:
|
||||||
case SQL_COLUMN_NAME:
|
case SQL_COLUMN_NAME:
|
||||||
|
alloced = TRUE;
|
||||||
|
bMax = cbDescMax * 3 / 2;
|
||||||
|
rgbD = malloc(bMax + 1);
|
||||||
|
rgbL = &blen;
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
rgbD = rgbDesc;
|
||||||
|
bMax = cbDescMax;
|
||||||
|
rgbL = pcbDesc;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = PGAPI_ColAttributes(hstmt, icol, fDescType, rgbDesc,
|
ret = PGAPI_ColAttributes(hstmt, icol, fDescType, rgbD,
|
||||||
cbDescMax, pcbDesc, pfDesc);
|
bMax, rgbL, pfDesc);
|
||||||
|
if (alloced)
|
||||||
|
{
|
||||||
|
blen = utf8_to_ucs2(rgbD, blen, (SQLWCHAR *) rgbDesc, cbDescMax / 2);
|
||||||
|
if (SQL_SUCCESS == ret && blen * 2 > cbDescMax)
|
||||||
|
{
|
||||||
|
StatementClass *stmt = (StatementClass *) hstmt;
|
||||||
|
|
||||||
|
ret = SQL_SUCCESS_WITH_INFO;
|
||||||
|
stmt->errornumber = STMT_TRUNCATED;
|
||||||
|
stmt->errormsg = "The buffer was too small for the rgbDesc.";
|
||||||
|
}
|
||||||
|
if (pcbDesc)
|
||||||
|
*pcbDesc = blen * 2;
|
||||||
|
free(rgbD);
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -304,7 +304,8 @@ parse_statement(StatementClass *stmt)
|
|||||||
in_on = FALSE,
|
in_on = FALSE,
|
||||||
in_from = FALSE,
|
in_from = FALSE,
|
||||||
in_where = FALSE,
|
in_where = FALSE,
|
||||||
in_table = FALSE;
|
in_table = FALSE,
|
||||||
|
out_table = TRUE;
|
||||||
char in_field = FALSE,
|
char in_field = FALSE,
|
||||||
in_expr = FALSE,
|
in_expr = FALSE,
|
||||||
in_func = FALSE,
|
in_func = FALSE,
|
||||||
@ -610,12 +611,21 @@ parse_statement(StatementClass *stmt)
|
|||||||
|
|
||||||
if (in_from)
|
if (in_from)
|
||||||
{
|
{
|
||||||
if (!in_table)
|
if (token[0] == ';')
|
||||||
{
|
{
|
||||||
if (!token[0])
|
in_from = FALSE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
switch (token[0])
|
||||||
|
{
|
||||||
|
case '\0':
|
||||||
continue;
|
continue;
|
||||||
if (token[0] == ';')
|
case ',':
|
||||||
break;
|
out_table = TRUE;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (out_table && !in_table) /* new table */
|
||||||
|
{
|
||||||
|
|
||||||
if (!(stmt->ntab % TAB_INCR))
|
if (!(stmt->ntab % TAB_INCR))
|
||||||
{
|
{
|
||||||
@ -660,22 +670,47 @@ parse_statement(StatementClass *stmt)
|
|||||||
mylog("got table = '%s'\n", ti[stmt->ntab]->name);
|
mylog("got table = '%s'\n", ti[stmt->ntab]->name);
|
||||||
|
|
||||||
if (delim == ',')
|
if (delim == ',')
|
||||||
|
{
|
||||||
|
out_table = TRUE;
|
||||||
mylog("more than 1 tables\n");
|
mylog("more than 1 tables\n");
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
out_table = FALSE;
|
||||||
in_table = TRUE;
|
in_table = TRUE;
|
||||||
|
}
|
||||||
stmt->ntab++;
|
stmt->ntab++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (token[0] == ';')
|
if (!dquote && stricmp(token, "JOIN") == 0)
|
||||||
break;
|
|
||||||
if (stricmp(token, "as"))
|
|
||||||
{
|
{
|
||||||
|
in_table = FALSE;
|
||||||
|
out_table = TRUE;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (in_table && stricmp(token, "as"))
|
||||||
|
{
|
||||||
|
if (!dquote)
|
||||||
|
{
|
||||||
|
if (stricmp(token, "LEFT") == 0 ||
|
||||||
|
stricmp(token, "RIGHT") == 0 ||
|
||||||
|
stricmp(token, "OUTER") == 0 ||
|
||||||
|
stricmp(token, "FULL") == 0 ||
|
||||||
|
stricmp(token, "ON") == 0)
|
||||||
|
{
|
||||||
|
in_table = FALSE;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
strcpy(ti[stmt->ntab - 1]->alias, token);
|
strcpy(ti[stmt->ntab - 1]->alias, token);
|
||||||
mylog("alias for table '%s' is '%s'\n", ti[stmt->ntab - 1]->name, ti[stmt->ntab - 1]->alias);
|
mylog("alias for table '%s' is '%s'\n", ti[stmt->ntab - 1]->name, ti[stmt->ntab - 1]->alias);
|
||||||
in_table = FALSE;
|
in_table = FALSE;
|
||||||
if (delim == ',')
|
if (delim == ',')
|
||||||
|
{
|
||||||
|
out_table = TRUE;
|
||||||
mylog("more than 1 tables\n");
|
mylog("more than 1 tables\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} /* in_from */
|
} /* in_from */
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
#include "descriptor.h"
|
#include "descriptor.h"
|
||||||
#include "pgapifunc.h"
|
#include "pgapifunc.h"
|
||||||
|
|
||||||
static HSTMT statementHandleFromDescHandle(HSTMT, SQLINTEGER *descType);
|
static HSTMT statementHandleFromDescHandle(SQLHDESC, SQLINTEGER *descType);
|
||||||
/* SQLError -> SQLDiagRec */
|
/* SQLError -> SQLDiagRec */
|
||||||
RETCODE SQL_API
|
RETCODE SQL_API
|
||||||
PGAPI_GetDiagRec(SQLSMALLINT HandleType, SQLHANDLE Handle,
|
PGAPI_GetDiagRec(SQLSMALLINT HandleType, SQLHANDLE Handle,
|
||||||
@ -75,7 +75,7 @@ PGAPI_GetDiagField(SQLSMALLINT HandleType, SQLHANDLE Handle,
|
|||||||
PTR DiagInfoPtr, SQLSMALLINT BufferLength,
|
PTR DiagInfoPtr, SQLSMALLINT BufferLength,
|
||||||
SQLSMALLINT *StringLengthPtr)
|
SQLSMALLINT *StringLengthPtr)
|
||||||
{
|
{
|
||||||
RETCODE ret = SQL_SUCCESS;
|
RETCODE ret = SQL_ERROR;
|
||||||
static const char *func = "PGAPI_GetDiagField";
|
static const char *func = "PGAPI_GetDiagField";
|
||||||
|
|
||||||
mylog("%s entering rec=%d", func, RecNumber);
|
mylog("%s entering rec=%d", func, RecNumber);
|
||||||
@ -122,6 +122,7 @@ PGAPI_GetDiagField(SQLSMALLINT HandleType, SQLHANDLE Handle,
|
|||||||
case SQL_DIAG_NUMBER:
|
case SQL_DIAG_NUMBER:
|
||||||
case SQL_DIAG_RETURNCODE:
|
case SQL_DIAG_RETURNCODE:
|
||||||
case SQL_DIAG_SERVER_NAME:
|
case SQL_DIAG_SERVER_NAME:
|
||||||
|
break;
|
||||||
case SQL_DIAG_SQLSTATE:
|
case SQL_DIAG_SQLSTATE:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -154,7 +155,12 @@ PGAPI_GetConnectAttr(HDBC ConnectionHandle,
|
|||||||
*((SQLUINTEGER *) Value) = SQL_FALSE;
|
*((SQLUINTEGER *) Value) = SQL_FALSE;
|
||||||
break;
|
break;
|
||||||
case SQL_ATTR_CONNECTION_DEAD:
|
case SQL_ATTR_CONNECTION_DEAD:
|
||||||
*((SQLUINTEGER *) Value) = SQL_CD_FALSE;
|
if (CC_is_in_trans(conn))
|
||||||
|
*((SQLUINTEGER *) Value) = SQL_CD_FALSE;
|
||||||
|
else if (conn->num_stmts > 0)
|
||||||
|
*((SQLUINTEGER *) Value) = SQL_CD_FALSE;
|
||||||
|
else
|
||||||
|
*((SQLUINTEGER *) Value) = SQL_CD_FALSE;
|
||||||
break;
|
break;
|
||||||
case SQL_ATTR_CONNECTION_TIMEOUT:
|
case SQL_ATTR_CONNECTION_TIMEOUT:
|
||||||
*((SQLUINTEGER *) Value) = 0;
|
*((SQLUINTEGER *) Value) = 0;
|
||||||
@ -172,7 +178,7 @@ PGAPI_GetConnectAttr(HDBC ConnectionHandle,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HSTMT
|
static SQLHDESC
|
||||||
descHandleFromStatementHandle(HSTMT StatementHandle, SQLINTEGER descType)
|
descHandleFromStatementHandle(HSTMT StatementHandle, SQLINTEGER descType)
|
||||||
{
|
{
|
||||||
switch (descType)
|
switch (descType)
|
||||||
@ -189,7 +195,7 @@ descHandleFromStatementHandle(HSTMT StatementHandle, SQLINTEGER descType)
|
|||||||
return (HSTMT) 0;
|
return (HSTMT) 0;
|
||||||
}
|
}
|
||||||
static HSTMT
|
static HSTMT
|
||||||
statementHandleFromDescHandle(HSTMT DescHandle, SQLINTEGER *descType)
|
statementHandleFromDescHandle(SQLHDESC DescHandle, SQLINTEGER *descType)
|
||||||
{
|
{
|
||||||
SQLUINTEGER res = (SQLUINTEGER) DescHandle % 4;
|
SQLUINTEGER res = (SQLUINTEGER) DescHandle % 4;
|
||||||
if (descType)
|
if (descType)
|
||||||
@ -209,6 +215,19 @@ statementHandleFromDescHandle(HSTMT DescHandle, SQLINTEGER *descType)
|
|||||||
return (HSTMT) ((SQLUINTEGER) DescHandle - res);
|
return (HSTMT) ((SQLUINTEGER) DescHandle - res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Desc_set_error(SQLHDESC hdesc, int errornumber, const char *errormsg)
|
||||||
|
{
|
||||||
|
SQLINTEGER descType;
|
||||||
|
HSTMT hstmt = statementHandleFromDescHandle(hdesc, &descType);
|
||||||
|
StatementClass *stmt;
|
||||||
|
|
||||||
|
if (!hstmt)
|
||||||
|
return;
|
||||||
|
stmt = (StatementClass *) hstmt;
|
||||||
|
stmt->errornumber = errornumber;
|
||||||
|
stmt->errormsg = errormsg; /* should be static */
|
||||||
|
}
|
||||||
|
|
||||||
static void column_bindings_set(ARDFields *opts, int cols, BOOL maxset)
|
static void column_bindings_set(ARDFields *opts, int cols, BOOL maxset)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@ -568,7 +587,7 @@ IPDSetField(StatementClass *stmt, SQLSMALLINT RecNumber,
|
|||||||
apdopts->parameters[RecNumber - 1].paramType = (Int2) Value;
|
apdopts->parameters[RecNumber - 1].paramType = (Int2) Value;
|
||||||
break;
|
break;
|
||||||
case SQL_DESC_SCALE:
|
case SQL_DESC_SCALE:
|
||||||
apdopts->parameters[RecNumber - 1].scale = (Int2) Value;
|
apdopts->parameters[RecNumber - 1].decimal_digits = (Int2) Value;
|
||||||
break;
|
break;
|
||||||
case SQL_DESC_ALLOC_TYPE: /* read-only */
|
case SQL_DESC_ALLOC_TYPE: /* read-only */
|
||||||
case SQL_DESC_CASE_SENSITIVE: /* read-only */
|
case SQL_DESC_CASE_SENSITIVE: /* read-only */
|
||||||
@ -599,7 +618,7 @@ ARDGetField(StatementClass *stmt, SQLSMALLINT RecNumber,
|
|||||||
SQLINTEGER *StringLength)
|
SQLINTEGER *StringLength)
|
||||||
{
|
{
|
||||||
RETCODE ret = SQL_SUCCESS;
|
RETCODE ret = SQL_SUCCESS;
|
||||||
SQLINTEGER len, ival;
|
SQLINTEGER len, ival, rettype = 0;
|
||||||
PTR ptr = NULL;
|
PTR ptr = NULL;
|
||||||
const ARDFields *opts = SC_get_ARD(stmt);
|
const ARDFields *opts = SC_get_ARD(stmt);
|
||||||
|
|
||||||
@ -610,9 +629,11 @@ ARDGetField(StatementClass *stmt, SQLSMALLINT RecNumber,
|
|||||||
ival = opts->rowset_size;
|
ival = opts->rowset_size;
|
||||||
break;
|
break;
|
||||||
case SQL_DESC_ARRAY_STATUS_PTR:
|
case SQL_DESC_ARRAY_STATUS_PTR:
|
||||||
|
rettype = SQL_IS_POINTER;
|
||||||
ptr = opts->row_operation_ptr;
|
ptr = opts->row_operation_ptr;
|
||||||
break;
|
break;
|
||||||
case SQL_DESC_BIND_OFFSET_PTR:
|
case SQL_DESC_BIND_OFFSET_PTR:
|
||||||
|
rettype = SQL_IS_POINTER;
|
||||||
ptr = opts->row_offset_ptr;
|
ptr = opts->row_offset_ptr;
|
||||||
break;
|
break;
|
||||||
case SQL_DESC_BIND_TYPE:
|
case SQL_DESC_BIND_TYPE:
|
||||||
@ -651,6 +672,7 @@ ARDGetField(StatementClass *stmt, SQLSMALLINT RecNumber,
|
|||||||
ival = opts->bindings[RecNumber - 1].returntype;
|
ival = opts->bindings[RecNumber - 1].returntype;
|
||||||
break;
|
break;
|
||||||
case SQL_DESC_DATA_PTR:
|
case SQL_DESC_DATA_PTR:
|
||||||
|
rettype = SQL_IS_POINTER;
|
||||||
if (!RecNumber)
|
if (!RecNumber)
|
||||||
ptr = opts->bookmark->buffer;
|
ptr = opts->bookmark->buffer;
|
||||||
else
|
else
|
||||||
@ -659,6 +681,7 @@ ARDGetField(StatementClass *stmt, SQLSMALLINT RecNumber,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SQL_DESC_INDICATOR_PTR:
|
case SQL_DESC_INDICATOR_PTR:
|
||||||
|
rettype = SQL_IS_POINTER;
|
||||||
if (!RecNumber)
|
if (!RecNumber)
|
||||||
ptr = opts->bookmark->used;
|
ptr = opts->bookmark->used;
|
||||||
else
|
else
|
||||||
@ -667,6 +690,7 @@ ARDGetField(StatementClass *stmt, SQLSMALLINT RecNumber,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SQL_DESC_OCTET_LENGTH_PTR:
|
case SQL_DESC_OCTET_LENGTH_PTR:
|
||||||
|
rettype = SQL_IS_POINTER;
|
||||||
if (!RecNumber)
|
if (!RecNumber)
|
||||||
ptr = opts->bookmark->used;
|
ptr = opts->bookmark->used;
|
||||||
else
|
else
|
||||||
@ -694,25 +718,13 @@ ARDGetField(StatementClass *stmt, SQLSMALLINT RecNumber,
|
|||||||
default:ret = SQL_ERROR;
|
default:ret = SQL_ERROR;
|
||||||
stmt->errornumber = STMT_INVALID_DESCRIPTOR_IDENTIFIER;
|
stmt->errornumber = STMT_INVALID_DESCRIPTOR_IDENTIFIER;
|
||||||
}
|
}
|
||||||
switch (BufferLength)
|
switch (rettype)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
case SQL_IS_INTEGER:
|
case SQL_IS_INTEGER:
|
||||||
len = 4;
|
len = 4;
|
||||||
*((SQLINTEGER *) Value) = ival;
|
*((SQLINTEGER *) Value) = ival;
|
||||||
break;
|
break;
|
||||||
case SQL_IS_UINTEGER:
|
|
||||||
len = 4;
|
|
||||||
*((UInt4 *) Value) = ival;
|
|
||||||
break;
|
|
||||||
case SQL_IS_SMALLINT:
|
|
||||||
len = 2;
|
|
||||||
*((SQLSMALLINT *) Value) = (SQLSMALLINT) ival;
|
|
||||||
break;
|
|
||||||
case SQL_IS_USMALLINT:
|
|
||||||
len = 2;
|
|
||||||
*((SQLUSMALLINT *) Value) = (SQLUSMALLINT) ival;
|
|
||||||
break;
|
|
||||||
case SQL_IS_POINTER:
|
case SQL_IS_POINTER:
|
||||||
len = 4;
|
len = 4;
|
||||||
*((void **) Value) = ptr;
|
*((void **) Value) = ptr;
|
||||||
@ -730,7 +742,7 @@ APDGetField(StatementClass *stmt, SQLSMALLINT RecNumber,
|
|||||||
SQLINTEGER *StringLength)
|
SQLINTEGER *StringLength)
|
||||||
{
|
{
|
||||||
RETCODE ret = SQL_SUCCESS;
|
RETCODE ret = SQL_SUCCESS;
|
||||||
SQLINTEGER ival = 0, len;
|
SQLINTEGER ival = 0, len, rettype = 0;
|
||||||
PTR ptr = NULL;
|
PTR ptr = NULL;
|
||||||
const APDFields *opts = SC_get_APD(stmt);
|
const APDFields *opts = SC_get_APD(stmt);
|
||||||
|
|
||||||
@ -738,12 +750,15 @@ APDGetField(StatementClass *stmt, SQLSMALLINT RecNumber,
|
|||||||
switch (FieldIdentifier)
|
switch (FieldIdentifier)
|
||||||
{
|
{
|
||||||
case SQL_DESC_ARRAY_SIZE:
|
case SQL_DESC_ARRAY_SIZE:
|
||||||
|
rettype = SQL_IS_POINTER;
|
||||||
ival = opts->paramset_size;
|
ival = opts->paramset_size;
|
||||||
break;
|
break;
|
||||||
case SQL_DESC_ARRAY_STATUS_PTR:
|
case SQL_DESC_ARRAY_STATUS_PTR:
|
||||||
|
rettype = SQL_IS_POINTER;
|
||||||
ptr = opts->param_operation_ptr;
|
ptr = opts->param_operation_ptr;
|
||||||
break;
|
break;
|
||||||
case SQL_DESC_BIND_OFFSET_PTR:
|
case SQL_DESC_BIND_OFFSET_PTR:
|
||||||
|
rettype = SQL_IS_POINTER;
|
||||||
ptr = opts->param_offset_ptr;
|
ptr = opts->param_offset_ptr;
|
||||||
break;
|
break;
|
||||||
case SQL_DESC_BIND_TYPE:
|
case SQL_DESC_BIND_TYPE:
|
||||||
@ -783,15 +798,18 @@ APDGetField(StatementClass *stmt, SQLSMALLINT RecNumber,
|
|||||||
ival = opts->parameters[RecNumber - 1].CType;
|
ival = opts->parameters[RecNumber - 1].CType;
|
||||||
break;
|
break;
|
||||||
case SQL_DESC_DATA_PTR:
|
case SQL_DESC_DATA_PTR:
|
||||||
|
rettype = SQL_IS_POINTER;
|
||||||
ptr = opts->parameters[RecNumber - 1].buffer;
|
ptr = opts->parameters[RecNumber - 1].buffer;
|
||||||
break;
|
break;
|
||||||
case SQL_DESC_INDICATOR_PTR:
|
case SQL_DESC_INDICATOR_PTR:
|
||||||
|
rettype = SQL_IS_POINTER;
|
||||||
ptr = opts->parameters[RecNumber - 1].used;
|
ptr = opts->parameters[RecNumber - 1].used;
|
||||||
break;
|
break;
|
||||||
case SQL_DESC_OCTET_LENGTH:
|
case SQL_DESC_OCTET_LENGTH:
|
||||||
ival = opts->parameters[RecNumber - 1].buflen;
|
ival = opts->parameters[RecNumber - 1].buflen;
|
||||||
break;
|
break;
|
||||||
case SQL_DESC_OCTET_LENGTH_PTR:
|
case SQL_DESC_OCTET_LENGTH_PTR:
|
||||||
|
rettype = SQL_IS_POINTER;
|
||||||
ptr = opts->parameters[RecNumber - 1].used;
|
ptr = opts->parameters[RecNumber - 1].used;
|
||||||
break;
|
break;
|
||||||
case SQL_DESC_COUNT:
|
case SQL_DESC_COUNT:
|
||||||
@ -800,33 +818,21 @@ APDGetField(StatementClass *stmt, SQLSMALLINT RecNumber,
|
|||||||
case SQL_DESC_ALLOC_TYPE: /* read-only */
|
case SQL_DESC_ALLOC_TYPE: /* read-only */
|
||||||
ival = SQL_DESC_ALLOC_AUTO;
|
ival = SQL_DESC_ALLOC_AUTO;
|
||||||
break;
|
break;
|
||||||
|
case SQL_DESC_PRECISION:
|
||||||
|
case SQL_DESC_SCALE:
|
||||||
case SQL_DESC_DATETIME_INTERVAL_PRECISION:
|
case SQL_DESC_DATETIME_INTERVAL_PRECISION:
|
||||||
case SQL_DESC_LENGTH:
|
case SQL_DESC_LENGTH:
|
||||||
case SQL_DESC_NUM_PREC_RADIX:
|
case SQL_DESC_NUM_PREC_RADIX:
|
||||||
case SQL_DESC_PRECISION:
|
|
||||||
case SQL_DESC_SCALE:
|
|
||||||
default:ret = SQL_ERROR;
|
default:ret = SQL_ERROR;
|
||||||
stmt->errornumber = STMT_INVALID_DESCRIPTOR_IDENTIFIER;
|
stmt->errornumber = STMT_INVALID_DESCRIPTOR_IDENTIFIER;
|
||||||
}
|
}
|
||||||
switch (BufferLength)
|
switch (rettype)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
case SQL_IS_INTEGER:
|
case SQL_IS_INTEGER:
|
||||||
len = 4;
|
len = 4;
|
||||||
*((Int4 *) Value) = ival;
|
*((Int4 *) Value) = ival;
|
||||||
break;
|
break;
|
||||||
case SQL_IS_UINTEGER:
|
|
||||||
len = 4;
|
|
||||||
*((UInt4 *) Value) = ival;
|
|
||||||
break;
|
|
||||||
case SQL_IS_SMALLINT:
|
|
||||||
len = 2;
|
|
||||||
*((SQLSMALLINT *) Value) = (SQLSMALLINT) ival;
|
|
||||||
break;
|
|
||||||
case SQL_IS_USMALLINT:
|
|
||||||
len = 2;
|
|
||||||
*((SQLUSMALLINT *) Value) = (SQLUSMALLINT) ival;
|
|
||||||
break;
|
|
||||||
case SQL_IS_POINTER:
|
case SQL_IS_POINTER:
|
||||||
len = 4;
|
len = 4;
|
||||||
*((void **) Value) = ptr;
|
*((void **) Value) = ptr;
|
||||||
@ -844,36 +850,33 @@ IRDGetField(StatementClass *stmt, SQLSMALLINT RecNumber,
|
|||||||
SQLINTEGER *StringLength)
|
SQLINTEGER *StringLength)
|
||||||
{
|
{
|
||||||
RETCODE ret = SQL_SUCCESS;
|
RETCODE ret = SQL_SUCCESS;
|
||||||
SQLINTEGER ival = 0, len;
|
SQLINTEGER ival = 0, len, rettype = 0;
|
||||||
PTR ptr = NULL;
|
PTR ptr = NULL;
|
||||||
|
BOOL bCallColAtt = FALSE;
|
||||||
const IRDFields *opts = SC_get_IRD(stmt);
|
const IRDFields *opts = SC_get_IRD(stmt);
|
||||||
|
|
||||||
switch (FieldIdentifier)
|
switch (FieldIdentifier)
|
||||||
{
|
{
|
||||||
case SQL_DESC_ARRAY_STATUS_PTR:
|
case SQL_DESC_ARRAY_STATUS_PTR:
|
||||||
|
rettype = SQL_IS_POINTER;
|
||||||
ptr = opts->rowStatusArray;
|
ptr = opts->rowStatusArray;
|
||||||
break;
|
break;
|
||||||
case SQL_DESC_ROWS_PROCESSED_PTR:
|
case SQL_DESC_ROWS_PROCESSED_PTR:
|
||||||
|
rettype = SQL_IS_POINTER;
|
||||||
ptr = opts->rowsFetched;
|
ptr = opts->rowsFetched;
|
||||||
break;
|
break;
|
||||||
case SQL_DESC_ALLOC_TYPE: /* read-only */
|
case SQL_DESC_ALLOC_TYPE: /* read-only */
|
||||||
|
ival = SQL_DESC_ALLOC_AUTO;
|
||||||
|
break;
|
||||||
case SQL_DESC_COUNT: /* read-only */
|
case SQL_DESC_COUNT: /* read-only */
|
||||||
case SQL_DESC_AUTO_UNIQUE_VALUE: /* read-only */
|
case SQL_DESC_AUTO_UNIQUE_VALUE: /* read-only */
|
||||||
case SQL_DESC_BASE_COLUMN_NAME: /* read-only */
|
|
||||||
case SQL_DESC_BASE_TABLE_NAME: /* read-only */
|
|
||||||
case SQL_DESC_CASE_SENSITIVE: /* read-only */
|
case SQL_DESC_CASE_SENSITIVE: /* read-only */
|
||||||
case SQL_DESC_CATALOG_NAME: /* read-only */
|
|
||||||
case SQL_DESC_CONCISE_TYPE: /* read-only */
|
case SQL_DESC_CONCISE_TYPE: /* read-only */
|
||||||
case SQL_DESC_DATETIME_INTERVAL_CODE: /* read-only */
|
case SQL_DESC_DATETIME_INTERVAL_CODE: /* read-only */
|
||||||
case SQL_DESC_DATETIME_INTERVAL_PRECISION: /* read-only */
|
case SQL_DESC_DATETIME_INTERVAL_PRECISION: /* read-only */
|
||||||
case SQL_DESC_DISPLAY_SIZE: /* read-only */
|
case SQL_DESC_DISPLAY_SIZE: /* read-only */
|
||||||
case SQL_DESC_FIXED_PREC_SCALE: /* read-only */
|
case SQL_DESC_FIXED_PREC_SCALE: /* read-only */
|
||||||
case SQL_DESC_LABEL: /* read-only */
|
|
||||||
case SQL_DESC_LENGTH: /* read-only */
|
case SQL_DESC_LENGTH: /* read-only */
|
||||||
case SQL_DESC_LITERAL_PREFIX: /* read-only */
|
|
||||||
case SQL_DESC_LITERAL_SUFFIX: /* read-only */
|
|
||||||
case SQL_DESC_LOCAL_TYPE_NAME: /* read-only */
|
|
||||||
case SQL_DESC_NAME: /* read-only */
|
|
||||||
case SQL_DESC_NULLABLE: /* read-only */
|
case SQL_DESC_NULLABLE: /* read-only */
|
||||||
case SQL_DESC_NUM_PREC_RADIX: /* read-only */
|
case SQL_DESC_NUM_PREC_RADIX: /* read-only */
|
||||||
case SQL_DESC_OCTET_LENGTH: /* read-only */
|
case SQL_DESC_OCTET_LENGTH: /* read-only */
|
||||||
@ -882,18 +885,40 @@ IRDGetField(StatementClass *stmt, SQLSMALLINT RecNumber,
|
|||||||
case SQL_DESC_ROWVER: /* read-only */
|
case SQL_DESC_ROWVER: /* read-only */
|
||||||
#endif /* ODBCVER */
|
#endif /* ODBCVER */
|
||||||
case SQL_DESC_SCALE: /* read-only */
|
case SQL_DESC_SCALE: /* read-only */
|
||||||
case SQL_DESC_SCHEMA_NAME: /* read-only */
|
|
||||||
case SQL_DESC_SEARCHABLE: /* read-only */
|
case SQL_DESC_SEARCHABLE: /* read-only */
|
||||||
case SQL_DESC_TABLE_NAME: /* read-only */
|
|
||||||
case SQL_DESC_TYPE: /* read-only */
|
case SQL_DESC_TYPE: /* read-only */
|
||||||
case SQL_DESC_TYPE_NAME: /* read-only */
|
|
||||||
case SQL_DESC_UNNAMED: /* read-only */
|
case SQL_DESC_UNNAMED: /* read-only */
|
||||||
case SQL_DESC_UNSIGNED: /* read-only */
|
case SQL_DESC_UNSIGNED: /* read-only */
|
||||||
case SQL_DESC_UPDATABLE: /* read-only */
|
case SQL_DESC_UPDATABLE: /* read-only */
|
||||||
|
bCallColAtt = TRUE;
|
||||||
|
break;
|
||||||
|
case SQL_DESC_BASE_COLUMN_NAME: /* read-only */
|
||||||
|
case SQL_DESC_BASE_TABLE_NAME: /* read-only */
|
||||||
|
case SQL_DESC_CATALOG_NAME: /* read-only */
|
||||||
|
case SQL_DESC_LABEL: /* read-only */
|
||||||
|
case SQL_DESC_LITERAL_PREFIX: /* read-only */
|
||||||
|
case SQL_DESC_LITERAL_SUFFIX: /* read-only */
|
||||||
|
case SQL_DESC_LOCAL_TYPE_NAME: /* read-only */
|
||||||
|
case SQL_DESC_NAME: /* read-only */
|
||||||
|
case SQL_DESC_SCHEMA_NAME: /* read-only */
|
||||||
|
case SQL_DESC_TABLE_NAME: /* read-only */
|
||||||
|
case SQL_DESC_TYPE_NAME: /* read-only */
|
||||||
|
rettype = SQL_NTS;
|
||||||
|
bCallColAtt = TRUE;
|
||||||
|
break;
|
||||||
default:ret = SQL_ERROR;
|
default:ret = SQL_ERROR;
|
||||||
stmt->errornumber = STMT_INVALID_DESCRIPTOR_IDENTIFIER;
|
stmt->errornumber = STMT_INVALID_DESCRIPTOR_IDENTIFIER;
|
||||||
}
|
}
|
||||||
switch (BufferLength)
|
if (bCallColAtt)
|
||||||
|
{
|
||||||
|
SQLSMALLINT pcbL;
|
||||||
|
|
||||||
|
ret = PGAPI_ColAttributes(stmt, RecNumber,
|
||||||
|
FieldIdentifier, Value, (SQLSMALLINT) BufferLength,
|
||||||
|
&pcbL, &ival);
|
||||||
|
len = pcbL;
|
||||||
|
}
|
||||||
|
switch (rettype)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
case SQL_IS_INTEGER:
|
case SQL_IS_INTEGER:
|
||||||
@ -904,14 +929,6 @@ IRDGetField(StatementClass *stmt, SQLSMALLINT RecNumber,
|
|||||||
len = 4;
|
len = 4;
|
||||||
*((UInt4 *) Value) = ival;
|
*((UInt4 *) Value) = ival;
|
||||||
break;
|
break;
|
||||||
case SQL_IS_SMALLINT:
|
|
||||||
len = 2;
|
|
||||||
*((SQLSMALLINT *) Value) = (SQLSMALLINT) ival;
|
|
||||||
break;
|
|
||||||
case SQL_IS_USMALLINT:
|
|
||||||
len = 2;
|
|
||||||
*((SQLUSMALLINT *) Value) = (SQLUSMALLINT) ival;
|
|
||||||
break;
|
|
||||||
case SQL_IS_POINTER:
|
case SQL_IS_POINTER:
|
||||||
len = 4;
|
len = 4;
|
||||||
*((void **) Value) = ptr;
|
*((void **) Value) = ptr;
|
||||||
@ -929,7 +946,7 @@ IPDGetField(StatementClass *stmt, SQLSMALLINT RecNumber,
|
|||||||
SQLINTEGER *StringLength)
|
SQLINTEGER *StringLength)
|
||||||
{
|
{
|
||||||
RETCODE ret = SQL_SUCCESS;
|
RETCODE ret = SQL_SUCCESS;
|
||||||
SQLINTEGER ival = 0, len;
|
SQLINTEGER ival = 0, len, rettype = 0;
|
||||||
PTR ptr = NULL;
|
PTR ptr = NULL;
|
||||||
const IPDFields *ipdopts = SC_get_IPD(stmt);
|
const IPDFields *ipdopts = SC_get_IPD(stmt);
|
||||||
const APDFields *apdopts = SC_get_APD(stmt);
|
const APDFields *apdopts = SC_get_APD(stmt);
|
||||||
@ -937,9 +954,11 @@ IPDGetField(StatementClass *stmt, SQLSMALLINT RecNumber,
|
|||||||
switch (FieldIdentifier)
|
switch (FieldIdentifier)
|
||||||
{
|
{
|
||||||
case SQL_DESC_ARRAY_STATUS_PTR:
|
case SQL_DESC_ARRAY_STATUS_PTR:
|
||||||
|
rettype = SQL_IS_POINTER;
|
||||||
ptr = ipdopts->param_status_ptr;
|
ptr = ipdopts->param_status_ptr;
|
||||||
break;
|
break;
|
||||||
case SQL_DESC_ROWS_PROCESSED_PTR:
|
case SQL_DESC_ROWS_PROCESSED_PTR:
|
||||||
|
rettype = SQL_IS_POINTER;
|
||||||
ptr = ipdopts->param_processed_ptr;
|
ptr = ipdopts->param_processed_ptr;
|
||||||
break;
|
break;
|
||||||
case SQL_DESC_UNNAMED: /* only SQL_UNNAMED is allowed */
|
case SQL_DESC_UNNAMED: /* only SQL_UNNAMED is allowed */
|
||||||
@ -981,8 +1000,24 @@ IPDGetField(StatementClass *stmt, SQLSMALLINT RecNumber,
|
|||||||
case SQL_DESC_PARAMETER_TYPE:
|
case SQL_DESC_PARAMETER_TYPE:
|
||||||
ival = apdopts->parameters[RecNumber - 1].paramType;
|
ival = apdopts->parameters[RecNumber - 1].paramType;
|
||||||
break;
|
break;
|
||||||
|
case SQL_DESC_PRECISION:
|
||||||
|
switch (apdopts->parameters[RecNumber - 1].CType)
|
||||||
|
{
|
||||||
|
case SQL_C_TYPE_DATE:
|
||||||
|
case SQL_C_TYPE_TIME:
|
||||||
|
case SQL_C_TYPE_TIMESTAMP:
|
||||||
|
case SQL_DATETIME:
|
||||||
|
ival = apdopts->parameters[RecNumber - 1].decimal_digits;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case SQL_DESC_SCALE:
|
case SQL_DESC_SCALE:
|
||||||
ival = apdopts->parameters[RecNumber - 1].scale ;
|
switch (apdopts->parameters[RecNumber - 1].CType)
|
||||||
|
{
|
||||||
|
case SQL_C_NUMERIC:
|
||||||
|
ival = apdopts->parameters[RecNumber - 1].decimal_digits;
|
||||||
|
break;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case SQL_DESC_ALLOC_TYPE: /* read-only */
|
case SQL_DESC_ALLOC_TYPE: /* read-only */
|
||||||
ival = SQL_DESC_ALLOC_AUTO;
|
ival = SQL_DESC_ALLOC_AUTO;
|
||||||
@ -996,7 +1031,6 @@ IPDGetField(StatementClass *stmt, SQLSMALLINT RecNumber,
|
|||||||
case SQL_DESC_NULLABLE: /* read-only */
|
case SQL_DESC_NULLABLE: /* read-only */
|
||||||
case SQL_DESC_NUM_PREC_RADIX:
|
case SQL_DESC_NUM_PREC_RADIX:
|
||||||
case SQL_DESC_OCTET_LENGTH:
|
case SQL_DESC_OCTET_LENGTH:
|
||||||
case SQL_DESC_PRECISION:
|
|
||||||
#if (ODBCVER >= 0x0350)
|
#if (ODBCVER >= 0x0350)
|
||||||
case SQL_DESC_ROWVER: /* read-only */
|
case SQL_DESC_ROWVER: /* read-only */
|
||||||
#endif /* ODBCVER */
|
#endif /* ODBCVER */
|
||||||
@ -1005,25 +1039,13 @@ IPDGetField(StatementClass *stmt, SQLSMALLINT RecNumber,
|
|||||||
default:ret = SQL_ERROR;
|
default:ret = SQL_ERROR;
|
||||||
stmt->errornumber = STMT_INVALID_DESCRIPTOR_IDENTIFIER;
|
stmt->errornumber = STMT_INVALID_DESCRIPTOR_IDENTIFIER;
|
||||||
}
|
}
|
||||||
switch (BufferLength)
|
switch (rettype)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
case SQL_IS_INTEGER:
|
case SQL_IS_INTEGER:
|
||||||
len = 4;
|
len = 4;
|
||||||
*((Int4 *) Value) = ival;
|
*((Int4 *) Value) = ival;
|
||||||
break;
|
break;
|
||||||
case SQL_IS_UINTEGER:
|
|
||||||
len = 4;
|
|
||||||
*((UInt4 *) Value) = ival;
|
|
||||||
break;
|
|
||||||
case SQL_IS_SMALLINT:
|
|
||||||
len = 2;
|
|
||||||
*((SQLSMALLINT *) Value) = (SQLSMALLINT) ival;
|
|
||||||
break;
|
|
||||||
case SQL_IS_USMALLINT:
|
|
||||||
len = 2;
|
|
||||||
*((SQLUSMALLINT *) Value) = (SQLUSMALLINT) ival;
|
|
||||||
break;
|
|
||||||
case SQL_IS_POINTER:
|
case SQL_IS_POINTER:
|
||||||
len = 4;
|
len = 4;
|
||||||
*((void **)Value) = ptr;
|
*((void **)Value) = ptr;
|
||||||
|
@ -265,6 +265,10 @@ RETCODE SQL_API PGAPI_GetDiagRec(SQLSMALLINT HandleType, SQLHANDLE Handle,
|
|||||||
SQLSMALLINT RecNumber, SQLCHAR *Sqlstate,
|
SQLSMALLINT RecNumber, SQLCHAR *Sqlstate,
|
||||||
SQLINTEGER *NativeError, SQLCHAR *MessageText,
|
SQLINTEGER *NativeError, SQLCHAR *MessageText,
|
||||||
SQLSMALLINT BufferLength, SQLSMALLINT *TextLength);
|
SQLSMALLINT BufferLength, SQLSMALLINT *TextLength);
|
||||||
|
RETCODE SQL_API PGAPI_GetDiagField(SQLSMALLINT HandleType, SQLHANDLE Handle,
|
||||||
|
SQLSMALLINT RecNumber, SQLSMALLINT DiagIdentifier,
|
||||||
|
PTR DiagInfoPtr, SQLSMALLINT BufferLength,
|
||||||
|
SQLSMALLINT *StringLengthPtr);
|
||||||
RETCODE SQL_API PGAPI_GetConnectAttr(HDBC ConnectionHandle,
|
RETCODE SQL_API PGAPI_GetConnectAttr(HDBC ConnectionHandle,
|
||||||
SQLINTEGER Attribute, PTR Value,
|
SQLINTEGER Attribute, PTR Value,
|
||||||
SQLINTEGER BufferLength, SQLINTEGER *StringLength);
|
SQLINTEGER BufferLength, SQLINTEGER *StringLength);
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
*
|
*
|
||||||
* Comments: See "notice.txt" for copyright and license information.
|
* Comments: See "notice.txt" for copyright and license information.
|
||||||
*
|
*
|
||||||
* $Id: psqlodbc.h,v 1.61 2002/03/28 08:08:06 inoue Exp $
|
* $Id: psqlodbc.h,v 1.62 2002/04/01 03:01:15 inoue Exp $
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -123,6 +123,7 @@ QR_Constructor()
|
|||||||
rv->rowset_size = 1;
|
rv->rowset_size = 1;
|
||||||
rv->haskeyset = 0;
|
rv->haskeyset = 0;
|
||||||
rv->keyset = NULL;
|
rv->keyset = NULL;
|
||||||
|
rv->rb_alloc = 0;
|
||||||
rv->rb_count = 0;
|
rv->rb_count = 0;
|
||||||
rv->rollback = NULL;
|
rv->rollback = NULL;
|
||||||
}
|
}
|
||||||
@ -233,6 +234,7 @@ QR_free_memory(QResultClass *self)
|
|||||||
if (self->rollback)
|
if (self->rollback)
|
||||||
{
|
{
|
||||||
free(self->rollback);
|
free(self->rollback);
|
||||||
|
self->rb_alloc = 0;
|
||||||
self->rb_count = 0;
|
self->rb_count = 0;
|
||||||
self->rollback = NULL;
|
self->rollback = NULL;
|
||||||
}
|
}
|
||||||
|
@ -74,7 +74,8 @@ struct QResultClass_
|
|||||||
char aborted; /* was aborted? */
|
char aborted; /* was aborted? */
|
||||||
char haskeyset; /* this result contains keyset ? */
|
char haskeyset; /* this result contains keyset ? */
|
||||||
KeySet *keyset;
|
KeySet *keyset;
|
||||||
UInt4 rb_count; /* count of rollback info */
|
UInt2 rb_alloc; /* count of allocated rollback info */
|
||||||
|
UInt2 rb_count; /* count of rollback info */
|
||||||
Rollback *rollback;
|
Rollback *rollback;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -491,7 +491,7 @@ PGAPI_ColAttributes(
|
|||||||
return SQL_SUCCESS;
|
return SQL_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stmt->parse_status != STMT_PARSE_FATAL && irdflds->fi && irdflds->fi[col_idx])
|
if (stmt->parse_status != STMT_PARSE_FATAL && irdflds->fi)
|
||||||
{
|
{
|
||||||
if (col_idx >= cols)
|
if (col_idx >= cols)
|
||||||
{
|
{
|
||||||
@ -500,9 +500,12 @@ PGAPI_ColAttributes(
|
|||||||
SC_log_error(func, "", stmt);
|
SC_log_error(func, "", stmt);
|
||||||
return SQL_ERROR;
|
return SQL_ERROR;
|
||||||
}
|
}
|
||||||
field_type = irdflds->fi[col_idx]->type;
|
if (irdflds->fi[col_idx])
|
||||||
if (field_type > 0)
|
{
|
||||||
parse_ok = TRUE;
|
field_type = irdflds->fi[col_idx]->type;
|
||||||
|
if (field_type > 0)
|
||||||
|
parse_ok = TRUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -756,14 +759,6 @@ inolog("COLUMN_TYPE=%d\n", value);
|
|||||||
|
|
||||||
if (rgbDesc)
|
if (rgbDesc)
|
||||||
{
|
{
|
||||||
#ifdef UNICODE_SUPPORT
|
|
||||||
if (conn->unicode)
|
|
||||||
{
|
|
||||||
len = utf8_to_ucs2(p, len, (SQLWCHAR *) rgbDesc, cbDescMax / 2);
|
|
||||||
len *= 2;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif /* UNICODE_SUPPORT */
|
|
||||||
strncpy_null((char *) rgbDesc, p, (size_t) cbDescMax);
|
strncpy_null((char *) rgbDesc, p, (size_t) cbDescMax);
|
||||||
|
|
||||||
if (len >= cbDescMax)
|
if (len >= cbDescMax)
|
||||||
@ -1343,8 +1338,6 @@ PGAPI_ExtendedFetch(
|
|||||||
#endif /* DRIVER_CURSOR_IMPLEMENT */
|
#endif /* DRIVER_CURSOR_IMPLEMENT */
|
||||||
else
|
else
|
||||||
*(rgfRowStatus + i) = SQL_ROW_SUCCESS;
|
*(rgfRowStatus + i) = SQL_ROW_SUCCESS;
|
||||||
if (rgfRowStatus[i] != SQL_ROW_SUCCESS)
|
|
||||||
inolog("rgfRowStatus[%d]=%d\n", i, rgfRowStatus[i]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1426,6 +1419,121 @@ static void KeySetSet(const TupleField *tuple, int num_fields, KeySet *keyset)
|
|||||||
sscanf(tuple[num_fields - 1].value, "%u", &keyset->oid);
|
sscanf(tuple[num_fields - 1].value, "%u", &keyset->oid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void AddRollback(ConnectionClass *conn, QResultClass *res, int index, const KeySet *keyset)
|
||||||
|
{
|
||||||
|
Rollback *rollback;
|
||||||
|
|
||||||
|
if (!res->rollback)
|
||||||
|
{
|
||||||
|
res->rb_count = 0;
|
||||||
|
res->rb_alloc = 10;
|
||||||
|
rollback = res->rollback = malloc(sizeof(Rollback) * res->rb_alloc);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (res->rb_count >= res->rb_alloc)
|
||||||
|
{
|
||||||
|
res->rb_alloc *= 2;
|
||||||
|
if (rollback = realloc(res->rollback, sizeof(Rollback) * res->rb_alloc), !rollback)
|
||||||
|
{
|
||||||
|
res->rb_alloc = res->rb_count = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
res->rollback = rollback;
|
||||||
|
}
|
||||||
|
rollback = res->rollback + res->rb_count;
|
||||||
|
}
|
||||||
|
rollback->index = index;
|
||||||
|
if (keyset)
|
||||||
|
{
|
||||||
|
rollback->blocknum = keyset[index].blocknum;
|
||||||
|
rollback->offset = keyset[index].offset;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rollback->offset = 0;
|
||||||
|
rollback->blocknum = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
conn->result_uncommitted = 1;
|
||||||
|
res->rb_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void DiscardRollback(QResultClass *res)
|
||||||
|
{
|
||||||
|
int i, index;
|
||||||
|
UWORD status;
|
||||||
|
Rollback *rollback;
|
||||||
|
KeySet *keyset;
|
||||||
|
|
||||||
|
if (0 == res->rb_count || NULL == res->rollback)
|
||||||
|
return;
|
||||||
|
rollback = res->rollback;
|
||||||
|
keyset = res->keyset;
|
||||||
|
for (i = 0; i < res->rb_count; i++)
|
||||||
|
{
|
||||||
|
index = rollback[i].index;
|
||||||
|
status = keyset[index].status;
|
||||||
|
keyset[index].status &= ~(CURS_SELF_DELETING | CURS_SELF_UPDATING | CURS_SELF_ADDING);
|
||||||
|
keyset[index].status |= ((status & (CURS_SELF_DELETING | CURS_SELF_UPDATING | CURS_SELF_ADDING)) << 3);
|
||||||
|
}
|
||||||
|
free(rollback);
|
||||||
|
res->rollback = NULL;
|
||||||
|
res->rb_count = res->rb_alloc = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void UndoRollback(QResultClass *res)
|
||||||
|
{
|
||||||
|
int i, index;
|
||||||
|
UWORD status;
|
||||||
|
Rollback *rollback;
|
||||||
|
KeySet *keyset;
|
||||||
|
|
||||||
|
if (0 == res->rb_count || NULL == res->rollback)
|
||||||
|
return;
|
||||||
|
rollback = res->rollback;
|
||||||
|
keyset = res->keyset;
|
||||||
|
for (i = res->rb_count - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
index = rollback[i].index;
|
||||||
|
status = keyset[index].status;
|
||||||
|
if ((status & CURS_SELF_ADDING) != 0)
|
||||||
|
{
|
||||||
|
if (index < res->fcount)
|
||||||
|
res->fcount = index;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
keyset[index].status &= ~(CURS_SELF_DELETING | CURS_SELF_UPDATING | CURS_SELF_ADDING | KEYSET_INFO_PUBLIC);
|
||||||
|
keyset[index].blocknum = rollback[i].blocknum;
|
||||||
|
keyset[index].offset = rollback[i].offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(rollback);
|
||||||
|
res->rollback = NULL;
|
||||||
|
res->rb_count = res->rb_alloc = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProcessRollback(ConnectionClass *conn, BOOL undo)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
StatementClass *stmt;
|
||||||
|
QResultClass *res;
|
||||||
|
|
||||||
|
for (i = 0; i < conn->num_stmts; i++)
|
||||||
|
{
|
||||||
|
if (stmt = conn->stmts[i], !stmt)
|
||||||
|
continue;
|
||||||
|
for (res = SC_get_Result(stmt); res; res = res->next)
|
||||||
|
{
|
||||||
|
if (undo)
|
||||||
|
UndoRollback(res);
|
||||||
|
else
|
||||||
|
DiscardRollback(res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#define LATEST_TUPLE_LOAD 1L
|
#define LATEST_TUPLE_LOAD 1L
|
||||||
#define USE_INSERTED_TID (1L << 1)
|
#define USE_INSERTED_TID (1L << 1)
|
||||||
static QResultClass *
|
static QResultClass *
|
||||||
@ -1534,7 +1642,8 @@ SC_pos_reload(StatementClass *stmt, UWORD irow, UDWORD global_ridx, UWORD *count
|
|||||||
ret = SQL_SUCCESS_WITH_INFO;
|
ret = SQL_SUCCESS_WITH_INFO;
|
||||||
if (stmt->options.cursor_type == SQL_CURSOR_KEYSET_DRIVEN)
|
if (stmt->options.cursor_type == SQL_CURSOR_KEYSET_DRIVEN)
|
||||||
{
|
{
|
||||||
res->keyset[global_ridx].oid = 0;
|
res->keyset[global_ridx].blocknum = 0;
|
||||||
|
res->keyset[global_ridx].offset = 0;
|
||||||
res->keyset[global_ridx].status |= SQL_ROW_DELETED;
|
res->keyset[global_ridx].status |= SQL_ROW_DELETED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1670,6 +1779,7 @@ SC_pos_update(StatementClass *stmt,
|
|||||||
num_cols,
|
num_cols,
|
||||||
upd_cols;
|
upd_cols;
|
||||||
QResultClass *res;
|
QResultClass *res;
|
||||||
|
ConnectionClass *conn = SC_get_conn(stmt);
|
||||||
ARDFields *opts = SC_get_ARD(stmt);
|
ARDFields *opts = SC_get_ARD(stmt);
|
||||||
IRDFields *irdflds = SC_get_IRD(stmt);
|
IRDFields *irdflds = SC_get_IRD(stmt);
|
||||||
BindInfoClass *bindings = opts->bindings;
|
BindInfoClass *bindings = opts->bindings;
|
||||||
@ -1735,7 +1845,7 @@ SC_pos_update(StatementClass *stmt,
|
|||||||
sprintf(updstr, "%s where ctid = '(%u, %u)' and oid = %u", updstr,
|
sprintf(updstr, "%s where ctid = '(%u, %u)' and oid = %u", updstr,
|
||||||
blocknum, pgoffset, oid);
|
blocknum, pgoffset, oid);
|
||||||
mylog("updstr=%s\n", updstr);
|
mylog("updstr=%s\n", updstr);
|
||||||
if (PGAPI_AllocStmt(SC_get_conn(stmt), &hstmt) != SQL_SUCCESS)
|
if (PGAPI_AllocStmt(conn, &hstmt) != SQL_SUCCESS)
|
||||||
return SQL_ERROR;
|
return SQL_ERROR;
|
||||||
qstmt = (StatementClass *) hstmt;
|
qstmt = (StatementClass *) hstmt;
|
||||||
apdopts = SC_get_APD(qstmt);
|
apdopts = SC_get_APD(qstmt);
|
||||||
@ -1788,8 +1898,11 @@ SC_pos_update(StatementClass *stmt,
|
|||||||
}
|
}
|
||||||
if (SQL_SUCCESS == ret && res->keyset)
|
if (SQL_SUCCESS == ret && res->keyset)
|
||||||
{
|
{
|
||||||
if (CC_is_in_trans(SC_get_conn(stmt)))
|
if (CC_is_in_trans(conn))
|
||||||
|
{
|
||||||
|
AddRollback(conn, res, global_ridx, res->keyset);
|
||||||
res->keyset[global_ridx].status |= (SQL_ROW_UPDATED | CURS_SELF_UPDATING);
|
res->keyset[global_ridx].status |= (SQL_ROW_UPDATED | CURS_SELF_UPDATING);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
res->keyset[global_ridx].status |= (SQL_ROW_UPDATED | CURS_SELF_UPDATED);
|
res->keyset[global_ridx].status |= (SQL_ROW_UPDATED | CURS_SELF_UPDATED);
|
||||||
}
|
}
|
||||||
@ -1815,12 +1928,12 @@ SC_pos_delete(StatementClass *stmt,
|
|||||||
{
|
{
|
||||||
UWORD offset;
|
UWORD offset;
|
||||||
QResultClass *res, *qres;
|
QResultClass *res, *qres;
|
||||||
|
ConnectionClass *conn = SC_get_conn(stmt);
|
||||||
ARDFields *opts = SC_get_ARD(stmt);
|
ARDFields *opts = SC_get_ARD(stmt);
|
||||||
IRDFields *irdflds = SC_get_IRD(stmt);
|
IRDFields *irdflds = SC_get_IRD(stmt);
|
||||||
BindInfoClass *bindings = opts->bindings;
|
BindInfoClass *bindings = opts->bindings;
|
||||||
char dltstr[4096];
|
char dltstr[4096];
|
||||||
RETCODE ret;
|
RETCODE ret;
|
||||||
/*const char *oidval;*/
|
|
||||||
UInt4 oid, blocknum;
|
UInt4 oid, blocknum;
|
||||||
|
|
||||||
mylog("POS DELETE ti=%x\n", stmt->ti);
|
mylog("POS DELETE ti=%x\n", stmt->ti);
|
||||||
@ -1844,7 +1957,7 @@ SC_pos_delete(StatementClass *stmt,
|
|||||||
stmt->ti[0]->name, blocknum, offset, oid);
|
stmt->ti[0]->name, blocknum, offset, oid);
|
||||||
|
|
||||||
mylog("dltstr=%s\n", dltstr);
|
mylog("dltstr=%s\n", dltstr);
|
||||||
qres = CC_send_query(SC_get_conn(stmt), dltstr, NULL, CLEAR_RESULT_ON_ABORT);
|
qres = CC_send_query(conn, dltstr, NULL, CLEAR_RESULT_ON_ABORT);
|
||||||
ret = SQL_SUCCESS;
|
ret = SQL_SUCCESS;
|
||||||
if (qres && QR_command_successful(qres))
|
if (qres && QR_command_successful(qres))
|
||||||
{
|
{
|
||||||
@ -1881,8 +1994,11 @@ SC_pos_delete(StatementClass *stmt,
|
|||||||
QR_Destructor(qres);
|
QR_Destructor(qres);
|
||||||
if (SQL_SUCCESS == ret && res->keyset)
|
if (SQL_SUCCESS == ret && res->keyset)
|
||||||
{
|
{
|
||||||
if (CC_is_in_trans(SC_get_conn(stmt)))
|
if (CC_is_in_trans(conn))
|
||||||
|
{
|
||||||
|
AddRollback(conn, res, global_ridx, res->keyset);
|
||||||
res->keyset[global_ridx].status |= (SQL_ROW_DELETED | CURS_SELF_DELETING);
|
res->keyset[global_ridx].status |= (SQL_ROW_DELETED | CURS_SELF_DELETING);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
res->keyset[global_ridx].status |= (SQL_ROW_DELETED | CURS_SELF_DELETED);
|
res->keyset[global_ridx].status |= (SQL_ROW_DELETED | CURS_SELF_DELETED);
|
||||||
}
|
}
|
||||||
@ -1988,7 +2104,7 @@ SC_pos_add(StatementClass *stmt,
|
|||||||
num_cols = irdflds->nfields;
|
num_cols = irdflds->nfields;
|
||||||
conn = SC_get_conn(stmt);
|
conn = SC_get_conn(stmt);
|
||||||
sprintf(addstr, "insert into \"%s\" (", stmt->ti[0]->name);
|
sprintf(addstr, "insert into \"%s\" (", stmt->ti[0]->name);
|
||||||
if (PGAPI_AllocStmt(SC_get_conn(stmt), &hstmt) != SQL_SUCCESS)
|
if (PGAPI_AllocStmt(conn, &hstmt) != SQL_SUCCESS)
|
||||||
return SQL_ERROR;
|
return SQL_ERROR;
|
||||||
if (opts->row_offset_ptr)
|
if (opts->row_offset_ptr)
|
||||||
offset = *opts->row_offset_ptr;
|
offset = *opts->row_offset_ptr;
|
||||||
@ -2068,10 +2184,15 @@ SC_pos_add(StatementClass *stmt,
|
|||||||
PGAPI_FreeStmt(hstmt, SQL_DROP);
|
PGAPI_FreeStmt(hstmt, SQL_DROP);
|
||||||
if (SQL_SUCCESS == ret && res->keyset)
|
if (SQL_SUCCESS == ret && res->keyset)
|
||||||
{
|
{
|
||||||
|
int global_ridx = res->fcount - 1;
|
||||||
if (CC_is_in_trans(conn))
|
if (CC_is_in_trans(conn))
|
||||||
res->keyset[res->fcount - 1].status |= (SQL_ROW_ADDED | CURS_SELF_ADDING);
|
{
|
||||||
|
|
||||||
|
AddRollback(conn, res, global_ridx, NULL);
|
||||||
|
res->keyset[global_ridx].status |= (SQL_ROW_ADDED | CURS_SELF_ADDING);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
res->keyset[res->fcount - 1].status |= (SQL_ROW_ADDED | CURS_SELF_ADDED);
|
res->keyset[global_ridx].status |= (SQL_ROW_ADDED | CURS_SELF_ADDED);
|
||||||
}
|
}
|
||||||
#if (ODBCVER >= 0x0300)
|
#if (ODBCVER >= 0x0300)
|
||||||
if (irdflds->rowStatusArray)
|
if (irdflds->rowStatusArray)
|
||||||
|
@ -503,8 +503,8 @@ SC_recycle_statement(StatementClass *self)
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < self->ntab; i++)
|
for (i = 0; i < self->ntab; i++)
|
||||||
if (self->ti)
|
if (self->ti[i])
|
||||||
free(self->ti);
|
free(self->ti[i]);
|
||||||
self->ti = NULL;
|
self->ti = NULL;
|
||||||
self->ntab = 0;
|
self->ntab = 0;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user