<html><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; ">
<span class="Apple-style-span" style="font-family: Monaco; font-size: 10px; "><div>The callback syntax is nice but the implicit thread-global transaction is confusing and can lead to programmer error and unneeded database locking.</div><div><br class="webkit-block-placeholder"></div><div>Commonly there is a implicit transaction per query if there is no explicit transaction created. I think this is what developers will expect, after using server side databases. In a complex web application, an implicit thread-global transaction will cause questions on when it began. The code can be spread all over, and will not always be written out using closures for the callbacks.</div><div><br class="webkit-block-placeholder"></div><div>It doesn't look like you can rollback the implicit transaction (one of the big features of transactions.) Also what access locks does the implicit transaction take? What if you need exclusive access to the database temporarily? These cases would be solved by adding explicit transactions with control to access locks and rolling back.</div><div><br class="webkit-block-placeholder"></div><div>If explicit transactions are not added developers will take advantage of what they have access to using the implicit transactions. (I assume each Database object will have it's own implicit thread-global transaction.) So you could open two Database objects for the same database and execute two simultaneous implicit transactions. But you would need to write your own rollback code if you need to programatically bail out of a transaction and restore any previous values.</div><div><br class="webkit-block-placeholder"></div><div>I propose that the implicit transaction be scoped to only one query at a time, like I mentioned earlier. Then add explicit transactions that you create from a Database object. Then you can start two simultaneous transactions on the same Database object, which is nicer than holding two Database objects for the same database just for concurrent access.</div><div><br class="webkit-block-placeholder"></div><div>Here is an example<span class="Apple-style-span" style="line-height: 20px; ">:</span></div><div><br></div><div><span class="Apple-style-span" style="line-height: 20px; "><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 10px/normal Monaco; "><span class="Apple-style-span" style="font-family: Verdana; font-size: 11px; line-height: 20px; ">    </span>transation1 = db.<span style="color: rgb(0, 51, 105); ">beginTransation</span>();</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 10px/normal Monaco; "><span class="Apple-style-span" style="font-family: Verdana; font-size: 11px; line-height: 20px; ">    </span>transation1.<span style="color: rgb(0, 51, 105); ">executeQuery</span>(<span style="color: rgb(235, 115, 0); ">"SELECT * FROM document"</span>, <span style="color: rgb(136, 19, 80); ">function</span>(result1) {</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 10px/normal Monaco; "><span class="Apple-style-span" style="font-family: Verdana; font-size: 11px; line-height: 20px; ">    </span><span style="color: rgb(136, 19, 80); ">    if</span>(...) {</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 10px/normal Monaco; color: rgb(235, 115, 0); "><span style="color: rgb(0, 0, 0); "><span class="Apple-style-span" style="font-family: Verdana; font-size: 11px; line-height: 20px; ">    </span>        result1.transation.</span><span style="color: rgb(0, 51, 105); ">executeQuery</span><span style="color: rgb(0, 0, 0); ">(</span>"UPDATE document WITH ... WHERE document = ?"<span style="color: rgb(0, 0, 0); ">, result1.</span><span style="color: rgb(0, 51, 105); ">namedItem</span><span style="color: rgb(0, 0, 0); ">(</span>"id"<span style="color: rgb(0, 0, 0); ">), </span><span style="color: rgb(136, 19, 80); ">function</span><span style="color: rgb(0, 0, 0); ">(result2) {</span></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 10px/normal Monaco; "><span class="Apple-style-span" style="font-family: Verdana; font-size: 11px; line-height: 20px; ">    </span>            ...</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 10px/normal Monaco; "><span class="Apple-style-span" style="font-family: Verdana; font-size: 11px; line-height: 20px; ">    </span>        });</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 10px/normal Monaco; "><span class="Apple-style-span" style="font-family: Verdana; font-size: 11px; line-height: 20px; ">    </span>    }</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 10px/normal Monaco; "><span class="Apple-style-span" style="font-family: Verdana; font-size: 11px; line-height: 20px; ">    </span>});</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 10px/normal Monaco; min-height: 14px; "><br class="webkit-block-placeholder"></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 10px/normal Monaco; min-height: 14px; "><span class="Apple-style-span" style="font-family: Verdana; font-size: 11px; line-height: 20px; ">    </span>transation2 = db.<span style="color: rgb(0, 51, 105); ">beginTransation</span>(Database.ExclusiveTransactionLocks);</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 10px/normal Monaco; color: rgb(235, 115, 0); "><span style="color: rgb(0, 0, 0); "><span class="Apple-style-span" style="font-family: Verdana; font-size: 11px; line-height: 20px; ">    </span>transation2.</span><span style="color: rgb(0, 51, 105); ">executeQuery</span><span style="color: rgb(0, 0, 0); ">(</span>"UPDATE user WITH ... WHERE user = ?"<span style="color: rgb(0, 0, 0); ">, </span>"123"<span style="color: rgb(0, 0, 0); ">, </span><span style="color: rgb(136, 19, 80); ">function</span><span style="color: rgb(0, 0, 0); ">(result1) {</span></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 10px/normal Monaco; "><span class="Apple-style-span" style="font-family: Verdana; font-size: 11px; line-height: 20px; ">    </span><span style="color: rgb(136, 19, 80); ">    if</span>(...) {</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 10px/normal Monaco; "><span class="Apple-style-span" style="font-family: Verdana; font-size: 11px; line-height: 20px; ">    </span>        result1.transation.<span style="color: rgb(0, 51, 105); ">executeQuery</span>(<span style="color: rgb(235, 115, 0); ">"UPDATE user WITH ... WHERE user = ?"</span>, result1.<span style="color: rgb(0, 51, 105); ">namedItem</span>(<span style="color: rgb(235, 115, 0); ">"id"</span>), <span style="color: rgb(136, 19, 80); ">function</span>(result2) {</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 10px/normal Monaco; "><span class="Apple-style-span" style="font-family: Verdana; font-size: 11px; line-height: 20px; ">    </span>            result1.transation.commit();</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 10px/normal Monaco; "><span class="Apple-style-span" style="font-family: Verdana; font-size: 11px; line-height: 20px; ">    </span>        });</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 10px/normal Monaco; "><span class="Apple-style-span" style="font-family: Verdana; font-size: 11px; line-height: 20px; ">    </span>    } <span style="color: rgb(136, 19, 80); ">else</span> {</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 10px/normal Monaco; "><span class="Apple-style-span" style="font-family: Verdana; font-size: 11px; line-height: 20px; ">    </span>        result1.transation.<span style="color: rgb(102, 26, 169); ">rollback</span>();</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 10px/normal Monaco; "><span class="Apple-style-span" style="font-family: Verdana; font-size: 11px; line-height: 20px; ">    </span>    }</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 10px/normal Monaco; "><span class="Apple-style-span" style="font-family: Verdana; font-size: 11px; line-height: 20px; ">    </span>});</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 10px/normal Monaco; "><br class="webkit-block-placeholder"></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 10px/normal Monaco; "><font class="Apple-style-span" color="#000000" face="Verdana" size="3">My example executes queries on the transaction object. The transaction object would internally keep track of the database connection it holds. Transactions can come in a couple of forms, shared and exclusive access locks (read <a href="http://www.sqlite.org/lang_transaction.html">http://www.sqlite.org/lang_transaction.html</a> for details on these.)</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 10px/normal Monaco; "><font class="Apple-style-span" color="#000000" face="Verdana" size="3"><br></font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 10px/normal Monaco; "><font class="Apple-style-span" color="#000000" face="Verdana" size="3">I think an explicit commit should be required for the transactions. So you can keep the transcript object around and add to it over time.</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 10px/normal Monaco; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 10px/normal Monaco; "><div><font class="Apple-style-span" face="Verdana" size="3">Above I have beginTransation taking a constant Database.ExclusiveTransactionLocks. Passing no argument would get shared access locks. Also in my example is an explicit rollback. Any query that fails will naturally rollback the transaction, but having progrmatic way to rollback is a necessity.</font></div><div><font class="Apple-style-span" face="Verdana" size="3"><br class="webkit-block-placeholder"></font></div><div><font class="Apple-style-span" face="Verdana" size="3"><div>The closeTransaction Database object function should be remove if explicit transactions are added and the implicit transaction is limited to one query.</div><div><br class="webkit-block-placeholder"></div></font></div><div><font class="Apple-style-span" face="Verdana" size="3">Some other comments:</font></div><div><font class="Apple-style-span" face="Verdana" size="3"><br class="webkit-block-placeholder"></font></div><div><font class="Apple-style-span" face="Verdana" size="3">You might notice that I have been using executeQuery() instead of executeSql(). I think it is weird and unneeded to say Sql in the function name. If anything, it should be executeSQL().</font></div><div><font class="Apple-style-span" face="Verdana" size="3"><br class="webkit-block-placeholder"></font></div><div><font class="Apple-style-span" face="Verdana" size="3">I think the ResultSet object should have a property to get the Database and the Transaction objects. As I mentioned earlier, not everyone will use closures and will need access to these to do anything else.</font></div><div><br></div></div></span></div></span><div> <span class="Apple-style-span" style="border-collapse: separate; border-spacing: 0px 0px; color: rgb(0, 0, 0); font-family: Verdana; font-size: 11px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; text-align: auto; -khtml-text-decorations-in-effect: none; text-indent: 0px; -apple-text-size-adjust: auto; text-transform: none; orphans: 2; white-space: normal; widows: 2; word-spacing: 0px; "><div style="word-wrap: break-word; -khtml-nbsp-mode: space; -khtml-line-break: after-white-space; "><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font class="Apple-style-span" size="2"><span class="Apple-style-span" style="font-size: 10px;"><span class="Apple-style-span" style="font-size: 10px; ">— Timothy Hatcher</span></span></font></div></div><br class="Apple-interchange-newline"></span> </div><br></body></html>