rittenhop-dev/versions/5.94.2/node_modules/mysql2/lib/commands/prepare.js

144 lines
4.0 KiB
JavaScript
Raw Normal View History

2024-09-23 19:40:12 -04:00
'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,
this.options.values
);
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) {
// there might be scenarios when mysql server reports more parameters than
// are actually present in the array of parameter definitions.
// if EOF packet is received we switch to "read fields" state if there are
// any fields reported by the server, otherwise we finish the command.
if (packet.isEOF()) {
if (this.fieldCount > 0) {
return Prepare.prototype.readField;
}
return this.prepareDone(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) {
if (packet.isEOF()) {
return this.prepareDone(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;