Skip to main content

Understanding the asynchronous execution model

One common concern about using asynchronous execution mode is the assumption that you can't start executing a SQLStatement instance if another SQLStatement is currently executing against the same database connection. In fact, this assumption isn't correct. While a SQLStatement instance is executing you can't change the text property of the statement. However, if you use a separate SQLStatement instance for each different SQL statement that you want to execute, you can call the execute() method of a SQLStatement while another SQLStatement instance is still executing, without causing an error.

Internally, when you're executing database operations using asynchronous execution mode, each database connection (each SQLConnection instance) has its own queue or list of operations that it is instructed to perform. The runtime executes each operation in sequence, in the order they are added to the queue. When you create a SQLStatement instance and call its execute() method, that statement execution operation is added to the queue for the connection. If no operation is currently executing on that SQLConnection instance, the statement begins executing in the background. Suppose that within the same block of code you create another SQLStatement instance and also call that method's execute() method. That second statement execution operation is added to the queue behind the first statement. As soon as the first statement finishes executing, the runtime moves to the next operation in the queue. The processing of subsequent operations in the queue happens in the background, even while the result event for the first operation is being dispatched in the main application code. The following code demonstrates this technique:

// Using asynchronous execution mode
var stmt1:SQLStatement = new SQLStatement();
stmt1.sqlConnection = conn;

// ... Set statement text and parameters, and register event listeners ...

stmt1.execute();

// At this point stmt1's execute() operation is added to conn's execution queue.

var stmt2:SQLStatement = new SQLStatement();
stmt2.sqlConnection = conn;

// ... Set statement text and parameters, and register event listeners ...

stmt2.execute();

// At this point stmt2's execute() operation is added to conn's execution queue.
// When stmt1 finishes executing, stmt2 will immediately begin executing
// in the background.

There is an important side effect of the database automatically executing subsequent queued statements. If a statement depends on the outcome of another operation, you can't add the statement to the queue (in other words, you can't call its execute() method) until the first operation completes. This is because once you've called the second statement's execute() method, you can't change the statement's text or parameters properties. In that case you must wait for the event indicating that the first operation completes before starting the next operation. For example, if you want to execute a statement in the context of a transaction, the statement execution depends on the operation of opening the transaction. After calling the SQLConnection.begin() method to open the transaction, you need to wait for the SQLConnection instance to dispatch its begin event. Only then can you call the SQLStatement instance's execute() method. In this example the simplest way to organize the application to ensure that the operations are executed properly is to create a method that's registered as a listener for the begin event. The code to call the SQLStatement.execute() method is placed within that listener method.