node-query/node_modules/mysql2/lib/commands/execute.js

126 lines
3.7 KiB
JavaScript

var util = require('util');
var Command = require('./command.js');
var Packets = require('../packets/index.js');
var compileParser = require('../compile_binary_parser.js');
function Execute(options, callback)
{
Command.call(this);
this.statement = options.statement;
this.onResult = callback;
this.parameters = options.values;
this.resultFields = [];
this.resultFieldCount = 0;
this.insertId = 0;
this.rows = [];
this.options = options;
}
util.inherits(Execute, Command);
Execute.prototype.buildParserFromFields = function(fields, connection) {
var parserKey;
if (!this.statement.parser) {
// compile row parser
parserKey = connection.keyFromFields(fields, this.options);
this.statement.parser = connection.binaryProtocolParsers[parserKey];
if (!this.statement.parser) {
this.statement.parser = compileParser(fields, this.options, connection.config);
connection.binaryProtocolParsers[parserKey] = this.statement.parser;
}
}
}
function statementKey(query, options) {
return (typeof options.nestTables) +
'/' + options.nestTables + '/' + options.rowsAsHash
+ query;
}
Execute.prototype.start = function(packet, connection) {
var cachedStatement = connection._statements[statementKey(this.query, this.options)];
var executePacket = new Packets.Execute(this.statement.id, this.parameters);
connection.writePacket(executePacket.toPacket(1));
return Execute.prototype.resultsetHeader;
};
Execute.prototype.resultsetHeader = function(packet) {
var self = this;
var header = new Packets.ResultSetHeader(packet);
this.resultFieldCount = header.fieldCount;
// we'll re-create row parser if schema reported by
// prepare is different from one in result set
if (this.statement.columns.length != this.resultFieldCount)
this.statement.parser = null;
this.insertId = header.insertId;
if (this.resultFieldCount === 0) {
if (this.onResult)
process.nextTick(function() {
self.onResult(null, header, []);
});
return null;
}
return Execute.prototype.readResultField;
};
Execute.prototype.readResultField = function(packet, connection) {
var def;
// TODO: this used to be performance optimisation (don't parse column def if we
// already have one in statement info, but since we can't 100% trust statement info
// column defs it's probably bettery to always use fields from result header.
// config option to ignore this?
// ignore result fields definition, we are reusing fields from prepare response
if (this.statement.parser)
this.resultFields.push(null);
else {
def = new Packets.ColumnDefinition(packet);
this.resultFields.push(def);
}
if (this.resultFields.length == this.resultFieldCount) {
return Execute.prototype.resultFieldsEOF;
}
return Execute.prototype.readResultField;
};
Execute.prototype.resultFieldsEOF = function(packet, connection) {
// check EOF
if (!packet.isEOF())
return connection.protocolError("Expected EOF packet");
if (!this.statement.parser)
this.buildParserFromFields(this.resultFields, connection)
return Execute.prototype.row;
};
Execute.prototype.row = function(packet, connection)
{
var self = this;
// TODO: refactor to share code with Query::row
if (packet.isEOF()) {
// TODO: multiple statements
//packet.eofStatusFlags() & ServerStatus.SERVER_MORE_RESULTS_EXISTS;
if (this.onResult)
process.nextTick(function() {
self.onResult(null, self.rows, self.resultFields);
})
return null;
}
var r = new this.statement.parser(packet);
if (this.onResult)
this.rows.push(r);
else
this.emit('result', r);
return Execute.prototype.row;
};
module.exports = Execute;