sql

All things SQL and JDBC...
seancorfield 2020-06-04T04:36:09.146Z

For those of you that use stored procedures, I would dearly love some simple examples that generate multiple results and also accept both in, inout, and out parameters. I would like to add these to the test suite so I can verify that all DBs that support SP at all can have them invoked.

seancorfield 2020-06-04T04:37:02.147100Z

This is a prelude to a) supporting multiple result sets (not possible today) and b) supporting stored procedure calling in a simpler manner somehow (but I don't know enough about SPs to be able to design this myself).

seancorfield 2020-06-04T04:38:09.147700Z

You can add notes to https://github.com/seancorfield/next-jdbc/issues/116 or post here or DM me

2020-06-04T17:26:48.151800Z

hi! we are migrating an app from jdbc. to next.jdbc and so far so good, only problem now is durings tests. we used to have a “wrapping txns” on a fixture that woould do something like

(defn with-rollback
  [f]
  (jdbc/with-db-transaction [tx db/*db*]
    (jdbc/db-set-rollback-only! tx)
       (binding [db/*db* tx]
          (f))))
tests were rolling back perfectly after execution. moving to next. we have this
(defn with-rollback
  [f]
  (jdbc/with-transaction [tx db/*db* {:rollback-only true}]
       (binding [db/*db* tx]
          (f))))

2020-06-04T17:27:07.152300Z

however tests are now not rolled back.

2020-06-04T17:28:18.153900Z

we do have inside our code other txns, that use the binded var, we were expeting the rollbacak flag would move down on those txns.

2020-06-04T17:28:36.154400Z

are we missing something obvious?

2020-06-04T17:49:16.156Z

debugging next.jdbc.transaction/transact* i noticed the opts are lost when inside the nested txns

seancorfield 2020-06-04T18:00:35.156500Z

@jmayaalv What is db/*db*? A db-spec? A datasource? A connection?

2020-06-04T18:02:34.158400Z

on prod is a datasource (a hikari pool), but the idea with the biding on the test fixture was to use it as the connection already marked as rollback.

seancorfield 2020-06-04T18:32:12.160700Z

You can't run multiple transactions on a single connection -- transaction is destructive on a connection. Transactions do not nest (in general) so you can't rely on wrapping code that uses transactions inside another transaction and expect the inner transactions to rollback (since they have their own commit phase).

2020-06-04T18:33:47.161200Z

i understand this. we don’t want to run multiple txns

2020-06-04T18:34:36.162300Z

on prod we have a pool, then we create a txn that runs some business logic.

2020-06-04T18:35:44.163700Z

on test what we were doing with the bind, was to replace the pool with a rollbacked transaction, so the inner macro would continued with an already rollback txn.

2020-06-04T18:38:46.166300Z

we have (jdbc/with-transaction) on our service layers and we are running some integrations tests, dont’ think can’t move all the transaction limits to a layer above.

2020-06-04T18:48:25.171100Z

so i believe next.jdbc creates a new transaction on every jdbc/with-transaction and clojure.jdbc was not creating a new one but using the outer transaction.

2020-06-04T19:10:32.172900Z

thank you @seancorfield we will see how to find a way around it 🙂

seancorfield 2020-06-04T20:21:28.178400Z

@jmayaalv clojure.java.jdbc had a very complicated piece of machinery for maintaining a "stack" of transaction contexts and effectively merging nested contexts into the outer context if needed. That was necessary partly because every SQL operation in c.j.j was wrapped in a transaction and you had to explicitly opt-out of that. next.jdbc instead relies on auto-commit on connections and so all transactions used are explicit and under user control. That means it's a lot easier to use savepoints with next.jdbc than with c.j.j and that you could safely wrap "regular" (non-explicitly-transacting) in an outer transaction and directly control the behavior from the outside. In addition, I used to get bug reports against c.j.j because of its transaction-handling from users of databases that actually did allow nested transactions and there was no way to workaround it -- you had to switch to interop and it got messy. next.jdbc avoids that completely, because a transaction does exactly what you expect for your database.

seancorfield 2020-06-04T20:22:09.179200Z

As with everything else, there are trade offs with both approaches, but I'm more comfortable with how next.jdbc deals with these trade offs overall.

2020-06-04T20:23:55.181900Z

totally agree, we are happy to pay for the trade offs, so far experience for us has been very possitive :)

2020-06-04T20:26:48.185400Z

we were expecting some issues when upgrading anyway. i am sure app will be better after 😉

seancorfield 2020-06-04T20:27:04.185800Z

A recent change has been to make transactions executed directly on connections lock on the connection object to improve reliability with multithreading (which I think should be avoided: connections are mutable and are not safe to be operated on in multiple threads in the first place!). That would prevent double-nesting transactions (it would deadlock) while still allowing single-nesting -- although with the behavior you noted above: nested commits affect the outer context. Your comment about nested transactions "losing" their options makes me wonder whether I could improve how (single) nested transactions work via a dynamic (thread local) var...

seancorfield 2020-06-04T20:27:43.186600Z

Because next.jdbc traffics in Java objects directly, there's nothing to attach options to -- so options literally cannot cascade into nested operations.

seancorfield 2020-06-04T20:29:03.187600Z

But having the ability to ignore nested transactions so your testing rollback fixture would work... that has value... and also being able to use the same machinery to detect and disallow nested transactions would also probably add value.

seancorfield 2020-06-04T20:29:32.188100Z

(at the cost of making transactions dependent on a global dynamic var)

2020-06-04T20:32:49.190Z

That would be awesome. i can imagine is a common use case.

2020-06-04T20:34:32.191500Z

one of the things we wanted to try was to add some meta-data on the with-transaction macro, so that we could reuse the metadata from the prev object, not sure if it will work. 😄

2020-06-04T20:51:20.192100Z

oh right, it can’t be done because they are java objects

seancorfield 2020-06-04T20:53:16.193Z

Yeah, that's why I'm looking at some sort of middleware/wrapper functionality. There's an issue open about that and some code and tests (in the test tree, not src).

2020-06-04T20:57:28.193800Z

a middleware would make a lot of sense. will check it out! thanks a lot