execute.js 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  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 clientFlags =
  41. connection.config.clientFlags & (connection.serverCapabilityFlags || 0);
  42. const executePacket = new Packets.Execute(
  43. this.statement.id,
  44. this.parameters,
  45. connection.config.charsetNumber,
  46. connection.config.timezone,
  47. this._executeOptions.attributes,
  48. clientFlags
  49. );
  50. //For reasons why this try-catch is here, please see
  51. // https://github.com/sidorares/node-mysql2/pull/689
  52. //For additional discussion, see
  53. // 1. https://github.com/sidorares/node-mysql2/issues/493
  54. // 2. https://github.com/sidorares/node-mysql2/issues/187
  55. // 3. https://github.com/sidorares/node-mysql2/issues/480
  56. try {
  57. connection.writePacket(executePacket.toPacket(1));
  58. } catch (error) {
  59. this.onResult(error);
  60. }
  61. return Execute.prototype.resultsetHeader;
  62. }
  63. readField(packet, connection) {
  64. let fields;
  65. // disabling for now, but would be great to find reliable way to parse fields only once
  66. // fields reported by prepare can be empty at all or just incorrect - see #169
  67. //
  68. // perfomance optimisation: if we already have this field parsed in statement header, use one from header
  69. // const field = this.statement.columns.length == this._fieldCount ?
  70. // this.statement.columns[this._receivedFieldsCount] : new Packets.ColumnDefinition(packet);
  71. const field = new Packets.ColumnDefinition(
  72. packet,
  73. connection.clientEncoding
  74. );
  75. this._receivedFieldsCount++;
  76. this._fields[this._resultIndex].push(field);
  77. if (this._receivedFieldsCount === this._fieldCount) {
  78. fields = this._fields[this._resultIndex];
  79. this.emit('fields', fields, this._resultIndex);
  80. return Execute.prototype.fieldsEOF;
  81. }
  82. return Execute.prototype.readField;
  83. }
  84. fieldsEOF(packet, connection) {
  85. // check EOF
  86. if (!packet.isEOF()) {
  87. return connection.protocolError('Expected EOF packet');
  88. }
  89. this._rowParser = new (this.buildParserFromFields(
  90. this._fields[this._resultIndex],
  91. connection
  92. ))();
  93. return Execute.prototype.row;
  94. }
  95. }
  96. Execute.prototype.done = Query.prototype.done;
  97. Execute.prototype.doneInsert = Query.prototype.doneInsert;
  98. Execute.prototype.resultsetHeader = Query.prototype.resultsetHeader;
  99. Execute.prototype._findOrCreateReadStream =
  100. Query.prototype._findOrCreateReadStream;
  101. Execute.prototype._streamLocalInfile = Query.prototype._streamLocalInfile;
  102. Execute.prototype._setTimeout = Query.prototype._setTimeout;
  103. Execute.prototype._handleTimeoutError = Query.prototype._handleTimeoutError;
  104. Execute.prototype.row = Query.prototype.row;
  105. Execute.prototype.stream = Query.prototype.stream;
  106. module.exports = Execute;