]> granicus.if.org Git - postgresql/commitdiff
1) Add rollback functionality to updatable cursors.
authorHiroshi Inoue <inoue@tpf.co.jp>
Mon, 1 Apr 2002 03:01:15 +0000 (03:01 +0000)
committerHiroshi Inoue <inoue@tpf.co.jp>
Mon, 1 Apr 2002 03:01:15 +0000 (03:01 +0000)
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.

17 files changed:
src/interfaces/odbc/bind.c
src/interfaces/odbc/bind.h
src/interfaces/odbc/connection.c
src/interfaces/odbc/connection.h
src/interfaces/odbc/convert.c
src/interfaces/odbc/convert.h
src/interfaces/odbc/descriptor.h
src/interfaces/odbc/odbcapi30.c
src/interfaces/odbc/odbcapi30w.c
src/interfaces/odbc/parse.c
src/interfaces/odbc/pgapi30.c
src/interfaces/odbc/pgapifunc.h
src/interfaces/odbc/psqlodbc.h
src/interfaces/odbc/qresult.c
src/interfaces/odbc/qresult.h
src/interfaces/odbc/results.c
src/interfaces/odbc/statement.c

index 397d984ec6c6bea046295fc1f36e27abe445d8e1..e931b8b8d51766aaf5332b2c5d8501cfe2916071 100644 (file)
@@ -67,8 +67,8 @@ PGAPI_BindParameter(
        opts->parameters[ipar].paramType = fParamType;
        opts->parameters[ipar].CType = fCType;
        opts->parameters[ipar].SQLType = fSqlType;
-       opts->parameters[ipar].precision = cbColDef;
-       opts->parameters[ipar].scale = ibScale;
+       opts->parameters[ipar].column_size = cbColDef;
+       opts->parameters[ipar].decimal_digits = ibScale;
 
        /*
         * If rebinding a parameter that had data-at-exec stuff in it, then
@@ -276,10 +276,10 @@ PGAPI_DescribeParam(
                *pfSqlType = opts->parameters[ipar].SQLType;
 
        if (pcbColDef)
-               *pcbColDef = opts->parameters[ipar].precision;
+               *pcbColDef = opts->parameters[ipar].column_size;
 
        if (pibScale)
-               *pibScale = opts->parameters[ipar].scale;
+               *pibScale = opts->parameters[ipar].decimal_digits;
 
        if (pfNullable)
                *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].SQLType = 0;
-       self->parameters[ipar].precision = 0;
-       self->parameters[ipar].scale = 0;
+       self->parameters[ipar].column_size = 0;
+       self->parameters[ipar].decimal_digits = 0;
        self->parameters[ipar].data_at_exec = FALSE;
        self->parameters[ipar].lobj_oid = 0;
 }
index 16d9f84b6e62817acef49146a8e4c543c22129cb..7eadea92e44c41a42b2bb4440ef7741b720c8258 100644 (file)
@@ -40,8 +40,8 @@ struct ParameterInfoClass_
        Int2            paramType;
        Int2            CType;
        Int2            SQLType;
-       UInt4           precision;
-       Int2            scale;
+       UInt4           column_size;
+       Int2            decimal_digits;
        Oid                     lobj_oid;
        Int4       *EXEC_used;          /* amount of data OR the oid of the large
                                                                 * object */
index db237b3f952866b79caedca309648bc374bacde4..d6b622a16d736df112b019bad220bcd78d9e9bdd 100644 (file)
@@ -288,6 +288,7 @@ CC_Constructor()
                rv->pg_version_minor = 0;
                rv->ms_jet = 0;
                rv->unicode = 0;
+               rv->result_uncommitted = 0;
 #ifdef MULTIBYTE
                rv->client_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 (set_no_trans)
-                       CC_set_no_trans(conn);
+#ifdef DRIVER_CURSOR_IMPLEMENT
+               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)
 {
        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)
                        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)
-                                               CC_on_commit(self, TRUE);
+                                               CC_on_commit(self);
                                        else if (strnicmp(cmdbuffer, "ROLLBACK", 8) == 0)
                                                CC_on_abort(self, TRUE);
                                        else if (strnicmp(cmdbuffer, "END", 3) == 0)
-                                               CC_on_commit(self, TRUE);
+                                               CC_on_commit(self);
                                        else if (strnicmp(cmdbuffer, "ABORT", 5) == 0)
                                                CC_on_abort(self, TRUE);
 
index 67411edd67a9dc6d4fdadb3abfba3a38c9d8e367..5d01dacd2148f368f40fc60c734d14e6a2fb7da0 100644 (file)
@@ -272,6 +272,7 @@ struct ConnectionClass_
        Int2            pg_version_minor;
        char            ms_jet;
        char            unicode;
+       char            result_uncommitted;
 #ifdef MULTIBYTE
        char       *client_encoding;
        char       *server_encoding;
@@ -318,8 +319,9 @@ void                CC_lookup_pg_version(ConnectionClass *conn);
 void           CC_initialize_pg_version(ConnectionClass *conn);
 void           CC_log_error(const char *func, const char *desc, 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           ProcessRollback(ConnectionClass *conn, BOOL undo);
 
 /* CC_send_query_options */
 #define        CLEAR_RESULT_ON_ABORT   1L
index c0a2706ef6116763577986c40d5d0dc3d02e8ebb..e4232137fef7dd292c2cdee3ec182b7f92abe69b 100644 (file)
@@ -265,6 +265,16 @@ stime2timestamp(const SIMPLE_TIME *st, char *str, BOOL bZone, BOOL precision)
        int                     i;
 
        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)
        {
                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_TIMESTAMP:
                        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)
                        {
                                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
  */
 char
-parse_datetime(char *buf, SIMPLE_TIME *st)
+parse_datetime(const char *buf, SIMPLE_TIME *st)
 {
        int                     y,
                                m,
index 2d5f01859f04dd87f253549a7a4f77f371d28151..1ca0b1bb0c94e251271eaccf2b4554b0ffc4ebf2 100644 (file)
@@ -25,6 +25,7 @@
 
 typedef struct
 {
+       int             infinity;
        int                     m;
        int                     d;
        int                     y;
@@ -42,7 +43,7 @@ int                   copy_statement_with_parameters(StatementClass *stmt);
 int            convert_escape(const char *value, StatementClass *stmt,
                        int *npos, int *stsize, const char **val_resume);
 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_special_chars(const char *si, char *dst, int used, BOOL convlf,int ccsc);
 
index 58036914ada6f94cf119f099a5b8e7a77eb072c6..5186810b21799e3b97c63e0a44b04b79cbb6d08c 100644 (file)
@@ -5,7 +5,7 @@
  *
  * 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   ARD_unbind_cols(ARDFields *self, BOOL freeall);
 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
index 0e9b63a304961eb27c78b9aadb522fa931a30040..8bcb1cab146bfd49929c38cb56a3b191e9d5edaf 100644 (file)
@@ -235,7 +235,8 @@ SQLGetDiagField(SQLSMALLINT HandleType, SQLHANDLE Handle,
                                SQLSMALLINT *StringLength)
 {
        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 */
index 0273f97b6b95376917d9ad1bbb7088c3e7f93604..ac0f1d9931fe361332929a3c06290a9e5b69ca7a 100644 (file)
@@ -89,10 +89,25 @@ SQLSetDescFieldW(SQLHDESC DescriptorHandle, SQLSMALLINT RecNumber,
        mylog("[SQLSetDescFieldW]");
        if (BufferLength > 0)
        {
-               uval = ucs2_to_utf8(Value, BufferLength / 2, &vallen);
-               val_alloced = TRUE;
+               switch (FieldIdentifier)
+               {
+                       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;
                vallen = BufferLength;
@@ -109,11 +124,49 @@ SQLGetDescFieldW(SQLHDESC hdesc, SQLSMALLINT iRecord, SQLSMALLINT iField,
                                SQLINTEGER *pcbValue)
 {
        RETCODE ret;
-        char    *qstr = NULL, *mtxt = NULL;
+       BOOL    alloced = FALSE;
+       SQLINTEGER      blen, bMax, *pcbV;
+        char    *rgbV = NULL;
 
        mylog("[SQLGetDescFieldW]");
-       ret = PGAPI_GetDescField(hdesc, iRecord, iField, rgbValue,
-                               cbValueMax, pcbValue);
+       switch (iField)
+       {
+               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;
 }
 
@@ -171,6 +224,9 @@ RETCODE SQL_API SQLColAttributeW(
     SQLINTEGER                   *pfDesc)
 {
        RETCODE ret;
+       BOOL    alloced = FALSE;
+       SQLSMALLINT     *rgbL, blen, bMax;
+        char    *rgbD = NULL;
 
        mylog("[SQLColAttributeW]");
        switch (fDescType)
@@ -187,11 +243,35 @@ RETCODE SQL_API SQLColAttributeW(
                case SQL_DESC_TABLE_NAME:
                case SQL_DESC_TYPE_NAME:
                case SQL_COLUMN_NAME:
+                       alloced = TRUE;
+                       bMax = cbDescMax * 3 / 2;
+                       rgbD = malloc(bMax + 1);
+                       rgbL = &blen;
                        break;
+               default:
+                       rgbD = rgbDesc;
+                       bMax = cbDescMax;
+                       rgbL = pcbDesc;
+                       break;
        }
 
-       ret = PGAPI_ColAttributes(hstmt, icol, fDescType, rgbDesc,
-               cbDescMax, pcbDesc, pfDesc);
+       ret = PGAPI_ColAttributes(hstmt, icol, fDescType, rgbD,
+               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;
 }
index 3549ff2ef7a0beae70b79b0c8fd9b28e70799c09..d86e62f85bb0af7cdc40320683638b4d998746ef 100644 (file)
@@ -304,7 +304,8 @@ parse_statement(StatementClass *stmt)
                                in_on = FALSE,
                                in_from = FALSE,
                                in_where = FALSE,
-                               in_table = FALSE;
+                               in_table = FALSE,
+                               out_table = TRUE;
        char            in_field = FALSE,
                                in_expr = FALSE,
                                in_func = FALSE,
@@ -610,12 +611,21 @@ parse_statement(StatementClass *stmt)
 
                if (in_from)
                {
-                       if (!in_table)
+                       if (token[0] == ';')
                        {
-                               if (!token[0])
+                               in_from = FALSE;
+                               break;
+                       }
+                       switch (token[0])
+                       {
+                               case '\0':
                                        continue;
-                               if (token[0] == ';')
-                                       break;
+                               case ',':
+                                       out_table = TRUE; 
+                                       continue;
+                       }
+                       if (out_table && !in_table) /* new table */
+                       {
 
                                if (!(stmt->ntab % TAB_INCR))
                                {
@@ -660,22 +670,47 @@ parse_statement(StatementClass *stmt)
                                mylog("got table = '%s'\n", ti[stmt->ntab]->name);
 
                                if (delim == ',')
+                               {
+                                       out_table = TRUE;
                                        mylog("more than 1 tables\n");
+                               }
                                else
+                               {
+                                       out_table = FALSE;
                                        in_table = TRUE;
+                               }
                                stmt->ntab++;
                                continue;
                        }
 
-                       if (token[0] == ';')
-                               break;
-                       if (stricmp(token, "as"))
+                       if (!dquote && stricmp(token, "JOIN") == 0)
+                       {
+                               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);
                                mylog("alias for table '%s' is '%s'\n", ti[stmt->ntab - 1]->name, ti[stmt->ntab - 1]->alias);
                                in_table = FALSE;
                                if (delim == ',')
+                               {
+                                       out_table = TRUE;
                                        mylog("more than 1 tables\n");
+                               }
                        }
                } /* in_from */
        }
index a67cc434fab5c1dca776dbbbed57540429ee4929..e73773931565aa784db8702d240c5d10c7c65536 100644 (file)
@@ -27,7 +27,7 @@
 #include "descriptor.h"
 #include "pgapifunc.h"
 
-static HSTMT statementHandleFromDescHandle(HSTMT, SQLINTEGER *descType); 
+static HSTMT statementHandleFromDescHandle(SQLHDESC, SQLINTEGER *descType); 
 /*     SQLError -> SQLDiagRec */
 RETCODE                SQL_API
 PGAPI_GetDiagRec(SQLSMALLINT HandleType, SQLHANDLE Handle,
@@ -75,7 +75,7 @@ PGAPI_GetDiagField(SQLSMALLINT HandleType, SQLHANDLE Handle,
                PTR DiagInfoPtr, SQLSMALLINT BufferLength,
                SQLSMALLINT *StringLengthPtr)
 {
-       RETCODE         ret = SQL_SUCCESS;
+       RETCODE         ret = SQL_ERROR;
        static const char *func = "PGAPI_GetDiagField";
 
        mylog("%s entering rec=%d", func, RecNumber);
@@ -122,6 +122,7 @@ PGAPI_GetDiagField(SQLSMALLINT HandleType, SQLHANDLE Handle,
                                case SQL_DIAG_NUMBER:
                                case SQL_DIAG_RETURNCODE:
                                case SQL_DIAG_SERVER_NAME:
+                                       break;
                                case SQL_DIAG_SQLSTATE:
                                        break;
                        }
@@ -154,7 +155,12 @@ PGAPI_GetConnectAttr(HDBC ConnectionHandle,
                        *((SQLUINTEGER *) Value) = SQL_FALSE;
                        break;
                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;
                case SQL_ATTR_CONNECTION_TIMEOUT:
                        *((SQLUINTEGER *) Value) = 0;
@@ -172,7 +178,7 @@ PGAPI_GetConnectAttr(HDBC ConnectionHandle,
        return ret;
 }
 
-static HSTMT
+static SQLHDESC
 descHandleFromStatementHandle(HSTMT StatementHandle, SQLINTEGER descType) 
 {
        switch (descType)
@@ -189,7 +195,7 @@ descHandleFromStatementHandle(HSTMT StatementHandle, SQLINTEGER descType)
        return (HSTMT) 0;
 }
 static HSTMT
-statementHandleFromDescHandle(HSTMT DescHandle, SQLINTEGER *descType) 
+statementHandleFromDescHandle(SQLHDESC DescHandle, SQLINTEGER *descType) 
 {
        SQLUINTEGER res = (SQLUINTEGER) DescHandle % 4;
        if (descType)
@@ -209,6 +215,19 @@ statementHandleFromDescHandle(HSTMT DescHandle, SQLINTEGER *descType)
        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)
 {
        int     i;
@@ -568,7 +587,7 @@ IPDSetField(StatementClass *stmt, SQLSMALLINT RecNumber,
                        apdopts->parameters[RecNumber - 1].paramType = (Int2) Value;
                        break;
                case SQL_DESC_SCALE:
-                       apdopts->parameters[RecNumber - 1].scale = (Int2) Value;
+                       apdopts->parameters[RecNumber - 1].decimal_digits = (Int2) Value;
                        break;
                case SQL_DESC_ALLOC_TYPE: /* read-only */ 
                case SQL_DESC_CASE_SENSITIVE: /* read-only */
@@ -599,7 +618,7 @@ ARDGetField(StatementClass *stmt, SQLSMALLINT RecNumber,
                SQLINTEGER *StringLength)
 {
        RETCODE         ret = SQL_SUCCESS;
-       SQLINTEGER      len, ival;
+       SQLINTEGER      len, ival, rettype = 0;
        PTR             ptr = NULL;
        const ARDFields *opts = SC_get_ARD(stmt);
 
@@ -610,9 +629,11 @@ ARDGetField(StatementClass *stmt, SQLSMALLINT RecNumber,
                        ival = opts->rowset_size;
                        break; 
                case SQL_DESC_ARRAY_STATUS_PTR:
+                       rettype = SQL_IS_POINTER;
                        ptr = opts->row_operation_ptr;
                        break;
                case SQL_DESC_BIND_OFFSET_PTR:
+                       rettype = SQL_IS_POINTER;
                        ptr = opts->row_offset_ptr;
                        break;
                case SQL_DESC_BIND_TYPE:
@@ -651,6 +672,7 @@ ARDGetField(StatementClass *stmt, SQLSMALLINT RecNumber,
                        ival = opts->bindings[RecNumber - 1].returntype;
                        break;
                case SQL_DESC_DATA_PTR:
+                       rettype = SQL_IS_POINTER;
                        if (!RecNumber)
                                ptr = opts->bookmark->buffer;
                        else
@@ -659,6 +681,7 @@ ARDGetField(StatementClass *stmt, SQLSMALLINT RecNumber,
                        }
                        break;
                case SQL_DESC_INDICATOR_PTR:
+                       rettype = SQL_IS_POINTER;
                        if (!RecNumber)
                                ptr = opts->bookmark->used;
                        else
@@ -667,6 +690,7 @@ ARDGetField(StatementClass *stmt, SQLSMALLINT RecNumber,
                        }
                        break;
                case SQL_DESC_OCTET_LENGTH_PTR:
+                       rettype = SQL_IS_POINTER;
                        if (!RecNumber)
                                ptr = opts->bookmark->used;
                        else
@@ -694,25 +718,13 @@ ARDGetField(StatementClass *stmt, SQLSMALLINT RecNumber,
                default:ret = SQL_ERROR;
                        stmt->errornumber = STMT_INVALID_DESCRIPTOR_IDENTIFIER; 
        }
-       switch (BufferLength)
+       switch (rettype)
        {
                case 0:
                case SQL_IS_INTEGER:
                        len = 4;
                        *((SQLINTEGER *) Value) = ival;
                        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:
                        len = 4;
                        *((void **) Value) = ptr;
@@ -730,7 +742,7 @@ APDGetField(StatementClass *stmt, SQLSMALLINT RecNumber,
                SQLINTEGER *StringLength)
 {
        RETCODE         ret = SQL_SUCCESS;
-       SQLINTEGER      ival = 0, len;
+       SQLINTEGER      ival = 0, len, rettype = 0;
        PTR             ptr = NULL;
        const APDFields *opts = SC_get_APD(stmt);
 
@@ -738,12 +750,15 @@ APDGetField(StatementClass *stmt, SQLSMALLINT RecNumber,
        switch (FieldIdentifier)
        {
                case SQL_DESC_ARRAY_SIZE:
+                       rettype = SQL_IS_POINTER;
                        ival = opts->paramset_size;
                        break; 
                case SQL_DESC_ARRAY_STATUS_PTR:
+                       rettype = SQL_IS_POINTER;
                        ptr = opts->param_operation_ptr;
                        break;
                case SQL_DESC_BIND_OFFSET_PTR:
+                       rettype = SQL_IS_POINTER;
                        ptr = opts->param_offset_ptr;
                        break;
                case SQL_DESC_BIND_TYPE:
@@ -783,15 +798,18 @@ APDGetField(StatementClass *stmt, SQLSMALLINT RecNumber,
                        ival = opts->parameters[RecNumber - 1].CType;
                        break;
                case SQL_DESC_DATA_PTR:
+                       rettype = SQL_IS_POINTER;
                        ptr = opts->parameters[RecNumber - 1].buffer;
                        break;
                case SQL_DESC_INDICATOR_PTR:
+                       rettype = SQL_IS_POINTER;
                        ptr = opts->parameters[RecNumber - 1].used;
                        break;
                case SQL_DESC_OCTET_LENGTH:
                        ival = opts->parameters[RecNumber - 1].buflen;
                        break;
                case SQL_DESC_OCTET_LENGTH_PTR:
+                       rettype = SQL_IS_POINTER;
                        ptr = opts->parameters[RecNumber - 1].used;
                        break;
                case SQL_DESC_COUNT:
@@ -800,33 +818,21 @@ APDGetField(StatementClass *stmt, SQLSMALLINT RecNumber,
                case SQL_DESC_ALLOC_TYPE: /* read-only */
                        ival = SQL_DESC_ALLOC_AUTO;
                        break;
+               case SQL_DESC_PRECISION:
+               case SQL_DESC_SCALE:
                case SQL_DESC_DATETIME_INTERVAL_PRECISION:
                case SQL_DESC_LENGTH:
                case SQL_DESC_NUM_PREC_RADIX:
-               case SQL_DESC_PRECISION:
-               case SQL_DESC_SCALE:
                default:ret = SQL_ERROR;
                        stmt->errornumber = STMT_INVALID_DESCRIPTOR_IDENTIFIER; 
        }
-       switch (BufferLength)
+       switch (rettype)
        {
                case 0:
                case SQL_IS_INTEGER:
                        len = 4;
                        *((Int4 *) Value) = ival;
                        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:
                        len = 4;
                        *((void **) Value) = ptr;
@@ -844,36 +850,33 @@ IRDGetField(StatementClass *stmt, SQLSMALLINT RecNumber,
                SQLINTEGER *StringLength)
 {
        RETCODE         ret = SQL_SUCCESS;
-       SQLINTEGER      ival = 0, len;
+       SQLINTEGER      ival = 0, len, rettype = 0;
        PTR             ptr = NULL;
+       BOOL            bCallColAtt = FALSE;
        const IRDFields *opts = SC_get_IRD(stmt);
 
        switch (FieldIdentifier)
        {
                case SQL_DESC_ARRAY_STATUS_PTR:
+                       rettype = SQL_IS_POINTER;
                        ptr = opts->rowStatusArray;
                        break;
                case SQL_DESC_ROWS_PROCESSED_PTR:
+                       rettype = SQL_IS_POINTER;
                        ptr = opts->rowsFetched;
                        break;
                case SQL_DESC_ALLOC_TYPE: /* read-only */
+                       ival = SQL_DESC_ALLOC_AUTO;
+                       break;
                case SQL_DESC_COUNT: /* 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_CATALOG_NAME: /* read-only */
                case SQL_DESC_CONCISE_TYPE: /* read-only */
                case SQL_DESC_DATETIME_INTERVAL_CODE: /* read-only */
                case SQL_DESC_DATETIME_INTERVAL_PRECISION: /* read-only */
                case SQL_DESC_DISPLAY_SIZE: /* 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_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_NUM_PREC_RADIX: /* read-only */
                case SQL_DESC_OCTET_LENGTH: /* read-only */
@@ -882,18 +885,40 @@ IRDGetField(StatementClass *stmt, SQLSMALLINT RecNumber,
                case SQL_DESC_ROWVER: /* read-only */
 #endif /* ODBCVER */
                case SQL_DESC_SCALE: /* read-only */
-               case SQL_DESC_SCHEMA_NAME: /* 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_NAME: /* read-only */
                case SQL_DESC_UNNAMED: /* read-only */
                case SQL_DESC_UNSIGNED: /* 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;
                        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 SQL_IS_INTEGER:
@@ -904,14 +929,6 @@ IRDGetField(StatementClass *stmt, SQLSMALLINT RecNumber,
                        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:
                        len = 4;
                        *((void **) Value) = ptr;
@@ -929,7 +946,7 @@ IPDGetField(StatementClass *stmt, SQLSMALLINT RecNumber,
                SQLINTEGER *StringLength)
 {
        RETCODE         ret = SQL_SUCCESS;
-       SQLINTEGER      ival = 0, len;
+       SQLINTEGER      ival = 0, len, rettype = 0;
        PTR             ptr = NULL;
        const IPDFields *ipdopts = SC_get_IPD(stmt);
        const APDFields *apdopts = SC_get_APD(stmt);
@@ -937,9 +954,11 @@ IPDGetField(StatementClass *stmt, SQLSMALLINT RecNumber,
        switch (FieldIdentifier)
        {
                case SQL_DESC_ARRAY_STATUS_PTR:
+                       rettype = SQL_IS_POINTER;
                        ptr = ipdopts->param_status_ptr;
                        break;
                case SQL_DESC_ROWS_PROCESSED_PTR:
+                       rettype = SQL_IS_POINTER;
                        ptr = ipdopts->param_processed_ptr;
                        break;
                case SQL_DESC_UNNAMED: /* only SQL_UNNAMED is allowed */
@@ -981,8 +1000,24 @@ IPDGetField(StatementClass *stmt, SQLSMALLINT RecNumber,
                case SQL_DESC_PARAMETER_TYPE:
                        ival = apdopts->parameters[RecNumber - 1].paramType;
                        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:
-                       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;
                case SQL_DESC_ALLOC_TYPE: /* read-only */
                        ival = SQL_DESC_ALLOC_AUTO;
@@ -996,7 +1031,6 @@ IPDGetField(StatementClass *stmt, SQLSMALLINT RecNumber,
                case SQL_DESC_NULLABLE: /* read-only */
                case SQL_DESC_NUM_PREC_RADIX:
                case SQL_DESC_OCTET_LENGTH:
-               case SQL_DESC_PRECISION:
 #if (ODBCVER >= 0x0350)
                case SQL_DESC_ROWVER: /* read-only */
 #endif /* ODBCVER */
@@ -1005,25 +1039,13 @@ IPDGetField(StatementClass *stmt, SQLSMALLINT RecNumber,
                default:ret = SQL_ERROR;
                        stmt->errornumber = STMT_INVALID_DESCRIPTOR_IDENTIFIER; 
        }
-       switch (BufferLength)
+       switch (rettype)
        {
                case 0:
                case SQL_IS_INTEGER:
                        len = 4;
                        *((Int4 *) Value) = ival;
                        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:
                        len = 4;
                        *((void **)Value) = ptr;
index a906a311debce5020c3f0b5117e3cd1942a6596c..f4c740bca84c60748434c3077776de63543c36e6 100644 (file)
@@ -265,6 +265,10 @@ RETCODE SQL_API PGAPI_GetDiagRec(SQLSMALLINT HandleType, SQLHANDLE Handle,
                SQLSMALLINT RecNumber, SQLCHAR *Sqlstate,
                SQLINTEGER *NativeError, SQLCHAR *MessageText,
                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,
                        SQLINTEGER Attribute, PTR Value,
                        SQLINTEGER BufferLength, SQLINTEGER *StringLength);
index a0d4be134b1435d411d2564690f8c316f6d9d1a6..839c6e4876cde49792d2592304e12c8a4e5c0ef5 100644 (file)
@@ -5,7 +5,7 @@
  *
  * 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 $
  *
  */
 
index 923448abeba844a9dea9140fff1817f69c559dcc..2817a7f316a3e2fc10e0dc746c0afa205207cff9 100644 (file)
@@ -123,6 +123,7 @@ QR_Constructor()
                rv->rowset_size = 1;
                rv->haskeyset = 0;
                rv->keyset = NULL;
+               rv->rb_alloc = 0;
                rv->rb_count = 0;
                rv->rollback = NULL;
        }
@@ -233,6 +234,7 @@ QR_free_memory(QResultClass *self)
        if (self->rollback)
        {
                free(self->rollback);
+               self->rb_alloc = 0;
                self->rb_count = 0;
                self->rollback = NULL;
        }
index a7291c43a6f325a6f0e9440fd91b48e63b7236ec..1bf1ce93b742f24d03f4b92fa6c791ee63948bf7 100644 (file)
@@ -74,7 +74,8 @@ struct QResultClass_
        char            aborted;                /* was aborted? */
        char            haskeyset;              /* this result contains 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;      
 };
 
index 6d20bbaad593b483f523ae133f7fc75019f880dd..517d5a234d1c99b8b9c91eadbd96e7087fdcb77e 100644 (file)
@@ -491,7 +491,7 @@ PGAPI_ColAttributes(
                        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)
                        {
@@ -500,9 +500,12 @@ PGAPI_ColAttributes(
                                SC_log_error(func, "", stmt);
                                return SQL_ERROR;
                        }
-                       field_type = irdflds->fi[col_idx]->type;
-                       if (field_type > 0)
-                               parse_ok = TRUE;
+                       if (irdflds->fi[col_idx])
+                       {
+                               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)
                {
-#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);
 
                        if (len >= cbDescMax)
@@ -1343,8 +1338,6 @@ 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]);
                }
        }
 
@@ -1426,6 +1419,121 @@ static void KeySetSet(const TupleField *tuple, int num_fields, KeySet *keyset)
        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        USE_INSERTED_TID        (1L << 1)
 static QResultClass *
@@ -1534,7 +1642,8 @@ SC_pos_reload(StatementClass *stmt, UWORD irow, UDWORD global_ridx, UWORD *count
                        ret = SQL_SUCCESS_WITH_INFO;
                        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;
                        }
                }
@@ -1670,6 +1779,7 @@ SC_pos_update(StatementClass *stmt,
                                num_cols,
                                upd_cols;
        QResultClass *res;
+       ConnectionClass *conn = SC_get_conn(stmt);
        ARDFields       *opts = SC_get_ARD(stmt);
        IRDFields       *irdflds = SC_get_IRD(stmt);
        BindInfoClass *bindings = opts->bindings;
@@ -1735,7 +1845,7 @@ SC_pos_update(StatementClass *stmt,
                sprintf(updstr, "%s where ctid = '(%u, %u)' and oid = %u", updstr,
                                blocknum, pgoffset, oid);
                mylog("updstr=%s\n", updstr);
-               if (PGAPI_AllocStmt(SC_get_conn(stmt), &hstmt) != SQL_SUCCESS)
+               if (PGAPI_AllocStmt(conn, &hstmt) != SQL_SUCCESS)
                        return SQL_ERROR;
                qstmt = (StatementClass *) hstmt;
                apdopts = SC_get_APD(qstmt);
@@ -1788,8 +1898,11 @@ SC_pos_update(StatementClass *stmt,
        }
        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);
+               }
                else
                        res->keyset[global_ridx].status |= (SQL_ROW_UPDATED  | CURS_SELF_UPDATED);
        }
@@ -1815,12 +1928,12 @@ SC_pos_delete(StatementClass *stmt,
 {
        UWORD           offset;
        QResultClass *res, *qres;
+       ConnectionClass *conn = SC_get_conn(stmt);
        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 ti=%x\n", stmt->ti);
@@ -1844,7 +1957,7 @@ SC_pos_delete(StatementClass *stmt,
                        stmt->ti[0]->name, blocknum, offset, oid);
 
        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;
        if (qres && QR_command_successful(qres))
        {
@@ -1881,8 +1994,11 @@ SC_pos_delete(StatementClass *stmt,
                QR_Destructor(qres);
        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);
+               }
                else
                        res->keyset[global_ridx].status |= (SQL_ROW_DELETED | CURS_SELF_DELETED);
        }
@@ -1988,7 +2104,7 @@ SC_pos_add(StatementClass *stmt,
        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)
+       if (PGAPI_AllocStmt(conn, &hstmt) != SQL_SUCCESS)
                return SQL_ERROR;
        if (opts->row_offset_ptr)
                offset = *opts->row_offset_ptr;
@@ -2068,10 +2184,15 @@ SC_pos_add(StatementClass *stmt,
        PGAPI_FreeStmt(hstmt, SQL_DROP);
        if (SQL_SUCCESS == ret && res->keyset)
        {
+               int     global_ridx = res->fcount - 1;
                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
-                       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 (irdflds->rowStatusArray)
index f48a1724219da2edac54a16ebe8d69618966e154..6bdac480872929beb87e9c2185d4b06c43415187 100644 (file)
@@ -503,8 +503,8 @@ SC_recycle_statement(StatementClass *self)
                int     i;
 
                for (i = 0; i < self->ntab; i++)
-                       if (self->ti)
-                               free(self->ti);
+                       if (self->ti[i])
+                               free(self->ti[i]);
                self->ti = NULL;
                self->ntab = 0;
        }