Friday, January 07, 2011

Testing IndexedDB with the Trial Tool Web App and Microsoft Internet Explorer 8 or 9 Beta

Update 1/9/2011: Parashuram eliminated spurious “Transaction Complete undefined” messages in the console response of the Save Data, Get Data and Create Index examples.

Narasimhan Parashuram (@nparashuram) added this comment to my Testing IndexedDB with the SqlCeJsE40.dll COM Server and Microsoft Internet Explorer 8 or 9 Beta post (updated 1/6/2011) about his TrialTool test pages for IE8 and IE9:

Here is a showcase of the IndexedDB API for IE - http://blog.nparashuram.com/2011/01/indexeddb-for-internet-explorer.html

- that opens this page:

image

Following the Demo link opens a page that’s identical to that described in my Testing IndexedDB with the Trial Tool Web App and Mozilla Firefox 4 Beta 8 (updated 1/6/2011). Clicking the Pre-Requisites link in the Examples list opens this page with additional instructions in the console window:

image

Important: Note the requirement for running vcredist_x86.exe, which you’ll find in the IndexedDB install directory, from a command prompt if you’re using 32-bit Windows. You must run vcredist_x86.exe before you run regsvr32.exe sqlcejse40.dll. Close and reopen IE after registering the COM server. You must run commands and IE with an Administrator account and enable running the two ActiveX controls from all Websites when prompted.

This version of the Trial Tool provides automated equivalents of the COM server package’s CodeSnippets, as well as many examples that the snippets don’t cover.


Here’s the basic prerequisite code for for all operations:

// Include Bootlib.js to get all the constants and functions required for the prototype. 

if (!window.indexedDB) {
  window.indexedDB = new ActiveXObject("SQLCE.Factory.4.0");
  window.indexedDBSync = new ActiveXObject("SQLCE.FactorySync.4.0");
  
  if (window.JSON) {
    window.indexedDB.json = window.JSON;
    window.indexedDBSync.json = window.JSON;
  }
  else {
    var jsonObject = {
      parse: function(txt){
        if (txt === "[]") 
          return [];
        if (txt === "{}") 
          return {};
        throw {
          message: "Unrecognized JSON to parse: " + txt
        };
      }
    };
    window.indexedDB.json = jsonObject;
    window.indexedDBSync.json = jsonObject;
  }
  
  // Add some interface-level constants and methods.
  window.IDBDatabaseException = {
    UNKNOWN_ERR: 0,
    NON_TRANSIENT_ERR: 1,
    NOT_FOUND_ERR: 2,
    CONSTRAINT_ERR: 3,
    DATA_ERR: 4,
    NOT_ALLOWED_ERR: 5,
    SERIAL_ERR: 11,
    RECOVERABLE_ERR: 21,
    TRANSIENT_ERR: 31,
    TIMEOUT_ERR: 32,
    DEADLOCK_ERR: 33
  };
  
  window.IDBKeyRange = {
    SINGLE: 0,
    LEFT_OPEN: 1,
    RIGHT_OPEN: 2,
    LEFT_BOUND: 4,
    RIGHT_BOUND: 8
  };
  
  window.IDBRequest = {
    INITIAL: 0,
    LOADING: 1,
    DONE: 2
  }
    
    window.IDBKeyRange.only = function(value){
    return window.indexedDB.range.only(value);
};

window.IDBKeyRange.leftBound = function(bound, open){
  return window.indexedDB.range.leftBound(bound, open);
};

window.IDBKeyRange.rightBound = function(bound, open){
  return window.indexedDB.range.rightBound(bound, open);
};

window.IDBKeyRange.bound = function(left, right, openLeft, openRight){
  return window.indexedDB.range.bound(left, right, openLeft, openRight);
};
}
  var DAO = {};

This code opens a named Database instance with a description:

/*Open Database*/

document.write("Trying to open database ...");
var request = window.indexedDB.open("BookShop", "My Book Shop Database");
request.onsuccess = function(event){
  DAO.db = event.result;
  document.write("Database Opened", DAO.db);
};

Creating Object Stores and Persisting Object Instances

A Database must have at least one Object Store, which corresponds to a Windows Azure table. Clicking the Create Object Store link, followed by the Load Prerequisites and Run buttons and the [Object] link, displays this code and result:

image

Clicking the Save Data link, followed by the Load Prerequisites and Run buttons and scrolling the code window, displays this code and the persisted object’s properties:

image

[The ===== Transaction Complete undefined message is a mystery. I’ve pinged Parashuram for details. Stay tuned for an update.]

Update 1/9/2011: Parashuram added the following comment on 1/7/2011 regarding the “Transaction Complete undefined” message:

[Re:] Transaction complete undefined.

In these examples, I am enclosing all examples in their own transactions. Hence, a read or a write always has a DAO.transaction.commit(). The DAO.transaction.oncomplete displays the message. The undefined is because I am trying to print the transaction, after it is is closed - my bad. Will remove it.

Clicking the Get Data link, followed by the Load Prerequisites and Run buttons, the [Object] link to expand it, and scrolling the code window, displays this code and returns the persisted object’s properties:

image

The id and bookName values differ from the preceding example because the code executes a new Save Data operation before Get Data.

Adding Indexes and Using Key Cursors

An Index on a property is required to retrieve objects by a property value [range]. Clicking the Create Index link, followed by the Load Prerequisites and Run buttons, adds an Index on the price field:

image

After you’ve created an Index, you can run the Save Data operation repeatedly to add several BookList instances. As noted in the preceding Examples list, Parashuram hadn’t competed code for the Geta All Data operation when the post was written.

Clicking the Key Cursor on Index link, followed by the Load Prerequisites and Run buttons, iterates the automatically created default auto-incrementing KeyCursor Index on the id field:

image

[It’s not clear why the cursorIterator() function doesn’t return indexed instances in numerical order.]

Summary

The similarity of Microsoft’s IndexedDB implementation with SQL Compact to the Windows Azure Platform’s early SQL Server Data Services (SSDS) and later SQL Data Services (SDS) running on SQL Server in the cloud is interesting.

I’m anxious to see what Pablo Castro’s team comes up with as JavaScript libraries to support T-SQL on IndexedDB ObjectStores. Stay tuned for further developments.

Related OakLeaf Posts


1 comments:

Anonymous said...

Transaction complete undefined.

In these examples, I am enclosing all examples in their own transactions. Hence, a read or a write always has a DAO.transaction.commit(). The DAO.transaction.oncomplete displays the message. The undefined is because I am trying to print the transaction, after it is is closed - my bad. Will remove it.


The key cursor orders the indexes based on the index - the priceIndex in this case. Hence,they are sorted on the value price. Will make this clearer in my examples. THnx for letting me know.