On Wed, 31 Oct 2007, Brady Eidson wrote:

My understanding with this design is that you would get this
SQLTransaction object back and it would just sit around, not doing
anything.  When you first call executeSql on it, you kick off the
transaction steps as they already exist.  Until you call
executeSql(), it's just a dummy object that doesn't interfere with
the database at all.

What if there's a problem with opening the transaction itself? You
don't want to run all the code for preparing the statement only to
find you didn't have a chance for the statement to run in the first
place.

While the spec *does* currently enforce preparing the statement at the time of calling executeSql() just to mark the statement bogus, "marking the statement bogus" is only a flag that takes effect later during the
transaction effects.

Therefore, why is it so necessary to prepare the statement before the
transaction is opened? Why don't we parse and validate the statement in
the transaction steps themselves?

If we adopted both of these models (Tims idea and allowing the statement
to be parsed in the transaction steps) and there was a problem with
opening the transaction itself, you'd get the
SQLTransactionErrorCallback and the statement would never even be
touched at all.

I'm talking about:

  var transaction = db.transaction(errorCallback);
  // the transaction has failed at this point
  // but we have no way to stop the next few lines from running:
  ...do lots of work to get the data to put into the transaction...
  transaction.executeSql('...', [expensiveData], ...);

vs:

  db.transaction(function (transaction) {
    // this never gets called, since the transaction failed
    ...do lots of work to get the data to put into the transaction...
    transaction.executeSql('...', [expensiveData], ...);
  }, errorCallback);

Interesting.  I think you've swayed me with this argument.

I have an alternative to propose - how about reinstating Database.executeSql(), and do something like this.

db.executeSql("select * from table;", [], <SQLStatementCallback>, <SQLStatementErrorCallback>, <SQLTransactionErrorCallback>);

This would "fire and forget" a single, individual statement in its own transaction. It would follow transaction steps exactly as they currently exist, except it would skip the SQLTransactionCallback because the first sql statement to execute is already queued.

This way you could do:

db.executeSql("SELECT * FROM Notes", [], function(tx, results) { // Start a new transaction with one sql statement on the queue tx.executeSql("INSERT INTO Notes...", [], ...); // Add a new statement to this transaction db.executeSql("SOME OTHER SQL STATEMENT", ...); // Start a new transaction with its first sql statement queued up
        }, statementErrorCallback, txErrorCallback);

But could also do something as simple as:

db.executeSql("CREATE TABLE Notes (...)", [], NULL, NULL, NULL);

Someone I talked to about this in person was concerned about the naming collision of executeSql() - it might be confusing if JS developers start making custom classes and you start seeing this.executeSql() - is it a database or a sqltransaction? Perhaps naming one of them something other than executeSql().

But I do think this is a reasonable way to A - make it easier to kick off an individual statement and B - allows the developer, in the best case scenario of no failures, kick off a sql statement that runs to completion with *no* callbacks.

I think both of these points are important.

Thanks,
~Brady

Reply via email to