diff --git a/server/model/monitor.js b/server/model/monitor.js index 3ad8cfafc..442faebe0 100644 --- a/server/model/monitor.js +++ b/server/model/monitor.js @@ -129,6 +129,7 @@ class Monitor extends BeanModel { mqttSuccessMessage: this.mqttSuccessMessage, mqttCheckType: this.mqttCheckType, databaseQuery: this.databaseQuery, + databaseQueryHandleEmptyAsFailure: this.isDatabaseQueryHandleEmptyAsFailure(), authMethod: this.authMethod, grpcUrl: this.grpcUrl, grpcProtobuf: this.grpcProtobuf, @@ -271,6 +272,14 @@ class Monitor extends BeanModel { 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 * @returns {boolean} Enable TLS for gRPC? @@ -760,7 +769,7 @@ class Monitor extends BeanModel { } else if (this.type === "sqlserver") { 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.status = UP; @@ -799,7 +808,7 @@ class Monitor extends BeanModel { } else if (this.type === "postgres") { 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.status = UP; @@ -811,7 +820,7 @@ class Monitor extends BeanModel { // TODO: rename `radius_password` to `password` later for general use 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.ping = dayjs().valueOf() - startTime; } else if (this.type === "radius") { diff --git a/server/server.js b/server/server.js index ec5ad49f6..6e5da348b 100644 --- a/server/server.js +++ b/server/server.js @@ -837,6 +837,7 @@ let needSetup = false; bean.mqttCheckType = monitor.mqttCheckType; bean.databaseConnectionString = monitor.databaseConnectionString; bean.databaseQuery = monitor.databaseQuery; + bean.databaseQueryHandleEmptyAsFailure = monitor.databaseQueryHandleEmptyAsFailure; bean.authMethod = monitor.authMethod; bean.authWorkstation = monitor.authWorkstation; bean.authDomain = monitor.authDomain; diff --git a/server/util-server.js b/server/util-server.js index ceb702e12..6df81e629 100644 --- a/server/util-server.js +++ b/server/util-server.js @@ -322,7 +322,7 @@ exports.dnsResolve = function (hostname, resolverServer, resolverPort, rrtype) { * @returns {Promise<(string[] | object[] | object)>} Response from * server */ -exports.mssqlQuery = async function (connectionString, query) { +exports.mssqlQuery = async function (connectionString, handleEmptyResult, query) { let pool; try { pool = new mssql.ConnectionPool(connectionString); @@ -330,7 +330,12 @@ exports.mssqlQuery = async function (connectionString, query) { if (!query) { 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(); } catch (e) { if (pool) { @@ -347,7 +352,7 @@ exports.mssqlQuery = async function (connectionString, query) { * @returns {Promise<(string[] | object[] | object)>} Response from * server */ -exports.postgresQuery = function (connectionString, query) { +exports.postgresQuery = function (connectionString, handleEmptyResult, query) { return new Promise((resolve, reject) => { const config = postgresConParse(connectionString); @@ -384,7 +389,13 @@ exports.postgresQuery = function (connectionString, query) { if (err) { reject(err); } 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(); }); @@ -405,7 +416,7 @@ exports.postgresQuery = function (connectionString, query) { * @param {?string} password The password to use * @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) => { const connection = mysql.createConnection({ uri: connectionString, @@ -421,7 +432,7 @@ exports.mysqlQuery = function (connectionString, query, password = undefined) { reject(err); } else { if (Array.isArray(res)) { - if (res.length === 0) { + if (handleEmptyResult && res.length === 0) { reject(new Error("No rows returned")); } else { resolve("Rows: " + res.length);