[whatwg] Some comments/questions on database storage

On Feb 25, 2008, at 3:12 PM, Ralf Stoltze wrote:

> On  Monday, February 25, 2008 10:56 PM, Brady Eidson wrote:
>
>> Placeholders are the mechanism the spec mandates to prevent SQL
>> injections et al.  *How* seems to be an implementation detail.
>> SQLite, for example, has the ? + argument structure in place already.
>
> So step 3 "Replace each ? placeholder" can be skipped if the  
> underlying
> DB architecture already has a similar mechanism.

It's not skipped - it's being fulfilled by the DB backend.

This part of the spec is about what the user agent must do, not how.

If the user agent uses SQLite as the backend as well as the `? + arg`  
API SQLite provides, I think it has fulfilled it's obligations under  
the HTML5 spec.

>>> Based on 4.11.6, step 6.7, I assume the following snippet to always
>>> execute in order 1, 2, 3?
>>>
>>> db.transaction(function(tx) {
>>> tx.executeSql('query 1', null, function(tx, rs) {
>>>   tx.executeSql('query 2', null, function(tx, rs) {
>>>   });
>>> });
>>> tx.executeSql('query 3', null, function(tx, rs) {
>>> });
>>> });
>>
>> 4.11.3 step 6 states that if an executeSql call passed steps
>> 1-5, the
>> statement is queued up in the transaction.
>> 4.11.6 step 6.7 says "move on to the next statement, if any"
>> I trust this means "the next statement in the transaction's
>> statement
>> queue" and that the queue pops statements in the order they
>> were queued.
>>
>> This means that query 1 would be queued, query 3 would be
>> queued, then
>> in the callback for query 1, query 2 would be queued.
>> Execution order 1, 3, 2
>
> Hmm. I'm confused.
>
> A statement can only be queued when executeSql() is invoked.
>
> It's not clear to me when the top-level executeSql() methods are  
> invoked
> with respect to the overall processing model from 4.11.6.

 From 4.11.3:
"When the executeSql(sqlStatement, arguments, callback, errorCallback)  
method is invoked, the user agent must run the following algorithm.
...
If the method was not invoked during the execution of a  
SQLTransactionCallback, SQLStatementCallback, or  
SQLStatementErrorCallback then raise an INVALID_STATE_ERR exception."

This means that calling executeSql() is only valid from within the  
single SQLTransactionCallback, a SQLStatementCallback, or a  
SQLStatementErrorCallback.

In the above example, the executeSql() call for query 1 and 3 are  
being called within the SQLTransactionCallback.  The executeSql() call  
for query 2 is being called within a SQLStatementCallback.

> 4.11.2:
> "The transaction() method takes one or two arguments. When called, the
> method must immediately return and then asynchronously run the
> transaction steps"

Right, and these transaction steps are covered under 4.11.6

4.11.6.4 states "Invoke the transaction callback with the  
aforementioned SQLTransaction object as its only argument."

As previously mentioned, one of the 3 times you are allowed to call  
executeSql() is from within the SQLTransactionCallback, so during step  
4 of the transaction steps is where the script first has the  
opportunity to call executeSql().

> That doesn't necessarily mean to me that any executeSql() is ever
> invoked before the transaction steps are run. Thus, the transaction
> queue would be empty (what makes no sense).

Read the entire set of transaction steps.  The first place a statement  
can be queued is during step 4 - from within the  
SQLTransactionCallback.  The first time a statement is actually pulled  
out of the transaction's statement queue to be run is step 6.

It is true that if the script doesn't queue any statements during step  
4, step 6 will be reached and the transaction queue would be empty.
And yes, that would make no sense for the script to do - it would be a  
waste of time.
Which is why you'll typically see a script call executeSql() at least  
once during the SQLTransactionCallback  ;)
(In the above example, it calls it twice - query 1 and query 3)

> Is it meant that all top-level executeSql() methods are executed  
> before
> the transaction steps are run? In this case, I also see execution  
> order
> 1,3,2.

I'd personally define "top-level executeSql() calls" to be  
"executeSql() calls made from within the SQLTransactionCallback"

Your example might also be written like this, which makes it more  
clear how the steps run:

function statementCallback(tx, results)
{
     // When this method is called, we're at 4.11.6, step 6.5 - the  
SQLStatement callback
     tx.executeSql('query 2', null);
}

function transactionCallback(tx)
{
     // When this method is called, the transaction steps have already  
commenced and we are in 4.11.6, step 4,
     // and are making our "top level" calls to executeSql(), queuing  
up the first two statements in this transaction
     tx.executeSql('query 1', null, statementCallback);
     tx.executeSql('query 3', null);
}

db.transaction(transactionCallback);

~Brady

>
> /ralf
>

Received on Monday, 25 February 2008 15:54:35 UTC