On 01/20/2015 06:53 AM, Thomas Lynch wrote:

According to the manual,
http://docs.racket-lang.org/db/query-api.html#%28part._transactions%29,
  section
3.5,  postgres transactions can be issued directly in SQL (so called
'unmanaged').   Here is a short code segment that fails doing unmanaged
transactions (and nothing else).

My question here is whether this code is doing unmanaged transactions
correctly, and they are not working as advertised, or if there is
something left out like an explicit reset to the connection after it
throws an exception.

For purposes of illustration, I run the following query here in the psql
shell to show the the error message that it correctly issues:

    => insert into x_unique_counters values ('table_author','1');
    ERROR:  duplicate key value violates unique constraint
    "x_unique_counters_pkey"
    DETAIL:  Key (name)=(table_author) already exists.


Now the racket program is ready for this kind of problem, here
'the-query' is the same query just shown above, but this time issued
from this code


            (begin
                 (semaphore-wait (current-db-semaphore))
                 (query-exec pgc  "begin")
                 (begin0
                  (with-handlers
                    (
                      [(lambda (v) #t) ; this handler catches anything
                        (lambda (v)
                          (query-exec pgc "rollback")
                          (semaphore-post (current-db-semaphore))
                          (raise v)
                          )
                        ]
                      )

                    (query-exec pgc the-query) ; this throws an exception

                    )
                   (db-exec "commit")
                   (semaphore-post (current-db-semaphore))
                 ))
             ]
           ))


So when query-exec throws an exception, the handler grabs it.  Then the
handler executes an SQL rollback to cancel the transaction.  All appears
to be good, but then bang!  we get an exception in the handler while
doing the rollback:

     >(db-exec* '("rollback"))
    query-exec: current transaction is invalid


All attempts to do any further queries on the connection fail with the
same error.   It appears to be foo-bar and a new connection must be made
before any further SQL can be issued against the database.

Hmm, what is going on here?  Unmanaged connections not working as
advertised .. or some switch that must be flipped to tell the connection
to work again?

That looks like a bug in the db library. It rejects all queries when the transaction is invalid, rather than allowing rollbacks through.

A workaround is to use (rollback-transaction pgc) in the exception handler. Despite what the docs say, it's okay to use rollback-transaction on a unmanaged transaction. I'll fix the docs.

Ryan

____________________
 Racket Users list:
 http://lists.racket-lang.org/users

Reply via email to