query.js
4.36 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
var Utils = require("../../utils")
, AbstractQuery = require('../abstract/query')
module.exports = (function() {
var Query = function(client, sequelize, callee, options) {
var self = this
this.client = client
this.callee = callee
this.sequelize = sequelize
this.options = Utils._.extend({
logging: console.log,
plain: false,
raw: false
}, options || {})
if(this.options.logging === true) {
console.log('DEPRECATION WARNING: The logging-option should be either a function or false. Default: console.log')
this.options.logging = console.log
}
if(this.options.logging == console.log) {
// using just console.log will break in node < 0.6
this.options.logging = function(s) { console.log(s) }
}
this.bindClientFunction = function(err) { onFailure.call(self, err) }
}
Utils.inherit(Query, require('../abstract/query'))
Query.prototype.run = function(sql) {
var self = this
this.sql = sql
bindClient.call(this)
if(this.options.logging !== false) {
this.options.logging('Executing: ' + this.sql)
}
this.client.query({ sql: this.sql, nestTables: true }, function(err, results, fields) {
self.emit('sql', self.sql)
if (err) {
onFailure.call(self, err)
} else {
if (Array.isArray(results) && !!results[0] && Utils._.keys(results[0]).length === 1) {
results = results.map(function(result){ return Utils._.values(result)[0] })
}
onSuccess.call(self, results, fields)
}
}).setMaxListeners(100)
return this
}
//private
var bindClient = function() {
this.client.on('error', this.bindClientFunction)
}
var unbindClient = function() {
this.client.removeListener('error', this.bindClientFunction)
}
var onSuccess = function(results, fields) {
var result = this.callee
, self = this
, hasJoin = !!results[0] && (Utils._.keys(results[0]).length > 1) && (Utils.isHash(results[0][Utils._.keys(results[0])[0]]))
// add the inserted row id to the instance
if (this.callee && (this.sql.indexOf('INSERT INTO') === 0) && (results.hasOwnProperty('insertId'))) {
this.callee[this.callee.__factory.autoIncrementField] = results.insertId
}
if (this.sql.indexOf('SELECT') === 0) {
// transform results into real model instances
// return the first real model instance if options.plain is set (e.g. Model.find)
if (this.options.raw) {
result = results
} else if (hasJoin) {
result = results.map(function(result) {
var dao = this.callee.build(result[this.callee.tableName], { isNewRecord: false })
for (var tableName in result) {
if (result.hasOwnProperty(tableName) && (tableName !== this.callee.tableName)) {
var associatedDao = this.sequelize.daoFactoryManager.getDAO(tableName, { attribute: 'tableName' })
, association = this.callee.associations[tableName]
, accessor = Utils._.camelize(association.associationAccessor)
, daoInstance = associatedDao.build(result[tableName], { isNewRecord: false })
// downcase the first char
accessor = accessor.slice(0,1).toLowerCase() + accessor.slice(1)
if (['BelongsTo', 'HasOne'].indexOf(association.associationType) > -1) {
accessor = Utils.singularize(accessor)
dao[accessor] = daoInstance
} else {
dao[accessor] = dao[accessor] || []
dao[accessor].push(daoInstance)
}
}
}
return dao
}.bind(this))
} else {
result = results.map(function(result) {
return self.callee.build(result, { isNewRecord: false })
})
}
if(this.options.plain) {
result = (result.length === 0) ? null : result[0]
}
} else if(this.sql.indexOf('SHOW TABLES') === 0) {
result = Utils._.flatten(results.map(function(resultSet) {
return Utils._.values(resultSet)
}))
} else if((this.sql.indexOf('SHOW') === 0) || (this.sql.indexOf('DESCRIBE') === 0)) {
result = results
}
unbindClient.call(this)
this.emit('success', result)
}
var onFailure = function(err) {
unbindClient.call(this)
this.emit('error', err, this.callee)
}
return Query
})()