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)
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).
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.
Glynn Bird said
at 7:51 am on Mar 4, 2009
Hi Douglas,
I saw this on the PhoneGap Google Group. It may be of interest to you:
http://groups.google.com/group/phonegap/browse_thread/thread/ca6c85f7d6c3976c/8c7a6cc5b0a236a1?lnk=gst&q=database#8c7a6cc5b0a236a1
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!
Douglas said
at 8:33 am on Mar 4, 2009
My bad, this IS about from the PhoneGap group.
Thinking-cap firmly attached.
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.
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.
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?
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?
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.