md/roadmap.md in pod4-0.7.2 vs md/roadmap.md in pod4-0.8.0
- old
+ new
@@ -1,45 +1,99 @@
-Connection Object
-=================
+Transactions
+============
-PgInterface and TdsInterface both take a connection Hash, which is all very
-well, but it means that we are running one database connection per model.
-Presumably this is a bad idea. :-)
+I'd like to support basic transactions because without it we can't really claim to do optimistic
+locking properly. And it would be nice to claim that.
-This actually hasn't come up in my own use of Pod4 -- for complex reasons I'm
-either using SequelInterface or running transient jobs which start up a couple
-of models, do some work, and then stop entirely -- but it _is_ rather silly.
+Thought I had a solid idea of how to do it without any faffing around, but, it had some holes. Will
+have to think again.
-Connection is baked into those interfaces, and interface dependant. So I'm
-thinking in terms of a memoising object that stores the connection hash and
-then gets passed to the interface. When the interface wants a connection, then
-it asks the connection object. If the connection object doesn't have one, then
-the interface connects, and gives the connection to the connection object.
+But, this is top of my wish list.
+For the record, my current thinking:
-Transactions
-============
+ customer.new(4).read.or_die
+ customer.transaction do |c|
+ c.update(foo: 'bar')
+ c.orders.update(foo: 'bar')
+ end.or_die
-We really need this, because without it we can't even pretend to be doing
-proper pessimistic locking.
+* a method supports_transactions() will control whether the interface does that. sql_helper will
+ define it to return true.
-I've got a pretty solid idea for a nice, simple way to make this happen. It
-will be in place soon.
+* sql_helper will define a sql_transaction method which wraps SQL as a transaction.
+* interface methods create() delete() and update now accept an extra parameter, a boolean; if true,
+ they will return sql (and values), rather than doing anything. This is defined in Pod4::Interface.
+* BasicModel defines @in_transaction = false; @tx_sql = ""; @tx_vals = [].
+
+* When a Model is @in_transaction, the create, delete and update methods pass the extra parameter
+ to the corresponding interface methods. The results are accumulated in @tx_sql and @tx_vals.
+
+* the method BasicModel.transaction will:
+
+ * set interface.in_transaction = true, or raise an error if the interface doesn't support them
+ * yield a block passing the model instance so that the caller can run methods inside it
+ * set in_transaction back to false.
+ * call interface.executep( interface._sql_transaction( @tx_sql ), @tx_vals )
+
+Notes:
+
+* We will either have to standardize the execute method or check for it each time?
+* Ditto with executep. Ditto with whether an interface supports parameterisation.
+* trying to do a transaction across databases will fall over, but, really, no expectation there.
+* You can't have a transaction that uses the result of the first half to do the last half.
+* You can no longer call select() in a create, as we currently do for some interfaces? This is the
+ real problem I am wrestling with -- how to allow a transaction that returns a value from create().
+
+
Migrations
==========
-This will almost certainly be something crude -- since we don't really control
-the database connection in the same way as, say, ActiveRecord -- but I honestly
-think it's a worthwhile feature. Just having something that you can version
-control and run to update a data model is enough, really.
+This will almost certainly be something crude -- since we don't really control the database
+connection in the same way as, say, ActiveRecord -- but I honestly think it's a worthwhile feature.
+Just having something that you can version control and run to update a data model is enough,
+really.
-I'm not yet sure of the least useless way to implement it. Again, I favour SQL
-as the DSL.
+I'm not yet sure of the least useless way to implement it. Again, I favour SQL as the DSL.
+We will clearly need transactions first, though.
+My Current thoughts:
+
+* a migration against a database is on a par with a model but very different. You subclass
+ migration and give it an interface, pointing to the table that stores the current migration
+ state.
+
+* The methods in a module are exectute() up() and down() -- the last two call the first one.
+
+* Each instance of a model is stored in a file and contains up and down SQL somehow. Each instance
+ has a version number.
+
+* You run a migration by running up or down on your migration class, passing a version?
+
+
+Connection Object
+=================
+
+PgInterface and TdsInterface both take a connection Hash, which is all very well, but it means that
+we are running one database connection per model. Presumably this is a bad idea. :-)
+
+This actually hasn't come up in my own use of Pod4 -- for complex reasons I'm either using
+SequelInterface or running transient jobs which start up a couple of models, do some work, and then
+stop entirely.
+
+Connection is baked into those interfaces, and interface dependant. So I'm thinking in terms of a
+memoising object that stores the connection hash and then gets passed to the interface. When the
+interface wants a connection, then it asks the connection object. If the connection object doesn't
+have one, then the interface connects, and gives the connection to the connection object.
+
+It's looking as if we don't need this right now. One connection per model might not be as daft as
+it seems.
+
+
JDBC-SQL interface
==================
For the jdbc-msssqlserver gem. Doable ... I *think*.
@@ -65,5 +119,7 @@
stmt.close
conn.close
see https://github.com/jruby/jruby/wiki/JDBC
+
+