Permalink
Browse files

Monotonic key encoding/decoding is implemented.

  • Loading branch information...
1 parent aca67c6 commit 791c626d6c8d55b579f973a6fb980713431a41c0 Khamza Davletov committed Jul 18, 2012
Showing with 231 additions and 232 deletions.
  1. +24 −28 IDBCursor.js
  2. +5 −5 IDBDatabase.js
  3. +19 −3 IDBFactory.js
  4. +20 −32 IDBIndex.js
  5. +7 −14 IDBKeyRange.js
  6. +43 −52 IDBObjectStore.js
  7. +2 −2 IDBRequest.js
  8. +1 −2 IDBTransaction.js
  9. +1 −3 README
  10. +29 −5 indexedDB.init.js
  11. +74 −83 key.js
  12. +6 −3 w3c-tests/testharness.js
View
@@ -11,7 +11,7 @@ if (window.indexedDB.polyfill)
this._request = request;
this._range = null;
this._gotValue = true;
- this._effectiveKey = null;
+ this._effectiveKeyEncoded = null;
};
IDBCursor.prototype.update = function (value)
@@ -36,7 +36,7 @@ if (window.indexedDB.polyfill)
noOverwrite : false,
value : value
},
- me._effectiveKey);
+ me._effectiveKeyEncoded);
});
return request;
};
@@ -64,7 +64,7 @@ if (window.indexedDB.polyfill)
var me = this;
objectStore.transaction._queueOperation(function (sqlTx, nextRequestCallback)
{
- objectStore._deleteRecord(sqlTx, me._effectiveKey,
+ objectStore._deleteRecord(sqlTx, me._effectiveKeyEncoded,
function ()
{
if (request.onsuccess) request.onsuccess(util.event("success", request));
@@ -130,18 +130,16 @@ if (window.indexedDB.polyfill)
me._request.readyState = util.IDBRequest.LOADING;
tx._queueOperation(function (sqlTx, nextRequestCallback)
{
- var sql = ["SELECT key, value FROM [" + me.source.name + "]"];
+ var sql = ["SELECT hex(key) 'key', value FROM [" + me.source.name + "]"];
var where = [];
var args = [];
if (filter.lower != null)
{
- where.push("(key >" + (filter.lowerOpen ? "" : "=") + " ?)");
- args.push(util.encodeKey(filter.lower));
+ where.push("(key >" + (filter.lowerOpen ? "" : "=") + " X'" + util.encodeKey(filter.lower) + "')");
}
if (filter.upper != null)
{
- where.push("(key <" + (filter.upperOpen ? "" : "=") + " ?)");
- args.push(util.encodeKey(filter.upper));
+ where.push("(key <" + (filter.upperOpen ? "" : "=") + " X'" + util.encodeKey(filter.upper) + "')");
}
if (where.length > 0)
{
@@ -157,14 +155,14 @@ if (window.indexedDB.polyfill)
request.readyState = util.IDBRequest.DONE;
if (results.rows.length < filter.count)
{
- me.key = me.primaryKey = me._effectiveKey = undefined;
+ me.key = me.primaryKey = me._effectiveKeyEncoded = undefined;
if (typeof me.value !== "undefined") me.value = undefined;
request.result = null;
}
else
{
var found = results.rows.item(filter.count - 1);
- me._effectiveKey = found.key;
+ me._effectiveKeyEncoded = found.key;
me.key = me.primaryKey = util.decodeKey(found.key);
if (typeof me.value !== "undefined") me.value = w_JSON.parse(found.value);
me._gotValue = true;
@@ -193,53 +191,51 @@ if (window.indexedDB.polyfill)
var desc = isDesc(me);
var objectStoreName = me.source.objectStore.name;
var tableName = util.indexTable(objectStoreName, me.source.name);
- var sql = ["SELECT i.key, i.primaryKey" + (withValue ? ", t.value" : ""),
+ var sql = ["SELECT hex(i.key) 'key', hex(i.primaryKey) 'primaryKey'" + (withValue ? ", t.value" : ""),
"FROM [" + tableName + "] as i"];
if (withValue)
{
sql.push("LEFT JOIN [" + objectStoreName + "] as t ON t.Id = i.recordId");
}
- var where = [], args = [];
+ var where = [], args = [], encoded;
if (filter.lower != null)
{
- var strLower = util.encodeKey(filter.lower);
- args.push(strLower);
+ encoded = util.encodeKey(filter.lower);
if (filter.lowerOpen)
{
- where.push("(i.key > ?)");
+ where.push("(i.key > X'" + encoded + "')");
}
else
{
- if (me._effectiveKey == null || desc)
+ if (me._effectiveKeyEncoded == null || desc)
{
- where.push("(i.key >= ?)");
+ where.push("(i.key >= X'" + encoded+ "')");
}
else
{
- where.push("((i.key > ?) OR (i.key = ? AND i.primaryKey > ?))");
- args.push(strLower, me._effectiveKey);
+ where.push("((i.key > X'" + encoded + "') OR (i.key = X'" + encoded +
+ "' AND i.primaryKey > X'" + me._effectiveKeyEncoded + "'))");
}
}
}
if (filter.upper != null)
{
- var strUpper = util.encodeKey(filter.upper);
- args.push(strUpper);
+ encoded = util.encodeKey(filter.upper);
if (filter.upperOpen)
{
- where.push("(i.key < ?)");
+ where.push("(i.key < X'" + encoded + "')");
}
else
{
- if (me._effectiveKey == null || !desc)
+ if (me._effectiveKeyEncoded == null || !desc)
{
- where.push("(i.key <= ?)");
+ where.push("(i.key <= X'" + encoded + "')");
}
else
{
- where.push("((i.key < ?) OR (i.key = ? AND i.primaryKey < ?))");
- args.push(strUpper, me._effectiveKey);
+ where.push("((i.key < X'" + encoded + "') OR (i.key = X'" + encoded +
+ "' AND i.primaryKey < X'" + me._effectiveKeyEncoded + "'))");
}
}
}
@@ -258,15 +254,15 @@ if (window.indexedDB.polyfill)
request.readyState = util.IDBRequest.DONE;
if (results.rows.length < filter.count)
{
- me.key = me.primaryKey = me._effectiveKey = undefined;
+ me.key = me.primaryKey = me._effectiveKeyEncoded = undefined;
if (typeof me.value !== "undefined") me.value = undefined;
request.result = null;
}
else
{
var found = results.rows.item(filter.count - 1);
me.key = util.decodeKey(found.key);
- me._effectiveKey = found.primaryKey;
+ me._effectiveKeyEncoded = found.primaryKey;
me.primaryKey = util.decodeKey(found.primaryKey);
if (typeof me.value !== "undefined") me.value = w_JSON.parse(found.value);
me._gotValue = true;
View
@@ -49,7 +49,7 @@ if (window.indexedDB.polyfill)
var objectStore = this._objectStores[name];
delete this._objectStores[name];
var me = this;
- var errorCallback = function (tx, sqlError)
+ var errorCallback = function (_, sqlError)
{
me.objectStoreNames.push(name);
me._objectStores[name] = objectStore;
@@ -66,7 +66,7 @@ if (window.indexedDB.polyfill)
IDBDatabase.prototype.transaction = function (storeNames, mode)
{
- // TODO: 4.2.1. throw InvalidStateError if a transaction being createing within transaction callback
+ // TODO: 4.2.1. throw InvalidStateError if a transaction being creating within transaction callback
if (storeNames instanceof Array || storeNames == null)
{
if (storeNames.length == 0) throw util.error("InvalidAccessError");
@@ -142,17 +142,17 @@ if (window.indexedDB.polyfill)
var objectStore = new util.IDBObjectStore(name, keyPath, autoIncrement, me._versionChangeTransaction);
me.objectStoreNames.push(name);
me._objectStores[name] = objectStore;
- var errorCallback = function (tx, sqlError)
+ var errorCallback = function (_, sqlError)
{
util.arrayRemove(me.objectStoreNames, name);
delete me._objectStores[name];
};
me._versionChangeTransaction._queueOperation(function (sqlTx, nextRequestCallback)
{
sqlTx.executeSql("CREATE TABLE [" + name + "] (id INTEGER PRIMARY KEY AUTOINCREMENT, " +
- "key TEXT UNIQUE, value BLOB)", [], null, errorCallback);
+ "key BLOB UNIQUE, value BLOB)", null, null, errorCallback);
- sqlTx.executeSql("CREATE INDEX INDEX_" + name + "_key ON [" + name + "] (key)", [], null, errorCallback);
+ sqlTx.executeSql("CREATE INDEX INDEX_" + name + "_key ON [" + name + "] (key)", null, null, errorCallback);
sqlTx.executeSql("INSERT INTO " + indexedDB.SCHEMA_TABLE +
" (type, name, keyPath, autoInc) VALUES ('table', ?, ?, ?)",
View
@@ -5,6 +5,7 @@ if (window.indexedDB.polyfill)
indexedDB.open = function (name, version)
{
+ console.group
if (arguments.length == 2 && version == undefined) throw util.error("TypeError");
if (version !== undefined)
{
@@ -168,24 +169,30 @@ if (window.indexedDB.polyfill)
// IDBFactory.deleteDatabase
indexedDB.deleteDatabase = function (name)
{
+ console.groupCollapsed("indexedDB.deleteDatabase('%s')", name);
// INFO: There is no way to delete database in Web SQL Database API.
var database = getOriginDatabase(name);
database.deletePending = true;
var request = new util.IDBOpenDBRequest(null);
util.async(function()
{
+ console.log("deleteDatabase async started.");
request.readyState = util.IDBRequest.DONE;
var sqldb = openSqlDB(name);
if (sqldb.version == "")
{
+ console.log("Database deleted succesfully. (No such database was found)");
+ console.groupEnd();
database.deletePending = false;
if (request.onsuccess) request.onsuccess(util.event("success", request));
}
else
{
+ console.log("Deleting existing database");
fireVersionChangeEvent(request, name, parseInt(sqldb.version), null);
util.wait(function ()
{
+ console.log("Waiting %d connection to be closed", database.connections.length);
return database.connections.length == 0;
},
function ()
@@ -245,45 +252,54 @@ if (window.indexedDB.polyfill)
var conn = database.connections[i];
if (conn._closePending) continue;
+ console.log("Open connection found, firing versionchange event on them.");
anyOpenConnection = true;
var event = new util.IDBVersionChangeEvent("versionchange", request, oldVersion, newVersion);
if (conn.onversionchange) conn.onversionchange(event);
}
if (anyOpenConnection)
{
+ console.log("Open connection found, firing onblocked event.");
var event = new util.IDBVersionChangeEvent("blocked", request, oldVersion, newVersion);
if (request.onblocked) request.onblocked(event);
}
}
function deleteDatabase(request, sqldb, database)
{
+ console.log("Setting sql database version %d to empty.", sqldb.version);
sqldb.changeVersion(sqldb.version, "",
function (sqlTx)
{
+ console.log("Selecting all tables and indexes from schema table.");
sqlTx.executeSql("SELECT a.type, a.name, b.name 'table' FROM " + indexedDB.SCHEMA_TABLE +
" a LEFT JOIN " + indexedDB.SCHEMA_TABLE + " b ON a.type = 'index' AND a.tableId = b.Id",
null,
- function (tx, results)
+ function (sqlTx, results)
{
var name;
for (var i = 0; i < results.rows.length; i++)
{
var item = results.rows.item(i);
name = item.type == 'table' ? item.name : util.indexTable(item.table, item.name);
- tx.executeSql("DROP TABLE [" + name + "]");
+ console.log("Dropping table %s.", name);
+ sqlTx.executeSql("DROP TABLE [" + name + "]");
}
- tx.executeSql("DROP TABLE " + indexedDB.SCHEMA_TABLE);
+ console.log("Dropping schema table.");
+ sqlTx.executeSql("DROP TABLE " + indexedDB.SCHEMA_TABLE);
});
},
function (sqlError)
{
+ console.error("Database (version %d) deletion failed.", sqldb.version, sqlError);
database.deletePending = false;
request.error = sqlError;
if (request.onerror) request.onerror(util.event("error", request));
},
function ()
{
+ console.log("Database deleted successfully.");
+ console.groupEnd();
database.deletePending = false;
if (request.onsuccess) request.onsuccess(util.event("success", request));
});
View
@@ -23,27 +23,23 @@ if (window.indexedDB.polyfill)
IDBIndex.prototype.get = function (key)
{
- key = util.validateKeyOrRange(key);
+ var encodedKeyOrRange = util.validateKeyOrRange(key);
var request = new util.IDBRequest(this);
var me = this;
this.objectStore.transaction._queueOperation(function (sqlTx, nextRequestCallback)
{
var sql = ["SELECT s.value FROM [" + util.indexTable(me) + "] AS i INNER JOIN"];
- sql.push("[" + me.objectStore.name + "] AS s ON s.id = i.recordId")
- var args = [];
- if (key instanceof util.IDBKeyRange)
+ sql.push("[" + me.objectStore.name + "] AS s ON s.id = i.recordId");
+ if (encodedKeyOrRange instanceof util.IDBKeyRange)
{
- var filter = key._getSqlFilter("i.key");
- sql.push("WHERE", filter.sql);
- args = filter.args;
+ sql.push("WHERE", encodedKeyOrRange._getSqlFilter("i.key"));
}
- else if (key != null)
+ else if (encodedKeyOrRange != null)
{
- sql.push("WHERE (i.key = ?)");
- args.push(key);
+ sql.push("WHERE (i.key = X'" + encodedKeyOrRange + "')");
}
sql.push("ORDER BY i.key, i.primaryKey LIMIT 1");
- sqlTx.executeSql(sql.join(" "), args,
+ sqlTx.executeSql(sql.join(" "), null,
function (_, results)
{
request.result = results.rows.length > 0 ? w_JSON.parse(results.rows.item(0).value) : undefined;
@@ -62,26 +58,22 @@ if (window.indexedDB.polyfill)
IDBIndex.prototype.getKey = function (key)
{
- key = util.validateKeyOrRange(key);
+ var encodedKeyOrRange = util.validateKeyOrRange(key);
var request = new util.IDBRequest(this);
var me = this;
this.objectStore.transaction._queueOperation(function (sqlTx, nextRequestCallback)
{
- var sql = ["SELECT primaryKey FROM [" + util.indexTable(me) + "]"];
- var args = [];
- if (key instanceof util.IDBKeyRange)
+ var sql = ["SELECT hex(primaryKey) 'primaryKey' FROM [" + util.indexTable(me) + "]"];
+ if (encodedKeyOrRange instanceof util.IDBKeyRange)
{
- var filter = key._getSqlFilter();
- sql.push("WHERE", filter.sql);
- args = filter.args;
+ sql.push("WHERE", encodedKeyOrRange._getSqlFilter());
}
- else if (key != null)
+ else if (encodedKeyOrRange != null)
{
- sql.push("WHERE (key = ?)");
- args.push(key);
+ sql.push("WHERE (key = X'" + encodedKeyOrRange + "')");
}
sql.push("LIMIT 1");
- sqlTx.executeSql(sql.join(" "), args,
+ sqlTx.executeSql(sql.join(" "), null,
function (_, results)
{
request.result = results.rows.length > 0 ?
@@ -101,25 +93,21 @@ if (window.indexedDB.polyfill)
IDBIndex.prototype.count = function (key)
{
- key = util.validateKeyOrRange(key);
+ var encodedKeyOrRange = util.validateKeyOrRange(key);
var request = new util.IDBRequest(this);
var me = this;
this.objectStore.transaction._queueOperation(function (sqlTx, nextRequestCallback)
{
var sql = ["SELECT COUNT(recordId) AS 'count' FROM [" + util.indexTable(me) + "]"];
- var args = [];
- if (key instanceof util.IDBKeyRange)
+ if (encodedKeyOrRange instanceof util.IDBKeyRange)
{
- var filter = key._getSqlFilter();
- sql.push("WHERE", filter.sql);
- args = filter.args;
+ sql.push("WHERE", encodedKeyOrRange._getSqlFilter());
}
- else if (key != null)
+ else if (encodedKeyOrRange != null)
{
- sql.push("WHERE (key = ?)");
- args.push(key);
+ sql.push("WHERE (key = X'" + encodedKeyOrRange + "')");
}
- sqlTx.executeSql(sql.join(" "), args,
+ sqlTx.executeSql(sql.join(" "), null,
function (_, results)
{
request.result = results.rows.item(0).count;
Oops, something went wrong.

0 comments on commit 791c626

Please sign in to comment.