Skip to content
This repository has been archived by the owner on Jan 10, 2023. It is now read-only.

Commit

Permalink
Disallowing multiple calls to connect().
Browse files Browse the repository at this point in the history
The connect() method is used to obtain a DB connection, either from an
lf.schema.Builder instance, or from the generated #namespace.connect() method for
SPAC. Calling connect() on an instance with active DB connection has no
valid use case, but it was allowed until now, causing confusion. For example
users thought that a DB connection to WebSQL and IndexedDB could be opened at
the same time with subsequent calls to connect(), with unexpected results.
  With this change misuse of connect() will result in an exception. The
connect() method can be called again only after the current DB connection has
been closed with a call to db.close().
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=104422821
  • Loading branch information
freshp86 committed Oct 2, 2015
1 parent aee7308 commit a87e893
Show file tree
Hide file tree
Showing 37 changed files with 725 additions and 579 deletions.
3 changes: 2 additions & 1 deletion dist/error_code.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"0": "System error",
"1": "Lovefield library version mismatch.",
"2": "The database has not initialized yet.",
"2": "The database connection is not active.",
"3": "Operation timeout.",
"4": "Operation blocked.",
"5": "Storage quota exceeded.",
Expand All @@ -20,6 +20,7 @@
"110": "Attempt to import into a non-empty database.",
"111": "Database name/version mismatch for import.",
"112": "Import data not found.",
"113": "Attempt to call connect() on an already opened DB connection.",

"200": "Constraint error",
"201": "Duplicate keys are not allowed.",
Expand Down
429 changes: 215 additions & 214 deletions dist/lovefield.es6.js

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions dist/lovefield.es6.js.map

Large diffs are not rendered by default.

106 changes: 57 additions & 49 deletions dist/lovefield.js

Large diffs are not rendered by default.

442 changes: 221 additions & 221 deletions dist/lovefield.min.js

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dist/lovefield.min.js.map

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion docs/spec/03_life_of_db.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ It will do the following:
`connect()` shall be called only once each session. In rare circumstances,
one can call `close()` on the opened connection first, then call `connect()`
again. However, this is not guaranteed to work due to IndexedDB limitations,
see [Data Store](02_data_store.md) for details.
see [Data Store](02_data_store.md) for details. Calling `connect()` when an
open connection exists will result in an exception.

Users are free to connect to two or more databases simultaneously in the same
session. Users shall not connect to the same database more than once in the same
Expand Down
43 changes: 26 additions & 17 deletions lib/proc/database.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,11 @@ lf.proc.Database = function(global) {
/** @private {!lf.schema.Database} */
this.schema_ = global.getService(lf.service.SCHEMA);

/** @private {boolean} */
this.initialized_ = false;
/**
* Whether this connection to the database is active.
* @private {boolean}
*/
this.isActive_ = false;

/** @private {!lf.proc.Runner} */
this.runner_;
Expand All @@ -64,7 +67,7 @@ lf.proc.Database.prototype.init = function(opt_options) {

return /** @type {!IThenable<!lf.proc.Database>} */ (
lf.base.init(this.global_, opt_options).then(function() {
this.initialized_ = true;
this.isActive_ = true;
this.runner_ = this.global_.getService(lf.service.RUNNER);
return this;
}.bind(this)));
Expand All @@ -78,17 +81,17 @@ lf.proc.Database.prototype.getSchema = function() {


/** @private */
lf.proc.Database.prototype.checkInit_ = function() {
if (!this.initialized_) {
// 2: The database has not initialized yet.
lf.proc.Database.prototype.checkActive_ = function() {
if (!this.isActive_) {
// 2: The database connection is not active.
throw new lf.Exception(2);
}
};


/** @override @export */
lf.proc.Database.prototype.select = function(var_args) {
this.checkInit_();
this.checkActive_();
var columns =
arguments.length == 1 && !goog.isDefAndNotNull(arguments[0]) ?
[] : Array.prototype.slice.call(arguments);
Expand All @@ -98,35 +101,35 @@ lf.proc.Database.prototype.select = function(var_args) {

/** @override @export */
lf.proc.Database.prototype.insert = function() {
this.checkInit_();
this.checkActive_();
return new lf.query.InsertBuilder(this.global_);
};


/** @override @export */
lf.proc.Database.prototype.insertOrReplace = function() {
this.checkInit_();
this.checkActive_();
return new lf.query.InsertBuilder(this.global_, /* allowReplace */ true);
};


/** @override @export */
lf.proc.Database.prototype.update = function(table) {
this.checkInit_();
this.checkActive_();
return new lf.query.UpdateBuilder(this.global_, table);
};


/** @override @export */
lf.proc.Database.prototype.delete = function() {
this.checkInit_();
this.checkActive_();
return new lf.query.DeleteBuilder(this.global_);
};


/** @override @export */
lf.proc.Database.prototype.observe = function(query, callback) {
this.checkInit_();
this.checkActive_();
var observerRegistry = this.global_.getService(
lf.service.OBSERVER_REGISTRY);
observerRegistry.addObserver(query, callback);
Expand All @@ -135,7 +138,7 @@ lf.proc.Database.prototype.observe = function(query, callback) {

/** @override @export */
lf.proc.Database.prototype.unobserve = function(query, callback) {
this.checkInit_();
this.checkActive_();
var observerRegistry = this.global_.getService(
lf.service.OBSERVER_REGISTRY);
observerRegistry.removeObserver(query, callback);
Expand All @@ -144,7 +147,7 @@ lf.proc.Database.prototype.unobserve = function(query, callback) {

/** @override @export */
lf.proc.Database.prototype.createTransaction = function(opt_type) {
this.checkInit_();
this.checkActive_();
return new lf.proc.Transaction(this.global_);
};

Expand All @@ -153,13 +156,13 @@ lf.proc.Database.prototype.createTransaction = function(opt_type) {
lf.proc.Database.prototype.close = function() {
lf.base.closeDatabase(this.global_);
this.global_.clear();
this.initialized_ = false;
this.isActive_ = false;
};


/** @override @export */
lf.proc.Database.prototype.export = function() {
this.checkInit_();
this.checkActive_();
var task = new lf.proc.ExportTask(this.global_);
return this.runner_.scheduleTask(task).then(function(results) {
return results[0].getPayloads()[0];
Expand All @@ -169,9 +172,15 @@ lf.proc.Database.prototype.export = function() {

/** @override @export */
lf.proc.Database.prototype.import = function(data) {
this.checkInit_();
this.checkActive_();
var task = new lf.proc.ImportTask(this.global_, data);
return this.runner_.scheduleTask(task).then(function() {
return null;
});
};


/** @return {boolean} */
lf.proc.Database.prototype.isOpen = function() {
return this.isActive_;
};
22 changes: 17 additions & 5 deletions lib/schema/builder.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ lf.schema.Builder = function(dbName, dbVersion) {

/** @private {boolean} */
this.finalized_ = false;

/** @private {?lf.proc.Database} */
this.db_ = null;
};


Expand Down Expand Up @@ -238,18 +241,27 @@ lf.schema.Builder.prototype.getGlobal = function() {


/**
* Instantiates a connection to the database. Note: This method can only be
* called once per Builder instance. Subsequent calls will throw an error.
* @param {!lf.schema.ConnectOptions=} opt_options
* @return {!IThenable<!lf.proc.Database>}
* @export
*/
lf.schema.Builder.prototype.connect = function(opt_options) {
var global = this.getGlobal();
if (!global.isRegistered(lf.service.SCHEMA)) {
global.registerService(lf.service.SCHEMA, this.getSchema());
if (!goog.isNull(this.db_) && this.db_.isOpen()) {
// 113: Attempt to call connect() on an already opened DB connection.
throw new lf.Exception(113);
}

if (goog.isNull(this.db_)) {
var global = this.getGlobal();
if (!global.isRegistered(lf.service.SCHEMA)) {
global.registerService(lf.service.SCHEMA, this.getSchema());
}
this.db_ = new lf.proc.Database(global);
}

var db = new lf.proc.Database(global);
return db.init(opt_options);
return this.db_.init(opt_options);
};


Expand Down
19 changes: 16 additions & 3 deletions spac/template/database.jstemplate
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ goog.provide('#namespace');

/// #sort
goog.require('#namespace.schema.Database');
goog.require('lf.Exception');
goog.require('lf.Global');
/** @suppress {extraRequire} */
goog.require('lf.fn');
Expand Down Expand Up @@ -51,7 +52,19 @@ goog.require('lf.service.ServiceId');
* @return {!IThenable<!lf.proc.Database>}
*/
#namespace.connect = function(opt_options) {
#namespace.getSchema();
var db = new lf.proc.Database(#namespace.getGlobal());
return db.init(opt_options);
if (!goog.isNull(#namespace.db_) && #namespace.db_.isOpen()) {
// 113: Attempt to call connect() on an already opened DB connection.
throw new lf.Exception(113);
}

if (goog.isNull(#namespace.db_)) {
#namespace.getSchema();
#namespace.db_ = new lf.proc.Database(#namespace.getGlobal());
}

return #namespace.db_.init(opt_options);
};


/** @private {?lf.proc.Database} */
#namespace.db_ = null;
19 changes: 16 additions & 3 deletions spac/testdata/database.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
goog.provide('lovefield.db');

goog.require('lf.Exception');
goog.require('lf.Global');
/** @suppress {extraRequire} */
goog.require('lf.fn');
Expand Down Expand Up @@ -47,7 +48,19 @@ lovefield.db.getSchema = function() {
* @return {!IThenable<!lf.proc.Database>}
*/
lovefield.db.connect = function(opt_options) {
lovefield.db.getSchema();
var db = new lf.proc.Database(lovefield.db.getGlobal());
return db.init(opt_options);
if (!goog.isNull(lovefield.db.db_) && lovefield.db.db_.isOpen()) {
// 113: Attempt to call connect() on an already opened DB connection.
throw new lf.Exception(113);
}

if (goog.isNull(lovefield.db.db_)) {
lovefield.db.getSchema();
lovefield.db.db_ = new lf.proc.Database(lovefield.db.getGlobal());
}

return lovefield.db.db_.init(opt_options);
};


/** @private {?lf.proc.Database} */
lovefield.db.db_ = null;
5 changes: 5 additions & 0 deletions tests/backstore/external_change_observer_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,11 @@ function setUp() {
}


function tearDown() {
db.close();
}


function testExternalChangesApplied() {
asyncTestCase.waitForAsync('testExternalChangesApplied');

Expand Down
5 changes: 5 additions & 0 deletions tests/base/simulate_error_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ function setUp() {
}


function tearDown() {
db.close();
}


/**
* Tests that when simulateErrors has been called BaseBuilder#exec() rejects.
*/
Expand Down
5 changes: 5 additions & 0 deletions tests/pred/combined_predicate_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ function setUp() {
}


function tearDown() {
db.close();
}


/**
* Tests that copy() creates an identical tree where each node is a new
* instance.
Expand Down
5 changes: 5 additions & 0 deletions tests/pred/join_predicate_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,11 @@ function setUp() {
}


function tearDown() {
db.close();
}


function testCopy() {
var original = e.jobId.eq(j.id);
var copy = original.copy();
Expand Down
5 changes: 5 additions & 0 deletions tests/pred/not_operator_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ function setUp() {
}


function tearDown() {
db.close();
}


/**
* Deletes the contents of all tables.
* @return {!IThenable}
Expand Down
5 changes: 5 additions & 0 deletions tests/pred/null_predicate_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ function setUp() {
}


function tearDown() {
db.close();
}


/**
* Deletes the contents of all tables.
* @return {!IThenable}
Expand Down
7 changes: 0 additions & 7 deletions tests/proc/aggregation_step_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ goog.require('lf.pred.JoinPredicate');
goog.require('lf.proc.AggregationStep');
goog.require('lf.proc.NoOpStep');
goog.require('lf.proc.Relation');
goog.require('lf.schema.DataStoreType');
goog.require('lf.testing.NullableDataGenerator');
goog.require('lf.testing.hrSchema.MockDataGenerator');

Expand Down Expand Up @@ -82,13 +81,11 @@ function testFloatEquals(expected, value) {


function setUp() {
asyncTestCase.waitForAsync('setUp');
var schema = hr.db.getSchema();
j = schema.getJob();
e = schema.getEmployee();
dataGenerator = new lf.testing.hrSchema.MockDataGenerator(schema);
dataGenerator.generate(20, 100, 0);
hr.db.connect({storeType: lf.schema.DataStoreType.MEMORY});

// For the tests involving nullable integer columns, a different schema
// is created. The tables in hr schema do not handle nullable integer
Expand All @@ -98,10 +95,6 @@ function setUp() {
nullableGenerator = new
lf.testing.NullableDataGenerator(schemaWithNullable);
nullableGenerator.generate();
schemaBuilder.connect({storeType: lf.schema.DataStoreType.MEMORY}).
then(function() {
asyncTestCase.continueTesting();
});
}


Expand Down
4 changes: 1 addition & 3 deletions tests/proc/end_to_end_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,15 +76,13 @@ function testEndToEnd_StaticSchemaBundled() {
}

asyncTestCase.waitForAsync('testEndToEnd_StaticSchemaBundled');
var dbGlobal;

var dbGlobal = new lf.Global();
var globalFn = function() {
return dbGlobal;
};
var connectFn = function() {
stub.reset();
var dbName = 'hrbdb' + goog.now();
dbGlobal = new lf.Global();
stub.replace(
goog.getObjectByName('hr.bdb.schema.Database.prototype'),
'name',
Expand Down
Loading

0 comments on commit a87e893

Please sign in to comment.