'use strict'; const Packets = require('../packets/index.js'); const Command = require('./command.js'); const CloseStatement = require('./close_statement.js'); const Execute = require('./execute.js'); class PreparedStatementInfo { constructor(query, id, columns, parameters, connection) { this.query = query; this.id = id; this.columns = columns; this.parameters = parameters; this.rowParser = null; this._connection = connection; } close() { return this._connection.addCommand(new CloseStatement(this.id)); } execute(parameters, callback) { if (typeof parameters === 'function') { callback = parameters; parameters = []; } return this._connection.addCommand( new Execute({ statement: this, values: parameters }, callback) ); } } class Prepare extends Command { constructor(options, callback) { super(); this.query = options.sql; this.onResult = callback; this.id = 0; this.fieldCount = 0; this.parameterCount = 0; this.fields = []; this.parameterDefinitions = []; this.options = options; } start(packet, connection) { const Connection = connection.constructor; this.key = Connection.statementKey(this.options); const statement = connection._statements.get(this.key); if (statement) { if (this.onResult) { this.onResult(null, statement); } return null; } const cmdPacket = new Packets.PrepareStatement( this.query, connection.config.charsetNumber ); connection.writePacket(cmdPacket.toPacket(1)); return Prepare.prototype.prepareHeader; } prepareHeader(packet, connection) { const header = new Packets.PreparedStatementHeader(packet); this.id = header.id; this.fieldCount = header.fieldCount; this.parameterCount = header.parameterCount; if (this.parameterCount > 0) { return Prepare.prototype.readParameter; } if (this.fieldCount > 0) { return Prepare.prototype.readField; } return this.prepareDone(connection); } readParameter(packet, connection) { const def = new Packets.ColumnDefinition(packet, connection.clientEncoding); this.parameterDefinitions.push(def); if (this.parameterDefinitions.length === this.parameterCount) { return Prepare.prototype.parametersEOF; } return this.readParameter; } readField(packet, connection) { const def = new Packets.ColumnDefinition(packet, connection.clientEncoding); this.fields.push(def); if (this.fields.length === this.fieldCount) { return Prepare.prototype.fieldsEOF; } return Prepare.prototype.readField; } parametersEOF(packet, connection) { if (!packet.isEOF()) { return connection.protocolError('Expected EOF packet after parameters'); } if (this.fieldCount > 0) { return Prepare.prototype.readField; } return this.prepareDone(connection); } fieldsEOF(packet, connection) { if (!packet.isEOF()) { return connection.protocolError('Expected EOF packet after fields'); } return this.prepareDone(connection); } prepareDone(connection) { const statement = new PreparedStatementInfo( this.query, this.id, this.fields, this.parameterDefinitions, connection ); connection._statements.set(this.key, statement); if (this.onResult) { this.onResult(null, statement); } return null; } } module.exports = Prepare;