Skip to content

Commit

Permalink
Merge pull request #306 from dresende/escaping
Browse files Browse the repository at this point in the history
Enable auto-escaping raw queries
  • Loading branch information
dxg committed Aug 22, 2013
2 parents 2f85e30 + 6f2889e commit 2a5abb8
Show file tree
Hide file tree
Showing 7 changed files with 132 additions and 29 deletions.
17 changes: 16 additions & 1 deletion Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -476,9 +476,24 @@ a few examples to describe it:

#### Raw queries

Note: This may change in future.
```js
db.driver.execQuery("SELECT id, email FROM user", function (err, data) { ... })

// You can escape identifiers and values.
// For identifier substitution use: ??
// For value substitution use: ?
db.driver.execQuery(
"SELECT user.??, user.?? FROM user WHERE user.?? LIKE ? AND user.?? > ?",
['id', 'name', 'name', 'john', 'id', 55],
function (err, data) { ... }
)

// Identifiers don't need to be scaped most of the time
db.driver.execQuery(
"SELECT user.id, user.name FROM user WHERE user.name LIKE ? AND user.id > ?",
['john', 55],
function (err, data) { ... }
)
```

### Caching & Integrity
Expand Down
22 changes: 13 additions & 9 deletions lib/Drivers/DML/mysql.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
var mysql = require("mysql");
var Query = require("sql-query").Query;
var _ = require("lodash");
var mysql = require("mysql");
var Query = require("sql-query").Query;
var helpers = require("../helpers");

exports.Driver = Driver;

Expand All @@ -24,6 +26,8 @@ function Driver(config, connection, opts) {
"DISTINCT"];
}

_.extend(Driver.prototype, helpers.sql);

Driver.prototype.sync = function (opts, cb) {
return require("../DDL/mysql").sync(this, opts, cb);
};
Expand Down Expand Up @@ -79,7 +83,7 @@ Driver.prototype.getQuery = function () {
return this.query;
};

Driver.prototype.execQuery = function (query, cb) {
Driver.prototype.execSimpleQuery = function (query, cb) {
if (this.opts.debug) {
require("../../Debug").sql('mysql', query);
}
Expand Down Expand Up @@ -128,7 +132,7 @@ Driver.prototype.find = function (fields, table, conditions, opts, cb) {

q = q.build();

this.execQuery(q, cb);
this.execSimpleQuery(q, cb);
};

Driver.prototype.count = function (table, conditions, opts, cb) {
Expand All @@ -155,7 +159,7 @@ Driver.prototype.count = function (table, conditions, opts, cb) {

q = q.build();

this.execQuery(q, cb);
this.execSimpleQuery(q, cb);
};

Driver.prototype.insert = function (table, data, id_prop, cb) {
Expand All @@ -164,7 +168,7 @@ Driver.prototype.insert = function (table, data, id_prop, cb) {
.set(data)
.build();

this.execQuery(q, function (err, info) {
this.execSimpleQuery(q, function (err, info) {
if (err) return cb(err);

var ids = {};
Expand All @@ -189,7 +193,7 @@ Driver.prototype.update = function (table, changes, conditions, cb) {
.where(conditions)
.build();

this.execQuery(q, cb);
this.execSimpleQuery(q, cb);
};

Driver.prototype.remove = function (table, conditions, cb) {
Expand All @@ -198,13 +202,13 @@ Driver.prototype.remove = function (table, conditions, cb) {
.where(conditions)
.build();

this.execQuery(q, cb);
this.execSimpleQuery(q, cb);
};

Driver.prototype.clear = function (table, cb) {
var q = "TRUNCATE TABLE " + this.query.escapeId(table);

this.execQuery(q, cb);
this.execSimpleQuery(q, cb);
};

Driver.prototype.poolQuery = function (query, cb) {
Expand Down
30 changes: 16 additions & 14 deletions lib/Drivers/DML/postgres.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
var pg = require("pg");
var Query = require("sql-query").Query;
var _ = require("lodash");
var pg = require("pg");
var Query = require("sql-query").Query;
var helpers = require("../helpers");

exports.Driver = Driver;

Expand Down Expand Up @@ -27,9 +29,7 @@ function Driver(config, connection, opts) {
}
}

for (var name in functions) {
this.constructor.prototype[name] = functions[name];
}
_.extend(this.constructor.prototype, functions);

this.aggregate_functions = [ "ABS", "CEIL", "FLOOR", "ROUND",
"AVG", "MIN", "MAX",
Expand All @@ -48,7 +48,7 @@ var switchableFunctions = {
cb(err);
});
},
execQuery: function (query, cb) {
execSimpleQuery: function (query, cb) {
if (this.opts.debug) {
require("../../Debug").sql('postgres', query);
}
Expand Down Expand Up @@ -77,7 +77,7 @@ var switchableFunctions = {
connect: function (cb) {
this.db.connect(cb);
},
execQuery: function (query, cb) {
execSimpleQuery: function (query, cb) {
if (this.opts.debug) {
require("../../Debug").sql('postgres', query);
}
Expand All @@ -99,6 +99,8 @@ var switchableFunctions = {
}
};

_.extend(Driver.prototype, helpers.sql);

Driver.prototype.sync = function (opts, cb) {
return require("../DDL/postgres").sync(this, opts, cb);
};
Expand All @@ -108,7 +110,7 @@ Driver.prototype.drop = function (opts, cb) {
};

Driver.prototype.ping = function (cb) {
this.execQuery("SELECT * FROM pg_stat_activity LIMIT 1", function () {
this.execSimpleQuery("SELECT * FROM pg_stat_activity LIMIT 1", function () {
return cb();
});
return this;
Expand Down Expand Up @@ -157,7 +159,7 @@ Driver.prototype.find = function (fields, table, conditions, opts, cb) {

q = q.build();

this.execQuery(q, cb);
this.execSimpleQuery(q, cb);
};

Driver.prototype.count = function (table, conditions, opts, cb) {
Expand All @@ -184,7 +186,7 @@ Driver.prototype.count = function (table, conditions, opts, cb) {

q = q.build();

this.execQuery(q, cb);
this.execSimpleQuery(q, cb);
};

Driver.prototype.insert = function (table, data, id_prop, cb) {
Expand All @@ -193,7 +195,7 @@ Driver.prototype.insert = function (table, data, id_prop, cb) {
.set(data)
.build();

this.execQuery(q + " RETURNING *", function (err, results) {
this.execSimpleQuery(q + " RETURNING *", function (err, results) {
if (err) {
return cb(err);
}
Expand All @@ -217,7 +219,7 @@ Driver.prototype.update = function (table, changes, conditions, cb) {
.where(conditions)
.build();

this.execQuery(q, cb);
this.execSimpleQuery(q, cb);
};

Driver.prototype.remove = function (table, conditions, cb) {
Expand All @@ -226,13 +228,13 @@ Driver.prototype.remove = function (table, conditions, cb) {
.where(conditions)
.build();

this.execQuery(q, cb);
this.execSimpleQuery(q, cb);
};

Driver.prototype.clear = function (table, cb) {
var q = "TRUNCATE TABLE " + this.query.escapeId(table);

this.execQuery(q, cb);
this.execSimpleQuery(q, cb);
};

Driver.prototype.valueToProperty = function (value, property) {
Expand Down
6 changes: 5 additions & 1 deletion lib/Drivers/DML/sqlite.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
var _ = require("lodash");
var sqlite3 = require("sqlite3");
var Query = require("sql-query").Query;
var helpers = require("../helpers");

exports.Driver = Driver;

Expand Down Expand Up @@ -28,6 +30,8 @@ function Driver(config, connection, opts) {
"DISTINCT" ];
}

_.extend(Driver.prototype, helpers.sql);

Driver.prototype.sync = function (opts, cb) {
return require("../DDL/sqlite").sync(this, opts, cb);
};
Expand Down Expand Up @@ -61,7 +65,7 @@ Driver.prototype.getQuery = function () {
return this.query;
};

Driver.prototype.execQuery = function (query, cb) {
Driver.prototype.execSimpleQuery = function (query, cb) {
if (this.opts.debug) {
require("../../Debug").sql('mysql', query);
}
Expand Down
13 changes: 13 additions & 0 deletions lib/Drivers/helpers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@

module.exports.sql = {
execQuery: function () {
if (arguments.length == 2) {
var query = arguments[0];
var cb = arguments[1];
} else if (arguments.length == 3) {
var query = this.query.escape(arguments[0], arguments[1]);
var cb = arguments[2];
}
return this.execSimpleQuery(query, cb);
}
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
"analyse" : false,
"dependencies": {
"enforce" : "0.1.2",
"sql-query" : "0.1.10",
"sql-query" : "0.1.11",
"hat" : "0.0.3",
"lodash" : "1.3.1"
},
Expand Down
71 changes: 68 additions & 3 deletions test/integration/db.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
var should = require('should');
var helper = require('../support/spec_helper');
var ORM = require('../../');
var should = require('should');
var helper = require('../support/spec_helper');
var ORM = require('../../');
var common = require('../common');

describe("db.use()", function () {
var db = null;
Expand Down Expand Up @@ -176,3 +177,67 @@ describe("db.serial()", function () {
});
});
});

describe("db.driver", function () {
var db = null;

before(function (done) {
helper.connect(function (connection) {
db = connection;

var Log = db.define('log', {
what : { type: 'text' },
when : { type: 'date', time: true },
who : { type: 'text' }
});

helper.dropSync(Log, function (err) {
if (err) return done(err);

Log.create([
{ what: "password reset", when: new Date('2013/04/07 12:33:05'), who: "jane" },
{ what: "user login", when: new Date('2013/04/07 13:01:44'), who: "jane" },
{ what: "user logout", when: new Date('2013/05/12 04:09:31'), who: "john" }
], done);
});
});
});

after(function () {
return db.close();
});

it("should be available", function () {
should.exist(db.driver);
});

if (common.protocol() == "mongodb") return;

describe("query", function () {
it("should be available", function () {
should.exist(db.driver.query);
});

describe("#execQuery", function () {
it("should execute sql queries", function (done) {
db.driver.execQuery("SELECT id FROM log", function (err, data) {
should.not.exist(err);

should(JSON.stringify(data) == JSON.stringify([{ id: 1 }, { id: 2 }, { id: 3 }]));
done();
});
});

it("should escape sql queries", function (done) {
var query = "SELECT log.?? FROM log WHERE log.?? LIKE ? AND log.?? > ?";
var args = ['what', 'who', 'jane', 'when', new Date('2013/04/07 12:40:00')];
db.driver.execQuery(query, args, function (err, data) {
should.not.exist(err);

should(JSON.stringify(data) == JSON.stringify([{ "what": "user login" }]));
done();
});
});
});
});
});

0 comments on commit 2a5abb8

Please sign in to comment.