Skip to content

Commit

Permalink
Tests and fixes for issue #1 (Calling SQLRunner.executeModify() with …
Browse files Browse the repository at this point in the history
…same statement multiple times throws error)
  • Loading branch information
probertson committed Apr 2, 2010
1 parent 9b81069 commit 09f2e5c
Show file tree
Hide file tree
Showing 8 changed files with 324 additions and 18 deletions.
16 changes: 5 additions & 11 deletions src/com/probertson/data/SQLRunner.as
Expand Up @@ -105,10 +105,13 @@ package com.probertson.data
{
var len:int = statementBatch.length;
var statements:Vector.<SQLStatement> = new Vector.<SQLStatement>(len);
var parameters:Vector.<Object> = new Vector.<Object>(len);

if (_batchStmtCache == null)
{
_batchStmtCache = new Object();
}

for (var i:int = 0; i < len; i++)
{
var sql:String = statementBatch[i].statementText;
Expand All @@ -120,20 +123,11 @@ package com.probertson.data
_batchStmtCache[sql] = stmt;
}

stmt.clearParameters();
var params:Object = statementBatch[i].parameters;
if (params != null)
{
for (var prop:String in params)
{
stmt.parameters[":" + prop] = params[prop];
}
}

statements[i] = stmt;
parameters[i] = statementBatch[i].parameters;
}

var pendingBatch:PendingBatch = new PendingBatch(statements, resultHandler, errorHandler, progressHandler);
var pendingBatch:PendingBatch = new PendingBatch(statements, parameters, resultHandler, errorHandler, progressHandler);
_connection.addBlockingBatch(pendingBatch);
}

Expand Down
33 changes: 26 additions & 7 deletions src/com/probertson/data/sqlRunnerClasses/PendingBatch.as
Expand Up @@ -30,14 +30,15 @@ package com.probertson.data.sqlRunnerClasses
import flash.data.SQLTransactionLockType;
import flash.errors.SQLError;
import flash.events.SQLErrorEvent;
import flash.events.SQLEvent;
import flash.events.SQLEvent;

public class PendingBatch
{

public function PendingBatch(batch:Vector.<SQLStatement>, resultHandler:Function, errorHandler:Function, progressHandler:Function=null)
public function PendingBatch(batch:Vector.<SQLStatement>, parameters:Vector.<Object>, resultHandler:Function, errorHandler:Function, progressHandler:Function=null)
{
_batch = batch;
_parameters = parameters;
_resultHandler = resultHandler;
_errorHandler = errorHandler;
_progressHandler = progressHandler;
Expand All @@ -47,6 +48,7 @@ package com.probertson.data.sqlRunnerClasses
// ------- Member vars -------

private var _batch:Vector.<SQLStatement>;
private var _parameters:Vector.<Object>;
private var _results:Vector.<SQLResult>;
private var _resultHandler:Function;
private var _errorHandler:Function;
Expand Down Expand Up @@ -94,28 +96,44 @@ package com.probertson.data.sqlRunnerClasses
private function conn_begin(event:SQLEvent):void
{
_conn.removeEventListener(SQLEvent.BEGIN, conn_begin);

executeStatements();
}


private function executeStatements():void
{
_results = new Vector.<SQLResult>();
executeNextStatement();
}


private function executeNextStatement():void
{
callProgressHandler();


while (_batch.length > 0)
if (_batch.length > 0)
{
var stmt:SQLStatement = _batch.shift();
if (stmt.sqlConnection == null)
{
stmt.sqlConnection = _conn;
}

stmt.clearParameters();
var params:Object = _parameters.shift();
if (params != null)
{
for (var prop:String in params)
{
stmt.parameters[":" + prop] = params[prop];
}
}

stmt.addEventListener(SQLEvent.RESULT, stmt_result);
stmt.addEventListener(SQLErrorEvent.ERROR, conn_error);
stmt.execute();
}

_results = new Vector.<SQLResult>();
}


Expand All @@ -128,7 +146,7 @@ package com.probertson.data.sqlRunnerClasses
_results[_results.length] = stmt.getResult();

_statementsCompleted++;
callProgressHandler();
executeNextStatement();

if (_statementsCompleted == _numStatements)
{
Expand Down Expand Up @@ -245,6 +263,7 @@ package com.probertson.data.sqlRunnerClasses
_conn = null;
_pool = null;
_batch = null;
_parameters = null;
_results = null;
_progressHandler = null;
_resultHandler = null;
Expand Down
40 changes: 40 additions & 0 deletions tests/events/ExecuteModifyErrorEvent.as
@@ -0,0 +1,40 @@
package events
{
import flash.errors.SQLError;
import flash.events.Event;

public class ExecuteModifyErrorEvent extends Event
{
// ------- Event type constants -------

public static const ERROR:String = "executeModifyError";


// ------- Constructor -------

public function ExecuteModifyErrorEvent(type:String, error:SQLError, bubbles:Boolean=false, cancelable:Boolean=false)
{
super(type, bubbles, cancelable);
this.error = error;
}


// ------- Public properties -------

public var error:SQLError;


// ------- Event overrides -------

public override function clone():Event
{
return new ExecuteModifyErrorEvent(type, error, bubbles, cancelable);
}


public override function toString():String
{
return formatToString("ExecuteModifyErrorEvent", "type", "bubbles", "cancelable", "eventPhase");
}
}
}
40 changes: 40 additions & 0 deletions tests/events/ExecuteModifyResultEvent.as
@@ -0,0 +1,40 @@
package events
{
import flash.data.SQLResult;
import flash.events.Event;

public class ExecuteModifyResultEvent extends Event
{
// ------- Event type constants -------

public static const RESULT:String = "executeModifyResult";


// ------- Constructor -------

public function ExecuteModifyResultEvent(type:String, results:Vector.<SQLResult>, bubbles:Boolean=false, cancelable:Boolean=false)
{
super(type, bubbles, cancelable);
this.results = results;
}


// ------- Public properties -------

public var results:Vector.<SQLResult>;


// ------- Event overrides -------

public override function clone():Event
{
return new ExecuteModifyResultEvent(type, results, bubbles, cancelable);
}


public override function toString():String
{
return formatToString("ExecuteModifyResultEvent", "type", "bubbles", "cancelable", "eventPhase");
}
}
}
10 changes: 10 additions & 0 deletions tests/sql/AddRow.sql
@@ -0,0 +1,10 @@
INSERT INTO main.testTable
(
colString,
colInt
)
VALUES
(
:colString,
:colInt
)
6 changes: 6 additions & 0 deletions tests/sql/create/CreateTable_testTable.sql
@@ -0,0 +1,6 @@
CREATE TABLE main.testTable
(
colIntPK int PRIMARY KEY AUTOINCREMENT,
colString String NOT NULL,
colInt int
)
154 changes: 154 additions & 0 deletions tests/tests/com/probertson/data/SQLRunnerExecuteModifyTest.as
@@ -0,0 +1,154 @@
package tests.com.probertson.data
{
import com.probertson.data.QueuedStatement;
import com.probertson.data.SQLRunner;
import events.ExecuteModifyErrorEvent;
import events.ExecuteModifyResultEvent;
import flash.data.SQLConnection;
import flash.data.SQLResult;
import flash.data.SQLStatement;
import flash.errors.SQLError;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.filesystem.File;
import flexunit.framework.Assert;
import org.flexunit.async.Async;
import utils.CreateDatabase;

public class SQLRunnerExecuteModifyTest extends EventDispatcher
{
// Reference declaration for class to test
private var _sqlRunner:com.probertson.data.SQLRunner;


public function SQLRunnerExecuteModifyTest()
{
}


// ------- Instance vars -------

private var _dbFile:File;


// ------- Setup/cleanup -------

[Before]
public function setup():void
{
_dbFile = File.createTempDirectory().resolvePath("test.db");
var createDB:CreateDatabase = new CreateDatabase(_dbFile);
createDB.createDatabase();
}


[After(async, timeout="250")]
public function teardown():void
{
_sqlRunner.close(sqlRunner_close);
}

private function sqlRunner_close():void
{
_sqlRunner = null;
var tempDir:File = _dbFile.parent;
tempDir.deleteDirectory(true);
}


// ------- Tests -------

[Test(async, timeout="500")]
public function testOneStatement():void
{
addEventListener(ExecuteModifyResultEvent.RESULT, Async.asyncHandler(this, testOneStatement_result2, 500));

_sqlRunner = new SQLRunner(_dbFile);
var stmt:QueuedStatement = new QueuedStatement(ADD_ROW_SQL, {colString:"Hello", colInt:7});
_sqlRunner.executeModify(Vector.<QueuedStatement>([stmt]), testOneStatement_result, testOneStatement_error);
}

// --- handlers ---

private function testOneStatement_result(results:Vector.<SQLResult>):void
{
dispatchEvent(new ExecuteModifyResultEvent(ExecuteModifyResultEvent.RESULT, results));
}

private function testOneStatement_result2(event:ExecuteModifyResultEvent, passThroughData:Object):void
{
Assert.assertEquals(1, event.results.length);
Assert.assertEquals(1, event.results[0].rowsAffected);
}

private function testOneStatement_error(error:SQLError):void
{
Assert.fail(error.message);
}


[Test(async, timeout="500")]
public function testReuseStatement():void
{
addEventListener(ExecuteModifyResultEvent.RESULT, Async.asyncHandler(this, testReuseStatement_result2, 500));

_sqlRunner = new SQLRunner(_dbFile);
var stmt1:QueuedStatement = new QueuedStatement(ADD_ROW_SQL, {colString:"Hello", colInt:7});
var stmt2:QueuedStatement = new QueuedStatement(ADD_ROW_SQL, {colString:"World", colInt:17});
_sqlRunner.executeModify(Vector.<QueuedStatement>([stmt1, stmt2]), testReuseStatement_result, testReuseStatement_error);
}

// --- handlers ---

private function testReuseStatement_result(results:Vector.<SQLResult>):void
{
dispatchEvent(new ExecuteModifyResultEvent(ExecuteModifyResultEvent.RESULT, results));
}

private function testReuseStatement_result2(event:ExecuteModifyResultEvent, passThroughData:Object):void
{
// verify that the inserts happened
Assert.assertEquals(2, event.results.length);
Assert.assertEquals(1, event.results[0].rowsAffected);
Assert.assertEquals(1, event.results[1].rowsAffected);

// verify that the inserted data matches
var id1:int = event.results[0].lastInsertRowID;
var id2:int = event.results[1].lastInsertRowID;

var conn:SQLConnection = new SQLConnection();
conn.open(_dbFile);

var stmt:SQLStatement = new SQLStatement();
stmt.sqlConnection = conn;
stmt.text = "SELECT colString, colInt FROM main.testTable WHERE colIntPK = :colIntPK";
var result:SQLResult;

stmt.parameters[":colIntPK"] = id1;
stmt.execute();
result = stmt.getResult();
Assert.assertEquals("Hello", result.data[0].colString);
Assert.assertEquals(7, result.data[0].colInt);

stmt.parameters[":colIntPK"] = id2;
stmt.execute();
result = stmt.getResult();
Assert.assertEquals("World", result.data[0].colString);
Assert.assertEquals(17, result.data[0].colInt);

conn.close();
}

private function testReuseStatement_error(error:SQLError):void
{
Assert.fail(error.message);
}


// ------- SQL statements -------

[Embed(source="sql/AddRow.sql", mimeType="application/octet-stream")]
private static const AddRowStatementText:Class;
private static const ADD_ROW_SQL:String = new AddRowStatementText();
}
}

0 comments on commit 09f2e5c

Please sign in to comment.