ydn.db
Version:
Javascript database library for IndexedDB, WebDatabase (WebSQL) and WebStorage (localStorage) storage mechanisms supporting version migration, advanced query and transaction workflow.
278 lines (224 loc) • 6.32 kB
JavaScript
// Copyright 2012 YDN Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/**
* @fileoverview Data store in memory.
*/
goog.provide('ydn.db.con.SimpleStorage');
goog.require('goog.asserts');
goog.require('goog.async.Deferred');
goog.require('ydn.db.Key');
goog.require('ydn.db.VersionError');
goog.require('ydn.db.con.IDatabase');
goog.require('ydn.db.con.simple');
goog.require('ydn.db.con.simple.IStorageProvider');
goog.require('ydn.db.con.simple.Store');
goog.require('ydn.db.con.simple.TxStorage');
goog.require('ydn.db.req.InMemoryStorage');
goog.require('ydn.debug.error.InternalError');
/**
* @implements {ydn.db.con.IDatabase}
* @param {!ydn.db.con.simple.IStorageProvider=} opt_provider storage provider.
* @constructor
* @extends {ydn.db.con.SimpleStorageService}
* @struct
*/
ydn.db.con.SimpleStorage = function(opt_provider) {
goog.base(this, opt_provider);
this.version_ = NaN;
};
goog.inherits(ydn.db.con.SimpleStorage, ydn.db.con.SimpleStorageService);
/**
* @protected
* @type {goog.debug.Logger} logger.
*/
ydn.db.con.SimpleStorage.prototype.logger =
goog.log.getLogger('ydn.db.con.SimpleStorage');
/**
* @private
* @type {number}
*/
ydn.db.con.SimpleStorage.prototype.version_;
/**
*
* @return {boolean} true if memory is supported.
*/
ydn.db.con.SimpleStorage.isSupported = function() {
return true;
};
/**
*
* @type {boolean} debug flag. should always be false.
*/
ydn.db.con.SimpleStorage.DEBUG = false;
/**
* @type {number}
* @private
*/
ydn.db.con.SimpleStorage.prototype.version_;
/**
* @inheritDoc
*/
ydn.db.con.SimpleStorage.prototype.getVersion = function() {
return this.version_;
};
/**
* @inheritDoc
*/
ydn.db.con.SimpleStorage.prototype.connect = function(dbname, schema) {
var me = this;
var df = new goog.async.Deferred();
/**
*
* @param {number} x
* @param {Error=} opt_err
*/
var callDf = function(x, opt_err) {
setTimeout(function() {
if (opt_err) {
goog.log.finer(me.logger, me + ' opening fail');
df.errback(opt_err);
} else {
goog.log.finer(me.logger, me + ' version ' + me.getVersion() + ' open');
df.callback(x);
}
}, 10);
};
/**
* @final
* @type {!Storage}
*/
this.storage_ = this.provider_.connectDb(dbname);
/**
* @final
* @type {string}
*/
this.dbname = dbname;
/**
* @final
* @type {!ydn.db.schema.Database}
*/
this.schema = schema;
var db_key = ydn.db.con.simple.makeKey(this.dbname);
this.version_ = NaN;
/**
*
* @type {DatabaseSchema}
*/
var ex_schema_json = /** @type {DatabaseSchema} */
(ydn.json.parse(this.storage_.getItem(db_key)));
if (goog.isDef(ex_schema_json.version)
&& !goog.isNumber(ex_schema_json.version)) {
ex_schema_json.version = NaN; // NaN is not serializable.
}
if (ex_schema_json) {
var ex_schema = new ydn.db.schema.Database(ex_schema_json);
var diff_msg = this.schema.difference(ex_schema, false, false);
if (diff_msg) {
if (!this.schema.isAutoVersion() &&
!isNaN(ex_schema.getVersion()) &&
this.schema.getVersion() > ex_schema.getVersion()) {
var msg = goog.DEBUG ? 'existing version ' + ex_schema.getVersion() +
' is larger than ' + this.schema.getVersion() : '';
callDf(NaN, new ydn.db.VersionError(msg));
} else {
// upgrade schema
var v = this.schema.getVersion();
this.version_ = goog.isDef(v) ? v : (ex_schema.getVersion() + 1);
for (var i = 0; i < this.schema.count(); i++) {
var store = this.schema.store(i);
}
if (this.schema instanceof ydn.db.schema.EditableDatabase) {
for (var i = 0; i < ex_schema.count(); i++) {
var store = ex_schema.store(i);
goog.asserts.assert(!goog.isNull(store), 'store at ' + i +
' is null');
this.schema.addStore(store);
}
}
var schema_json = this.schema.toJSON();
schema_json.version = this.version_ || NaN;
this.storage_.setItem(db_key, ydn.json.stringify(schema_json));
callDf(ex_schema.getVersion() || NaN);
}
} else {
for (var i = 0; i < this.schema.count(); i++) {
var store = this.schema.store(i);
}
this.version_ = ex_schema.getVersion() || NaN;
callDf(this.version_);
}
} else {
var json = schema.toJSON();
this.version_ = 1;
var old_version = NaN;
json.version = this.version_;
this.storage_.setItem(db_key, ydn.json.stringify(json));
callDf(old_version);
}
return df;
};
/**
* @inheritDoc
*/
ydn.db.con.SimpleStorage.prototype.isReady = function() {
return !!this.dbname;
};
/**
* @inheritDoc
*/
ydn.db.con.SimpleStorage.prototype.getDbInstance = function() {
return this.storage_ || null;
};
/**
* @inheritDoc
*/
ydn.db.con.SimpleStorage.prototype.onFail = function(e) {};
/**
* @inheritDoc
*/
ydn.db.con.SimpleStorage.prototype.onError = function(e) {};
/**
* @inheritDoc
*/
ydn.db.con.SimpleStorage.prototype.onVersionChange = function(e) {};
/**
* @inheritDoc
*/
ydn.db.con.SimpleStorage.prototype.getType = function() {
return 'memory';
};
/**
* @inheritDoc
*/
ydn.db.con.SimpleStorage.prototype.close = function() {
};
/**
* @inheritDoc
*/
ydn.db.con.SimpleStorage.prototype.doTransaction = function(trFn, scopes, mode,
oncompleted) {
var tx = new ydn.db.con.simple.TxStorage(this, function(t, e) {
oncompleted(t, e);
});
trFn(tx);
};
if (goog.DEBUG) {
/**
* @override
*/
ydn.db.con.SimpleStorage.prototype.toString = function() {
var s = this.dbname + ':' + this.version_;
return 'SimpleStorage:' + this.getType() + ':' + s;
};
}