108 lines
3.6 KiB
JavaScript
108 lines
3.6 KiB
JavaScript
'use strict';
|
|
|
|
const Command = require('./command.js');
|
|
const Query = require('./query.js');
|
|
const Packets = require('../packets/index.js');
|
|
|
|
const getBinaryParser = require('../parsers/binary_parser.js');
|
|
|
|
class Execute extends Command {
|
|
constructor(options, callback) {
|
|
super();
|
|
this.statement = options.statement;
|
|
this.sql = options.sql;
|
|
this.values = options.values;
|
|
this.onResult = callback;
|
|
this.parameters = options.values;
|
|
this.insertId = 0;
|
|
this.timeout = options.timeout;
|
|
this.queryTimeout = null;
|
|
this._rows = [];
|
|
this._fields = [];
|
|
this._result = [];
|
|
this._fieldCount = 0;
|
|
this._rowParser = null;
|
|
this._executeOptions = options;
|
|
this._resultIndex = 0;
|
|
this._localStream = null;
|
|
this._unpipeStream = function() {};
|
|
this._streamFactory = options.infileStreamFactory;
|
|
this._connection = null;
|
|
}
|
|
|
|
buildParserFromFields(fields, connection) {
|
|
return getBinaryParser(fields, this.options, connection.config);
|
|
}
|
|
|
|
start(packet, connection) {
|
|
this._connection = connection;
|
|
this.options = Object.assign({}, connection.config, this._executeOptions);
|
|
this._setTimeout();
|
|
const executePacket = new Packets.Execute(
|
|
this.statement.id,
|
|
this.parameters,
|
|
connection.config.charsetNumber,
|
|
connection.config.timezone
|
|
);
|
|
//For reasons why this try-catch is here, please see
|
|
// https://github.com/sidorares/node-mysql2/pull/689
|
|
//For additional discussion, see
|
|
// 1. https://github.com/sidorares/node-mysql2/issues/493
|
|
// 2. https://github.com/sidorares/node-mysql2/issues/187
|
|
// 3. https://github.com/sidorares/node-mysql2/issues/480
|
|
try {
|
|
connection.writePacket(executePacket.toPacket(1));
|
|
} catch (error) {
|
|
this.onResult(error);
|
|
}
|
|
return Execute.prototype.resultsetHeader;
|
|
}
|
|
|
|
readField(packet, connection) {
|
|
let fields;
|
|
// disabling for now, but would be great to find reliable way to parse fields only once
|
|
// fields reported by prepare can be empty at all or just incorrect - see #169
|
|
//
|
|
// perfomance optimisation: if we already have this field parsed in statement header, use one from header
|
|
// const field = this.statement.columns.length == this._fieldCount ?
|
|
// this.statement.columns[this._receivedFieldsCount] : new Packets.ColumnDefinition(packet);
|
|
const field = new Packets.ColumnDefinition(
|
|
packet,
|
|
connection.clientEncoding
|
|
);
|
|
this._receivedFieldsCount++;
|
|
this._fields[this._resultIndex].push(field);
|
|
if (this._receivedFieldsCount === this._fieldCount) {
|
|
fields = this._fields[this._resultIndex];
|
|
this.emit('fields', fields, this._resultIndex);
|
|
return Execute.prototype.fieldsEOF;
|
|
}
|
|
return Execute.prototype.readField;
|
|
}
|
|
|
|
fieldsEOF(packet, connection) {
|
|
// check EOF
|
|
if (!packet.isEOF()) {
|
|
return connection.protocolError('Expected EOF packet');
|
|
}
|
|
this._rowParser = new (this.buildParserFromFields(
|
|
this._fields[this._resultIndex],
|
|
connection
|
|
))();
|
|
return Execute.prototype.row;
|
|
}
|
|
}
|
|
|
|
Execute.prototype.done = Query.prototype.done;
|
|
Execute.prototype.doneInsert = Query.prototype.doneInsert;
|
|
Execute.prototype.resultsetHeader = Query.prototype.resultsetHeader;
|
|
Execute.prototype._findOrCreateReadStream =
|
|
Query.prototype._findOrCreateReadStream;
|
|
Execute.prototype._streamLocalInfile = Query.prototype._streamLocalInfile;
|
|
Execute.prototype._setTimeout = Query.prototype._setTimeout;
|
|
Execute.prototype._handleTimeoutError = Query.prototype._handleTimeoutError;
|
|
Execute.prototype.row = Query.prototype.row;
|
|
Execute.prototype.stream = Query.prototype.stream;
|
|
|
|
module.exports = Execute;
|