Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

now using orlandos async node-sqlite and flow.js

  • Loading branch information...
commit ecac378ab770625a549f07047d2136405fd7e270 1 parent 323d196
@mrjjwright authored
View
14 README.md
@@ -21,18 +21,20 @@ Other goals
How to use
-------------------
-Put `nosqlite.js`, `sql.js` and `uuid.js` in your node.requires path.
+# Put all the NoSQLite files together in one directory in your node.requires.path.
-You will also need an HTML5 compatible sqlite driver. [Node-sql](http://github.com/mrjjwright/node-sqlite) is what I (mrjjwright) use and is the only one tested with NoSQLite at the moment. If you want to use it, download it, compile it for node and put it in the node.requires. path.
+# NoSQLite uses my fork (temporarily) of the new async [node-sqlite](http://github.com/mrjjwright/node-sqlite) and it is the only sqlite driver. tested with NoSQLite at the moment. You will need to download it, run `node-waf configure` and `node-waf build` and copy the `sqlite.js` and `build/default/sqlite3_bindings.node` into the NoSQLite directory.
Add necessary requires to the top of your JS (examples are shown in CoffeeScript):
- sqlite: require("node-sqlite")
- nosql: require("nosqlite")
+ nosqlite: require("nosqlite")
Open up a reference to your database and pass it to NoSQLite
- db: nosqlite.connect(sqlite.openDatabaseSync("my_db.sqlite3"))
+ db: nosqlite.connect("/mypath/my_db.sqlite3", ->
+ #start your work in a callback
+ )
+
Now you are ready to start working with NoSQLite. NoSQLite is motivated by the idea that if we work simply with a one-to-one mapping between a JS object and a SQLite table (no joins), we can get an awful lot for free, and better querying capabilities than other NoSQL stores out there.
@@ -124,5 +126,5 @@ Currently Requires
* [node](http://nodejs.org)
* [CoffeeScript](http://jashkenas.github.com/coffee-script/) - fun, clean way to write JavaScript. Includes Cake to run the Cakefile and tests.
-* [node-sqlite](http://github.com/grumdrig/node-sqlite) or another HTML5 compatible database - I am working on rewriting this to be async and be more HTML 5 compatible. You will have to get it and compile the node bindings and put it in your node require path
+* [node-sqlite](http://github.com/orlandov/node-sqlite) You will have to get it and compile the node bindings and put it in your node requires path.
* [restler](http://github.com/danwrong/restler) - only needed to execute the tests for web API. Not needed otherwise.
View
142 flow.js
@@ -0,0 +1,142 @@
+// Javascript Library for Multi-step Asynchronous Logic
+// Version 0.2
+// Copyright (c) 2010 William R. Conant, WillConant.com
+// Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+
+(function(){
+ // converts native arguments object to an array and applies function
+ function applyArgs(func, thisObj, args) {
+ return func.apply(thisObj, Array.prototype.slice.call(args));
+ }
+
+ // defines a flow given any number of functions as arguments
+ function define() {
+ var thisFlow = function() {
+ applyArgs(thisFlow.exec, thisFlow, arguments);
+ }
+
+ thisFlow.blocks = arguments;
+
+ thisFlow.exec = function() {
+ // The flowState is the actual object each step in the flow is applied to. It acts as a
+ // callback to the next function. It also maintains the internal state of each execution
+ // and acts as a place for users to save values between steps of the flow.
+ var flowState = function() {
+ if (flowState.__frozen) return;
+
+ if (flowState.__timeoutId) {
+ clearTimeout(flowState.__timeoutId);
+ delete flowState.__timeoutId;
+ }
+
+ var blockIdx = flowState.__nextBlockIdx ++;
+ var block = thisFlow.blocks[blockIdx];
+
+ if (block === undefined) {
+ return;
+ }
+ else {
+ applyArgs(block, flowState, arguments);
+ }
+ }
+
+ // __nextBlockIdx specifies which function is the next step in the flow.
+ flowState.__nextBlockIdx = 0;
+
+ // __multiCount is incremented every time MULTI is used to createa a multiplexed callback
+ flowState.__multiCount = 0;
+
+ // __multiOutputs accumulates the arguments of each call to callbacks generated by MULTI
+ flowState.__multiOutputs = [];
+
+ // REWIND signals that the next call to thisFlow should repeat this step. It allows you
+ // to create serial loops.
+ flowState.REWIND = function() {
+ flowState.__nextBlockIdx -= 1;
+ }
+
+ // MULTI can be used to generate callbacks that must ALL be called before the next step
+ // in the flow is executed. Arguments to those callbacks are accumulated, and an array of
+ // of those arguments objects is sent as the one argument to the next step in the flow.
+ flowState.MULTI = function() {
+ flowState.__multiCount += 1;
+ return function() {
+ flowState.__multiCount -= 1;
+ flowState.__multiOutputs.push(arguments);
+
+ if (flowState.__multiCount === 0) {
+ var multiOutputs = flowState.__multiOutputs;
+ flowState.__multiOutputs = [];
+ flowState(multiOutputs);
+ }
+ }
+ }
+
+ // TIMEOUT sets a timeout that freezes a flow and calls the provided callback. This
+ // timeout is cleared if the next flow step happens first.
+ flowState.TIMEOUT = function(milliseconds, timeoutCallback) {
+ if (flowState.__timeoutId !== undefined) {
+ throw new Error("timeout already set for this flow step");
+ }
+
+ flowState.__timeoutId = setTimeout(function() {
+ flowState.__frozen = true;
+ timeoutCallback();
+ }, milliseconds);
+ }
+
+ applyArgs(flowState, this, arguments);
+ }
+
+ return thisFlow;
+ }
+
+ // defines a flow and evaluates it immediately. The first flow function won't receive any arguments.
+ function exec() {
+ applyArgs(exports.define, exports, arguments)();
+ }
+
+ // a very useful flow for serial execution of asynchronous functions over a list of values
+ // (idea suggested by John Wright, http://github.com/mrjjwright)
+ var serialForEach = define(
+ function(items, job, between, finish) {
+ this.items = items;
+ this.curItem = 0;
+ this.job = job;
+ this.between = between;
+ this.finish = finish;
+ this();
+
+ },function() {
+ if (this.curItem > 0 && this.between) {
+ applyArgs(this.between, this, arguments);
+ }
+
+ if (this.curItem >= this.items.length) {
+ this();
+ }
+ else {
+ this.REWIND();
+ this.curItem += 1;
+ this.job(this.items[this.curItem - 1]);
+ }
+
+ },function() {
+ if (this.finish) this.finish();
+ }
+ );
+
+ // export our functions
+ if (exports !== undefined) {
+ exports.define = define;
+ exports.exec = exec;
+ exports.serialForEach = serialForEach;
+ }
+ else if (window !== undefined) {
+ window.flow = {
+ define: define,
+ exec: exec,
+ serialForEach: serialForEach
+ };
+ }
+})();
View
229 nosqlite.coffee
@@ -1,6 +1,9 @@
-require "underscore"
+require "./underscore"
sql: require "./sql"
-uuid: require "./uuid"
+require "./Math.uuid"
+sys: require "sys"
+flow: require "./flow"
+sqlite: require "./sqlite"
# NoSQLite - SQLite for Javascript
# ---------------------------------
@@ -10,21 +13,29 @@ uuid: require "./uuid"
# Attempts to store JS objects as intelligently as possible in SQLite.
class NoSQLite
- # Pass in a valid HTML 5 compatible SQLite object
+ # Pass in a path to a sqlite file
# Pass in an optional Core Data compatible mode flag.
# params:
- # * A HTML 5 compatible JS object.
+ # * path to db.
# * (optional) If set to `true` will create a core data compatible schema.
- constructor: (db, options) ->
+ constructor: (db_file, options, callback) ->
sys.debug("creating instance of NoSQLite")
- @db: db
+ @db: new sqlite.Database()
@table_descriptions: []
@options = {
core_data_mode: false
no_guid: false
}
- @options = _.extend(@options, options) if options?
+
+ if _.isFunction(options)
+ the_callback: options
+ else
+ @options: _.extend(@options, options) if options?
+ the_callback: callback
+ #go ahead and open the db
+ @db.open db_file, ->
+ the_callback()
# Finds an object or objects in the SQLite by running a query
@@ -44,8 +55,8 @@ class NoSQLite
@hash_flag: true
try
- db.query(select.escaped, (select) ->
- callback(null, select)
+ db.query(select.escaped, (res) ->
+ callback(null, res)
)
catch the_err
debug "error on find: " + the_err
@@ -124,8 +135,12 @@ class NoSQLite
- # Stores an object or objects in SQLite even if the table doesn't exist.
- # NoSQLite will create the table for you.
+ # Stores an object or objects in SQLite.
+ # If the table doesn't exist, NoSQLite will create the table for you.
+ #
+ # If the objects already exist in the database NoSQL they will be updated because
+ # NoSQLite issues an "insert or replace"
+ #
# One table is created for the object with the name supplied in param table.
# One column is created for each top-level attribute of the object.
# All columns are stored with SQLite type affinity "TEXT" except
@@ -135,85 +150,94 @@ class NoSQLite
# * Dates are stored as numbers, Unix epochs since 1970
# * Booleans are stored as numbers, 1 for true or 0 for false
# * Other objects (arrays, complex objects) are simply stored as JSON.stringify text
- # You can pass in an array of objects as well. If over a certain limit,
- # NoSQLite will batch the inserts together using a SQLite import command
- # which is really fast.
+ # You can pass in an array of objects as well. Each row will be inserted
#
- # If the objects already exist in the database NoSQL will overwrite them for you with an update
# As always, we'll call you back when everything is ready!
- save: (table, obj, callback) ->
-
+ save: (table, obj, in_transaction, the_callback) ->
+
#augment object with guid unless options say not to
- if @options_no_guid is false
+ if @options.no_guid is false
if not _.isArray(obj)
obj.guid: Math.uuidFast()
else for o in obj
o.guid: Math.uuidFast()
+ tx_flag: false
+ callback: in_transaction
+ if _.isBoolean(in_transaction)
+ tx_flag: in_transaction
+ callback: the_callback
+
+
inserts: []
inserts: sql.insert(table, table_obj, @options.core_data_mode) for table_obj in obj if _.isArray(obj)
inserts.push(sql.insert(table, obj, @options.core_data_mode)) if not _.isArray(obj)
the_obj: if _.isArray(obj) then obj[0] else obj
self: this
db: @db
- array_of_inserts: [inserts[0]]
- first_one: (tx)->
- try
- if tx?
- db.query(inserts[0].escaped)
- if not tx?
- db.transaction(insert_into_db, null, process_rest)
- catch error
- errback(tx, error) if error?
-
- process_rest: (tx) ->
- if inserts.length > 1
- #process the rest
- array_of_inserts: inserts[1..inserts.length]
- db.transaction(insert_into_db, null, (res) ->
- callback(null, "success") if callback?
- )
- else
+ flow.exec(
+ ->
+ # start a transaction if we aren't in one
+ if not tx_flag
+ db.query "begin transaction", this
+ else
+ this()
+ ->
+ # save the first one
+ self_this: this
+ try_first_one: ->
+ db.query inserts[0].escaped, null, (err) ->
+ if err?
+ # This is NoSQLite, let's see if we can fix this!
+ compensating_sql: self.compensating_sql(table, the_obj, err)
+ if compensating_sql?
+ db.query compensating_sql, null, (err) ->
+ if err? then callback(err) if callback?
+ else try_first_one()
+ else
+ callback(err) if callback?
+ else
+ self_this()
+ try_first_one()
+ ->
+ # save the rest
+ self_this: this
+ do_insert: (i) ->
+ db.query inserts[i].escaped, (err) ->
+ if err?
+ callback(err)
+ return
+ if i-- then do_insert(i)
+ else self_this()
+ if inserts.length > 1 then do_insert(inserts.length-1)
+ else this()
+ ->
+ # commit the transaction
+ if not tx_flag
+ db.query "commit", this
+ else
+ this()
+ ->
+ # callback to the user
callback(null, "success") if callback?
+ )
-
- errback: (tx, the_err) ->
- err: if the_err? and the_err.message? then the_err.message else the_err
-
- debug "received error: " + err
- self.parse_error(err)
- compensating_sql: switch self.errobj.code
- when NO_SUCH_TABLE then sql.create_table(table, the_obj, self.options.core_data_mode).sql
- when NO_SUCH_COLUMN then sql.add_column(table, self.errobj.column, null, self.options.core_data_mode).sql
- else null
-
- sys.debug "compensating sql: " + compensating_sql
-
- if compensating_sql?
- db.query(compensating_sql)
- first_one(tx)
- else callback(err) if callback?
- debug "exiting errback"
-
- insert_into_db: (tx) ->
- for insert in array_of_inserts
- try
- tx.executeSql(insert.escaped);
- catch error2
- errback(tx, error2)
-
- # try the first insert first to see if there any errors
- # then the rest
- # this all happens within one sql transaction to make it really fast
- first_one()
-
-
+
+ compensating_sql: (table, the_obj, the_err) ->
+ err: if the_err? and the_err.message? then the_err.message else the_err
+ @parse_error(err)
+ return compensating_sql: switch @errobj.code
+ when NO_SUCH_TABLE then sql.create_table(table, the_obj, @options.core_data_mode).sql
+ when NO_SUCH_COLUMN then sql.add_column(table, @errobj.column, null, @options.core_data_mode).sql
+ else null
+
# closes any underlying SQLite connection
# currently, this means closes the underlying SQLite db process
close: ->
- @db.close()
+ @db.close(->
+ )
# Error Handling
# ------------------------
@@ -234,6 +258,66 @@ class NoSQLite
else
@errobj.code = UNRECOGNIZED_ERROR
+ # Migrations
+ # -------------------------------------
+ # A handy utility for doing a SQLite table schema migration.
+ #
+ # If something goes wrong here at the wrong time,
+ # not that it will, I know you have a backup. :)
+ #
+ # First creates a temporary table and dumps all the rows from the old table.
+ # The old table is then dropped.
+ #
+ # The convert_callback(old_obj) will then be called for the first row in
+ # in the temp table. The object returned by convert_callback
+ # should implicitly describe (using nosqlite conventions, detailed in docs for save)
+ # the new schema that will be used to create the new table.
+ # The first row will be inserted and convert_callback will be called for
+ # for every other row in the temp table.
+ #
+ # Finally, the temp table is deleted and the callback(err, res) function is called.
+ # If any errors occur, callback(err) will be called.
+ #
+ # (Based roughly on the approach detailed in http://www.sqlite.org/faq.html, question 11)
+ migrate_table: (table, convert_callback, callback) ->
+ self: this
+ row1: {}
+ flow.exec(
+ ->
+ #create the temp table
+ self.find table, {rowid: 1}, (err, res) ->
+ row1: res[0]
+ create_temp_table(row1, this)
+ ->
+ this_flow: this
+ #convert and save the first row
+ new_obj: convert_callback(row1)
+ self.save table, new_obj, (err, res) ->
+ if err? then callback(err)
+ this_flow()
+ ->
+ this_flow()
+ #convert the rest of the rows
+ self.find table, {'rowid >': 1}, (err, res) ->
+ for row in res
+ converted_obj: convert_callback(row)
+ self.save table, converted_obj, (err, res) ->
+ if err? then callback(err)
+ this_flow()
+ ->
+ callback(null, "success") if callback?
+ )
+ # create the temp table.
+ # We create it with the same number of cols as the old table
+ # We don't care about the types
+ create_temp_table: (obj, callback)->
+ # execute a pragma to get the number of cols in the old table
+ temp_cols: obj.keys.join(",")
+ temp_table_sql: "create temporary table ${table}_backup(${temp_cols});"
+ # this doesn't execute async (yet)
+ db.query(temp_table_sql)
+ callback()
+
# Web API
# --------------------------------------
@@ -278,7 +362,8 @@ class NoSQLite
when "find"
predicate: JSON.parse(body)
self.find(table, predicate, (err, result) ->
- self.write_res(response, err, result)
+ if result?
+ self.write_res(response, err, result)
)
when "find_or_save"
args: JSON.parse(body)
@@ -303,6 +388,6 @@ String.prototype.trim: ->
return this.replace(/^\s*(\S*(\s+\S+)*)\s*$/, "$1")
# connect to NoSQLite this way.
-exports.connect: (db, options) ->
- return new NoSQLite(db, options)
+exports.connect: (db, options, callback) ->
+ return new NoSQLite(db, options, callback)
View
280 nosqlite.js
@@ -1,31 +1,44 @@
(function(){
- var NO_SUCH_COLUMN, NO_SUCH_TABLE, NoSQLite, S4, UNRECOGNIZED_ERROR, guid, sql, uuid;
- require("underscore");
+ var NO_SUCH_COLUMN, NO_SUCH_TABLE, NoSQLite, UNRECOGNIZED_ERROR, flow, sql, sqlite, sys;
+ require("./underscore");
sql = require("./sql");
- uuid = require("./uuid");
+ require("./Math.uuid");
+ sys = require("sys");
+ flow = require("./flow");
+ sqlite = require("./sqlite");
// NoSQLite - SQLite for Javascript
// ---------------------------------
//
// A library to make it as easy as possible to store and retrieve JS objects
// from SQLite. Zero-configuration!
// Attempts to store JS objects as intelligently as possible in SQLite.
- NoSQLite = function NoSQLite(db, options) {
+ NoSQLite = function NoSQLite(db_file, options, callback) {
+ var the_callback;
sys.debug("creating instance of NoSQLite");
- this.db = db;
+ this.db = new sqlite.Database();
this.table_descriptions = [];
this.options = {
core_data_mode: false,
no_guid: false
};
- if ((typeof options !== "undefined" && options !== null)) {
- this.options = _.extend(this.options, options);
+ if (_.isFunction(options)) {
+ the_callback = options;
+ } else {
+ if ((typeof options !== "undefined" && options !== null)) {
+ this.options = _.extend(this.options, options);
+ }
+ the_callback = callback;
+ //go ahead and open the db
}
+ this.db.open(db_file, function() {
+ return the_callback();
+ });
return this;
};
- // Pass in a valid HTML 5 compatible SQLite object
+ // Pass in a path to a sqlite file
// Pass in an optional Core Data compatible mode flag.
// params:
- // * A HTML 5 compatible JS object.
+ // * path to db.
// * (optional) If set to `true` will create a core data compatible schema.
// Finds an object or objects in the SQLite by running a query
// derived from the supplied predicate on the supplied table.
@@ -44,8 +57,8 @@
predicate = predicate;
this.hash_flag = true;
try {
- return db.query(select.escaped, function(select) {
- return callback(null, select);
+ return db.query(select.escaped, function(res) {
+ return callback(null, res);
});
} catch (the_err) {
debug("error on find: " + the_err);
@@ -125,8 +138,10 @@
}) : callback(null, result);
});
};
- // Stores an object or objects in SQLite even if the table doesn't exist.
- // NoSQLite will create the table for you.
+ // Stores an object or objects in SQLite.
+ // If the table doesn't exist, NoSQLite will create the table for you.
+ // If the objects already exist in the database NoSQL they will be updated because
+ // NoSQLite issues an "insert or replace"
// One table is created for the object with the name supplied in param table.
// One column is created for each top-level attribute of the object.
// All columns are stored with SQLite type affinity "TEXT" except
@@ -136,25 +151,28 @@
// * Dates are stored as numbers, Unix epochs since 1970
// * Booleans are stored as numbers, 1 for true or 0 for false
// * Other objects (arrays, complex objects) are simply stored as JSON.stringify text
- // You can pass in an array of objects as well. If over a certain limit,
- // NoSQLite will batch the inserts together using a SQLite import command
- // which is really fast.
- // If the objects already exist in the database NoSQL will overwrite them for you with an update
+ // You can pass in an array of objects as well. Each row will be inserted
// As always, we'll call you back when everything is ready!
- NoSQLite.prototype.save = function save(table, obj, callback) {
- var _a, _b, _c, _d, _e, _f, _g, array_of_inserts, db, errback, first_one, insert_into_db, inserts, o, process_rest, self, table_obj, the_obj;
+ NoSQLite.prototype.save = function save(table, obj, in_transaction, the_callback) {
+ var _a, _b, _c, _d, _e, _f, _g, callback, db, inserts, o, self, table_obj, the_obj, tx_flag;
//augment object with guid unless options say not to
- if (this.options_no_guid === false) {
+ if (this.options.no_guid === false) {
if (!_.isArray(obj)) {
- obj.guid = guid();
+ obj.guid = Math.uuidFast();
} else {
_a = obj;
for (_b = 0, _c = _a.length; _b < _c; _b++) {
o = _a[_b];
- o.guid = guid();
+ o.guid = Math.uuidFast();
}
}
}
+ tx_flag = false;
+ callback = in_transaction;
+ if (_.isBoolean(in_transaction)) {
+ tx_flag = in_transaction;
+ callback = the_callback;
+ }
inserts = [];
if (_.isArray(obj)) {
inserts = (function() {
@@ -172,77 +190,80 @@
the_obj = _.isArray(obj) ? obj[0] : obj;
self = this;
db = this.db;
- array_of_inserts = [inserts[0]];
- first_one = function first_one(tx) {
- try {
- (typeof tx !== "undefined" && tx !== null) ? db.query(inserts[0].escaped) : null;
- return !(typeof tx !== "undefined" && tx !== null) ? db.transaction(insert_into_db, null, process_rest) : null;
- } catch (error) {
- if ((typeof error !== "undefined" && error !== null)) {
- return errback(tx, error);
- }
- }
- };
- process_rest = function process_rest(tx) {
- if (inserts.length > 1) {
- //process the rest
- array_of_inserts = inserts.slice(1, inserts.length + 1);
- return db.transaction(insert_into_db, null, function(res) {
- if ((typeof callback !== "undefined" && callback !== null)) {
- return callback(null, "success");
+ return flow.exec(function() {
+ // start a transaction if we aren't in one
+ return !tx_flag ? db.query("begin transaction", this) : this();
+ }, function() {
+ var self_this, try_first_one;
+ // save the first one
+ self_this = this;
+ try_first_one = function try_first_one() {
+ return db.query(inserts[0].escaped, null, function(err) {
+ var compensating_sql;
+ if ((typeof err !== "undefined" && err !== null)) {
+ // This is NoSQLite, let's see if we can fix this!
+ compensating_sql = self.compensating_sql(table, the_obj, err);
+ if ((typeof compensating_sql !== "undefined" && compensating_sql !== null)) {
+ return db.query(compensating_sql, null, function(err) {
+ if ((typeof err !== "undefined" && err !== null)) {
+ if ((typeof callback !== "undefined" && callback !== null)) {
+ return callback(err);
+ }
+ } else {
+ return try_first_one();
+ }
+ });
+ } else if ((typeof callback !== "undefined" && callback !== null)) {
+ return callback(err);
+ }
+ } else {
+ return self_this();
+ }
+ });
+ };
+ return try_first_one();
+ }, function() {
+ var do_insert, self_this;
+ // save the rest
+ self_this = this;
+ do_insert = function do_insert(i) {
+ return db.query(inserts[i].escaped, function(err) {
+ if ((typeof err !== "undefined" && err !== null)) {
+ callback(err);
+ return null;
}
+ return i-- ? do_insert(i) : self_this();
});
- } else if ((typeof callback !== "undefined" && callback !== null)) {
+ };
+ return inserts.length > 1 ? do_insert(inserts.length - 1) : this();
+ }, function() {
+ // commit the transaction
+ return !tx_flag ? db.query("commit", this) : this();
+ }, function() {
+ // callback to the user
+ if ((typeof callback !== "undefined" && callback !== null)) {
return callback(null, "success");
}
- };
- errback = function errback(tx, the_err) {
- var _h, _i, compensating_sql, err;
- err = (typeof the_err !== "undefined" && the_err !== null) && (typeof (_h = the_err.message) !== "undefined" && _h !== null) ? the_err.message : the_err;
- debug("received error: " + err);
- self.parse_error(err);
- compensating_sql = (function() {
- if ((_i = self.errobj.code) === NO_SUCH_TABLE) {
- return sql.create_table(table, the_obj, self.options.core_data_mode).sql;
- } else if (_i === NO_SUCH_COLUMN) {
- return sql.add_column(table, self.errobj.column, null, self.options.core_data_mode).sql;
- } else {
- return null;
- }
- }).call(this);
- sys.debug("compensating sql: " + compensating_sql);
- if ((typeof compensating_sql !== "undefined" && compensating_sql !== null)) {
- db.query(compensating_sql);
- first_one(tx);
- } else if ((typeof callback !== "undefined" && callback !== null)) {
- callback(err);
- }
- return debug("exiting errback");
- };
- insert_into_db = function insert_into_db(tx) {
- var _h, _i, _j, _k, insert;
- _h = []; _i = array_of_inserts;
- for (_j = 0, _k = _i.length; _j < _k; _j++) {
- insert = _i[_j];
- _h.push((function() {
- try {
- return tx.executeSql(insert.escaped);
- } catch (error2) {
- return errback(tx, error2);
- }
- }).call(this));
+ });
+ };
+ NoSQLite.prototype.compensating_sql = function compensating_sql(table, the_obj, the_err) {
+ var _a, _b, compensating_sql, err;
+ err = (typeof the_err !== "undefined" && the_err !== null) && (typeof (_a = the_err.message) !== "undefined" && _a !== null) ? the_err.message : the_err;
+ this.parse_error(err);
+ return (compensating_sql = (function() {
+ if ((_b = this.errobj.code) === NO_SUCH_TABLE) {
+ return sql.create_table(table, the_obj, this.options.core_data_mode).sql;
+ } else if (_b === NO_SUCH_COLUMN) {
+ return sql.add_column(table, this.errobj.column, null, this.options.core_data_mode).sql;
+ } else {
+ return null;
}
- return _h;
- };
- // try the first insert first to see if there any errors
- // then the rest
- // this all happens within one sql transaction to make it really fast
- return first_one();
+ }).call(this));
};
// closes any underlying SQLite connection
// currently, this means closes the underlying SQLite db process
NoSQLite.prototype.close = function close() {
- return this.db.close();
+ return this.db.close(function() { });
};
// Error Handling
// ------------------------
@@ -265,6 +286,85 @@
return (this.errobj.code = UNRECOGNIZED_ERROR);
}
};
+ // Migrations
+ // -------------------------------------
+ // A handy utility for doing a SQLite table schema migration.
+ //
+ // If something goes wrong here at the wrong time,
+ // not that it will, I know you have a backup. :)
+ //
+ // First creates a temporary table and dumps all the rows from the old table.
+ // The old table is then dropped.
+ //
+ // The convert_callback(old_obj) will then be called for the first row in
+ // in the temp table. The object returned by convert_callback
+ // should implicitly describe (using nosqlite conventions, detailed in docs for save)
+ // the new schema that will be used to create the new table.
+ // The first row will be inserted and convert_callback will be called for
+ // for every other row in the temp table.
+ //
+ // Finally, the temp table is deleted and the callback(err, res) function is called.
+ // If any errors occur, callback(err) will be called.
+ // (Based roughly on the approach detailed in http://www.sqlite.org/faq.html, question 11)
+ NoSQLite.prototype.migrate_table = function migrate_table(table, convert_callback, callback) {
+ var create_temp_table, row1, self;
+ self = this;
+ row1 = {};
+ flow.exec(function() {
+ //create the temp table
+ return self.find(table, {
+ rowid: 1
+ }, function(err, res) {
+ row1 = res[0];
+ return create_temp_table(row1, this);
+ });
+ }, function() {
+ var new_obj, this_flow;
+ this_flow = this;
+ //convert and save the first row
+ new_obj = convert_callback(row1);
+ return self.save(table, new_obj, function(err, res) {
+ (typeof err !== "undefined" && err !== null) ? callback(err) : null;
+ return this_flow();
+ });
+ }, function() {
+ this_flow();
+ //convert the rest of the rows
+ return self.find(table, {
+ 'rowid >': 1
+ }, function(err, res) {
+ var _a, _b, _c, _d, converted_obj, row;
+ _a = []; _b = res;
+ for (_c = 0, _d = _b.length; _c < _d; _c++) {
+ row = _b[_c];
+ _a.push((function() {
+ converted_obj = convert_callback(row);
+ return self.save(table, converted_obj, function(err, res) {
+ (typeof err !== "undefined" && err !== null) ? callback(err) : null;
+ return this_flow();
+ });
+ }).call(this));
+ }
+ return _a;
+ });
+ }, function() {
+ if ((typeof callback !== "undefined" && callback !== null)) {
+ return callback(null, "success");
+ }
+ });
+ // create the temp table.
+ // We create it with the same number of cols as the old table
+ // We don't care about the types
+ return create_temp_table = function create_temp_table(obj, callback) {
+ var temp_cols, temp_table_sql;
+ // execute a pragma to get the number of cols in the old table
+ temp_cols = obj.keys.join(",");
+ temp_table_sql = "create temporary table " + (table) + "_backup(" + (temp_cols) + ");";
+ // this doesn't execute async (yet)
+ db.query(temp_table_sql);
+ return callback();
+ };
+ };
// Web API
// --------------------------------------
NoSQLite.prototype.write_res = function write_res(response, err, result) {
@@ -325,7 +425,7 @@
} else if (_c === "find") {
predicate = JSON.parse(body);
return self.find(table, predicate, function(err, result) {
- return self.write_res(response, err, result);
+ return (typeof result !== "undefined" && result !== null) ? self.write_res(response, err, result) : null;
});
} else if (_c === "find_or_save") {
args = JSON.parse(body);
@@ -351,13 +451,7 @@
return this.replace(/^\s*(\S*(\s+\S+)*)\s*$/, "$1");
};
// connect to NoSQLite this way.
- exports.connect = function connect(db, options) {
- return new NoSQLite(db, options);
- };
- S4 = function S4() {
- return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
- };
- guid = function guid() {
- return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4());
+ exports.connect = function connect(db, options, callback) {
+ return new NoSQLite(db, options, callback);
};
})();
View
396 test/test_nosqlite.coffee
@@ -1,104 +1,21 @@
-nosqlite: require "./nosqlite"
-sqlite: require "./sqlite"
+nosqlite: require "../nosqlite"
+sqlite: require "../sqlite"
+sys: require "sys"
+fs: require "fs"
+assert: require "assert"
remove_file: (file) ->
try
fs.unlinkSync(file)
catch err
- puts err
+ sys.puts err
test_find: ->
db_file: "./test/test_find.db"
remove_file(db_file)
- db1: nosqlite.connect(sqlite.openDatabaseSync(db_file))
- log: {
- text: "hello",
- occurred_at: new Date().getTime(),
- created_at: new Date().getTime(),
- updated_at: new Date().getTime(),
- source: "string1",
- log_type: "string1",
- geo_lat: "string1",
- geo_long: "string1",
- metric: 5,
- external_id: 10,
- level: 5,
- readable_metric: "5 miles",
- facts: ["hello", "hello", "hello1"],
- original: {id: 1, text: "some crazy object"}
- }
-
- db1.save("log", log, (res) ->
- db1.find("log", {text: "hello"}, (err, result) ->
- ok(result[0].text, "hello", "should find single object")
- #db.close()
- )
- )
-
-test_save_cd: ->
- db_file: "./test/test_save_cd.db"
- remove_file(db_file)
- options: {}
- options.core_data_mode: true
- db: nosqlite.connect(sqlite.openDatabaseSync(db_file), options)
- log: {
- text: "hello",
- occurred_at: new Date().getTime(),
- created_at: new Date().getTime(),
- updated_at: new Date().getTime(),
- source: "string1",
- log_type: "string1",
- geo_lat: "string1",
- geo_long: "string1",
- metric: 5,
- external_id: 10,
- level: 5,
- readable_metric: "5 miles",
- facts: ["hello", "hello", "hello1"],
- original: {id: 1, text: "some crazy object"}
- }
-
- db.save("log", log, (err, res) ->
- puts res
- ok(res, "success", "should save single obj")
- )
-
-
-test_save: ->
- db_file: "./test/test_save.db"
- remove_file(db_file)
-
- db: nosqlite.connect(sqlite.openDatabaseSync(db_file))
- log: {
- text: "hello",
- occurred_at: new Date().getTime(),
- created_at: new Date().getTime(),
- updated_at: new Date().getTime(),
- source: "string1",
- log_type: "string1",
- geo_lat: "string1",
- geo_long: "string1",
- metric: 5,
- external_id: 10,
- level: 5,
- readable_metric: "5 miles",
- facts: ["hello", "hello", "hello1"],
- original: {id: 1, text: "some crazy object"}
- }
-
- db.save("log", log, (err, res) ->
- puts res
- ok(res, "success", "should save single obj")
- )
-
-test_save_multiple: ->
- db_file: "./test/test_save_multiple.db"
- remove_file(db_file)
-
- db: nosqlite.connect(sqlite.openDatabaseSync(db_file))
- logs: [
+ db: nosqlite.connect db_file, ->
log: {
text: "hello",
occurred_at: new Date().getTime(),
@@ -114,7 +31,22 @@ test_save_multiple: ->
readable_metric: "5 miles",
facts: ["hello", "hello", "hello1"],
original: {id: 1, text: "some crazy object"}
- },
+ }
+
+ db.save("log", log, (res) ->
+ db.find("log", {text: "hello"}, (err, result) ->
+ db.close(->
+ assert.ok(result.text, "hello", "should find single object")
+ )
+ )
+ )
+
+test_save_cd: ->
+ db_file: "./test/test_save_cd.db"
+ remove_file(db_file)
+ options: {}
+ options.core_data_mode: true
+ db: nosqlite.connect db_file, ->
log: {
text: "hello",
occurred_at: new Date().getTime(),
@@ -130,7 +62,18 @@ test_save_multiple: ->
readable_metric: "5 miles",
facts: ["hello", "hello", "hello1"],
original: {id: 1, text: "some crazy object"}
- },
+ }
+
+ db.save("log", log, (err, res) ->
+ assert.ok(res, "success", "should save single obj")
+ )
+
+
+test_save: ->
+ db_file: "./test/test_save.db"
+ remove_file(db_file)
+
+ db: nosqlite.connect db_file, ->
log: {
text: "hello",
occurred_at: new Date().getTime(),
@@ -147,54 +90,83 @@ test_save_multiple: ->
facts: ["hello", "hello", "hello1"],
original: {id: 1, text: "some crazy object"}
}
- ]
+
+ db.save("log", log, false, (err, res) ->
+ assert.ok(res, "success", "should save single obj")
+ db.close()
+ )
+
+test_save_multiple: ->
+ db_file: "./test/test_save_multiple.db"
+ remove_file(db_file)
+
+ db: nosqlite.connect db_file, ->
+ logs: [
+ log: {
+ text: "hello",
+ occurred_at: new Date().getTime(),
+ created_at: new Date().getTime(),
+ updated_at: new Date().getTime(),
+ source: "string2",
+ log_type: "string1",
+ geo_lat: "string1",
+ geo_long: "string1",
+ metric: 5,
+ external_id: 10,
+ level: 5,
+ readable_metric: "5 miles",
+ facts: ["hello", "hello", "hello1"],
+ original: {id: 1, text: "some crazy object"}
+ },
+ log: {
+ text: "hello",
+ occurred_at: new Date().getTime(),
+ created_at: new Date().getTime(),
+ updated_at: new Date().getTime(),
+ source: "string1",
+ log_type: "string1",
+ geo_lat: "string1",
+ geo_long: "string1",
+ metric: 5,
+ external_id: 10,
+ level: 5,
+ readable_metric: "5 miles",
+ facts: ["hello", "hello", "hello1"],
+ original: {id: 1, text: "some crazy object"}
+ },
+ log: {
+ text: "hello",
+ occurred_at: new Date().getTime(),
+ created_at: new Date().getTime(),
+ updated_at: new Date().getTime(),
+ source: "string1",
+ log_type: "string1",
+ geo_lat: "string1",
+ geo_long: "string1",
+ metric: 5,
+ external_id: 10,
+ level: 5,
+ readable_metric: "5 miles",
+ facts: ["hello", "hello", "hello1"],
+ original: {id: 1, text: "some crazy object"}
+ }
+ ]
- db.save("log", logs, (err, res) ->
- ok(res, "success", "should save multiple obj")
- db.close()
- )
+ db.save("log", logs, false, (err, res) ->
+ assert.ok(res, "success", "should save multiple obj")
+ db.close()
+ )
test_save_bulk: ->
db_file: "./test/test_save_bulk.db"
remove_file(db_file)
options: {}
- options.add_guid: true
- db: nosqlite.connect(sqlite.openDatabaseSync(db_file), options)
- log: {
- text: "hello",
- occurred_at: new Date().getTime(),
- created_at: new Date().getTime(),
- updated_at: new Date().getTime(),
- source: "string1",
- log_type: "string1",
- geo_lat: "string1",
- geo_long: "string1",
- metric: 5,
- external_id: 10,
- level: 5,
- readable_metric: "5 miles",
- facts: ["hello", "hello", "hello1"],
- original: {id: 1, text: "some crazy object"}
- }
-
- logs: []
- for i in [1..250000]
- logs.push(_.clone(log))
+ options.no_guid: true
- db.save("log", logs, (err, res) ->
- ok(res, "success", "should save 25,000 log messages quickly")
- db.close()
- )
-
-
-test_find_or_save: ->
- db_file: "./test/test_find_or_save.db"
- remove_file(db_file)
-
- db: nosqlite.connect(sqlite.openDatabaseSync(db_file))
- logs: [
+ db: nosqlite.connect db_file, ->
+ nosqlite_db: nosqlite.connect(db,options)
log: {
text: "hello",
occurred_at: new Date().getTime(),
@@ -210,7 +182,90 @@ test_find_or_save: ->
readable_metric: "5 miles",
facts: ["hello", "hello", "hello1"],
original: {id: 1, text: "some crazy object"}
- },
+ }
+
+ logs: []
+ for i in [1..250000]
+ logs.push(_.clone(log))
+
+ db.save("log", logs, false, (err, res) ->
+ assert.ok(res, "success", "should save 250000 log messages quickly")
+ db.close()
+ )
+
+
+test_find_or_save: ->
+ db_file: "./test/test_find_or_save.db"
+ remove_file(db_file)
+
+ db: nosqlite.connect db_file, ->
+ logs: [
+ log: {
+ text: "hello",
+ occurred_at: new Date().getTime(),
+ created_at: new Date().getTime(),
+ updated_at: new Date().getTime(),
+ source: "string1",
+ log_type: "string1",
+ geo_lat: "string1",
+ geo_long: "string1",
+ metric: 5,
+ external_id: 10,
+ level: 5,
+ readable_metric: "5 miles",
+ facts: ["hello", "hello", "hello1"],
+ original: {id: 1, text: "some crazy object"}
+ },
+ log: {
+ text: "hello",
+ occurred_at: new Date().getTime(),
+ created_at: new Date().getTime(),
+ updated_at: new Date().getTime(),
+ source: "string1",
+ log_type: "string1",
+ geo_lat: "string1",
+ geo_long: "string1",
+ metric: 5,
+ external_id: 10,
+ level: 5,
+ readable_metric: "5 miles",
+ facts: ["hello", "hello", "hello1"],
+ original: {id: 1, text: "some crazy object"}
+ },
+ log: {
+ text: "hello2",
+ occurred_at: new Date().getTime(),
+ created_at: new Date().getTime(),
+ updated_at: new Date().getTime(),
+ source: "string1",
+ log_type: "string1",
+ geo_lat: "string1",
+ geo_long: "string1",
+ metric: 5,
+ external_id: 10,
+ level: 5,
+ readable_metric: "5 miles",
+ facts: ["hello", "hello", "hello1"],
+ original: {id: 1, text: "some crazy object"}
+ }
+ ]
+
+ db.find_or_save("log", {text: "hello"}, logs, (err, res) ->
+ assert.ok(res, 2, "should save not find these obj")
+ db.close()
+ )
+
+
+test_save_web: ->
+
+ db_file: "./test/test_save_web.db"
+ remove_file(db_file)
+ rest: require "restler" if not rest?
+
+ #start the listener
+ db: nosqlite.connect db_file, ->
+ server: db.listen(5000)
+
log: {
text: "hello",
occurred_at: new Date().getTime(),
@@ -226,70 +281,23 @@ test_find_or_save: ->
readable_metric: "5 miles",
facts: ["hello", "hello", "hello1"],
original: {id: 1, text: "some crazy object"}
- },
- log: {
- text: "hello2",
- occurred_at: new Date().getTime(),
- created_at: new Date().getTime(),
- updated_at: new Date().getTime(),
- source: "string1",
- log_type: "string1",
- geo_lat: "string1",
- geo_long: "string1",
- metric: 5,
- external_id: 10,
- level: 5,
- readable_metric: "5 miles",
- facts: ["hello", "hello", "hello1"],
- original: {id: 1, text: "some crazy object"}
}
- ]
-
- db.find_or_save("log", {text: "hello"}, logs, (err, res) ->
- ok(res, 2, "should save not find these obj")
- db.close()
- )
-
-
-test_save_web: ->
-
- db_file: "./test/test_save_web.db"
- remove_file(db_file)
- rest: require "restler" if not rest?
-
- #start the listener
- db: nosqlite.connect(sqlite.openDatabaseSync(db_file))
- server: db.listen(5000)
-
- log: {
- text: "hello",
- occurred_at: new Date().getTime(),
- created_at: new Date().getTime(),
- updated_at: new Date().getTime(),
- source: "string1",
- log_type: "string1",
- geo_lat: "string1",
- geo_long: "string1",
- metric: 5,
- external_id: 10,
- level: 5,
- readable_metric: "5 miles",
- facts: ["hello", "hello", "hello1"],
- original: {id: 1, text: "some crazy object"}
- }
- url: "http://localhost:5000?method=save&table=log"
- puts "Invoking ${url}"
- rest.post(url, {data: JSON.stringify(log)}).addListener("complete", (data) ->
- ok(data, "success,", "should save record over http")
- predicate: {text: "hello"}
- find_url: "http://localhost:5000?method=find&table=log"
- data = [predicate, log]
- rest.post(find_url, {data: JSON.stringify(data)}).addListener("complete", (data) ->
- ok(data, JSON.stringify([log]), "should find record over http")
- server.close()
+ url: "http://localhost:5000?method=save&table=log"
+ rest.post(url, {data: JSON.stringify(log)}).addListener("complete", (data) ->
+ assert.ok(data, "success,", "should save record over http")
+ predicate: {text: "hello"}
+ find_url: "http://localhost:5000?method=find&table=log"
+ data = [predicate, log]
+ rest.post(find_url, {data: JSON.stringify(data)}).addListener("complete", (data) ->
+ assert.ok(data, JSON.stringify([log]), "should find record over http")
+ server.close()
+ )
)
- )
-test_save_bulk()
+test_find()
+test_find_or_save()
+test_save()
+test_save_multiple()
+#test_save_web()
View
457 test/test_nosqlite.js
@@ -1,113 +1,24 @@
(function(){
- var nosqlite, remove_file, sqlite, test_find, test_find_or_save, test_save, test_save_bulk, test_save_cd, test_save_multiple, test_save_web;
- nosqlite = require("./nosqlite");
- sqlite = require("./sqlite");
+ var assert, fs, nosqlite, remove_file, sqlite, sys, test_find, test_find_or_save, test_save, test_save_bulk, test_save_cd, test_save_multiple, test_save_web;
+ nosqlite = require("../nosqlite");
+ sqlite = require("../sqlite");
+ sys = require("sys");
+ fs = require("fs");
+ assert = require("assert");
remove_file = function remove_file(file) {
try {
return fs.unlinkSync(file);
} catch (err) {
- return puts(err);
+ return sys.puts(err);
}
};
test_find = function test_find() {
- var db1, db_file, log;
+ var db, db_file;
db_file = "./test/test_find.db";
remove_file(db_file);
- db1 = nosqlite.connect(sqlite.openDatabaseSync(db_file));
- log = {
- text: "hello",
- occurred_at: new Date().getTime(),
- created_at: new Date().getTime(),
- updated_at: new Date().getTime(),
- source: "string1",
- log_type: "string1",
- geo_lat: "string1",
- geo_long: "string1",
- metric: 5,
- external_id: 10,
- level: 5,
- readable_metric: "5 miles",
- facts: ["hello", "hello", "hello1"],
- original: {
- id: 1,
- text: "some crazy object"
- }
- };
- return db1.save("log", log, function(res) {
- return db1.find("log", {
- text: "hello"
- }, function(err, result) {
- return ok(result[0].text, "hello", "should find single object");
- //db.close()
- });
- });
- };
- test_save_cd = function test_save_cd() {
- var db, db_file, log, options;
- db_file = "./test/test_save_cd.db";
- remove_file(db_file);
- options = {};
- options.core_data_mode = true;
- db = nosqlite.connect(sqlite.openDatabaseSync(db_file), options);
- log = {
- text: "hello",
- occurred_at: new Date().getTime(),
- created_at: new Date().getTime(),
- updated_at: new Date().getTime(),
- source: "string1",
- log_type: "string1",
- geo_lat: "string1",
- geo_long: "string1",
- metric: 5,
- external_id: 10,
- level: 5,
- readable_metric: "5 miles",
- facts: ["hello", "hello", "hello1"],
- original: {
- id: 1,
- text: "some crazy object"
- }
- };
- return db.save("log", log, function(err, res) {
- puts(res);
- return ok(res, "success", "should save single obj");
- });
- };
- test_save = function test_save() {
- var db, db_file, log;
- db_file = "./test/test_save.db";
- remove_file(db_file);
- db = nosqlite.connect(sqlite.openDatabaseSync(db_file));
- log = {
- text: "hello",
- occurred_at: new Date().getTime(),
- created_at: new Date().getTime(),
- updated_at: new Date().getTime(),
- source: "string1",
- log_type: "string1",
- geo_lat: "string1",
- geo_long: "string1",
- metric: 5,
- external_id: 10,
- level: 5,
- readable_metric: "5 miles",
- facts: ["hello", "hello", "hello1"],
- original: {
- id: 1,
- text: "some crazy object"
- }
- };
- return db.save("log", log, function(err, res) {
- puts(res);
- return ok(res, "success", "should save single obj");
- });
- };
- test_save_multiple = function test_save_multiple() {
- var db, db_file, log, logs;
- db_file = "./test/test_save_multiple.db";
- remove_file(db_file);
- db = nosqlite.connect(sqlite.openDatabaseSync(db_file));
- logs = [(log = {
+ return db = nosqlite.connect(db_file, function() {
+ var log;
+ log = {
text: "hello",
occurred_at: new Date().getTime(),
created_at: new Date().getTime(),
@@ -125,7 +36,27 @@
id: 1,
text: "some crazy object"
}
- }), (log = {
+ };
+ return db.save("log", log, function(res) {
+ return db.find("log", {
+ text: "hello"
+ }, function(err, result) {
+ return db.close(function() {
+ return assert.ok(result.text, "hello", "should find single object");
+ });
+ });
+ });
+ });
+ };
+ test_save_cd = function test_save_cd() {
+ var db, db_file, options;
+ db_file = "./test/test_save_cd.db";
+ remove_file(db_file);
+ options = {};
+ options.core_data_mode = true;
+ return db = nosqlite.connect(db_file, function() {
+ var log;
+ log = {
text: "hello",
occurred_at: new Date().getTime(),
created_at: new Date().getTime(),
@@ -143,7 +74,19 @@
id: 1,
text: "some crazy object"
}
- }), (log = {
+ };
+ return db.save("log", log, function(err, res) {
+ return assert.ok(res, "success", "should save single obj");
+ });
+ });
+ };
+ test_save = function test_save() {
+ var db, db_file;
+ db_file = "./test/test_save.db";
+ remove_file(db_file);
+ return db = nosqlite.connect(db_file, function() {
+ var log;
+ log = {
text: "hello",
occurred_at: new Date().getTime(),
created_at: new Date().getTime(),
@@ -161,55 +104,91 @@
id: 1,
text: "some crazy object"
}
- })
- ];
- return db.save("log", logs, function(err, res) {
- ok(res, "success", "should save multiple obj");
- return db.close();
+ };
+ return db.save("log", log, false, function(err, res) {
+ assert.ok(res, "success", "should save single obj");
+ return db.close();
+ });
});
};
- test_save_bulk = function test_save_bulk() {
- var _a, _b, _c, _d, db, db_file, i, log, logs, options;
- db_file = "./test/test_save_bulk.db";
+ test_save_multiple = function test_save_multiple() {
+ var db, db_file;
+ db_file = "./test/test_save_multiple.db";
remove_file(db_file);
- options = {};
- options.add_guid = true;
- db = nosqlite.connect(sqlite.openDatabaseSync(db_file), options);
- log = {
- text: "hello",
- occurred_at: new Date().getTime(),
- created_at: new Date().getTime(),
- updated_at: new Date().getTime(),
- source: "string1",
- log_type: "string1",
- geo_lat: "string1",
- geo_long: "string1",
- metric: 5,
- external_id: 10,
- level: 5,
- readable_metric: "5 miles",
- facts: ["hello", "hello", "hello1"],
- original: {
- id: 1,
- text: "some crazy object"
- }
- };
- logs = [];
- _c = 1; _d = 250000;
- for (_b = 0, i = _c; (_c <= _d ? i <= _d : i >= _d); (_c <= _d ? i += 1 : i -= 1), _b++) {
- logs.push(_.clone(log));
- }
- return db.save("log", logs, function(err, res) {
- ok(res, "success", "should save 25,000 log messages quickly");
- return db.close();
+ return db = nosqlite.connect(db_file, function() {
+ var log, logs;
+ logs = [(log = {
+ text: "hello",
+ occurred_at: new Date().getTime(),
+ created_at: new Date().getTime(),
+ updated_at: new Date().getTime(),
+ source: "string2",
+ log_type: "string1",
+ geo_lat: "string1",
+ geo_long: "string1",
+ metric: 5,
+ external_id: 10,
+ level: 5,
+ readable_metric: "5 miles",
+ facts: ["hello", "hello", "hello1"],
+ original: {
+ id: 1,
+ text: "some crazy object"
+ }
+ }), (log = {
+ text: "hello",
+ occurred_at: new Date().getTime(),
+ created_at: new Date().getTime(),
+ updated_at: new Date().getTime(),
+ source: "string1",
+ log_type: "string1",
+ geo_lat: "string1",
+ geo_long: "string1",
+ metric: 5,
+ external_id: 10,
+ level: 5,
+ readable_metric: "5 miles",
+ facts: ["hello", "hello", "hello1"],
+ original: {
+ id: 1,
+ text: "some crazy object"
+ }
+ }), (log = {
+ text: "hello",
+ occurred_at: new Date().getTime(),
+ created_at: new Date().getTime(),
+ updated_at: new Date().getTime(),
+ source: "string1",
+ log_type: "string1",
+ geo_lat: "string1",
+ geo_long: "string1",
+ metric: 5,
+ external_id: 10,
+ level: 5,
+ readable_metric: "5 miles",
+ facts: ["hello", "hello", "hello1"],
+ original: {
+ id: 1,
+ text: "some crazy object"
+ }
+ })
+ ];
+ return db.save("log", logs, false, function(err, res) {
+ assert.ok(res, "success", "should save multiple obj");
+ return db.close();
+ });
});
};
- test_find_or_save = function test_find_or_save() {
- var db, db_file, log, logs;
- db_file = "./test/test_find_or_save.db";
+ test_save_bulk = function test_save_bulk() {
+ var db, db_file, options;
+ db_file = "./test/test_save_bulk.db";
remove_file(db_file);
- db = nosqlite.connect(sqlite.openDatabaseSync(db_file));
- logs = [(log = {
+ options = {};
+ options.no_guid = true;
+ return db = nosqlite.connect(db_file, function() {
+ var _a, _b, _c, _d, i, log, logs, nosqlite_db;
+ nosqlite_db = nosqlite.connect(db, options);
+ log = {
text: "hello",
occurred_at: new Date().getTime(),
created_at: new Date().getTime(),
@@ -227,7 +206,100 @@
id: 1,
text: "some crazy object"
}
- }), (log = {
+ };
+ logs = [];
+ _c = 1; _d = 250000;
+ for (_b = 0, i = _c; (_c <= _d ? i <= _d : i >= _d); (_c <= _d ? i += 1 : i -= 1), _b++) {
+ logs.push(_.clone(log));
+ }
+ return db.save("log", logs, false, function(err, res) {
+ assert.ok(res, "success", "should save 250000 log messages quickly");
+ return db.close();
+ });
+ });
+ };
+ test_find_or_save = function test_find_or_save() {
+ var db, db_file;
+ db_file = "./test/test_find_or_save.db";
+ remove_file(db_file);
+ return db = nosqlite.connect(db_file, function() {
+ var log, logs;
+ logs = [(log = {
+ text: "hello",
+ occurred_at: new Date().getTime(),
+ created_at: new Date().getTime(),
+ updated_at: new Date().getTime(),
+ source: "string1",
+ log_type: "string1",
+ geo_lat: "string1",
+ geo_long: "string1",
+ metric: 5,
+ external_id: 10,
+ level: 5,
+ readable_metric: "5 miles",
+ facts: ["hello", "hello", "hello1"],
+ original: {
+ id: 1,
+ text: "some crazy object"
+ }
+ }), (log = {
+ text: "hello",
+ occurred_at: new Date().getTime(),
+ created_at: new Date().getTime(),
+ updated_at: new Date().getTime(),
+ source: "string1",
+ log_type: "string1",
+ geo_lat: "string1",
+ geo_long: "string1",
+ metric: 5,
+ external_id: 10,
+ level: 5,
+ readable_metric: "5 miles",
+ facts: ["hello", "hello", "hello1"],
+ original: {
+ id: 1,
+ text: "some crazy object"
+ }
+ }), (log = {
+ text: "hello2",
+ occurred_at: new Date().getTime(),
+ created_at: new Date().getTime(),
+ updated_at: new Date().getTime(),
+ source: "string1",
+ log_type: "string1",
+ geo_lat: "string1",
+ geo_long: "string1",
+ metric: 5,
+ external_id: 10,
+ level: 5,
+ readable_metric: "5 miles",
+ facts: ["hello", "hello", "hello1"],
+ original: {
+ id: 1,
+ text: "some crazy object"
+ }
+ })
+ ];
+ return db.find_or_save("log", {
+ text: "hello"
+ }, logs, function(err, res) {
+ assert.ok(res, 2, "should save not find these obj");
+ return db.close();
+ });
+ });
+ };
+ test_save_web = function test_save_web() {
+ var db, db_file, rest;
+ db_file = "./test/test_save_web.db";
+ remove_file(db_file);
+ if (!(typeof rest !== "undefined" && rest !== null)) {
+ rest = require("restler");
+ }
+ //start the listener
+ return db = nosqlite.connect(db_file, function() {
+ var log, server, url;
+ server = db.listen(5000);
+ log = {
text: "hello",
occurred_at: new Date().getTime(),
created_at: new Date().getTime(),
@@ -245,81 +317,30 @@
id: 1,
text: "some crazy object"
}
- }), (log = {
- text: "hello2",
- occurred_at: new Date().getTime(),
- created_at: new Date().getTime(),
- updated_at: new Date().getTime(),
- source: "string1",
- log_type: "string1",
- geo_lat: "string1",
- geo_long: "string1",
- metric: 5,
- external_id: 10,
- level: 5,
- readable_metric: "5 miles",
- facts: ["hello", "hello", "hello1"],
- original: {
- id: 1,
- text: "some crazy object"
- }
- })
- ];
- return db.find_or_save("log", {
- text: "hello"
- }, logs, function(err, res) {
- ok(res, 2, "should save not find these obj");
- return db.close();
- });
- };
- test_save_web = function test_save_web() {
- var db, db_file, log, rest, server, url;
- db_file = "./test/test_save_web.db";
- remove_file(db_file);
- if (!(typeof rest !== "undefined" && rest !== null)) {
- rest = require("restler");
- }
- //start the listener
- db = nosqlite.connect(sqlite.openDatabaseSync(db_file));
- server = db.listen(5000);
- log = {
- text: "hello",
- occurred_at: new Date().getTime(),
- created_at: new Date().getTime(),
- updated_at: new Date().getTime(),
- source: "string1",
- log_type: "string1",
- geo_lat: "string1",
- geo_long: "string1",
- metric: 5,
- external_id: 10,
- level: 5,
- readable_metric: "5 miles",
- facts: ["hello", "hello", "hello1"],
- original: {
- id: 1,
- text: "some crazy object"
- }
- };
- url = "http://localhost:5000?method=save&table=log";
- puts("Invoking " + (url));
- return rest.post(url, {
- data: JSON.stringify(log)
- }).addListener("complete", function(data) {
- var find_url, predicate;
- ok(data, "success,", "should save record over http");
- predicate = {
- text: "hello"
};
- find_url = "http://localhost:5000?method=find&table=log";
- data = [predicate, log];
- return rest.post(find_url, {
- data: JSON.stringify(data)
+ url = "http://localhost:5000?method=save&table=log";
+ return rest.post(url, {
+ data: JSON.stringify(log)
}).addListener("complete", function(data) {
- ok(data, JSON.stringify([log]), "should find record over http");
- return server.close();
+ var find_url, predicate;
+ assert.ok(data, "success,", "should save record over http");
+ predicate = {
+ text: "hello"
+ };
+ find_url = "http://localhost:5000?method=find&table=log";
+ data = [predicate, log];
+ return rest.post(find_url, {
+ data: JSON.stringify(data)
+ }).addListener("complete", function(data) {
+ assert.ok(data, JSON.stringify([log]), "should find record over http");
+ return server.close();
+ });
});
});
};
- test_save_bulk();
+ test_find();
+ test_find_or_save();
+ test_save();
+ test_save_multiple();
+ //test_save_web()
})();
Please sign in to comment.
Something went wrong with that request. Please try again.