- From: Keean Schupke <keean@fry-it.com>
- Date: Thu, 31 Mar 2011 15:33:44 +0000
- To: Nathan Kitchen <w3c@nathankitchen.com>
- Cc: public-webapps@w3.org
- Message-ID: <AANLkTinhtPu5NRwEv4Kg0rBi3jnX04Na0ZwAULcjVUYG@mail.gmail.com>
Have a look at my RelationalDB API
https://github.com/keean/RelationalDB
In particular examples/candy.html
A lot of work went into the underlying concepts - Its work originally
published by myself and others at the 2004 Haskell Workshop, and follows on
from HaskellDB which was the original inspiration behind C#s Linq
functionality).
It implements the relational-algebra operators as methods that operate on
relation objects.
Let me know what you think.
Cheers,
Keean.
On 31 March 2011 15:19, Nathan Kitchen <w3c@nathankitchen.com> wrote:
> Hi.
>
> I've been watching discussions on IndexedDB for a while now, and wondered
> if anyone would mind spending a few moments to explain how IndexedDB is
> related (or not) to WebSQL. Is IndexedDB seen as replacing the functionality
> originally offered by WebSQL? If not, are there any plans to make a
> cross-platform variant of Web SQL?
>
> If (?) most web developers know SQL, is there a case to be made for
> abstracting SQL into JSON/JavaScript rather than moving to IndexedDB
> document storage? Reasons for asking this:
>
> - Many of the posts appearing to come from "the dev community" rather
> than W3C seem to expect more SQL-esque functionality from IndexedDB. If the
> enthusiasts who get involved enough to post to the board are expecting
> SQL/query type experience, maybe there is a driver for a native database API
> supporting this.
> - Several people have noted that third-party frameworks could implement
> this functionality. This might be a daft question, but isn't it easier to
> implement an "IndexedDB"-like framework on top of "WebSQL", than a
> "WebSQL"-like framework on top of "IndexedDB" (overuse of quotes to indicate
> the general concept).
>
> I had a ponder on how I'd like to see such a framework implemented (in both
> Access & SQLite :p ), and came up with a stack of pseudo-code below in my
> lunch break. Might make an interesting discussion point. It's not really
> IndexedDB, it's WebSQL v2. Or maybe WebJSQL or something. I'd be really
> interested to understand what advantages IndexedDB has over an
> implementation like the one below though.
>
> // DATABASE
> // First, open a database with the specified name. The number at the
> // end denotes the version of the specification that the application
> // plans to use. This allows forward-compatibility with vNext.
> var db = window.openDatabase("shoppinglist", 1.0);
>
> // MIGRATIONS
> // Next, create some migrations. These are predefined structures which
> // are validated by the browser database engine. A migration consists
> // of two actions: one "up", one "down". Each action specifies some
> // operations and parameters. It's up to the browser database to read
> // these and perform the appropriate action, as defined in the spec.
>
> // Other actions may include a "batch add" for "static" data. It could
> // also be valid to have key and index creation and removal as separate
> // actions.
>
> // SHOPPING TRIP
> var createTripTableAction = {
> action: "create-table",
> params: {
> name: "trip",
> columns: [
> { name: "id", type: "whole-number", primaryKey: true },
> { name: "name", type: "string", length: 32, regex: "[A-Z]{1,32}"
> } // regex: wouldn't that be nice...
> ],
> indexes: [
> {
> columns: [
> { name: "name", type: "full-text" }
> ]
> } // More indexes here if required
> ]
> }
> };
>
> var removeTripTableAction = {
> action: "remove-table",
> params: {
> name: "shopping",
> cleardata: true
> }
> };
>
>
> // SHOPPING
> var createShoppingTableAction = {
> action: "create-table",
> params: {
> name: "shopping",
> columns: [
> { name: "id", type: "whole-number", primaryKey: true },
> { name: "tripid", type: "whole-number" },
> { name: "name", type: "string", length: 128, nillable: false },
> { name: "cost", type: "decimal-number" }
> ],
> keys: [
> { local: "tripid", foreign: { table: "trips", column: "id" },
> cascade-delete: true } }
> ],
> indexes: [
> {
> columns: [
> { name: "tripid", type: "asc" },
> { name: "name", type: "full-text" }
> ]
> }
> ]
> }
> };
>
> var removeShoppingTableAction = {
> action: "remove-table",
> params: {
> name: "shopping",
> cleardata: true
> }
> };
>
> var migTrip = { up: createTripTableAction, down: removeTripTableAction };
> var migShopping = { up: createShoppingTableAction, down:
> removeShoppingTableAction };
>
> // Example calls which might be appropriate here, where the word
> // "callback" is placeholder for async operations:
>
> db.getVersion(); // Returns 0
> db.migrations.add(migTrip); // Persists the up/down actions as
> a list somewhere
> db.migrations.add(migShopping); // Persists the up/down actions as
> a list somewhere
> db.migrateUp(2, callback); // Runs the two migrations
> db.getVersion(); // Returns 2
> db.migrateDown(0, callback); // Runs all "down" migrations to
> schema version 0.
> db.getVersion(); // Returns 0
> db.destroy(true); // Get rid of the database,
> optionally running "down" migrations
>
> // * Note that during migration operations the database should be locked:
> no other threads should
> // * be able to interact/access the database while this is taking place.
>
> // QUERIES
> // Invent a JSON structure for creating queries. There could be simple
> // versions to support simple queries similar to the one below. I
> personally
> // think that the key here is readability:
>
> var query = { from: "shopping", select: ["name", "cost"], where: [ {
> column: "name", operator: "equals", value: "cookies"} ] };
>
> // And provide the capability to evaluate more complex query structures if
> needed:
>
> var queryJoin = {
> select: [ { table: "shopping", column: "name" }, { table: "shopping",
> column: "cost" } ],
> join: [
> { from: { table: "trips", column: "id" }, to: { table: "trips",
> column: "id" } }
> ],
> where: [
> { operator: "and",
> clause: [
> { table: "trips", column: "name", operator: "equals", value:
> "Costco" },
> { table: "shopping", column: "name", operator: "like", value:
> "*cookies" } // Can only use "like" on full-text indexed columns
> ]
> }
> ]
> };
>
> // Querying returns results to callback methods
> db.query(query, callback);
>
>
> // CREATE/UPDATE
> // Treat everything as "put" operations. Optionally specifying the ID
> // (Primary Key) of the object being added to the database should update
> // an existing item.
>
> var toy = { tripid: 1, name: "Flag", cost: 12.99 };
> var toys = [
> { tripid: 1, name: "Water pistol", cost: 27.50 }
> { tripid: 1, name: "Football", cost: 4.99 }
> { tripid: 1, name: "Rocket", cost: 8.99 }
> ];
>
> db.put("shopping", toy, callback);
> db.put("shopping", toys, callback);
>
> var replacementToy = { id: 3, tripid: 1, name: "England Flag", cost: 12.99
> };
>
> db.put("shopping", replacementToy);
>
> // There also needs to be functionality to batch update:
>
> var epicSale = { cost: 0.99 };
> var putQuery = {
> where: [
> { column: "tripid", operator: "equals", value: 1 }
> ]
> };
>
> // This effectively does: "UPDATE shopping SET cost=0.99 WHERE tripid=1;"
> db.put("shopping", putQuery, epicSale);
>
> // DELETE
> // Finally, provide the same kind of mechanisms for deleting data.
> db.remove("shopping", 1);
>
> var queryRemove = {
> remove: { table: "shopping", column: "name" },
> join: [
> { from: { table: "trips", column: "id" }, to: { table: "trips",
> column: "id" } }
> ],
> where: [
> { operator: "and",
> clause: [
> { table: "trips", column: "name", operator: "equals", value:
> "Costco" },
> { table: "shopping", column: "name", operator: "like", value:
> "*cookies" }
> ]
> }
> ]
> };
>
> db.remove("shopping", queryRemove);
>
Received on Thursday, 31 March 2011 15:34:22 UTC