phonegap

 

Adding SQL Database support to your iPhone App

Page history last edited by Doc Falken 6 mos ago

Introduction

 

If you are using PhoneGap to create your iPhone application, you may be interested to know that you can create SQL Databases for use by your application and access them from your application's Javascript. This is all possible because of HTML5 support built into Safari, the iPhone's native browser. This guide aims to show how to add database support to your iPhone application through simple examples

 

Step 1 - Initialising the database

 

When your iPhone application runs for the first time, there will be no database and no tables. The first task is to create the database and the tables within it:

 

 

    var mydb=false;

 

    // initialise the database

    initDB = function() {

      try

        if (!window.openDatabase) { 

          alert('not supported'); 

        } else

          var shortName = 'phonegap'

          var version = '1.0'

          var displayName = 'PhoneGap Test Database'

          var maxSize = 65536; // in bytes 

          mydb = openDatabase(shortName, version, displayName, maxSize); 

         }

      } catch(e) { 

        // Error handling code goes here. 

        if (e == INVALID_STATE_ERR) { 

          // Version number mismatch. 

          alert("Invalid database version."); 

        } else

          alert("Unknown error "+e+"."); 

        } 

        return

      } 

    }

 

The initDB function first checks whether databases are supported or not. If they are, then a database called "phonegap" is created/opened. The version number of the database allows future versions of your application to upgrade existing tables (by adding tables, columns etc) without loss of data. The global variable "mydb" is used as the database handle. 

 

Step 2 - Filling the database

 

The data in your database is entirely up to you and learning SQL is beyond the scope of this tutorial. For the purposes of this example, I shall assume we are storing the names of our favourite celebrities:

 

    // db error handler - prevents the rest of the transaction going ahead on failure

    errorHandler = function (transaction, error) { 

      // returns true to rollback the transaction

      return true;  

    } 

 

    // null db data handler

    nullDataHandler = function (transaction, results) { } 

 

 

    // create tables for the database

    createTables = function() {

 

      try {

 

        mydb.transaction(

          function(transaction) {

            transaction.executeSql('CREATE TABLE celebs(id INTEGER NOT NULL PRIMARY KEY, name TEXT NOT NULL DEFAULT "");', [], nullDataHandler, errorHandler); 

            transaction.executeSql('insert into celebs (id,name) VALUES (1,"Kylie Minogue");', [], nullDataHandler, errorHandler); 

            transaction.executeSql('insert into celebs (id,name) VALUES (2,"Keira Knightley");', [], nullDataHandler, errorHandler); 

          });

 

      } catch(e) {

        /// alert(e.message);

        return;

      }

    }

 

The "createTables" function creates a single table called "celebs" which has two rows:

  • id - the primary key of the table
  • name - the name of the celebrity

 

For good measure, it also primes the table with two rows. Each SQL statement is executed as part of a "transaction"; if a single SQL statement in the transaction fails, then none of the transaction is committed to the database. The first time your application is run, it will create the table and create the two rows in it. On subsequent runs, the "CREATE" statement fails because the table already exists, so the following "INSERT" statements are never attempted.

 

Step 3 - Retrieving data from the database

 

To load our data from the database we can use the "loadCelebs" function, which performs a "SELECT" statement. 

 

    // callback function to retrieve the data from the prefs table

    celebsDataHandler=function(transaction, results) {

      // Handle the results 

      var html = "<ul>"

      for (var i=0; i<results.rows.length; i++) { 

        var row = results.rows.item(i); 

        html += '<li>'+row['name']+'</li>\n';

      } 

      html +='</ul>';

      alert(html);

    }

 

 

    // load the currently selected icons

    loadCelebs = function() {

      try {

 

        mydb.transaction(

            function(transaction) {

               transaction.executeSql('SELECT * FROM celebs ORDER BY name',[], celebsDataHandler, errorHandler);

            });

 

      } catch(e) {

        alert(e.message);

      }

 

} 

 

The resultant data is sent to "celebsDataHandler", where the data can be manipulated as desired. 

 

Links

 

Comments (10)

profile picture

Martijn Pannevis said

at 5:26 am on Mar 2, 2009

Does anybody know if the native code has access to the same database? I would like to use the database to cache some images in (so the app can show them offline), but I'm afraid that's not possible from just JS (maybe with canvas, I haven't looked into that yet).

profile picture

Douglas said

at 6:58 am on Mar 4, 2009

PhoneGap is blowing my mind! I am seriously digging this project. Here's a sqlite problem I'm having, hope someone can help.

I want to create a semi-large (50k row) database, that will be used for read-only purposes in my app.

Now I have managed to do this using sqlite3 on the command line. I have a myapp.db file that does indeed work. I can log into it, run queries, etc. No problems.

But the example above, and others I've seen, all seem to be about creating a db and populating it from within your app. All I want to do is get the app to load MY database, then I think I can handle running the select queries against it.

I've tried playing around a lot with the example above, substituting the file name. I think I've managed to add my myapp.db file as a resource, but I can't seem to get the database recognized.

It doesn't help that I'm a major Xcode noob.

Your help much appreciated.

profile picture

Glynn Bird said

at 7:51 am on Mar 4, 2009

profile picture

Douglas said

at 8:32 am on Mar 4, 2009

Wow, Thanks Glynn.

I don't know if that article will solve my problems, as I am of small-brain and trying to figure it out, but I really appreciate the post. It seems along the same lines as my problem, but I gather in Objective-C (a language I know nothing about), rather than this remarkable PhoneGap framework.

I'll keep reading it until something absorbs by osmosis.

Thanks!

profile picture

Douglas said

at 8:33 am on Mar 4, 2009

My bad, this IS about from the PhoneGap group.

Thinking-cap firmly attached.

profile picture

Douglas said

at 8:50 am on Mar 4, 2009

This seems like it could potential solve my problems. It's not trivial for me, by any means, but it's comparable.

But it seems like what would really rock would be a way to just open the damn database file then work with that. I've already added the functioning sqlite database to my Resources. I've tried it with different extensions (.db, .sqlite).

Maybe, just maybe, there's a simple way in Xcode (and with PhoneGap) to access this file. By path?

From my experiments, "shortName" won't do jack for this.

Is it possible there's a javascript method to just open a sqlite database file and create a db from that?

I've been googling all kinds of WebKit, HTML5, PhoneGap, SQLITE stuff to try to find it, but so far no luck.

Does anyone know of an API resource that would relate to this? I don't think the openDatabase() function above will cut it.

Again, thanks. I think it's possible if I follow this guy's steps I might be able to pull it off, but I'm using PhoneGap specifically because of my lack of Cocoa/Objective-C skills.

This seems like just such ... a ... small... step. If only I knew what it was.

profile picture

Douglas said

at 7:08 am on Mar 6, 2009

SUCCESS!

Thanks Glynn for the link:
http://groups.google.com/group/phonegap/browse_thread/thread/ca6c85f7d6c3976c/8c7a6cc5b0a236a1?lnk=gst&q=database#8c7a6cc5b0a236a1

I posted my own note there. His solution did work, and as I note, also worked with a large database file created elsewhere. All a bit hackish, but can't really complain.

profile picture

vinay moharil said

at 8:40 am on Mar 17, 2009

As part of our iPhone app - we store a good size xml to the local file system so that we have to write a single xml parser - from the server or from local disk. Does PhoneGap have support for local files? If not - what is the best way to store mid-size (1-2k) xml in SQLlite using PhoneGap?

profile picture

SkunkfireJoe said

at 1:31 pm on May 8, 2009

I get this error when i call the function: <script type="text/javascript">loadCelebs();</script>

Value undefined (result of expression mydb.transaction) is not object.

If I put this function: <script type="text/javascript">initDB(); createTables(); loadCelebs();</script> in the file it sometimes echoes the rows but it also ignores the database sometimes. What is the right way to use the script?

profile picture

Howard Fore said

at 4:43 pm on Aug 9, 2009

So how do these functions typically get used? I'm used to have the functions just declared in a js file or script tag. These examples look they're declared are properties to a script object. True?

You don't have permission to comment on this page.