feat: add handling for empty result sets in backend

pull/5429/head
Antonino Natale 2 weeks ago
parent 0817515b10
commit bdbd9e5d05

@ -129,6 +129,7 @@ class Monitor extends BeanModel {
mqttSuccessMessage: this.mqttSuccessMessage, mqttSuccessMessage: this.mqttSuccessMessage,
mqttCheckType: this.mqttCheckType, mqttCheckType: this.mqttCheckType,
databaseQuery: this.databaseQuery, databaseQuery: this.databaseQuery,
databaseQueryHandleEmptyAsFailure: this.isDatabaseQueryHandleEmptyAsFailure(),
authMethod: this.authMethod, authMethod: this.authMethod,
grpcUrl: this.grpcUrl, grpcUrl: this.grpcUrl,
grpcProtobuf: this.grpcProtobuf, grpcProtobuf: this.grpcProtobuf,
@ -271,6 +272,14 @@ class Monitor extends BeanModel {
return Boolean(this.invertKeyword); return Boolean(this.invertKeyword);
} }
/**
* Parse to boolean
* @returns {boolean} Is sql query empty result handled as failure?
*/
isDatabaseQueryHandleEmptyAsFailure() {
return Boolean(this.databaseQueryHandleEmptyAsFailure);
}
/** /**
* Parse to boolean * Parse to boolean
* @returns {boolean} Enable TLS for gRPC? * @returns {boolean} Enable TLS for gRPC?
@ -760,7 +769,7 @@ class Monitor extends BeanModel {
} else if (this.type === "sqlserver") { } else if (this.type === "sqlserver") {
let startTime = dayjs().valueOf(); let startTime = dayjs().valueOf();
await mssqlQuery(this.databaseConnectionString, this.databaseQuery || "SELECT 1"); await mssqlQuery(this.databaseConnectionString, this.databaseQueryHandleEmptyAsFailure, this.databaseQuery || "SELECT 1");
bean.msg = ""; bean.msg = "";
bean.status = UP; bean.status = UP;
@ -799,7 +808,7 @@ class Monitor extends BeanModel {
} else if (this.type === "postgres") { } else if (this.type === "postgres") {
let startTime = dayjs().valueOf(); let startTime = dayjs().valueOf();
await postgresQuery(this.databaseConnectionString, this.databaseQuery || "SELECT 1"); await postgresQuery(this.databaseConnectionString, this.databaseQueryHandleEmptyAsFailure, this.databaseQuery || "SELECT 1");
bean.msg = ""; bean.msg = "";
bean.status = UP; bean.status = UP;
@ -811,7 +820,7 @@ class Monitor extends BeanModel {
// TODO: rename `radius_password` to `password` later for general use // TODO: rename `radius_password` to `password` later for general use
let mysqlPassword = this.radiusPassword; let mysqlPassword = this.radiusPassword;
bean.msg = await mysqlQuery(this.databaseConnectionString, this.databaseQuery || "SELECT 1", mysqlPassword); bean.msg = await mysqlQuery(this.databaseConnectionString, this.databaseQueryHandleEmptyAsFailure, this.databaseQuery || "SELECT 1", mysqlPassword);
bean.status = UP; bean.status = UP;
bean.ping = dayjs().valueOf() - startTime; bean.ping = dayjs().valueOf() - startTime;
} else if (this.type === "radius") { } else if (this.type === "radius") {

@ -837,6 +837,7 @@ let needSetup = false;
bean.mqttCheckType = monitor.mqttCheckType; bean.mqttCheckType = monitor.mqttCheckType;
bean.databaseConnectionString = monitor.databaseConnectionString; bean.databaseConnectionString = monitor.databaseConnectionString;
bean.databaseQuery = monitor.databaseQuery; bean.databaseQuery = monitor.databaseQuery;
bean.databaseQueryHandleEmptyAsFailure = monitor.databaseQueryHandleEmptyAsFailure;
bean.authMethod = monitor.authMethod; bean.authMethod = monitor.authMethod;
bean.authWorkstation = monitor.authWorkstation; bean.authWorkstation = monitor.authWorkstation;
bean.authDomain = monitor.authDomain; bean.authDomain = monitor.authDomain;

@ -322,7 +322,7 @@ exports.dnsResolve = function (hostname, resolverServer, resolverPort, rrtype) {
* @returns {Promise<(string[] | object[] | object)>} Response from * @returns {Promise<(string[] | object[] | object)>} Response from
* server * server
*/ */
exports.mssqlQuery = async function (connectionString, query) { exports.mssqlQuery = async function (connectionString, handleEmptyResult, query) {
let pool; let pool;
try { try {
pool = new mssql.ConnectionPool(connectionString); pool = new mssql.ConnectionPool(connectionString);
@ -330,7 +330,12 @@ exports.mssqlQuery = async function (connectionString, query) {
if (!query) { if (!query) {
query = "SELECT 1"; query = "SELECT 1";
} }
await pool.request().query(query); result = await pool.request().query(query);
if (Array.isArray(result.recordset)) {
if (handleEmptyResult && result.recordset.length === 0) {
throw new Error("No rows returned");
}
}
pool.close(); pool.close();
} catch (e) { } catch (e) {
if (pool) { if (pool) {
@ -347,7 +352,7 @@ exports.mssqlQuery = async function (connectionString, query) {
* @returns {Promise<(string[] | object[] | object)>} Response from * @returns {Promise<(string[] | object[] | object)>} Response from
* server * server
*/ */
exports.postgresQuery = function (connectionString, query) { exports.postgresQuery = function (connectionString, handleEmptyResult, query) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const config = postgresConParse(connectionString); const config = postgresConParse(connectionString);
@ -384,7 +389,13 @@ exports.postgresQuery = function (connectionString, query) {
if (err) { if (err) {
reject(err); reject(err);
} else { } else {
resolve(res); if (Array.isArray(res.rows)) {
if (handleEmptyResult && res.rows.length === 0) {
reject(new Error("No rows returned"));
} else {
resolve(res);
}
}
} }
client.end(); client.end();
}); });
@ -405,7 +416,7 @@ exports.postgresQuery = function (connectionString, query) {
* @param {?string} password The password to use * @param {?string} password The password to use
* @returns {Promise<(string)>} Response from server * @returns {Promise<(string)>} Response from server
*/ */
exports.mysqlQuery = function (connectionString, query, password = undefined) { exports.mysqlQuery = function (connectionString, handleEmptyResult, query, password = undefined) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const connection = mysql.createConnection({ const connection = mysql.createConnection({
uri: connectionString, uri: connectionString,
@ -421,7 +432,7 @@ exports.mysqlQuery = function (connectionString, query, password = undefined) {
reject(err); reject(err);
} else { } else {
if (Array.isArray(res)) { if (Array.isArray(res)) {
if (res.length === 0) { if (handleEmptyResult && res.length === 0) {
reject(new Error("No rows returned")); reject(new Error("No rows returned"));
} else { } else {
resolve("Rows: " + res.length); resolve("Rows: " + res.length);

Loading…
Cancel
Save