Thursday, 9 May 2013

HTML5 IndexedDB

Why IndexedDB? 

When WebStorage stands for key/value persistence system, it does not features any enhanced database operations. For example, you have to locally store employee data and later, you need to fetch all those employees whose first name starts with ‘A’. From Web Storage in order to find out those records, you have to iterate through all data. IndexedDB is there to help you to fetch the data easily by the use of indexes. IndexedDB can be used to store values of any type such as DOMString, Date, Object, Array etc. Web SQL Database also gives the same set of features. But this specification is no longer actively maintained. So I thought of writing about IndexedDB, with which the Web Applications Working Group continues work on.
IndexedDB supports 2 kinds of APIs. Asynchronous and Synchronous. But due to potential lack of implementations, the features in Synchronous APIs may be removed. So lets filter that too. Also IndexedDB in Mozilla is implemented a bit different from Webkit.
And hence the topic of our discussion is Asynchronous API of IndexedDB
You can work with IndexedDB as follows
  1. Open a database
  2. Start a transaction.
  3. Create an object store.
  4. Request an operation.
  5. Listen to suitable event
  6. Get the result and work on it
Be ready to spend a couple of minutes on each example.

 Database

Every database has a name which identifies it within a specific origin. Each database also has a current version. When a database is first created, its version is zero. At present browsers are working on their versions of indexedDB object. For example, mozIndexedDB for Mozilla, webkitIndexedDB for webkit etc.
 <html>  
 <head>  
 <script>  
 function test(){  
     var indexedDB = window.indexedDB ||   
                          window.webkitIndexedDB ||   
                          window.mozIndexedDB ||   
                          window.moz_indexedDB ||   
                          window.msIndexedDB ||   
                          window.shimIndexedDB;  
 var databaseName = “empdatabase12″;  
 var request = indexedDB.open(databaseName);  
 try{  
   request.onerror = function(event) {  
     // Error handling code goes here.  
     console.log(event);  
 };  
 request.onupgradeneeded = function(event) {  
   console.log(“inside upgradeevent”);  
    var database = event.target.result;  
   console.log(‘version>>’+database.version);  
 };  
 request.onsuccess = function(event) {  
   console.log(“inside onsuccess”);  
    var database = event.target.result;  
   var versionRequest = database.setVersion(1);  
   console.log(‘version>>’+database.version);  
 };  
 } catch(e){  
   console.log(e.message);  
 }  
 }  
 </script>  
 </head>  
 <body>  
   <button onclick=’test()’>check database</button>  
 </body>  
 </html>  
When open() method of indexDB is invoked, a database is created if it does not exist. As per the specification, objectstore or index CRUD operations can be performed on a database only when a version is changed, which happens when a database is created as well as when explicitly specified.
In Mozilla, a version is changed in 2 ways.
  1. var request_IDBRequest = indexedDB.open(databaseName)                                                                  If database does not exist, creates a new one
  2. var request_IDBRequest = indexedDB.open(databaseName, higher_version_number)     Database exists and opening with a higher version.
When you run above example in Firefox, you can see result as follows
inside upgradeevent
version>>1
inside onsuccess
TypeError: database.setVersion is not a function [Break On This Error]
var versionRequest = database.setVersion(1);
Mozilla does not provide a ‘setVersion’ method in ‘IDBDatabase’ object.
A version can be changed in webkit browsers as follows.
  1. var request_IDBRequest = indexedDB.open(databaseName)                                                                  If database does not exist, creates a new one
  2. var versionRequest = database.setVersion(higher_version_number);                               After opening database, explicitly change its version using setVersion of ‘IDBDatabase’ object.
When you run above example in Chrome, you can see result as follows
 inside onsuccess 
 version>>1

ObjectStore and Index

An object store is the primary storage mechanism for storing data in a database. Each database can contain a set of object stores. Every object store has a unique name. Whenever a value is stored in an object store, it is associated with a key. There are several different ways that a key can be supplied depending on whether the object store uses a key path or a key generator.
An index can be used to fetch records in an object store using properties of the values stored. An index is again a key-value storage and will always have a referenced object store. The changes in the referenced object store will automatically reflect in the records of an index. There can be several indexes referencing the same object store.
 <html>  
 <head>  
 <script>  
 function test(){  
     var indexedDB = window.indexedDB ||   
 window.webkitIndexedDB ||   
 window.mozIndexedDB ||   
 window.moz_indexedDB ||   
 window.msIndexedDB || window.shimIndexedDB;  
 var empData = [  
  { empid: "101", empname: "Ram", age: 29, email: "ram@rom.com" },  
  { empid: "102", empname: "Harry", age: 28, email: "harry@rom.com" },  
  { empid: "103", empname: "Ram", age: 35, email: "ra1@rom.com" }  
 ];  
 var databaseName = “empdatabase”;  
  var request = indexedDB.open(databaseName,2);  
 request.onerror = function(event) {  
  // Error handling code goes here.  
 console.log(event);  
 };  
 request.onupgradeneeded = function(event) {  
 console.log(“inside upgradeevent”);  
  var database = event.target.result;  
 /*Create an objectstore for storing employee data*/  
 var objectStore = database.createObjectStore(“emps”, { keyPath: “empid” }, {autoIncrement:true});  
  /* Create an index to search employees by name. Since there can be   
 duplicate employee names, unique index can’t be used*/  
  objectStore.createIndex(“empnameidx”, “empname”, { unique: false });  
  /*Create an index to search employees by email. To ensure email id is unique,   
 unique index can be used*/  
  objectStore.createIndex(“emailidx”, “email”, { unique: true });  
  // Store data in objectStore.  
  for (var i in empData) {  
   objectStore.add(empData[i]);  
  console.log(‘employee data added to object store’+empData[i]);  
  }  
 };  
 request.onsuccess = function(event) {  
 console.log(“inside onsuccess”);  
  var database = event.target.result;  
 var versionRequest = database.setVersion(2);  
 versionRequest.onsuccess = function(event){  
 /*Create an objectstore for storing employee data*/  
 var objectStore = database.createObjectStore(“emps”, { keyPath: “empid” }, {autoIncrement:true});  
  /* Create an index to search employees by name. Since there can be   
 duplicate employee names, unique index can’t be used*/  
  objectStore.createIndex(“empnameidx”, “empname”, { unique: false });  
  /*Create an index to search employees by email. To ensure email id is unique,   
 unique index can be used*/  
  objectStore.createIndex(“emailidx”, “email”, { unique: true });  
  // Store data in objectStore.  
  for (var i in empData) {  
   objectStore.add(empData[i]);  
 console.log(‘employee data added to object store’+empData[i]);  
  }  
 }  
 versionRequest.onerror = function(event){  
 console.log(‘error in versionrequest>>’+event);  
 }  
 };  
   }  
 </script>  
 </head>  
 <body>  
   <button onclick=’test()’>check database</button>  
 </body>  
 </html>  

As mentioned in previous example, on objectStore or index can be created only during a version change.
Will follow details on transaction, cursors etc.

No comments:

Post a Comment