Comparing version 2.0.6 to 2.0.7
116
index.js
var Runner = require("./lib/runner"); | ||
var _ = require("underscore")._; | ||
var fs = require("fs"); | ||
var Queryable = require("./lib/queryable"); | ||
var Table = require("./lib/table"); | ||
@@ -22,2 +23,3 @@ var util = require("util"); | ||
this.tables = []; | ||
this.views = []; | ||
this.queryFiles = []; | ||
@@ -37,4 +39,4 @@ this.schemas = []; | ||
this.excludeFunctions = args.excludeFunctions; | ||
this.functionBlacklist = this.getTableFilter(args.functionBlacklist) | ||
} | ||
this.functionBlacklist = this.getTableFilter(args.functionBlacklist); | ||
}; | ||
@@ -86,3 +88,3 @@ Massive.prototype.getSchemaFilter = function(allowedSchemas) { | ||
this.query(args); | ||
} | ||
}; | ||
Massive.prototype.runSync = DA(Massive.prototype.run); | ||
@@ -94,4 +96,3 @@ | ||
Massive.prototype.loadTables = function(next){ | ||
Massive.prototype.loadTables = function(next) { | ||
var tableSql = __dirname + "/lib/scripts/tables.sql"; | ||
@@ -104,23 +105,45 @@ var parameters = [this.allowedSchemas, this.blacklist, this.exceptions]; | ||
tableSql = __dirname + "/lib/scripts/whitelist.sql"; | ||
var parameters = [this.whitelist] | ||
parameters = [this.whitelist]; | ||
} | ||
this.executeSqlFile({file : tableSql, params: parameters}, function(err,tables){ | ||
if(err){ | ||
next(err,null); | ||
}else{ | ||
_.each(tables, function(table){ | ||
var _table = new Table({ | ||
schema : table.schema, | ||
name : table.name, | ||
pk : table.pk, | ||
db : self | ||
}); | ||
// This refactoring appears to work well: | ||
MapTableToNamespace(_table); | ||
this.executeSqlFile({file : tableSql, params: parameters}, function(err,tables) { | ||
if (err) { return next(err, null); } | ||
_.each(tables, function(table){ | ||
var _table = new Table({ | ||
schema : table.schema, | ||
name : table.name, | ||
pk : table.pk, | ||
db : self | ||
}); | ||
next(null,self); | ||
} | ||
MapToNamespace(_table); | ||
}); | ||
next(null,self); | ||
}); | ||
} | ||
}; | ||
Massive.prototype.loadViews = function(next) { | ||
var viewSql = __dirname + "/lib/scripts/views.sql"; | ||
var parameters = [this.allowedSchemas, this.blacklist, this.exceptions]; | ||
var self = this; | ||
this.executeSqlFile({file : viewSql, params: parameters}, function(err, views){ | ||
if (err) { return next(err, null); } | ||
_.each(views, function(view) { | ||
var _view = new Queryable({ | ||
schema : view.schema, | ||
name : view.name, | ||
db : self | ||
}); | ||
MapToNamespace(_view, "views"); | ||
}); | ||
next(null, self); | ||
}); | ||
}; | ||
Massive.prototype.saveDoc = function(collection, doc, next){ | ||
@@ -157,2 +180,3 @@ var self = this; | ||
var sql = this.documentTableSql(collection); | ||
this.query(sql, function(err,res){ | ||
@@ -162,3 +186,3 @@ if(err){ | ||
} else { | ||
MapTableToNamespace(_table); | ||
MapToNamespace(_table); | ||
// recurse | ||
@@ -172,6 +196,9 @@ self.saveDoc(collection,doc,next); | ||
var MapTableToNamespace = function(table) { | ||
var db = table.db; | ||
if(table.schema !== "public") { | ||
schemaName = table.schema; | ||
var MapToNamespace = function(queryable, collection) { | ||
collection = collection || "tables"; | ||
var db = queryable.db; | ||
if (queryable.schema !== "public") { | ||
schemaName = queryable.schema; | ||
// is this schema already attached? | ||
@@ -182,10 +209,10 @@ if(!db[schemaName]) { | ||
} | ||
// attach the table to the schema: | ||
db[schemaName][table.name] = table; | ||
db.tables.push(table); | ||
// attach the queryable to the schema: | ||
db[schemaName][queryable.name] = queryable; | ||
} else { | ||
//it's public - just pin table to the root to namespace | ||
db[table.name] = table; | ||
db.tables.push(table); | ||
db[queryable.name] = queryable; | ||
} | ||
db[collection].push(queryable); | ||
}; | ||
@@ -198,3 +225,3 @@ | ||
var indexName = tableName.replace(".", "_"); | ||
sql = util.format(sql, tableName, indexName, tableName); | ||
sql = util.format(sql, tableName, indexName, tableName, indexName, tableName); | ||
return sql; | ||
@@ -274,3 +301,3 @@ }; | ||
var newFn, pushOnTo | ||
var newFn, pushOnTo; | ||
if(schema !== "public"){ | ||
@@ -344,15 +371,22 @@ self[schema] || (self[schema] = {}); | ||
//override if there's a db name passed in | ||
if(args.db){ | ||
if (args.db) { | ||
args.connectionString = "postgres://localhost/"+args.db; | ||
} | ||
var massive = new Massive(args); | ||
var massive = new Massive(args); | ||
//load up the tables, queries, and commands | ||
massive.loadTables(function(err,db){ | ||
massive.loadTables(function(err, db) { | ||
assert(!err, err); | ||
self = db; | ||
massive.loadFunctions(function(err,db){ | ||
massive.loadViews(function(err, db) { | ||
assert(!err, err); | ||
//synchronous | ||
db.loadQueries(); | ||
next(null,db); | ||
massive.loadFunctions(function(err, db) { | ||
assert(!err, err); | ||
//synchronous | ||
db.loadQueries(); | ||
next(null,db); | ||
}); | ||
}); | ||
@@ -359,0 +393,0 @@ }); |
@@ -17,4 +17,5 @@ var pg = require("pg"); | ||
var args = ArgTypes.queryArgs(arguments); | ||
var e = new Error(); // initialize error object before we do any async stuff to get a useful stacktrace | ||
//check to see if the params are an array, which they need to be | ||
//check to see if the params are an array, which they need to be | ||
//for the pg module | ||
@@ -39,3 +40,3 @@ if(_.isObject(args.params)){ | ||
if(err){ | ||
if (err) { | ||
//DO NOT THROW if there's a query error | ||
@@ -45,16 +46,16 @@ //bubble it up | ||
//wish I could find a way to deal with this | ||
if(err.toString().indexOf("there is no parameter") > -1){ | ||
err = "You need to wrap your parameter into an array"; | ||
if (err.toString().indexOf("there is no parameter") > -1) { | ||
e.message = "You need to wrap your parameter into an array"; | ||
} else { | ||
e.message = err.message || err.toString(); | ||
} | ||
args.next(err,null); | ||
}else{ | ||
args.next(e, null); | ||
} else { | ||
//only return one result if single is sent in | ||
if(args.options.single){ | ||
var singleRow = result.rows.length >= 0 ? result.rows[0] : null; | ||
args.next(null,singleRow); | ||
}else{ | ||
//got some records, adios | ||
args.next(err, result.rows); | ||
if (args.options.single) { | ||
result.rows = result.rows.length >= 0 ? result.rows[0] : null; | ||
} | ||
args.next(null, result.rows); | ||
} | ||
@@ -69,3 +70,3 @@ }); | ||
//check to see if the params are an array, which they need to be | ||
//check to see if the params are an array, which they need to be | ||
//for the pg module | ||
@@ -103,5 +104,8 @@ if(_.isObject(args.params)){ | ||
// close connections immediately | ||
DB.prototype.end = function(){ | ||
pg.end(); | ||
}; | ||
module.exports = DB; |
133
lib/table.js
@@ -6,2 +6,3 @@ var _ = require("underscore")._; | ||
var DocumentTable = require("./document_table"); | ||
var Queryable = require("./queryable"); | ||
var Where = require("./where"); | ||
@@ -12,136 +13,12 @@ var ArgTypes = require("./arg_types"); | ||
//a simple wrapper for a table | ||
var Table = function(args){ | ||
this.schema = args.schema; | ||
this.name = args.name; | ||
var Table = function(args) { | ||
Queryable.apply(this, arguments); | ||
this.pk = args.pk; | ||
this.db = args.db; | ||
// Build a fully qualified name if the schema is other than public: | ||
this.fullname = this.name; | ||
if(this.schema !== "public") { | ||
this.fullname = this.schema + "." + this.name; | ||
} | ||
// build delimited names in one spot instead of when building sql: | ||
this.delimitedName = "\"" + this.name + "\""; | ||
this.delimitedSchema = "\"" + this.schema + "\""; | ||
this.delimitedFullName = this.delimitedName; | ||
// if the schema is other than public blah blah... | ||
if(this.schema !== "public") { | ||
this.delimitedFullName = this.delimitedSchema + "." + this.delimitedName; | ||
} | ||
_.extend(this,DocumentTable); | ||
}; | ||
//a simple alias for returning a single record | ||
Table.prototype.findOne = function(args, next){ | ||
if(_.isFunction(args)){ | ||
next = args; | ||
args = {}; | ||
} | ||
util.inherits(Table, Queryable); | ||
this.find(args, function(err,results){ | ||
if(err){ | ||
next(err,null); | ||
}else{ | ||
var result; | ||
if (_.isArray(results)) { | ||
if (results.length > 0) { result = results[0]; } | ||
} else { | ||
result = results; | ||
} | ||
next(null,result); | ||
} | ||
}); | ||
}; | ||
Table.prototype.findOneSync = DA(Table.prototype.findOne); | ||
/** | ||
* Counts rows and calls back with any error and the total. There are two ways to use this method: | ||
* | ||
* 1. find() style: db.mytable.count({field: value}, callback); | ||
* 2. where() style: db.mytable.count("field=$1", [value], callback); | ||
*/ | ||
Table.prototype.count = function() { | ||
var args; | ||
var where; | ||
if (_.isObject(arguments[0])) { | ||
args = ArgTypes.findArgs(arguments); | ||
where = _.isEmpty(args.conditions) ? {where : " "} : Where.forTable(args.conditions); | ||
} else { | ||
args = ArgTypes.whereArgs(arguments); | ||
where = {where: " where " + args.where}; | ||
} | ||
var sql = "select COUNT(1) from " + this.delimitedFullName + where.where; | ||
this.db.query(sql, where.params || args.params, {single : true}, function(err, res) { | ||
if (err) args.next(err, null); | ||
else args.next(null, res.count); | ||
}); | ||
}; | ||
Table.prototype.countSync = DA(Table.prototype.count); | ||
//a simple way to just run something | ||
//just pass in "id=$1" and the criteria | ||
Table.prototype.where = function(){ | ||
var args = ArgTypes.whereArgs(arguments); | ||
var sql = "select * from " + this.delimitedFullName + " where " + args.where; | ||
this.db.query(sql, args.params, args.next); | ||
}; | ||
Table.prototype.whereSync = DA(Table.prototype.where); | ||
Table.prototype.find = function(){ | ||
var args = ArgTypes.findArgs(arguments); | ||
//set default options | ||
args.options.order || (args.options.order = util.format('"%s"', this.pk)); | ||
args.options.limit || (args.options.limit = "1000"); | ||
args.options.offset || (args.options.offset = "0"); | ||
args.options.columns || (args.options.columns = "*"); | ||
if(_.isFunction(args.conditions)){ | ||
//this is our callback as the only argument, caught by Args.ANY | ||
args.next = args.conditions; | ||
} | ||
var returnSingle = false; | ||
var where, order, limit, cols="*", offset; | ||
if(args.options.columns){ | ||
if(_.isArray(args.options.columns)){ | ||
cols = args.options.columns.join(','); | ||
}else{ | ||
cols = args.options.columns; | ||
} | ||
} | ||
order = " order by " + args.options.order; | ||
limit = " limit " + args.options.limit; | ||
offset = " offset " + args.options.offset; | ||
if(_.isNumber(args.conditions)){ | ||
//a primary key search | ||
var newArgs = {}; | ||
newArgs[this.primaryKeyName()] = args.conditions; | ||
args.conditions = newArgs; | ||
returnSingle = true; | ||
} | ||
where = _.isEmpty(args.conditions) ? {where : " "} : Where.forTable(args.conditions); | ||
var sql = "select " + cols + " from " + this.delimitedFullName + where.where + order + limit + offset; | ||
if (args.options.stream) { | ||
this.db.stream(sql, where.params, null, args.next); | ||
} else { | ||
this.db.query(sql, where.params, {single : returnSingle}, args.next); | ||
} | ||
}; | ||
Table.prototype.findSync = DA(Table.prototype.find); | ||
Table.prototype.insert = function(data, next) { | ||
@@ -148,0 +25,0 @@ if(!data) throw "insert should be called with data"; |
{ | ||
"name": "massive", | ||
"version": "2.0.6", | ||
"version": "2.0.7", | ||
"description": "A small query tool for Postgres that embraces json and makes life simpler", | ||
@@ -33,3 +33,3 @@ "main": "index.js", | ||
"commander": "^2.6.0", | ||
"deasync": "^0.0.10", | ||
"deasync": "^0.1.1", | ||
"glob": "^4.4.1", | ||
@@ -36,0 +36,0 @@ "pg": "^4.3.0", |
Sorry, the diff of this file is not supported yet
83490
32
1141
+ Addedbindings@1.5.0(transitive)
+ Addeddeasync@0.1.30(transitive)
+ Addedfile-uri-to-path@1.0.0(transitive)
+ Addednode-addon-api@1.7.2(transitive)
- Removedbindings@1.1.1(transitive)
- Removeddeasync@0.0.10(transitive)
- Removednan@1.9.0(transitive)
Updateddeasync@^0.1.1