A Twitch.tv viewer reward and games system.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

162 lines
4.0 KiB

12 years ago
  1. var Sequence = require('./Sequence');
  2. var Util = require('util');
  3. var Packets = require('../packets');
  4. var ResultSet = require('../ResultSet');
  5. var ServerStatus = require('../constants/server_status');
  6. var fs = require('fs');
  7. module.exports = Query;
  8. Util.inherits(Query, Sequence);
  9. function Query(options, callback) {
  10. Sequence.call(this, callback);
  11. this.sql = options.sql;
  12. this.typeCast = (options.typeCast === undefined)
  13. ? true
  14. : options.typeCast;
  15. this.nestTables = options.nestTables || false;
  16. this._resultSet = null;
  17. this._results = [];
  18. this._fields = [];
  19. this._index = 0;
  20. this._loadError = null;
  21. }
  22. Query.prototype.start = function() {
  23. this.emit('packet', new Packets.ComQueryPacket(this.sql));
  24. };
  25. Query.prototype.determinePacket = function(firstByte, parser) {
  26. if (firstByte === 0) {
  27. // If we have a resultSet and got one eofPacket
  28. if (this._resultSet && this._resultSet.eofPackets.length === 1) {
  29. // Then this is a RowDataPacket with an empty string in the first column.
  30. // See: https://github.com/felixge/node-mysql/issues/222
  31. } else {
  32. return;
  33. }
  34. }
  35. if (firstByte === 255) {
  36. return;
  37. }
  38. // EofPacket's are 5 bytes in mysql >= 4.1
  39. // This is the only / best way to differentiate their firstByte from a 9
  40. // byte length coded binary.
  41. if (firstByte === 0xfe && parser.packetLength() < 9) {
  42. return Packets.EofPacket;
  43. }
  44. if (!this._resultSet) {
  45. return Packets.ResultSetHeaderPacket;
  46. }
  47. return (this._resultSet.eofPackets.length === 0)
  48. ? Packets.FieldPacket
  49. : Packets.RowDataPacket;
  50. };
  51. Query.prototype['OkPacket'] = function(packet) {
  52. // try...finally for exception safety
  53. try {
  54. if (!this._callback) {
  55. this.emit('result', packet, this._index);
  56. } else {
  57. this._results.push(packet);
  58. this._fields.push(undefined);
  59. }
  60. } finally {
  61. this._index++;
  62. this._handleFinalResultPacket(packet);
  63. }
  64. };
  65. Query.prototype['ErrorPacket'] = function(packet) {
  66. var err = this._packetToError(packet);
  67. var results = (this._results.length > 0)
  68. ? this._results
  69. : undefined;
  70. var fields = (this._fields.length > 0)
  71. ? this._fields
  72. : undefined;
  73. err.index = this._index;
  74. this.end(err, results, fields);
  75. };
  76. Query.prototype['ResultSetHeaderPacket'] = function(packet) {
  77. this._resultSet = new ResultSet(packet);
  78. // used by LOAD DATA LOCAL INFILE queries
  79. if (packet.fieldCount === null) {
  80. this._sendLocalDataFile(packet.extra);
  81. }
  82. };
  83. Query.prototype['FieldPacket'] = function(packet) {
  84. this._resultSet.fieldPackets.push(packet);
  85. };
  86. Query.prototype['EofPacket'] = function(packet) {
  87. this._resultSet.eofPackets.push(packet);
  88. if (this._resultSet.eofPackets.length === 1 && !this._callback) {
  89. this.emit('fields', this._resultSet.fieldPackets, this._index);
  90. }
  91. if (this._resultSet.eofPackets.length !== 2) {
  92. return;
  93. }
  94. if (this._callback) {
  95. this._results.push(this._resultSet.rows);
  96. this._fields.push(this._resultSet.fieldPackets);
  97. }
  98. this._index++;
  99. this._resultSet = null;
  100. this._handleFinalResultPacket(packet);
  101. };
  102. Query.prototype._handleFinalResultPacket = function(packet) {
  103. if (packet.serverStatus & ServerStatus.SERVER_MORE_RESULTS_EXISTS) {
  104. return;
  105. }
  106. var results = (this._results.length > 1)
  107. ? this._results
  108. : this._results[0];
  109. var fields = (this._fields.length > 1)
  110. ? this._fields
  111. : this._fields[0];
  112. this.end(this._loadError, results, fields);
  113. };
  114. Query.prototype['RowDataPacket'] = function(packet, parser, connection) {
  115. packet.parse(parser, this._resultSet.fieldPackets, this.typeCast, this.nestTables, connection);
  116. if (this._callback) {
  117. this._resultSet.rows.push(packet);
  118. } else {
  119. this.emit('result', packet, this._index);
  120. }
  121. };
  122. Query.prototype._sendLocalDataFile = function(path) {
  123. var self = this;
  124. fs.readFile(path, 'utf-8', function(err, data) {
  125. if (err) {
  126. self._loadError = err;
  127. } else {
  128. self.emit('packet', new Packets.LocalDataFilePacket(data));
  129. }
  130. self.emit('packet', new Packets.EmptyPacket());
  131. });
  132. };