A Storage Example in XUL using SQL Select and an XUL Grid
From MDC
As of Sunday, May 27, I have decided to "delete" this page and just link to the source in the mozstorage article. This page is redundant .
A work in progress as of April 26, 2007
To be done
Check out templates, and re review style guides
Here is a link Image:TTRW2.zip to the complete source.
The following is a long snippet of the example JavaScript source. It is self explanatory, if you know JavaScript, the DOM and have used the Mozilla interfaces. This is a working, annotated source example, my favorite way to get started on a new API.
/*
see http://www.sqlite.org/ for more information on sqlite
see http://developer.mozilla.org for more information on the storage layer
see the TTRW2.xul file for additional comments
Logging
NSPR_LOG_MODULES mozStorage:5
Change log
Apr 21 2007
use storageService lastErrorString for more information
Apr 26 2007
changed to gjSQLonerror(e, strDB.value ," Error on Open "); for openDatabase
*/
// a class to hold a few variables
function gjSQLHelper()
{
this.colNameArray = new Array();
this.resultsArray = new Array();
this.statsArray = new Array(2); // 0 = Rows, 1 = columnCount
}
// this function is called from TTRW2, the xul page that shows input boxes for an SQL query and
// an SQL databse
function runStorage()
{
theResults = new gjSQLHelper;
//get the query string from an xul page
var strQuery=document.getElementById('testgj53runSQL');
if(strQuery.value.length == 0)
{
document.getElementById("testgj53runSQL").value = 'Please Enter Something and Hit Search';
return;
}
// get the file name and path to the database
var strDB=document.getElementById('testgj53runDB');
if(strDB.value.length == 0)
{
document.getElementById("testgj53runDB").value = 'Please Enter Something and Hit Search';
return;
}
// nsILocalFile extends nsIFile, the input into Storage Service Open Data Base call
var ifile = Components.classes["@mozilla.org/file/local;1"].
createInstance(Components.interfaces.nsILocalFile);
//if the database does not exist, storageService.openDatabase creates it
ifile.initWithPath(strDB.value);
//Warning, if the file does not exist, openDatabase below will create if for you
if(!(ifile.exists()))
{
// addIt shows messages on the XUL page. function addIt(where, what)
// It adds the what to whatever is already there on id where
addIt('tb2', "File " strDB.value " does not exist, You are creating a new Database");
}
else
{
addIt('tb2', "File " strDB.value " exists");
}
// get an interface to MOZSTORAGE
var storageService = Components.classes["@mozilla.org/storage/service;1"]
.getService(Components.interfaces.mozIStorageService);
try
{
var mDBConn = storageService.openDatabase(ifile);
// if the db does not exist it does not give us any indication
// mDBConn.lastErrorString returns "not an error"
}
catch (e)
{
gjSQLonerror(e, strDB.value ," Error on Open ");
}
// After and Open or Create of a DB above doSQL gets the column names and
// the data from the SQLite DB and stores it the helper object (theResults = new gjSQLHelper;)
if(doSQL(mDBConn,theResults, strQuery.value))
{
// display whatever results we have
doDisplay (theResults);
}
}
function doSQL(theConn, theHelper, thesql)
{
// if there is a problem with in the Select, Replace, Insert, Count, Delete etc SQL statement
// if the table does not exist
// createStatement throws JS error.name == NS_ERROR_FAILURE, there is no return,the statement is undefined
// theConn.lastErrorString contains the SQL Syntax error hint
// use the Step (Fetch a row at a time) method of using SQLite, so we keep track rows
try
{
var myRows = 0;
var statement = theConn.createStatement(thesql);
}
catch (e)
{
// statement will be undefined because it throws error);
gjSQLonerror(e, "Likely SQL syntax error: " thesql, theConn.lastErrorString );
//statement.reset; //if it gets here and a statement does not exist, it says "Statement has no properties"
return false;
}
// executeStep once to look at stats and get colnames etc (the first fetch)
// store column names in colNameArray
try
{
rc = statement.executeStep();
if(rc)
{
myRows ;
// if you use statement.columnCount in the for loops, it looks like it
// goes over to C land to get this already known value
var cols = statement.columnCount;
for (var i = 0; i < cols; i )
{
theHelper.colNameArray.push(statement.getColumnName(i));
}
}
else
{
// might as well bail
addIt('tb2', "No Results from query " thesql);
statement.reset;
return;
}
// store the results row wise, column wise in resultsArray vector AKA array of one dimension
// row1 col1, row1, col2, row1 colx.. , row2 col1, row2 col2
for (var i = 0; i < cols; i )
{
theHelper.resultsArray.push(statement.getString(i));
}
// executeStep to get the rest of the results a row at a time
while (statement.executeStep())
{
myRows ;
for (var i = 0; i < cols; i )
{
theHelper.resultsArray.push(statement.getString(i));
}
}
addIt('tb2', " statement.numEntries " statement.numEntries ); //?
addIt('tb2', " statement.columnCount " cols );
addIt('tb2', " myRows " myRows ); // step walks through stuff so I do not think we know the count until the end
addIt('tb2', " lastErrorString " theConn.lastErrorString);
//store the counts and stats in stats arrray
theHelper.statsArray[1] = cols;
theHelper.statsArray[0] = myRows;
}
catch (e)
{
gjSQLonerror(e, "Database Error ", theConn.lastErrorString );
}
// what about cleaning up these arrays?
// the database is closed on html or xul page close
// I think this is safe to reset here, if we do not get here, we are probably too hosed to do anything anyways
statement.reset;
return true;
}
Categories: XUL | Toolkit API | Storage