tuain-dbpool-mysql
Version:
Database pool class to perform standard database operations on MySQL databases using a common interface for simple operations as part of the Tuain Application Development Framework
152 lines (140 loc) • 5.2 kB
JavaScript
const mysql = require('mysql');
const DatabasePool = require('tuain-dbpool-generic');
const modErrs = {
mysql: {
procedureError: ['04', 'Error en ejecución de procedimiento'],
generalError: ['99', 'Error general de base de datos'],
},
};
const legacyModErrs = {
moduleName: 'dbpool-lib-mysql',
moduleCode: '01',
defaultLanguage: 'es',
contexts: {
mysql: {
contextCode: '01',
items: {
procedureError: {
errorCode: '04',
defaultMessage: 'Error en ejecución de procedimiento',
},
generalError: {
errorCode: '99',
defaultMessage: 'Error general de base de datos',
},
},
},
},
};
class DatabasePoolMySQL extends DatabasePool {
constructor(poolAttributes, logger, errors) {
super(logger, errors);
if (this.legacyErrors) {
this.legacyErrors = true;
this.errors.addModuleSet(legacyModErrs);
} else {
this.errors.addModuleSet('dbpool-lib-mysql', modErrs);
}
this.parameters = poolAttributes;
this.engineName = 'mysql';
this.knexParameters = {
client: this.engineName,
connection: {
user: poolAttributes.user,
password: poolAttributes.password,
host: poolAttributes.host,
port: poolAttributes.port,
database: poolAttributes.database,
},
pool: { min: poolAttributes.pool.min, max: poolAttributes.pool.max },
};
}
async open() {
const { knex, setupPaginator } = this;
this.knexPool = knex(this.knexParameters);
if (!this.parameters?.avoidPaginator) {
setupPaginator(this.knexPool);
}
}
async executeRawQuery(sql) {
const rawQueryResult = await this.knexPool.raw(sql);
return rawQueryResult[0];
}
async getPool() {
return this.knexPool;
}
async executeProcedure(queryObject, recordFields) {
const sentenceInsertsOutParams = [];
const sentenceInsertsInParams = [];
let setOutputVarSentence = '';
let procedureFieldsSentence = '';
let getOutputVarSentence = '';
queryObject.procedureFields.forEach((parameterName) => {
let procedureFieldsSegment = '';
let setOutputVarSegment = '';
let fieldValue = '';
if (parameterName[0] === '@') {
const fieldAlias = parameterName.substring(1);
// Es una variable de salida, se incluye en la asignación inicial
setOutputVarSegment = `SET ${parameterName} = ?; `;
if (recordFields && recordFields[fieldAlias] != null) {
fieldValue = recordFields[fieldAlias];
}
sentenceInsertsOutParams.push(fieldValue);
procedureFieldsSegment += parameterName;
getOutputVarSentence += getOutputVarSentence ? ', ' : '';
getOutputVarSentence += parameterName;
} else {
const requiredFields = queryObject.requiredFields || queryObject.procedureFields;
if (requiredFields.indexOf(parameterName) >= 0 && (!recordFields || recordFields[parameterName] == null)) {
throw new Error(`Parametros insuficientes ${parameterName}`);
}
fieldValue = recordFields[parameterName];
// Es una variable solamente de entrada
procedureFieldsSegment += '?';
sentenceInsertsInParams.push(fieldValue);
}
procedureFieldsSentence += procedureFieldsSentence ? ', ' : '';
procedureFieldsSentence += procedureFieldsSegment;
setOutputVarSentence += setOutputVarSegment;
});
getOutputVarSentence = getOutputVarSentence ? `SELECT ${getOutputVarSentence}` : '';
setOutputVarSentence = setOutputVarSentence ? ` ${setOutputVarSentence}` : '';
let sqlSentence = `${setOutputVarSentence}CALL ${queryObject.procedureName}`;
sqlSentence += `( ${procedureFieldsSentence} ); ${getOutputVarSentence}`;
// Se formatea la sentencia que se va a ejecutar en la base de datos
const finalSql = mysql.format(sqlSentence, sentenceInsertsOutParams.concat(sentenceInsertsInParams));
try {
this.logger.log({
level: 'silly',
message: `Ejecución procedimiento: ${finalSql}`,
});
const resp = await this.knexPool.raw(finalSql);
const resultData = resp[0][0];
this.logger.log({
level: 'silly',
message: `Respuesta del procedimiento: ${JSON.stringify(resultData)}`,
});
const [procResult] = resultData;
if (procResult.errorCode !== 0) {
const errorDetail = `${procResult.errorCode}`;
const errorObj = (this.legacyErrors)
? this.errors.get(legacyModErrs.contexts.mysql.items.procedureError, errorDetail)
: this.errors.get(modErrs.mysql.procedureError, errorDetail);
return [errorObj, null];
}
return [null, procResult];
} catch (err) {
this.logger.log({
level: 'error',
message: err,
});
const errorDetail = `${err.message}/${err.stack}`;
const errorObj = (this.legacyErrors)
? this.errors.get(legacyModErrs.contexts.mysql.items.procedureError, errorDetail)
: this.errors.get(modErrs.mysql.procedureError, errorDetail);
return [errorObj, null];
}
}
}
module.exports = DatabasePoolMySQL;