Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Refactors postgres driver to use helpers

Some tweaks were made to acomodate postgres differences from mysql
  • Loading branch information...
commit 6a280c675abf0089fa6f659be7c69d96fe2b6e42 1 parent 0eed10a
@dresende authored
View
33 lib/databases/helpers.js
@@ -60,6 +60,7 @@ module.exports = {
},
buildSqlWhere: function (conditions, escapeCb, opts) {
var _conditions = [], _values = [], prop, op, i;
+ var token_n = 1;
if (!opts) opts = {};
@@ -85,7 +86,7 @@ module.exports = {
if (escapeCb) prop = escapeCb(prop);
if (typeof conditions[k] == "boolean") {
- _conditions.push(prop + op + "?");
+ _conditions.push(prop + op + (opts.tokenCb ? opts.tokenCb(token_n++) : "?"));
if (typeof opts.boolean_convert == "function") {
_values.push(opts.boolean_convert(conditions[k]));
} else {
@@ -95,7 +96,11 @@ module.exports = {
}
if (Array.isArray(conditions[k])) {
if (conditions[k].length > 0) {
- _conditions.push(prop + " " + (op == "!=" ? "NOT " : "") + "IN (" + (new Array(conditions[k].length)).join("?,") + "?)");
+ var tmp = [];
+ for (i = 0; i < conditions[k].length; i++) {
+ tmp.push((opts.tokenCb ? opts.tokenCb(token_n++) : "?"));
+ }
+ _conditions.push(prop + " " + (op == "!=" ? "NOT " : "") + "IN (" + tmp.join(",") + ")");
_values = _values.concat(conditions[k]);
} else {
// ?
@@ -104,11 +109,11 @@ module.exports = {
continue;
}
if (typeof conditions[k] == "object" && conditions[k].hasOwnProperty("__ormFunction")) {
- _conditions.push(conditions[k].__ormFunction.replace(/\#\#/g, "`" + prop + "`") + op + "?");
+ _conditions.push(conditions[k].__ormFunction.replace(/\#\#/g, escapeCb(prop)) + op + (opts.tokenCb ? opts.tokenCb(token_n++) : "?"));
_values.push(conditions[k].v);
continue;
}
- _conditions.push(prop + op + "?");
+ _conditions.push(prop + op + (opts.tokenCb ? opts.tokenCb(token_n++) : "?"));
_values.push(conditions[k]);
}
@@ -121,7 +126,7 @@ module.exports = {
query = query.replace("%values", opts.info.query);
- //console.log(query, opts.info.values);
+ // console.log(query, opts.info.values);
return opts.db.query(query, opts.info.values, this.handleSqlUpdateCall(opts.callback));
},
@@ -132,7 +137,7 @@ module.exports = {
query = query.replace("%fields", Object.keys(opts.data).map(opts.escape).join(", "));
query = query.replace("%values", opts.info.escapes.join(", "));
- //console.log(query, opts.info.values);
+ // console.log(query, opts.info.values);
return opts.db.query(query, opts.info.values, this.handleSqlInsertCall(opts.callback));
},
@@ -155,18 +160,18 @@ module.exports = {
},
escapeUpdateFields: function (data, escapeCb, opts) {
- var val = [], id = [];
+ var val = [], id = [], token_n = 1;
for (var k in data) {
if (!data.hasOwnProperty(k)) continue;
if (typeof data[k] == "boolean") {
- id.push(escapeCb(k) + " = ?");
+ id.push(escapeCb(k) + " = " + (opts.tokenCb ? opts.tokenCb(token_n++) : "?"));
val.push(opts.boolean_convert(data[k]));
continue;
}
if (data[k] === null) {
- id.push(escapeCb(k) + " = ?");
+ id.push(escapeCb(k) + " = " + (opts.tokenCb ? opts.tokenCb(token_n++) : "?"));
val.push(null);
continue;
}
@@ -175,25 +180,25 @@ module.exports = {
val.push(moment.utc(data[k]).unix());
continue;
}
- id.push(escapeCb(k) + " = ?");
+ id.push(escapeCb(k) + " = " + (opts.tokenCb ? opts.tokenCb(token_n++) : "?"));
val.push(data[k]);
}
return { query: id.join(", "), values: val };
},
escapeInsertFields: function (data, opts) {
- var val = [], escapes = [];
+ var val = [], escapes = [], token_n = 1;
for (var k in data) {
if (!data.hasOwnProperty(k)) continue;
if (typeof data[k] == "boolean") {
- escapes.push("?");
+ escapes.push(opts.tokenCb ? opts.tokenCb(token_n++) : "?");
val.push(opts.boolean_convert(data[k]));
continue;
}
if (data[k] === null) {
- escapes.push("?");
+ escapes.push(opts.tokenCb ? opts.tokenCb(token_n++) : "?");
val.push(null);
continue;
}
@@ -202,7 +207,7 @@ module.exports = {
val.push(moment.utc(data[k]).unix());
continue;
}
- escapes.push("?");
+ escapes.push(opts.tokenCb ? opts.tokenCb(token_n++) : "?");
val.push(data[k]);
}
View
24 lib/databases/mysql.js
@@ -222,39 +222,35 @@ DBClient.prototype._insertRecord = function (collection, data, cb) {
return helpers.createSqlInsert({
table: this._collectionToTable(collection),
escape: this._escapeId,
- info: helpers.escapeInsertFields(data, {
- date_convert_fmt: "FROM_UNIXTIME(?)",
- boolean_convert: this._booleanToSqlValue
- }),
+ info: helpers.escapeInsertFields(data, this._helperOpts),
orm: this._orm,
data: data,
db: this._client,
callback: cb
});
};
-DBClient.prototype._updateRecord = function (collection, idProp, data, id, cb) {
+DBClient.prototype._updateRecord = function (collection, propertyId, data, id, cb) {
return helpers.createSqlUpdate({
table: this._collectionToTable(collection),
- key: idProp,
+ key: propertyId,
id: id,
escape: this._escapeId,
- info: helpers.escapeUpdateFields(data, this._escapeId, {
- date_convert_fmt: "FROM_UNIXTIME(?)",
- boolean_convert: this._booleanToSqlValue
- }),
+ info: helpers.escapeUpdateFields(data, this._escapeId, this._helperOpts),
db: this._client,
callback: cb
});
};
DBClient.prototype._addQueryConditions = function (conditions) {
- return helpers.buildSqlWhere(conditions, this._escapeId, {
- additional_operators:"LIKE", "ILIKE" ],
- boolean_convert: this._booleanToSqlValue
- });
+ return helpers.buildSqlWhere(conditions, this._escapeId, this._helperOpts);
};
DBClient.prototype._collectionToTable = function (collection) {
return collection.toLowerCase();
};
+DBClient.prototype._helperOpts = {
+ date_convert_fmt: "FROM_UNIXTIME(?)",
+ additional_operators: [ "LIKE", "ILIKE" ],
+ boolean_convert: this._booleanToSqlValue
+};
DBClient.prototype._booleanToSqlValue = function (value) {
return value ? 1 : 0;
};
View
264 lib/databases/postgresql.js
@@ -1,5 +1,6 @@
-var util = require("util"),
- events = require("events");
+var util = require("util");
+var events = require("events");
+var helpers = require("./helpers");
function DBQuery(query) {
events.EventEmitter.call(this);
@@ -137,24 +138,39 @@ DBClient.prototype.createCollection = function (collection, fields, assocs, opts
});
};
DBClient.prototype.selectRecords = function (collection, config) {
- var _table = collection.toLowerCase(collection),
- _query = "SELECT * FROM \"" + _table + "\"",
- _escapes = [], tmp;
+ var query = "SELECT * FROM ";
+ var query_tables = this._escapeId(this._collectionToTable(collection)) + " t0";
+ var values = [];
+ var tmp;
config = config || {};
- if (config.conditions) {
- tmp = this._addQueryConditions(_query, config.conditions);
- _query = tmp[0];
- _escapes = tmp[1];
+ if (config.rel && config.rel.length) {
+ for (var i = 0; i < config.rel.length; i++) {
+ query_tables = "(" + query_tables + ") JOIN " +
+ this._escapeId(config.rel[i].collection) + " t" + (i + 1) +
+ " ON " + this._escapeId("t" + i + "." + config.rel[i].rel[0]) +
+ " = " + this._escapeId("t" + (i + 1) + "." + config.rel[i].rel[1]);
+ config.conditions["t" + (i + 1) + "." + config.rel[i].rel[2]] = config.rel[i].value;
+ }
}
- if (config.order) _query = this._addQueryOrder(_query, config.order);
- if (config.limit) _query = this._addQueryLimit(_query, config.limit, config.skip);
- // console.log(_query, _escapes);
+ query += query_tables;
+
+ if (config.conditions) {
+ tmp = this._addQueryConditions(config.conditions);
+ query += tmp[0];
+ values = values.concat(tmp[1]);
+ }
+ if (config.order) {
+ query += helpers.buildSqlOrder(config.order, this._escapeId);
+ }
+ if (config.limit) {
+ query += helpers.buildSqlLimit(config.limit, config.skip);
+ }
if (typeof config.callback == "function") {
- this._client.query(_query, _escapes, function (err, info) {
+ this._client.query(query, values, function (err, info) {
if (err) {
config.callback(err);
return;
@@ -163,9 +179,10 @@ DBClient.prototype.selectRecords = function (collection, config) {
config.callback(null, info.rows);
});
} else {
- return new DBQuery(this._client.query(_query, _escapes));
+ return new DBQuery(this._client.query(query, values));
}
};
+// this should not be used for now..
DBClient.prototype.searchRecords = function (collection, config) {
var _table = collection.toLowerCase(collection);
var _query = "SELECT * FROM \"" + _table + "\" WHERE to_tsvector(body) @@ to_tsquery('%text')";
@@ -175,7 +192,9 @@ DBClient.prototype.searchRecords = function (collection, config) {
config.text = config.text.replace(/\Wnot\W/gi, " !");
_query = _query.replace("%text", config.text.replace("'", "''"));
- if (config.limit) _query = this._addQueryLimit(_query, config.limit, config.skip);
+ if (config.limit) {
+ query += helpers.buildSqlLimit(config.limit, config.skip);
+ }
//console.log(_query);
@@ -189,23 +208,25 @@ DBClient.prototype.searchRecords = function (collection, config) {
});
};
DBClient.prototype.clearRecords = function (collection, config, callback) {
- var _table = collection.toLowerCase(collection),
- _query = "DELETE FROM \"" + _table + "\"",
- _escapes = [];
+ var query = "DELETE FROM " + this._escapeId(this._collectionToTable(collection));
+ var tmp;
+ var values = [];
config = config || {};
if (config.conditions) {
- tmp = this._addQueryConditions(_query, config.conditions);
- _query = tmp[0];
- _escapes = tmp[1];
+ tmp = this._addQueryConditions(config.conditions);
+ query += tmp[0];
+ values = values.concat(tmp[1]);
+ }
+ if (config.order) {
+ query += helpers.buildSqlOrder(config.order, this._escapeId);
+ }
+ if (config.limit) {
+ query += helpers.buildSqlLimit(config.limit, config.skip);
}
- if (config.order) _query = this._addQueryOrder(_query, config.order);
- if (config.limit) _query = this._addQueryLimit(_query, config.limit, config.skip);
-
- //console.log(_query, _escapes);
- this._client.query(_query, _escapes, function (err, info) {
+ this._client.query(query, values, function (err, info) {
if (err) {
config.callback(err);
return;
@@ -214,156 +235,75 @@ DBClient.prototype.clearRecords = function (collection, config, callback) {
config.callback(null, info.rows);
});
};
-DBClient.prototype.saveRecord = function (idProp, collection, data, callback) {
- if (data[idProp] && parseInt(data[idProp], 10) > 0) {
- var id = data[idProp];
- delete data[idProp];
+DBClient.prototype.saveRecord = function (propertyId, collection, data, callback) {
+ if (data[propertyId] && parseInt(data[propertyId], 10) > 0) {
+ var id = data[propertyId];
+ delete data[propertyId];
- this._updateRecord(collection, idProp, data, id, callback);
+ this._updateRecord(collection, propertyId, data, id, callback);
} else {
- this._insertRecord(collection, idProp, data, callback);
+ this._insertRecord(collection, propertyId, data, callback);
}
};
-DBClient.prototype._insertRecord = function (collection, idProp, data, callback) {
- var _table = collection.toLowerCase(), self = this;
- var _query = "INSERT INTO \"" + _table + "\" (%fields) VALUES (%values)",
- _fields = [], _values = [], _escapes = [], n = 1;
-
- for (var k in data) {
- if (!data.hasOwnProperty(k)) continue;
-
- _fields.push("\"" + k + "\"");
- _values.push("$" + (n++));
-
- switch (typeof data[k]) {
- case "undefined":
- _values.pop();
- _fields.pop();
- n--;
- break;
- default:
- _escapes.push(data[k]);
- }
- }
-
- _query = _query.replace("%fields", _fields.join(", "));
- _query = _query.replace("%values", _values.join(", "));
-
- //console.log(_query, _escapes);
-
- this._client.query(_query, _escapes, function (err, info) {
- if (err) {
- callback(err);
- return;
- }
-
- self._client.query("SELECT CURRVAL(pg_get_serial_sequence('" + _table + "', '" + idProp + "'))", function (err, info) {
+DBClient.prototype._insertRecord = function (collection, propertyId, data, cb) {
+ var self = this;
+
+ return helpers.createSqlInsert({
+ table: this._collectionToTable(collection),
+ escape: this._escapeId,
+ info: helpers.escapeInsertFields(data, this._helperOpts),
+ orm: this._orm,
+ data: data,
+ db: this._client,
+ callback: function (err, info) {
if (err) {
- callback(err);
- return;
+ return cb(err);
}
- callback(null, info.rows[0].currval);
- });
- });
-};
-DBClient.prototype._updateRecord = function (collection, idProp, data, id, callback) {
- var _table = collection.toLowerCase();
- var _query = "UPDATE \"" + _table + "\" SET %values WHERE \"" + idProp + "\"=" + id,
- _values = [], _escapes = [], n = 1;
-
- for (var k in data) {
- if (!data.hasOwnProperty(k)) continue;
-
- _values.push("\"" + k + "\"=$" + (n++));
+ self._client.query("SELECT CURRVAL(pg_get_serial_sequence('" +
+ self._collectionToTable(collection) + "', '" +
+ propertyId + "'))", function (err, info) {
+ if (err) {
+ return cb(err);
+ }
- switch (typeof data[k]) {
- case "undefined":
- _values.pop();
- n--;
- break;
- default:
- _escapes.push(data[k]);
+ return cb(null, info.rows[0].currval);
+ });
}
- }
-
- _query = _query.replace("%values", _values.join(", "));
- //console.log(_query. _escapes);
-
- this._client.query(_query, _escapes, function (err, info) {
- if (err) {
- callback(err);
- return;
- }
-
- callback(null);
});
};
-DBClient.prototype._addQueryConditions = function (query, conditions, escapes) {
- var _conditions = [], prop, op,
- _escapes = (escapes || []), n = _escapes.length + 1;
-
- for (var k in conditions) {
- if (!conditions.hasOwnProperty(k)) continue;
-
- if (k.indexOf(" ") > 0) {
- op = k.substr(k.indexOf(" ") + 1, k.length).replace(/^\s+/, "");
- prop = k.substr(0, k.indexOf(" "));
-
- if ( ["like", "ilike" ].indexOf(op) >= 0 ) {
- op = " " + op + " ";
- } else if ([ "=", "!", ">", "<", ">=", "<=" ].indexOf(op) == -1) {
- op = "=";
- } else if (op == "!") {
- op = "!=";
- }
- } else {
- prop = k;
- op = "=";
- }
-
- switch (typeof conditions[k]) {
- case "boolean":
- case "number":
- _conditions.push("\"" + prop + "\"" + op + conditions[k]);
- break;
- default:
- if (Array.isArray(conditions[k])) {
- var array_conditions = [];
-
- for (var i = 0; i < conditions[k].length; i++) {
- array_conditions.push("$" + (n++));
- _escapes.push(conditions[k][i]);
- }
- _conditions.push("\"" + prop + "\"" + (op == "!=" ? " NOT" : "") + " IN (" + array_conditions.join(", ") + ")");
- } else if (typeof conditions[k] == "object" && conditions[k].hasOwnProperty("__ormFunction")) {
- _conditions.push(conditions[k].__ormFunction.replace(/\#\#/g, "\"" + prop + "\"") + op + "$" + (n++));
- _values.push(conditions[k].v);
- } else {
- _conditions.push("\"" + prop + "\"" + op + "$" + (n++));
- _escapes.push(conditions[k]);
- }
- }
- }
-
- return [ query + " WHERE " + _conditions.join(" AND "), _escapes ];
-};
-DBClient.prototype._addQueryOrder = function (query, order) {
- if (!order.match(/\s(asc|desc)$/i)) {
- order += " asc";
- }
-
- return query + " ORDER BY " + order.replace(/\w+/g, function (word) {
- if ([ "ASC", "DESC" ].indexOf(word.toUpperCase()) != -1)
- return word.toUpperCase();
- return "\"" + word + "\"";
+DBClient.prototype._updateRecord = function (collection, propertyId, data, id, cb) {
+ return helpers.createSqlUpdate({
+ table: this._collectionToTable(collection),
+ key: propertyId,
+ id: id,
+ escape: this._escapeId,
+ info: helpers.escapeUpdateFields(data, this._escapeId, this._helperOpts),
+ db: this._client,
+ callback: cb
});
};
-DBClient.prototype._addQueryLimit = function (query, limit, skip) {
- if (skip) {
- return query + " LIMIT " + skip + ", " + limit;
+DBClient.prototype._addQueryConditions = function (conditions) {
+ return helpers.buildSqlWhere(conditions, this._escapeId, this._helperOpts);
+};
+DBClient.prototype._collectionToTable = function (collection) {
+ return collection.toLowerCase();
+};
+DBClient.prototype._helperOpts = {
+ additional_operators: [ "LIKE", "ILIKE" ],
+ date_convert_fmt: "TO_TIMESTAMP(?)::timestamp",
+ boolean_convert: this._booleanToSqlValue,
+ tokenCb: function (n) { return '$' + n; }
+};
+DBClient.prototype._booleanToSqlValue = function (value) {
+ return value ? 1 : 0;
+};
+DBClient.prototype._escapeId = function (id) {
+ if (id.indexOf(".") == -1) {
+ return "\"" + id + "\"";
+ } else {
+ return "\"" + id.substr(0, id.indexOf(".")) + "\".\"" + id.substr(id.indexOf(".") + 1) + "\"";
}
- return query + " LIMIT " + limit;
};
DBClient.prototype.end = function () {
this._client.end();
Please sign in to comment.
Something went wrong with that request. Please try again.