From Zoltan Kovacs back in April (sorry for the delay Zoltan!):
authorThomas G. Lockhart
Wed, 25 Oct 2000 14:15:49 +0000 (14:15 +0000)
committerThomas G. Lockhart
Wed, 25 Oct 2000 14:15:49 +0000 (14:15 +0000)
I modified the current ODBC driver for

* referential integrity error reporting,
* SELECT in transactions and
* disabling autocommit.

I tested these changes with Borland C++ Builder -> ODBCExpress ->
WinODBC driver (DLL) -> Postgres 7.0beta1 and Borland C++ Builder -> BDE ->
WinODBC driver (DLL) -> Postgres 7.0beta1. The patch is based on snapshot of
22th April (I don't think that someone has modified it since that: Byron
hasn't gave any sign of living for about a month and I didn't find any
comments about the ODBC driver on the list).

src/interfaces/odbc/connection.c
src/interfaces/odbc/options.c
src/interfaces/odbc/statement.c

index e3d444997ec32053df0853922ae8f62c0ef4e378..d5b0d12dffed1a651c160afc82ab38c3b9e0d15c 100644 (file)
@@ -947,6 +947,19 @@ char cmdbuffer[MAX_MESSAGE_LEN+1]; /* QR_set_command() dups this string so dont
                    case 'E':
                        SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH);
                        qlog("ERROR from backend during clear: '%s'\n", cmdbuffer);
+                       /* We must report this type of error as well
+                          (practically for reference integrity violation
+                          error reporting, from PostgreSQL 7.0).
+                          (Zoltan Kovacs, 04/26/2000)
+                       */
+                       self->errormsg = cmdbuffer;
+                       if ( ! strncmp(self->errormsg, "FATAL", 5)) {
+                           self->errornumber = CONNECTION_SERVER_REPORTED_ERROR;
+                           CC_set_no_trans(self);
+                           }
+                       else 
+                           self->errornumber = CONNECTION_SERVER_REPORTED_WARNING;
+                       QR_set_status(res, PGRES_NONFATAL_ERROR);
                        break;
                    }
                }
@@ -1001,14 +1014,20 @@ char cmdbuffer[MAX_MESSAGE_LEN+1];  /* QR_set_command() dups this string so dont
            mylog("send_query: 'E' - %s\n", self->errormsg);
            qlog("ERROR from backend during send_query: '%s'\n", self->errormsg);
 
+           /* We should report that an error occured. Zoltan */
+           res = QR_Constructor();
+
            if ( ! strncmp(self->errormsg, "FATAL", 5)) {
                self->errornumber = CONNECTION_SERVER_REPORTED_ERROR;
                CC_set_no_trans(self);
+               QR_set_status(res, PGRES_FATAL_ERROR);
            }
-           else
+           else {
                self->errornumber = CONNECTION_SERVER_REPORTED_WARNING;
+               QR_set_status(res, PGRES_NONFATAL_ERROR);
+           }
 
-           return NULL;
+           return res; /* instead of NULL. Zoltan */
 
        case 'P' : /* get the Portal name */
            SOCK_get_string(sock, msgbuffer, MAX_MESSAGE_LEN);
index eb67dd590faecf20be952ab804fccbb7caba9d8b..217f063338ebde0622bf413bf0c82a8a05659726 100644 (file)
@@ -330,6 +330,15 @@ int i;
        switch(vParam) {
        case SQL_AUTOCOMMIT_OFF:
            CC_set_autocommit_off(conn);
+       /* The following two lines are new.
+          With this modification the SELECT statements
+          are also included in the transactions.
+          Error handling should be written, 
+          this is missing yet, see
+          SC_execute in statement.c for details. Zoltan
+       */    
+           CC_send_query(conn,"BEGIN",NULL);
+           CC_set_in_trans(conn);
            break;
 
        case SQL_AUTOCOMMIT_ON:
index 95c9e8986e7f6148bad61d45a1eb869bd75791ef..0fac4d6bc089fca1844f25bb36f8ef2b34c9e80a 100644 (file)
@@ -748,8 +748,14 @@ QueryInfo qi;
    /*  Begin a transaction if one is not already in progress */
    /*  The reason is because we can't use declare/fetch cursors without
        starting a transaction first.
+
+       A transaction should be begun if and only if
+       we use declare/fetch and the statement is SELECT.
+       We assume that the Postgres backend has an autocommit
+       feature as default. (Zoltan Kovacs, 04/26/2000)
    */
-   if ( ! self->internal && ! CC_is_in_trans(conn) && (globals.use_declarefetch || STMT_UPDATE(self))) {
+   // if ( ! self->internal && ! CC_is_in_trans(conn) && (globals.use_declarefetch || STMT_UPDATE(self))) {
+   if ( ! self->internal && ! CC_is_in_trans(conn) && globals.use_declarefetch && self->statement_type == STMT_TYPE_SELECT) {
 
        mylog("   about to begin a transaction on statement = %u\n", self);
        res = CC_send_query(conn, "BEGIN", NULL);
@@ -826,11 +832,14 @@ QueryInfo qi;
        self->result = CC_send_query(conn, self->stmt_with_params, NULL);
 
        /*  If we are in autocommit, we must send the commit. */
-       if ( ! self->internal && CC_is_in_autocommit(conn) && STMT_UPDATE(self)) {
+       /*  No, we shouldn't. Postgres backend does the
+           autocommit if neccessary. (Zoltan, 04/26/2000)
+       */
+/*     if ( ! self->internal && CC_is_in_autocommit(conn) && STMT_UPDATE(self)) {
        res = CC_send_query(conn, "COMMIT", NULL);
        QR_Destructor(res);
        CC_set_no_trans(conn);
-       }
+       }*/     
 
    }
 
@@ -889,10 +898,12 @@ QueryInfo qi;
    if (self->errornumber == STMT_OK)
        return SQL_SUCCESS;
 
-   else if (self->errornumber == STMT_INFO_ONLY)
-       return SQL_SUCCESS_WITH_INFO;
-
    else {
+       // Modified, 04/29/2000, Zoltan
+       if (self->errornumber == STMT_INFO_ONLY)
+           self->errormsg = "Error while executing the query (non-fatal)";
+       else
+           self->errormsg = "Unknown error";
        SC_log_error(func, "", self);
        return SQL_ERROR;
    }