不要怂,就是干,撸起袖子干!

Commit 5dfd4c86 by Sascha Depold

first preps for prefetching associated objects

1 parent 1cd32292
...@@ -102,6 +102,8 @@ module.exports = (function() { ...@@ -102,6 +102,8 @@ module.exports = (function() {
} }
DAOFactory.prototype.find = function(options) { DAOFactory.prototype.find = function(options) {
// no options defined?
// return an emitter which emits null
if([null, undefined].indexOf(options) > -1) { if([null, undefined].indexOf(options) > -1) {
return new Utils.CustomEventEmitter(function(emitter) { return new Utils.CustomEventEmitter(function(emitter) {
setTimeout(function() { emitter.emit('success', null) }, 10) setTimeout(function() { emitter.emit('success', null) }, 10)
...@@ -121,6 +123,14 @@ module.exports = (function() { ...@@ -121,6 +123,14 @@ module.exports = (function() {
}) })
options = { where: where } options = { where: where }
} else if((typeof options === 'object') && (options.hasOwnProperty('include'))) {
var includes = options.include
options.include = {}
includes.forEach(function(daoName) {
options.include[daoName] = this.daoFactoryManager.getDAO(daoName)
}.bind(this))
} }
options.limit = 1 options.limit = 1
......
...@@ -94,21 +94,30 @@ module.exports = (function() { ...@@ -94,21 +94,30 @@ module.exports = (function() {
}, },
selectQuery: function(tableName, options) { selectQuery: function(tableName, options) {
var query = "SELECT <%= attributes %> FROM <%= table %>"
options = options || {} options = options || {}
options.table = Array.isArray(tableName) ? tableName.map(function(tbl){return Utils.addTicks(tbl)}).join(", ") : Utils.addTicks(tableName) options.table = Array.isArray(tableName) ? tableName.map(function(tbl){ return Utils.addTicks(tbl) }).join(", ") : Utils.addTicks(tableName)
options.attributes = options.attributes && options.attributes.map(function(attr){ options.attributes = options.attributes && options.attributes.map(function(attr){
if(Array.isArray(attr) && attr.length == 2) if(Array.isArray(attr) && attr.length == 2)
return [attr[0], Utils.addTicks(attr[1])].join(' as ') return [attr[0], Utils.addTicks(attr[1])].join(' as ')
else else
return attr.indexOf(Utils.TICK_CHAR)<0 ? Utils.addTicks(attr) : attr return attr.indexOf(Utils.TICK_CHAR) < 0 ? Utils.addTicks(attr) : attr
}).join(", ") }).join(", ")
options.attributes = options.attributes || '*' options.attributes = options.attributes || '*'
var query = "SELECT <%= attributes %> FROM <%= table %>" if (options.include) {
var tableNames = []
for (var daoName in options.include) {
tableNames.push(Utils.addTicks(options.include[daoName].tableName))
}
options.table = [options.table].concat(tableNames).join(', ')
}
if(options.where) { if(options.where) {
options.where = QueryGenerator.getWhereConditions(options.where) options.where = QueryGenerator.getWhereConditions(options.where, tableName)
query += " WHERE <%= where %>" query += " WHERE <%= where %>"
} }
...@@ -122,8 +131,11 @@ module.exports = (function() { ...@@ -122,8 +131,11 @@ module.exports = (function() {
} }
if(options.limit) { if(options.limit) {
if(options.offset) query += " LIMIT <%= offset %>, <%= limit %>" if(options.offset) {
else query += " LIMIT <%= limit %>" query += " LIMIT <%= offset %>, <%= limit %>"
} else {
query += " LIMIT <%= limit %>"
}
} }
query += ";" query += ";"
...@@ -235,16 +247,18 @@ module.exports = (function() { ...@@ -235,16 +247,18 @@ module.exports = (function() {
return Utils._.template(sql)({ tableName: tableName, indexName: indexName }) return Utils._.template(sql)({ tableName: tableName, indexName: indexName })
}, },
getWhereConditions: function(smth) { getWhereConditions: function(smth, tableName) {
var result = null var result = null
if(Utils.isHash(smth)) { if(Utils.isHash(smth)) {
smth = Utils.prependTableNameToHash(tableName, smth)
result = QueryGenerator.hashToWhereConditions(smth) result = QueryGenerator.hashToWhereConditions(smth)
} else if(typeof smth === 'number') { } else if (typeof smth === 'number') {
result = Utils.addTicks('id') + "=" + Utils.escape(smth) smth = Utils.prependTableNameToHash(tableName, { id: smth })
} else if(typeof smth === "string") { result = QueryGenerator.hashToWhereConditions(smth)
} else if (typeof smth === "string") {
result = smth result = smth
} else if(Array.isArray(smth)) { } else if (Array.isArray(smth)) {
result = Utils.format(smth) result = Utils.format(smth)
} }
...@@ -257,18 +271,21 @@ module.exports = (function() { ...@@ -257,18 +271,21 @@ module.exports = (function() {
var _key = key.split('.').map(function(col){return Utils.addTicks(col)}).join(".") var _key = key.split('.').map(function(col){return Utils.addTicks(col)}).join(".")
, _value = null , _value = null
if(Array.isArray(value)) { if (Array.isArray(value)) {
// is value an array?
_value = "(" + Utils._.map(value, function(subvalue) { _value = "(" + Utils._.map(value, function(subvalue) {
return Utils.escape(subvalue); return Utils.escape(subvalue);
}).join(',') + ")" }).join(',') + ")"
return [_key, _value].join(" IN ") return [_key, _value].join(" IN ")
} } else if ((value) && (typeof value == 'object')) {
else if ((value) && (typeof value == 'object')) { // is value an object?
//using as sentinel for join column => value
_value = value.join.split('.').map(function(col){return Utils.addTicks(col)}).join(".") //using as sentinel for join column => value
return [_key, _value].join("=") _value = value.join.split('.').map(function(col){return Utils.addTicks(col)}).join(".")
} else { return [_key, _value].join("=")
} else {
_value = Utils.escape(value) _value = Utils.escape(value)
return (_value == 'NULL') ? _key + " IS NULL" : [_key, _value].join("=") return (_value == 'NULL') ? _key + " IS NULL" : [_key, _value].join("=")
} }
......
...@@ -33,12 +33,18 @@ module.exports = (function() { ...@@ -33,12 +33,18 @@ module.exports = (function() {
bindClient.call(this) bindClient.call(this)
if(this.options.logging !== false) if(this.options.logging !== false) {
this.options.logging('Executing: ' + this.sql) this.options.logging('Executing: ' + this.sql)
}
this.client.query(this.sql, function(err, results, fields) { this.client.query(this.sql, function(err, results, fields) {
self.emit('sql', self.sql) self.emit('sql', self.sql)
err ? onFailure.call(self, err) : onSuccess.call(self, results, fields)
if (err) {
onFailure.call(self, err)
} else {
onSuccess.call(self, results, fields)
}
}).setMaxListeners(100) }).setMaxListeners(100)
return this return this
......
...@@ -128,6 +128,24 @@ var Utils = module.exports = { ...@@ -128,6 +128,24 @@ var Utils = module.exports = {
} }
return result return result
},
prependTableNameToHash: function(tableName, hash) {
if (tableName) {
var _hash = {}
for (var key in hash) {
if (key.indexOf('.') === -1) {
_hash[tableName + '.' + key] = hash[key]
} else {
_hash[key] = hash[key]
}
}
return _hash
} else {
return hash
}
} }
} }
......
...@@ -41,16 +41,16 @@ describe('QueryGenerator', function() { ...@@ -41,16 +41,16 @@ describe('QueryGenerator', function() {
expectation: "SELECT `id`, `name` FROM `myTable`;" expectation: "SELECT `id`, `name` FROM `myTable`;"
}, { }, {
arguments: ['myTable', {where: {id: 2}}], arguments: ['myTable', {where: {id: 2}}],
expectation: "SELECT * FROM `myTable` WHERE `id`=2;" expectation: "SELECT * FROM `myTable` WHERE `myTable`.`id`=2;"
}, { }, {
arguments: ['myTable', {where: {name: 'foo'}}], arguments: ['myTable', {where: {name: 'foo'}}],
expectation: "SELECT * FROM `myTable` WHERE `name`='foo';" expectation: "SELECT * FROM `myTable` WHERE `myTable`.`name`='foo';"
}, { }, {
arguments: ['myTable', {where: {name: "foo';DROP TABLE myTable;"}}], arguments: ['myTable', {where: {name: "foo';DROP TABLE myTable;"}}],
expectation: "SELECT * FROM `myTable` WHERE `name`='foo\\';DROP TABLE myTable;';" expectation: "SELECT * FROM `myTable` WHERE `myTable`.`name`='foo\\';DROP TABLE myTable;';"
}, { }, {
arguments: ['myTable', {where: 2}], arguments: ['myTable', {where: 2}],
expectation: "SELECT * FROM `myTable` WHERE `id`=2;" expectation: "SELECT * FROM `myTable` WHERE `myTable`.`id`=2;"
}, { }, {
arguments: ['foo', { attributes: [['count(*)', 'count']] }], arguments: ['foo', { attributes: [['count(*)', 'count']] }],
expectation: 'SELECT count(*) as `count` FROM `foo`;' expectation: 'SELECT count(*) as `count` FROM `foo`;'
...@@ -206,7 +206,7 @@ describe('QueryGenerator', function() { ...@@ -206,7 +206,7 @@ describe('QueryGenerator', function() {
// Options would normally be set by the query interface that instantiates the query-generator, but here we specify it explicitly // Options would normally be set by the query interface that instantiates the query-generator, but here we specify it explicitly
var context = test.context || {options: {}}; var context = test.context || {options: {}};
var conditions = QueryGenerator[suiteTitle].apply(context, test.arguments) var conditions = QueryGenerator[suiteTitle].apply(context, test.arguments)
expect(conditions).toEqual(test.expectation) expect(conditions).toEqual(test.expectation)
}) })
}) })
......
...@@ -360,28 +360,34 @@ dialects.forEach(function(dialect) { ...@@ -360,28 +360,34 @@ dialects.forEach(function(dialect) {
}) })
}) })
it('=>fetches associated objects for 1:1 associations', function(done) { it('//fetches associated objects for 1:1 associations', function(done) {
var Task = this.sequelize.define('Task', { var Task = this.sequelize.define('Task', {
title: Sequelize.STRING title: Sequelize.STRING
}) })
this.User.hasOne(Task) var User = this.sequelize.define('UserWithName', {
Task.belongsTo(this.User) name: Sequelize.STRING
})
User.hasOne(Task)
Task.belongsTo(User)
this.sequelize.sync({ force: true }).success(function() { this.sequelize.sync({ force: true }).success(function() {
Task.create({ title: 'task' }).success(function(task) { User.create({ name: 'barfooz' }).success(function(user) {
this.user.setTask(task).success(function() { Task.create({ title: 'task' }).success(function(task) {
this.User.find({ user.setTask(task).success(function() {
where: { id: 1 }, User.find({
include: 'Task' where: { 'UserWithNames.id': 1 },
}).success(function(user) { include: [ 'Task' ]
expect(user.task).toBeDefined() }).success(function(user) {
expect(user.task).toEqual(task) expect(user.task).toBeDefined()
done() expect(user.task).toEqual(task)
}.bind(this)) done()
}.bind(this)) })
}.bind(this)) }) //- setTask
}.bind(this)) }) //- Task.create
}) //- User.create
}) //- sequelize.sync
}) })
}) })
}) })
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!