query.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. var Utils = require("../../utils")
  2. , AbstractQuery = require('../abstract/query')
  3. module.exports = (function() {
  4. var Query = function(client, sequelize, callee, options) {
  5. this.client = client
  6. this.callee = callee
  7. this.sequelize = sequelize
  8. this.options = Utils._.extend({
  9. logging: console.log,
  10. plain: false,
  11. raw: false
  12. }, options || {})
  13. this.checkLoggingOption()
  14. }
  15. Utils.inherit(Query, AbstractQuery)
  16. Query.prototype.run = function(sql) {
  17. this.sql = sql
  18. if (this.options.logging !== false) {
  19. this.options.logging('Executing (' + this.options.uuid + '): ' + this.sql)
  20. }
  21. var resultSet = [],
  22. errorDetected = false,
  23. alreadyEnded = false, // This is needed because CALL queries emit 'end' twice...
  24. self = this
  25. this.client.query(this.sql)
  26. .on('result', function(results) {
  27. results
  28. .on('row', function(row, metadata) {
  29. var type
  30. for (var prop in row) {
  31. if (row.hasOwnProperty(prop)) {
  32. if (row[prop] === null) {
  33. continue
  34. }
  35. type = metadata.types[prop]
  36. switch (type) {
  37. case "TINYINT":
  38. case "SMALLINT":
  39. case "INTEGER":
  40. case "MEDIUMINT":
  41. case "BIGINT":
  42. case "YEAR":
  43. row[prop] = parseInt(row[prop], 10)
  44. break
  45. case "DECIMAL":
  46. case "FLOAT":
  47. case "DOUBLE":
  48. row[prop] = parseFloat(row[prop])
  49. break
  50. case "DATE":
  51. case "TIMESTAMP":
  52. case "DATETIME":
  53. row[prop] = new Date(row[prop] + 'Z')
  54. break
  55. case "BIT":
  56. case "BLOB":
  57. case "TINYBLOB":
  58. case "MEDIUMBLOB":
  59. case "LONGBLOB":
  60. if (metadata.charsetNrs[prop] === 63) { // binary
  61. row[prop] = new Buffer(row[prop])
  62. }
  63. break
  64. case "TIME":
  65. case "CHAR":
  66. case "VARCHAR":
  67. case "SET":
  68. case "ENUM":
  69. case "GEOMETRY":
  70. case "NULL":
  71. break
  72. default:
  73. // blank
  74. }
  75. }
  76. }
  77. resultSet.push(row)
  78. })
  79. .on('error', function(err) {
  80. errorDetected = true
  81. self.emit('sql', self.sql)
  82. err.sql = sql
  83. self.emit('error', err, self.callee)
  84. })
  85. .on('end', function(info) {
  86. if (alreadyEnded || errorDetected) {
  87. return
  88. }
  89. alreadyEnded = true
  90. self.emit('sql', self.sql)
  91. // we need to figure out whether to send the result set
  92. // or info depending upon the type of query
  93. if (/^call/.test(self.sql.toLowerCase())) {
  94. self.emit('success', resultSet)
  95. } else if( /^show/.test(self.sql.toLowerCase()) ||
  96. /^select/.test(self.sql.toLowerCase()) ||
  97. /^describe/.test(self.sql.toLowerCase())) {
  98. self.emit('success', self.formatResults(resultSet))
  99. } else {
  100. self.emit('success', self.formatResults(info))
  101. }
  102. })
  103. })
  104. .on('error', function(err) {
  105. if (errorDetected) {
  106. return
  107. }
  108. errorDetected = true
  109. self.emit('sql', self.sql)
  110. self.emit('error', err, self.callee)
  111. })
  112. .setMaxListeners(100)
  113. return this
  114. }
  115. return Query
  116. })()