Review CC_send_query_append(.., .., ROLLBACK_ON_ERROR | IGNORE_ABORT_ON_CONN, .....
authorHiroshi Inoue <h-inoue@dream.email.ne.jp>
Sun, 18 Jun 2017 10:09:45 +0000 (19:09 +0900)
committerHiroshi Inoue <h-inoue@dream.email.ne.jp>
Fri, 30 Jun 2017 02:52:43 +0000 (11:52 +0900)
  [in the multiple command]

 SAVEPOINT xxxxx;exec something;REALEASExxxxx

1. Discard the result and the effect of RELEASE as well as of SAVEPOINT.
2. Suppress CC_on_abort_partial() calls.
3. For an error resetting command 'ROLLBACK to xxxxx;RELEASE xxxxx', call PQsendQuery() instead of PQexec().

connection.c
connection.h
execute.c
qresult.c

index c6a198bcc9cfa9d2ce66be7f50346b33af37b6cd..1392a2fc52c59d88e009da7dcbb9984a62115b4e 100644 (file)
@@ -631,7 +631,7 @@ CC_send_client_encoding(ConnectionClass *self, const char * encoding)
        BOOL    cmd_success;
 
        SPRINTF_FIXED(query, "set client_encoding to '%s'", encoding);
-       res = CC_send_query(self, query, NULL, IGNORE_ABORT_ON_CONN | ROLLBACK_ON_ERROR, NULL);
+       res = CC_send_query(self, query, NULL, 0, NULL);
        cmd_success = QR_command_maybe_successful(res);
        QR_Destructor(res);
        CC_set_errornumber(self, errnum);
@@ -875,7 +875,8 @@ handle_pgres_error(ConnectionClass *self, const PGresult *pgres,
        goto cleanup;
    }
 
-   mylog("error message len=%d\n", strlen(errmsg));
+   if (get_mylog() > 0)
+       mylog("error message=%s(%d)\n", errmsg, strlen(errmsg));
 
    if (res)
    {
@@ -1432,12 +1433,14 @@ static void CC_clear_cursors(ConnectionClass *self, BOOL on_abort)
                    CONNLOCK_RELEASE(self);
                    wres = CC_send_query(self, cmd, NULL, ROLLBACK_ON_ERROR | IGNORE_ABORT_ON_CONN | READ_ONLY_QUERY, NULL);
                    QR_set_no_survival_check(res);
-                   if (QR_command_maybe_successful(wres))
+                   if (QR_command_maybe_successful(wres) &&
+                       CONN_ERROR_IGNORED != CC_get_errornumber(self))
                        QR_set_permanent(res);
                    else
                        QR_set_cursor(res, NULL);
                    QR_Destructor(wres);
                    CONNLOCK_ACQUIRE(self);
+inolog(" !!!! %s:%p->permanent -> %d %p\n", __FUNCTION__, res, QR_is_permanent(res), QR_get_cursor(res));
                }
                else
                    QR_set_permanent(res);
@@ -1604,6 +1607,8 @@ CC_internal_rollback(ConnectionClass *self, int rollback_type, BOOL ignore_abort
    char        cmd[64];
    PGresult   *pgres = NULL;
 
+   if (!CC_is_in_error_trans(self))
+       return 1;
    switch (rollback_type)
    {
        case PER_STATEMENT_ROLLBACK:
@@ -1620,12 +1625,37 @@ CC_internal_rollback(ConnectionClass *self, int rollback_type, BOOL ignore_abort
                    LIBPQ_update_transaction_status(self);
                    break;
            }
-           if (pgres)
-               PQclear(pgres);
            break;
        case PER_QUERY_ROLLBACK:
+           SPRINTF_FIXED(cmd, "%s TO %s;%s %s"
+               , rbkcmd, per_query_svp , rlscmd, per_query_svp);
+           mylog(" %s:query_rollback PQsendQuery %s\n", __FUNCTION__, cmd);
+           PQsendQuery(self->pqconn, cmd);
+           ret = 1;
+           while (self->pqconn && (pgres = PQgetResult(self->pqconn)) != NULL)
+           {
+               switch (PQresultStatus(pgres))
+               {
+                   case PGRES_COMMAND_OK:
+                   case PGRES_NONFATAL_ERROR:
+                       break;
+                   default:
+                       ret = 0;
+               }
+           }
+           if (ret)
+           {
+               if (ignore_abort)
+                   CC_set_no_error_trans(self);
+           }
+           else
+               mylog(" %s:return error\n", __FUNCTION__);
+           LIBPQ_update_transaction_status(self);
            break;
    }
+   if (pgres)
+       PQclear(pgres);
+
    return ret;
 }
 
@@ -1665,6 +1695,7 @@ CC_send_query_append(ConnectionClass *self, const char *query, QueryInfo *qi, UD
                used_passed_result_object = FALSE,
            discard_next_begin = FALSE,
            discard_next_savepoint = FALSE,
+           discard_next_release = FALSE,
            consider_rollback;
    int     func_cs_count = 0, i;
    size_t      query_buf_len = 0;
@@ -1912,8 +1943,9 @@ inolog("!!!! %s:query_buf=%s(%d)\n", __FUNCTION__, query_buf, query_buf_len);
                {
                    if (discard_next_savepoint)
                    {
-inolog("Discarded the first SAVEPOINT\n");
                        discard_next_savepoint = FALSE;
+                       discard_next_release = TRUE;
+inolog("Discarded a SAVEPOINT result\n");
                        break; /* discard the result */
                    }
                    if (SAVEPOINT_IN_PROGRESS == self->internal_op)
@@ -1935,6 +1967,12 @@ inolog("Discarded the first SAVEPOINT\n");
                }
                else if (strnicmp(cmdbuffer, rlscmd, strlen(rlscmd)) == 0)
                {
+                   if (discard_next_release)
+                   {
+inolog("Discarded a RELEASE result\n");
+                       discard_next_release = FALSE;
+                       break; /* discard the result */
+                   }
                    self->internal_svp = 0;
                    if (SAVEPOINT_IN_PROGRESS == self->internal_op)
                        break; /* discard the result */
@@ -2102,27 +2140,13 @@ cleanup:
        PQclear(pgres);
        pgres = NULL;
    }
+inolog(" !!!! %s:rollback_on_error=%d CC_is_in_trans=%d discard_next_savepoint=%d query_rollback=%d\n", __FUNCTION__, rollback_on_error, CC_is_in_trans(self), discard_next_savepoint, query_rollback);
    if (rollback_on_error && CC_is_in_trans(self) && !discard_next_savepoint)
    {
        if (query_rollback)
        {
-           if (CC_is_in_error_trans(self))
-           {
-               char tmpsqlbuf[100];
-
-               SPRINTF_FIXED(tmpsqlbuf,
-                       "%s TO %s"
-                       ";%s %s"
-                       , rbkcmd, per_query_svp
-                       , rlscmd, per_query_svp);
-               pgres = PQexec(self->pqconn, tmpsqlbuf);
-               /*
-                * Though it's not appropriate to
-                * call PQExec for a multiple command,
-                * it seems OK because we don't check
-                * the result here.
-                */
-           }
+           if (!CC_internal_rollback(self, PER_QUERY_ROLLBACK, ignore_abort_on_conn))
+               ignore_abort_on_conn = FALSE;
        }
        else if (CC_is_in_error_trans(self))
            pgres = PQexec(self->pqconn, rbkcmd);
@@ -2187,7 +2211,12 @@ cleanup:
                 *  If error message isn't set
                 */
                if (ignore_abort_on_conn)
-                   CC_set_errornumber(self, 0);
+               {
+                   CC_set_errornumber(self, CONN_ERROR_IGNORED);
+                   if (retres)
+                       QR_set_rstatus(retres, PORES_NONFATAL_ERROR);
+inolog(" !!!! %s:ignored abort_on_conn\n", __FUNCTION__);
+               }
                else if (retres)
                {
                    if (NULL == CC_get_errormsg(self) ||
index c9b037f5bfed13f2594736624f2ced0f42b75ba4..e7c7294cdd2fe904618e3c2978ea84d8c8b6c9fe 100644 (file)
@@ -47,6 +47,7 @@ typedef enum
 #define CONNECTION_NEED_PASSWORD               112
 #define CONNECTION_COMMUNICATION_ERROR             113
 
+#define CONN_ERROR_IGNORED                     (-3)
 #define CONN_TRUNCATED                         (-2)
 #define CONN_OPTION_VALUE_CHANGED                  (-1)
 /* These errors correspond to specific SQL states */
index fb6f042e5e914b17c5156e72df605f27b559ec86..2156d5fe3bb6e9daff5a123f6f6614b7018a9d80 100644 (file)
--- a/execute.c
+++ b/execute.c
@@ -621,7 +621,7 @@ RETCODE
 SetStatementSvp(StatementClass *stmt, unsigned int option)
 {
    CSTR    func = "SetStatementSvp";
-   char    esavepoint[32], cmd[64];
+   char    cmd[64];
    ConnectionClass *conn = SC_get_conn(stmt);
    QResultClass *res;
    RETCODE ret = SQL_SUCCESS_WITH_INFO;
@@ -690,10 +690,8 @@ RETCODE
 DiscardStatementSvp(StatementClass *stmt, RETCODE ret, BOOL errorOnly)
 {
    CSTR    func = "DiscardStatementSvp";
-   char    cmd[64];
    ConnectionClass *conn = SC_get_conn(stmt);
-   QResultClass *res;
-   BOOL    cmd_success, start_stmt = FALSE;
+   BOOL    start_stmt = FALSE;
 
 inolog("%s:%p->accessed=%d is_in=%d is_rb=%d is_tc=%d\n", func, conn, CC_accessed_db(conn),
 CC_is_in_trans(conn), SC_is_rb_stmt(stmt), SC_is_tc_stmt(stmt));
@@ -724,7 +722,6 @@ CC_is_in_trans(conn), SC_is_rb_stmt(stmt), SC_is_tc_stmt(stmt));
            if (!cmd_success)
            {
                SC_set_error(stmt, STMT_INTERNAL_ERROR, "internal ROLLBACK failed", func);
-               CC_abort(conn);
                goto cleanup;
            }
        }
index 96a8410970b57d15b3d4eff7d7d179c669e54681..a373e308a10c13b657fbd16fe017788439899bc8 100644 (file)
--- a/qresult.c
+++ b/qresult.c
@@ -760,6 +760,7 @@ QR_close(QResultClass *self)
                    does_commit = TRUE;
            }
 
+inolog(" !!!! %s:Case I CC_send_query %s flag=%x\n", __FUNCTION__, buf, flag);
            res = CC_send_query(conn, buf, NULL, flag, NULL);
            QR_Destructor(res);
            if (does_commit)