execute.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. 'use strict';
  2. const Command = require('./command.js');
  3. const Query = require('./query.js');
  4. const Packets = require('../packets/index.js');
  5. const getBinaryParser = require('../parsers/binary_parser.js');
  6. const getStaticBinaryParser = require('../parsers/static_binary_parser.js');
  7. class Execute extends Command {
  8. constructor(options, callback) {
  9. super();
  10. this.statement = options.statement;
  11. this.sql = options.sql;
  12. this.values = options.values;
  13. this.onResult = callback;
  14. this.parameters = options.values;
  15. this.insertId = 0;
  16. this.timeout = options.timeout;
  17. this.queryTimeout = null;
  18. this._rows = [];
  19. this._fields = [];
  20. this._result = [];
  21. this._fieldCount = 0;
  22. this._rowParser = null;
  23. this._executeOptions = options;
  24. this._resultIndex = 0;
  25. this._localStream = null;
  26. this._unpipeStream = function () {};
  27. this._streamFactory = options.infileStreamFactory;
  28. this._connection = null;
  29. }
  30. buildParserFromFields(fields, connection) {
  31. if (this.options.disableEval) {
  32. return getStaticBinaryParser(fields, this.options, connection.config);
  33. }
  34. return getBinaryParser(fields, this.options, connection.config);
  35. }
  36. start(packet, connection) {
  37. this._connection = connection;
  38. this.options = Object.assign({}, connection.config, this._executeOptions);
  39. this._setTimeout();
  40. const executePacket = new Packets.Execute(
  41. this.statement.id,
  42. this.parameters,
  43. connection.config.charsetNumber,
  44. connection.config.timezone
  45. );
  46. //For reasons why this try-catch is here, please see
  47. // https://github.com/sidorares/node-mysql2/pull/689
  48. //For additional discussion, see
  49. // 1. https://github.com/sidorares/node-mysql2/issues/493
  50. // 2. https://github.com/sidorares/node-mysql2/issues/187
  51. // 3. https://github.com/sidorares/node-mysql2/issues/480
  52. try {
  53. connection.writePacket(executePacket.toPacket(1));
  54. } catch (error) {
  55. this.onResult(error);
  56. }
  57. return Execute.prototype.resultsetHeader;
  58. }
  59. readField(packet, connection) {
  60. let fields;
  61. // disabling for now, but would be great to find reliable way to parse fields only once
  62. // fields reported by prepare can be empty at all or just incorrect - see #169
  63. //
  64. // perfomance optimisation: if we already have this field parsed in statement header, use one from header
  65. // const field = this.statement.columns.length == this._fieldCount ?
  66. // this.statement.columns[this._receivedFieldsCount] : new Packets.ColumnDefinition(packet);
  67. const field = new Packets.ColumnDefinition(
  68. packet,
  69. connection.clientEncoding
  70. );
  71. this._receivedFieldsCount++;
  72. this._fields[this._resultIndex].push(field);
  73. if (this._receivedFieldsCount === this._fieldCount) {
  74. fields = this._fields[this._resultIndex];
  75. this.emit('fields', fields, this._resultIndex);
  76. return Execute.prototype.fieldsEOF;
  77. }
  78. return Execute.prototype.readField;
  79. }
  80. fieldsEOF(packet, connection) {
  81. // check EOF
  82. if (!packet.isEOF()) {
  83. return connection.protocolError('Expected EOF packet');
  84. }
  85. this._rowParser = new (this.buildParserFromFields(
  86. this._fields[this._resultIndex],
  87. connection
  88. ))();
  89. return Execute.prototype.row;
  90. }
  91. }
  92. Execute.prototype.done = Query.prototype.done;
  93. Execute.prototype.doneInsert = Query.prototype.doneInsert;
  94. Execute.prototype.resultsetHeader = Query.prototype.resultsetHeader;
  95. Execute.prototype._findOrCreateReadStream =
  96. Query.prototype._findOrCreateReadStream;
  97. Execute.prototype._streamLocalInfile = Query.prototype._streamLocalInfile;
  98. Execute.prototype._setTimeout = Query.prototype._setTimeout;
  99. Execute.prototype._handleTimeoutError = Query.prototype._handleTimeoutError;
  100. Execute.prototype.row = Query.prototype.row;
  101. Execute.prototype.stream = Query.prototype.stream;
  102. module.exports = Execute;