Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

sqlite backed rdf datasource

68 views
Skip to first unread message

Dave Townsend

unread,
Aug 27, 2007, 10:16:57 PM8/27/07
to
I've been looking to play with sqlite for a little while and today came
up with something insane enough for me to try. I've implemented an
nsIRDFDataSource that rather than holding all it's data in memory and
dumping to an RDF/XML file instead holds it in an sqlite database.

There's a few benefits to this:

Initialisation time is reduced. An sqlite database initialises almost
immediately compared to a traditional source which has to parse the XML
first.

Data is flushed immediately. Any assertions go straight into the
database, though it is possible to wrap a bunch of changes in a
transaction for performance wins.

The database is fault tolerant. Unlike our rdf serializer which has to
overwrite the entire file, sqlite writes incrementally and if there is a
complete failure can recover the next time the database is opened.

I don't yet know what the performance is like for general use of the
datasource, my implementation is pretty rough and ready so could
probably get optimised some which I don't really want to do unless
anyone thinks it might actually be useful to have in tree?

I did hook this up to the localstore which I could benefit quite a lot
given the issues we have had with corruption of it, and it worked well,
quick tests showed a bit of a Ts win as well. I know the long-term goal
would be to move away from rdf, but in the short term this could give
localstore some extra resilience without requiring any real core changes.

Any thoughts?

Dave

Benjamin Smedberg

unread,
Aug 27, 2007, 10:27:49 PM8/27/07
to
Dave Townsend wrote:
> I've been looking to play with sqlite for a little while and today came
> up with something insane enough for me to try. I've implemented an
> nsIRDFDataSource that rather than holding all it's data in memory and
> dumping to an RDF/XML file instead holds it in an sqlite database.

Yeah, I did a pass at this about a year ago: it's a good idea.

--BDS

Justin Wood (Callek)

unread,
Aug 28, 2007, 1:07:07 AM8/28/07
to

for what little my opinion counts, I'm *all for this*.

~Justin Wood (Callek)

Matthew Gertner

unread,
Aug 28, 2007, 8:09:30 AM8/28/07
to

I'd encourage anyone interested in this to take a look at our
implementation of an object->relational mapping based on mozStorage. We
used to use the Mozilla RDF interfaces but for a number of reasons
migrated to a roll-your-own solution. Nonetheless, the principle is the
same, and we've done a lot of work to produce an efficient database
schema that works with real-world data volumes. (To me this means
domain-specific tables and not a single table of assertions that holds
everything).

There isn't much documentation, unfortunately. There's some high-level
information here:

http://developer.allpeers.com/src:hack:starting

Relevant source code:

http://lxr.allpeers.com/source/resource/
http://lxr.allpeers.com/source/database/

Writing much more complete and lower level documentation is slowly
creeping towards the top of my to do list.

Cheers,
Matt

Axel Hecht

unread,
Aug 29, 2007, 4:58:09 AM8/29/07
to

I have seen a talk on storing RDF in relational databases, and I was not
impressed.

The fault-tolerance is fixed by now, the incremental datastore can be
done with any format that isn't RDF/XML (nturtle or any other triple
based format).

I have several questions on the performance of such a datastore as well,
in particular how efficiently it handles typed literals. Runtime memory
consumption is a question, too.

Axel

Neil

unread,
Aug 29, 2007, 6:22:10 AM8/29/07
to
Axel Hecht wrote:

> I have several questions on the performance of such a datastore as
> well, in particular how efficiently it handles typed literals. Runtime
> memory consumption is a question, too.

Ah, but sqlite is tunable, so for history you can ask it to cache the
entire database in memory (for fast :visited handling) while for
localstore you might only need a small cache.

--
Warning: May contain traces of nuts.

Dave Townsend

unread,
Aug 29, 2007, 7:31:00 PM8/29/07
to

Well it looks like you are right. I now have the datasource operating
what I'd consider to be API complete and as tuned as I can without
really spending a great deal of time over it and it turns out to be
around 1000 times slower than an in-memory datasource for common operations.

So I guess I'll give up playing with it, I still have the code if anyone
wants a look. Shame really, it was a fun experiment while it lasted.

Dave

Myk Melez

unread,
Aug 29, 2007, 7:39:31 PM8/29/07
to Dave Townsend
Dave Townsend wrote:
> Well it looks like you are right. I now have the datasource operating
> what I'd consider to be API complete and as tuned as I can without
> really spending a great deal of time over it and it turns out to be
> around 1000 times slower than an in-memory datasource for common
> operations.
>
> So I guess I'll give up playing with it, I still have the code if anyone
> wants a look. Shame really, it was a fun experiment while it lasted.

Dave,

Could you rerun those performance tests on an in-memory database?
That'd be a better apples-to-apples comparison.

-myk

Dave Townsend

unread,
Aug 29, 2007, 8:07:14 PM8/29/07
to

Ah interesting. I hadn't realised we could do this. It's obviously much
faster, but still coming out as around 8 times slower than the plain rdf.

Dave

Michael Vincent van Rantwijk, MultiZilla

unread,
Aug 29, 2007, 8:12:14 PM8/29/07
to

And how about memory usage? Which one is the heavy one?

--
Michael Vincent van Rantwijk
- MultiZilla Project Team Lead
- XUL Boot Camp Staff member (ActiveState Training Partner)
- iPhone Application Developer

Benjamin Smedberg

unread,
Aug 29, 2007, 9:17:49 PM8/29/07
to
Dave Townsend wrote:

> Well it looks like you are right. I now have the datasource operating
> what I'd consider to be API complete and as tuned as I can without
> really spending a great deal of time over it and it turns out to be
> around 1000 times slower than an in-memory datasource for common
> operations.

Would you mind posting your code somewhere?

--BDS

Dave Townsend

unread,
Aug 30, 2007, 6:15:41 AM8/30/07
to

Sure, it's still pretty rough and ready but here is the patch for just
the datasource:

http://people.mozilla.org/~dtownsend/experiments/sqliteds/rdfsql.patch

Dave

Axel Hecht

unread,
Aug 30, 2007, 7:06:34 AM8/30/07
to

There are likely a bunch of optimizations possible in that patch, in
particular on string usage and the number of db queries per, say,
GetTarget (you JOIN already, why get the source and property id
separately? not that I know jack about sql).

Anyway, you need to move back and forth between lexical representations
and already unique rdf objects every time, that has to be dog slow.

As RDF is dynamically typed, and SQL is statically typed, you need to
bridge that gap somehow. In C++, we use pointers and QIs, in SQL you
would probably use the lexical representation. I can't come up with
something better, at least. So that perf impact is going to stay, even
if we dropped the C++ pointer oriented API on top.

I don't see any other reason that a memory-exceeding size of graphs for
using a relational database, merely because writing code that maps the
right parts of your disk data into memory is hard, and at that point,
the perf impact of the table<->graph foo is negligible compared to the
disk IO part. Not sure if I'd use sqlite at that point, though.

Axel

Myk Melez

unread,
Sep 4, 2007, 9:03:28 PM9/4/07
to
Axel Hecht wrote:

> Dave Townsend wrote:
>> http://people.mozilla.org/~dtownsend/experiments/sqliteds/rdfsql.patch
>
> There are likely a bunch of optimizations possible in that patch

Right. And I suspect we could get this performing well enough, perhaps
better than the current implementation.

But the larger question is why we're using RDF for things like
localstore, which don't require the complexity of a graph structure. I
think we'd be better off designing databases specific to the task at
hand, and those are likely to be more performant.

-myk

Neil Deakin

unread,
Sep 4, 2007, 11:10:28 PM9/4/07
to
Myk Melez wrote:
> But the larger question is why we're using RDF for things like
> localstore,

Well, localstore is supposed to be used for storing local rdf data. It
currently is used mostly for storing UI annotations, of which only a few
types, persistent attributes and tree row open states, are actually
stored there. For this, the triples model is a natural fit.

> think we'd be better off designing databases specific to the task at
> hand, and those are likely to be more performant.
>

Do you mean storage? A relational database table isn't a suitable
structure for storing or querying data that more naturally fits into
triples. I did this for 'DOM Storage' and think it wasn't a good fit, as
in this case, usually only one piece of data (one triple) is requested
at a time, either by key or value.

Neil

Myk Melez

unread,
Sep 5, 2007, 3:53:46 PM9/5/07
to
Neil Deakin wrote:
> Do you mean storage? A relational database table isn't a suitable
> structure for storing or querying data that more naturally fits into
> triples. I did this for 'DOM Storage' and think it wasn't a good fit, as
> in this case, usually only one piece of data (one triple) is requested
> at a time, either by key or value.

It's not clear to me why a SQLite table is a poor fit for such queries.
Can you explain further?

-myk

Neil Deakin

unread,
Sep 5, 2007, 4:53:30 PM9/5/07
to
Myk Melez wrote:

> Neil Deakin wrote:
>
> It's not clear to me why a SQLite table is a poor fit for such queries.
>

Why would you want to use an sql database to hold data which is just a
hashtable?

/ Neil

Robert Sayre

unread,
Sep 5, 2007, 8:44:20 PM9/5/07
to Neil Deakin

That doesn't answer the question as I understood it. Why would you want
to use RDF triples where a hashtable will do?

- Rob

Neil

unread,
Sep 6, 2007, 5:38:13 AM9/6/07
to
Robert Sayre wrote:

Then let's use JSON for localstore.

Neil Deakin

unread,
Sep 7, 2007, 8:24:11 AM9/7/07
to
Robert Sayre wrote:
> Neil Deakin wrote:
>> Myk Melez wrote:
>>> Neil Deakin wrote:
>>>
>>> It's not clear to me why a SQLite table is a poor fit for such queries.
>>
>> Why would you want to use an sql database to hold data which is just a
>> hashtable?
>
> That doesn't answer the question as I understood it.

I can give a more detailed answer, although I was asking because I
wanted to know whether an sql table was desired because it offered some
specific advantage(s), whether it was out of convenience, or whether it
was due to a "let's use sql for everything" model.

Why would you want
> to use RDF triples where a hashtable will do?

I never mentioned RDF.

Myk Melez

unread,
Sep 10, 2007, 5:16:03 AM9/10/07
to Neil Deakin
Neil Deakin wrote:
> I can give a more detailed answer, although I was asking because I
> wanted to know whether an sql table was desired because it offered some
> specific advantage(s), whether it was out of convenience, or whether it
> was due to a "let's use sql for everything" model.

I think there are two issues, how we persist the data and how we cache
it in memory for performance when on-demand retrieval from the
persistent store isn't performant enough.

For the former, I'll wager that SQLite database files are the right
solution for most cases because of their schema flexibility,
reliability, and robust, standard API for data retrieval and
modification (although some work could be done on our wrapper API).

For the latter, in-memory SQLite might be the right solution, depending
on the requirements, but is not, as you note, necessarily so. And for
the localstore case, where a simpler hashtable and key-based querying
will do, it's not necessary.

-myk

Matthew Gertner

unread,
Sep 11, 2007, 7:36:13 AM9/11/07
to
Myk Melez wrote:
> ....

> For the former, I'll wager that SQLite database files are the right
> solution for most cases because of their schema flexibility,
> reliability, and robust, standard API for data retrieval and
> modification (although some work could be done on our wrapper API).

What sort of changes would you like to see in the wrapper API?

Matt

Myk Melez

unread,
Sep 12, 2007, 3:05:28 AM9/12/07
to Matthew Gertner
Matthew Gertner wrote:
> What sort of changes would you like to see in the wrapper API?

(Looking back over my code and trying to remember what I've talked about
with folks...)

None of these are critical, but here are a few short term improvements
that would be useful:

* placeholder indices that match parameter indices;
* a less critical reset (see bug 328884 [1], but I'm quite sure
what this would entail);
* perhaps an mozIStorageStatement::bindParameter method that takes
an nsIVariant.

In the long term, I'd like to have an ORM or some other kind of JS
object persistence mechanism (perhaps bug 394732 [2] is the start of
this), and I'd like to see us fix ACID compliance, which we broke to
improve Places performance.

-myk

[1] https://bugzilla.mozilla.org/show_bug.cgi?id=328884
[2] https://bugzilla.mozilla.org/show_bug.cgi?id=394732

Myk Melez

unread,
Sep 12, 2007, 5:43:00 AM9/12/07
to Matthew Gertner
Myk Melez wrote:
> * a less critical reset (see bug 328884 [1], but I'm quite sure
> what this would entail);

Err, I meant to say that I'm *not* quite sure what this would entail.
And by "less critical" I mean "less error-prone", i.e. less likely to
get you into trouble (like the trouble that dmose got into, described in
bug 328884).

-myk

Matthew Gertner

unread,
Sep 12, 2007, 6:07:20 AM9/12/07
to
Myk Melez wrote:
> * placeholder indices that match parameter indices;

Why, what's wrong with the current approach (piggybacking on SQLite's
binding support)?

> * a less critical reset (see bug 328884 [1], but I'm quite sure
> what this would entail);

This just sounds like a bug to me, not a design issue with the wrapper API.

> * perhaps an mozIStorageStatement::bindParameter method that takes
> an nsIVariant.

This is a nice idea but I've been working for months on getting all the
nsIVariants out of our code. The main reason is the totally unnecessary
number of data types it supports. I've abandoned this in favor of
string, integer, decimal, boolean, date and binary as our only data
types. I'd be thrilled to see a universal variant (i.e. JS, app data
model and DB) that is simpler and more rational. Why did we need 40,000
overlapping data types in the first place?

>
> In the long term, I'd like to have an ORM or some other kind of JS
> object persistence mechanism (perhaps bug 394732 [2] is the start of
> this), and I'd like to see us fix ACID compliance, which we broke to
> improve Places performance.

I'm going to start publishing information about our ORM based on
mozStorage. Regarding ACID compliance, are you referring to the
asynchronous storage thread? IMO this should have been architected on a
much higher level. In our architecture we have a database background
thread that uses mozStorage which uses SQLite. So we don't have the
problem of writes holding up the UI thread, but we don't sacrifice basic
database engine characteristics either.

Matt

Jeff Rose

unread,
Sep 12, 2007, 9:45:27 AM9/12/07
to Matthew Gertner, dev-pl...@lists.mozilla.org

Hello all,
I'm currently developing on top of the storage API, and I've got a
couple questions and ideas that figured I'd throw out there...

Quick question first. I'm getting an error when trying to execute
ALTER statements through the storage API. The exact statements work
through the sqlite shell, but not through either the simple or full
createStatement interfaces.

Executing sql: ALTER TABLE foo RENAME TO bar

Which produces:

ERROR: Error executing SQL: [Exception... "Component returned failure
code: 0x80004005 (NS_ERROR_FAILURE)
[mozIStorageConnection.createStatement]" nsresult: "0x80004005
(NS_ERROR_FAILURE)" location: "JS frame ::
chrome://lugano/content/db.js :: anonymous :: line 92" data: no]

Any ideas? Are alter statements not supported for some reason?

---------------

I think the current API is pretty solid and seems like a great
foundation, but for javascript it is not very nimble. For example, it
should be easier to just run sql statements (full strings with
parameters embedded), and get back a json or javascript object as the
return rather than iterating over an awkward c++ object.

So, I'm currently working on a storage system that might be of interest
to people, and could maybe work as a solution for replacing some uses of
RDF while not requiring SQL for people that don't want it. At the
bottom is a simple object-relational mapping layer built on top of the
Storage API. (The API is inspired by ActiveRecord, if you know that...)

// Open a DB
var db = new DB.Store('test_db');

// You can of course setup your DB schema and then just use the
// DB file, but you can also do it programattically like this,
// which also allows for easy migration to new schemas.
db.create_table('items', function(t) {
t.column('name', 'string');
t.column('value', 'string');
});

// The system inspects the schema and automatically builds a set
// of objects that can be used to find and manipulate entries.
var a = new DB.Item(); // Item func could be put elsewhere too
a.name = "a name";
a.value = "a value";
var b = new DB.Item({ name: 'test', value: 'blah blah'});

// These can be saved into the db
a.save();
b.save();

// And queried
var i = DB.Item.find(DB.first, {conditions: "name = 'test'"});
var vals = DB.Item.find(DB.all);

There is more, but that should give you the idea. This works now, and
if I figure out what is wrong with ALTER it will be able to rename, add
and remove columns etc., on the fly. (Unit Tested as well...)

Despite this ease of use, I think the vast majority of storage needs are
much better served by a dirt simple JSON object store API. So this is
what I plan to do next. (Probably this week.) It will let you create a
little object store, and then store json objects and get an object ID.
The API on top will be a simple map/reduce. So you would hand the layer
a function that would run over the items in the store, and then get back
a set of results:

var id = Dirt.store({ data: "foo"...})
Dirt.query( function(obj) {(obj.data == "foo") ? return obj : return;})

Stupid, super flexible, unstructured storage. JSON is far and away the
easiest thing to work with, and especially with the upgrade to Tamarind
it seems like the right direction, no? This could easily be thrown on
top of the DOM storage api as well, but I'm not sure how that works for
code running out of chrome.

On top of this I'm building a graph oriented storage system that I hope
to use as the basis for my research in building a firefox hosted P2P
application container. I'm all about simple and lightweight though, so
my take is different from a lot of these massive API's like in Flock or
AllPeers. Oh, and it's all over HTTP so it's compatible with the web.
(I have a full asynchronous web server implemented in JS on top of the
socket APIs...)

Ciao,
Jeff

Neil

unread,
Sep 12, 2007, 11:01:12 AM9/12/07
to
Jeff Rose wrote:

> I think the current API is pretty solid and seems like a great
> foundation, but for javascript it is not very nimble. For example, it
> should be easier to just run sql statements (full strings with
> parameters embedded),

Ah, but getting developers to embed parameters safely is much harder
than persuading them to use positional parameters.

> and get back a json or javascript object as the return rather than
> iterating over an awkward c++ object.

C++ objects don't have to be awkward, for instance you can use
window.frames[0] or window.frames.foo instead of
window.frames.getItemByName("foo") (OK I cheated window.frames doesn't
have a getItemByName method), it's just that nobody's implemented that
yet ;-)

Nickolay Ponomarev

unread,
Sep 12, 2007, 11:38:19 AM9/12/07
to Jeff Rose, dev-pl...@lists.mozilla.org
On 9/12/07, Jeff Rose <ros...@gmail.com> wrote:

> Matthew Gertner wrote:
> Quick question first. I'm getting an error when trying to execute
> ALTER statements through the storage API. The exact statements work
> through the sqlite shell, but not through either the simple or full
> createStatement interfaces.
>
> Executing sql: ALTER TABLE foo RENAME TO bar
>
> Which produces:
>
> ERROR: Error executing SQL: [Exception... "Component returned failure
> code: 0x80004005 (NS_ERROR_FAILURE)
> [mozIStorageConnection.createStatement]" nsresult: "0x80004005
> (NS_ERROR_FAILURE)" location: "JS frame ::
> chrome://lugano/content/db.js :: anonymous :: line 92" data: no]
>
> Any ideas? Are alter statements not supported for some reason?
>
Did you try looking at the last error message from sqlite (available
as a connection attribute, iirc)? If it doesn't clearly point to the
cause and nobody answers you here, please file this in bugzilla please
(preferably with a testcase one can run to reproduce).

> So, I'm currently working on a storage system that might be of interest
> to people, and could maybe work as a solution for replacing some uses of
> RDF while not requiring SQL for people that don't want it. At the
> bottom is a simple object-relational mapping layer built on top of the
> Storage API. (The API is inspired by ActiveRecord, if you know that...)
>

This sounds quite similar to what bug 394732 requested. To avoid
duplicating work, you might want to comment in that bug about your
work.

> (I have a full asynchronous web server implemented in JS on top of the
> socket APIs...)
>

You know we have an in-tree HTTP server (httpd.js), right?

Nickolay

Myk Melez

unread,
Sep 12, 2007, 3:06:03 PM9/12/07
to
Neil wrote:
> Jeff Rose wrote:
>
>> I think the current API is pretty solid and seems like a great
>> foundation, but for javascript it is not very nimble. For example, it
>> should be easier to just run sql statements (full strings with
>> parameters embedded),
>
> Ah, but getting developers to embed parameters safely is much harder
> than persuading them to use positional parameters.

I don't think Jeff was suggesting embedding values directly into the
statement, I think he was suggesting something like the following:

var resultSet =
connection.execute("SELECT foo FROM bar WHERE baz = ?1 AND buz = ?2",
baz, buz);

Implementing this in an XPCOM component probably requires passing the
parameter values in an array. And parameter indices are unnecessary for
matching parameters to values (one could just match the first parameter
value with the first question mark), although SQLite may require them.

-myk

Myk Melez

unread,
Sep 12, 2007, 3:34:51 PM9/12/07
to Matthew Gertner, Seth Spitzer
Matthew Gertner wrote:
>> * perhaps an mozIStorageStatement::bindParameter method that takes
>> an nsIVariant.
>
> This is a nice idea but I've been working for months on getting all the
> nsIVariants out of our code. The main reason is the totally unnecessary
> number of data types it supports. I've abandoned this in favor of
> string, integer, decimal, boolean, date and binary as our only data
> types. I'd be thrilled to see a universal variant (i.e. JS, app data
> model and DB) that is simpler and more rational. Why did we need 40,000
> overlapping data types in the first place?

I don't know why nsIVariant is so complex, but I've made good use of it
to provide a simple API for the content pref service, which takes and
returns nsIVariant pref values that it stores in a BLOB column (so that
SQLite doesn't attempt to do type conversion on the values).

I haven't tested it with every possible data type, but I've tested the
round-trip data integrity of integer, float, boolean, string, and null
nsIVariants going from frontend JS code to the service to the database
and back.

It works well for those data types, and it should also work when the
values are stored in another type of column as long as you're aware of
the schema and understand SQLite's type conversion rules.

And it's much simpler, for JS callers anyway, than type-specific APIs
like the bind*Parameter methods provided by mozIStorageStatement.


> Regarding ACID compliance, are you referring to the
> asynchronous storage thread?

Yup, that's the one.


> IMO this should have been architected on a
> much higher level. In our architecture we have a database background
> thread that uses mozStorage which uses SQLite. So we don't have the
> problem of writes holding up the UI thread, but we don't sacrifice basic
> database engine characteristics either.

Hmm, this sounds interesting. Perhaps we could use this approach to
boost Places write performance without giving up ACID compliance for all
databases. cc:ing Seth Spitzer for his thoughts.

-myk

Boris Zbarsky

unread,
Sep 12, 2007, 3:58:51 PM9/12/07
to
Myk Melez wrote:
> I don't know why nsIVariant is so complex

Presumably at least in part because it mirrors the Variant type from MS-COM
(like nsISupports mirrors ISupports from MS-COM).

That said, it's also the way it is to make it possible to pass strongly typed
information through a variant. Clearly not much use to JS, where there is no
such thing.

-Boris


Axel Hecht

unread,
Sep 12, 2007, 7:48:32 PM9/12/07
to

I don't think that XPCOM is the solution here. Just like DOM is only
half-way painful due to JS-specific language bindings (i.e., scriptable
helpers), and other query API would suffer if you try to write it down
in IDL.

In sqlalchemy (which is the only ORM I remotely know), you'd do

var result = bar.query().filter_by({baz:baz, buz:buz});
for (r in result) {
r.foo;
};

I'm not sure if sqlachemy would offer to just get a list of values for
foo directly, but that seems like something that'd be useful.

The whole idea of specifying queries as plain text feels really
non-JavaScript to me, and I'm a lot less alienated by dealing with sql
storage now that I learned to avoid that in my python life.

Axel

Matthew Gertner

unread,
Sep 13, 2007, 8:48:56 AM9/13/07
to sspi...@mozilla.com
Myk Melez wrote:
> I don't know why nsIVariant is so complex, but I've made good use of it
> to provide a simple API for the content pref service, which takes and
> returns nsIVariant pref values that it stores in a BLOB column (so that
> SQLite doesn't attempt to do type conversion on the values).
>
> I haven't tested it with every possible data type, but I've tested the
> round-trip data integrity of integer, float, boolean, string, and null
> nsIVariants going from frontend JS code to the service to the database
> and back.
>
> It works well for those data types, and it should also work when the
> values are stored in another type of column as long as you're aware of
> the schema and understand SQLite's type conversion rules.
>
> And it's much simpler, for JS callers anyway, than type-specific APIs
> like the bind*Parameter methods provided by mozIStorageStatement.

We used nsIVariant very intensively and, with a couple of exceptions
(64-bit integers IIRC) type conversion worked without issue. The problem
is more the fact that generic operations need to use enormous switch
statements to handle all the possible types.

>> IMO this should have been architected on a much higher level. In our
>> architecture we have a database background thread that uses mozStorage
>> which uses SQLite. So we don't have the problem of writes holding up
>> the UI thread, but we don't sacrifice basic database engine
>> characteristics either.
>
> Hmm, this sounds interesting. Perhaps we could use this approach to
> boost Places write performance without giving up ACID compliance for all
> databases. cc:ing Seth Spitzer for his thoughts.

You can see our approach in
http://lxr/source/database/src/apDatabaseService.cpp. The
ExecuteSqlWithParams method posts the SQL to another thread, where it is
process by the apExecuteSqlEvent (which calls DoExecuteSqlWithParams).
I'm interested to know what you guys think.

Matt

Matthew Gertner

unread,
Sep 13, 2007, 9:59:12 AM9/13/07
to
Matthew Gertner wrote:
> You can see our approach in
> http://lxr/source/database/src/apDatabaseService.cpp. The
> ExecuteSqlWithParams method posts the SQL to another thread, where it is
> process by the apExecuteSqlEvent (which calls DoExecuteSqlWithParams).
> I'm interested to know what you guys think.

Sorry, should be
http://lxr.allpeers.com/source/database/src/apDatabaseService.cpp

Jeff Rose

unread,
Sep 13, 2007, 10:12:13 AM9/13/07
to dev-pl...@lists.mozilla.org

Well, I respectfully disagree with you on both these points. First, it
should be possible to run queries and get results without having to deal
with the binding API. I think for any SQL interface a text only API is
the first and most basic thing that should be built. Database
safety/security should not be forced by using a binding API when there
are many, many ways it could be dealt with. Second, there should not be
a mandatory extraction process for query results. All of these things
are fine for the bottom end, but on top you should be able to do this:

var items = db.execute("select * from items");

which returns a javascript object:

items = [{id: 1, value: "foo"}, {id: 2, value: "bar"}];

The work on FUEL is moving in exactly this direction for some aspects of
the browser API, but if higher level constructs like this were more
prevalent I think the amount of innovation and the number of
contributers connected with Mozilla would sky-rocket.

Message has been deleted

Dan Mosedale

unread,
Sep 13, 2007, 6:23:15 PM9/13/07
to
Matthew Gertner wrote:
> Myk Melez wrote:
>
>> * a less critical reset (see bug 328884 [1], but I'm quite sure
>> what this would entail);
>
> This just sounds like a bug to me, not a design issue with the wrapper API.

The API design issue is that a method named "reset" on a statement
sounds like it should only effect that statement. The fact that it has
the rather bizarre semantic of being required in order to not hork the
database connection for subsequent statements is extremely unintuitive.

Dan

Axel Hecht

unread,
Sep 14, 2007, 1:44:03 PM9/14/07
to

I hacked something together.

Can you say "mozIStorageStatementWrapper" 10 times in a row?

And why didn't anybody implement enumerating rows? Sob.

Anyway, this should give folks an idea on how stuff could be done. If I
only could get the column names from somewhere.

Axel

sql-iter.js

Myk Melez

unread,
Sep 14, 2007, 4:02:08 PM9/14/07
to
Axel Hecht wrote:
> I don't think that XPCOM is the solution here. Just like DOM is only
> half-way painful due to JS-specific language bindings (i.e., scriptable
> helpers), and other query API would suffer if you try to write it down
> in IDL.

I'd be just as happy with a JavaScript module. The key isn't XPCOM,
it's having a simple interface to the database engine.


> In sqlalchemy (which is the only ORM I remotely know), you'd do
>
> var result = bar.query().filter_by({baz:baz, buz:buz});
> for (r in result) {
> r.foo;
> };

That's a complimentary interface which is fine for applications using
ORM. But for those not yet ORM yet, or who need to be closer to the
metal for some of their queries, it'd still be useful to have a simpler
interface for direct querying.

-myk

Matthew Gertner

unread,
Sep 17, 2007, 12:09:38 PM9/17/07
to
Axel Hecht wrote:
> I hacked something together.
>
> Can you say "mozIStorageStatementWrapper" 10 times in a row?
>
> And why didn't anybody implement enumerating rows? Sob.
>
> Anyway, this should give folks an idea on how stuff could be done. If I
> only could get the column names from somewhere.

Can't you just call _inner.getColumnName(index)?

Matt

Jeff Rose

unread,
Sep 18, 2007, 7:29:41 AM9/18/07
to dev-pl...@lists.mozilla.org
> I hacked something together.
>
> Can you say "mozIStorageStatementWrapper" 10 times in a row?
>
> And why didn't anybody implement enumerating rows? Sob.
>
> Anyway, this should give folks an idea on how stuff could be done. If I
> only could get the column names from somewhere.
>

You can pull them out with a query. I do it like this in my db layer on
top of moz storage:

column_names: function(table_name) {
var names = this.execute(
"PRAGMA table_info(" + table_name + ")").pluck('name');

return names.select( function(name) { return (name != "id") } ); }

Attached is the rest of the code, which might come in handy...

-Jeff

db

Axel Hecht

unread,
Sep 18, 2007, 8:27:17 AM9/18/07
to

Yes. Not that that's exposed on .Wrapper anymore, so you need both around.

function iterStatement(conn, statement) {
var _inner = conn.createStatement(statement);
var wrapper = new Wrapper(_inner);
function __createObjectFromWrapper() {
var o = {};
for (var i=0; i < _inner.columnCount; ++i) {
var k = _inner.getColumnName(i);
o[k] = wrapper.row[k]
}
return o;
};
return {
__iterator__: function() {
wrapper.execute();
try {
while (wrapper.step()) {
yield __createObjectFromWrapper();
}
} finally {
wrapper.reset();
}
}
}
}

i=iterStatement(mDBConn, 'SELECT * FROM data');
for (r in i) {
print(r);
for (var k in r) {
print(k + ' -> ' + r[k]);
}
// do other stuff if you know your column names.
}


works, of course it's kind-of sad to have a well-formed js object and to
just use it to get a fully implemented one from grabbing information
from different places.

Axel

0 new messages