execute.js 3.4 KB

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