|
|
var Sequence = require('./Sequence'); var Util = require('util'); var Packets = require('../packets'); var ResultSet = require('../ResultSet'); var ServerStatus = require('../constants/server_status'); var fs = require('fs');
module.exports = Query; Util.inherits(Query, Sequence); function Query(options, callback) { Sequence.call(this, callback);
this.sql = options.sql; this.typeCast = (options.typeCast === undefined) ? true : options.typeCast; this.nestTables = options.nestTables || false;
this._resultSet = null; this._results = []; this._fields = []; this._index = 0; this._loadError = null; }
Query.prototype.start = function() { this.emit('packet', new Packets.ComQueryPacket(this.sql)); };
Query.prototype.determinePacket = function(firstByte, parser) { if (firstByte === 0) { // If we have a resultSet and got one eofPacket
if (this._resultSet && this._resultSet.eofPackets.length === 1) { // Then this is a RowDataPacket with an empty string in the first column.
// See: https://github.com/felixge/node-mysql/issues/222
} else { return; } }
if (firstByte === 255) { return; }
// EofPacket's are 5 bytes in mysql >= 4.1
// This is the only / best way to differentiate their firstByte from a 9
// byte length coded binary.
if (firstByte === 0xfe && parser.packetLength() < 9) { return Packets.EofPacket; }
if (!this._resultSet) { return Packets.ResultSetHeaderPacket; }
return (this._resultSet.eofPackets.length === 0) ? Packets.FieldPacket : Packets.RowDataPacket; };
Query.prototype['OkPacket'] = function(packet) { // try...finally for exception safety
try { if (!this._callback) { this.emit('result', packet, this._index); } else { this._results.push(packet); this._fields.push(undefined); } } finally { this._index++; this._handleFinalResultPacket(packet); } };
Query.prototype['ErrorPacket'] = function(packet) { var err = this._packetToError(packet);
var results = (this._results.length > 0) ? this._results : undefined;
var fields = (this._fields.length > 0) ? this._fields : undefined;
err.index = this._index; this.end(err, results, fields); };
Query.prototype['ResultSetHeaderPacket'] = function(packet) { this._resultSet = new ResultSet(packet);
// used by LOAD DATA LOCAL INFILE queries
if (packet.fieldCount === null) { this._sendLocalDataFile(packet.extra); } };
Query.prototype['FieldPacket'] = function(packet) { this._resultSet.fieldPackets.push(packet); };
Query.prototype['EofPacket'] = function(packet) { this._resultSet.eofPackets.push(packet);
if (this._resultSet.eofPackets.length === 1 && !this._callback) { this.emit('fields', this._resultSet.fieldPackets, this._index); }
if (this._resultSet.eofPackets.length !== 2) { return; }
if (this._callback) { this._results.push(this._resultSet.rows); this._fields.push(this._resultSet.fieldPackets); }
this._index++; this._resultSet = null; this._handleFinalResultPacket(packet); };
Query.prototype._handleFinalResultPacket = function(packet) { if (packet.serverStatus & ServerStatus.SERVER_MORE_RESULTS_EXISTS) { return; }
var results = (this._results.length > 1) ? this._results : this._results[0];
var fields = (this._fields.length > 1) ? this._fields : this._fields[0];
this.end(this._loadError, results, fields); };
Query.prototype['RowDataPacket'] = function(packet, parser, connection) { packet.parse(parser, this._resultSet.fieldPackets, this.typeCast, this.nestTables, connection);
if (this._callback) { this._resultSet.rows.push(packet); } else { this.emit('result', packet, this._index); } };
Query.prototype._sendLocalDataFile = function(path) { var self = this; fs.readFile(path, 'utf-8', function(err, data) { if (err) { self._loadError = err; } else { self.emit('packet', new Packets.LocalDataFilePacket(data)); }
self.emit('packet', new Packets.EmptyPacket()); }); };
|