Added parsing for partialMatch parameter in generateReadQuery function. To see all contents, send no params. To see exact matches, send no partialMatch param or send partialMatch: false. Send partialMatch: true to see all partial matches.
Additionally, moved parameter definitions out of paramLibrary into paramsConfig.json - you can now add/remove/change parameter data type definitions inside of this file. If you get a console error of "Unsupported Param Type" then you may need to also update paramLibrary with handling for the data type you're using- use the existing definitions in functions such as formatMSSQLParams as a guide. Added testing for the partialMatch parameter to client.js.
This commit is contained in:
@@ -47,7 +47,7 @@ function getDBConfig(dbType) {
|
||||
database: process.env.DB_DATABASE,
|
||||
options: {
|
||||
encrypt: true, // for secure connection
|
||||
trustServerCertificate: process.env.DB_TRUST_CERT
|
||||
trustServerCertificate: true
|
||||
}
|
||||
};
|
||||
case 'ORACLE':
|
||||
|
||||
@@ -3,6 +3,14 @@
|
||||
const sql = require('mssql');
|
||||
const oracledb = require('oracledb');
|
||||
|
||||
// Load paramsConfig.json once at the start
|
||||
let paramsConfig;
|
||||
try {
|
||||
paramsConfig = require('./paramsConfig.json');
|
||||
} catch (error) {
|
||||
console.error('Error reading JSON config:', error);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats query parameters based on their keys and types, specific to each database type.
|
||||
*
|
||||
@@ -18,16 +26,16 @@ async function formatQueryParams(params) {
|
||||
|
||||
switch (DB_TYPE.toUpperCase()) {
|
||||
case 'MSSQL':
|
||||
formattedParams = formatMSSQLParams(params);
|
||||
formattedParams = formatMSSQLParams(params, paramsConfig.mssql);
|
||||
break;
|
||||
case 'ORACLE':
|
||||
formattedParams = formatOracleParams(params);
|
||||
formattedParams = formatOracleParams(params, paramsConfig.oracle);
|
||||
break;
|
||||
case 'MARIADB':
|
||||
formattedParams = formatMariaDBParams(params);
|
||||
formattedParams = formatMariaDBParams(params, paramsConfig.mariaDB);
|
||||
break;
|
||||
case 'POSTGRES':
|
||||
formattedParams = formatPostgresParams(params);
|
||||
formattedParams = formatPostgresParams(params, paramsConfig.postgres);
|
||||
break;
|
||||
default:
|
||||
throw new Error('Unsupported database type');
|
||||
@@ -41,66 +49,90 @@ async function formatQueryParams(params) {
|
||||
* Formats query parameters for MSSQL.
|
||||
*
|
||||
* @param {Object} params - An object containing the parameters to format.
|
||||
* @param {Object} config - Database-specific configuration from JSON.
|
||||
* @returns {Object} Formatted parameters.
|
||||
*/
|
||||
function formatMSSQLParams(params) {
|
||||
function formatMSSQLParams(params, config) {
|
||||
const formattedParams = {};
|
||||
for (const key in params) {
|
||||
if (key === 'ID') {
|
||||
console.log(`Formatting ID: ${params[key]}`); // Debugging log
|
||||
formattedParams[key] = { type: sql.UniqueIdentifier, value: params[key] };
|
||||
} else if (
|
||||
['Name', 'Description', 'Building', 'Owner', 'Role', 'Location', 'Route', 'Email', 'DisplayName', 'Team'].includes(key)
|
||||
) {
|
||||
formattedParams[key] = { type: sql.NVarChar(255), value: params[key] };
|
||||
} else if (key === 'Username' || key === 'AuthenticatedUsername') {
|
||||
formattedParams[key] = { type: sql.NVarChar(50), value: params[key].toLowerCase() }; // Normalize to lowercase
|
||||
} else if (key === 'UITheme' || key === 'UITHeme') {
|
||||
formattedParams[key] = { type: sql.NVarChar(50), value: params[key] };
|
||||
} else if (['Bio', 'PasswordHash', 'Image', 'AvatarURL'].includes(key)) {
|
||||
formattedParams[key] = { type: sql.Text, value: params[key] };
|
||||
} else if (key === 'SQL_USER') {
|
||||
formattedParams[key] = { type: sql.Bit, value: params[key] }; // Support for bit data type
|
||||
} else if (typeof params[key] === 'string') {
|
||||
formattedParams[key] = { type: sql.NVarChar(255), value: params[key] };
|
||||
} else if (typeof params[key] === 'number') {
|
||||
formattedParams[key] = { type: sql.Int, value: params[key] };
|
||||
if (!config[key]) {
|
||||
console.warn(`Parameter '${key}' not defined in the configuration.`);
|
||||
continue;
|
||||
}
|
||||
|
||||
const paramConfig = config[key];
|
||||
let type;
|
||||
|
||||
switch (paramConfig.type.toLowerCase()) {
|
||||
case 'uniqueidentifier':
|
||||
type = sql.UniqueIdentifier;
|
||||
break;
|
||||
case 'nvarchar':
|
||||
if (!paramConfig.maxLength) {
|
||||
throw new Error(`Parameter '${key}' is missing maxLength in configuration.`);
|
||||
}
|
||||
type = sql.NVarChar(paramConfig.maxLength);
|
||||
break;
|
||||
case 'text':
|
||||
type = sql.Text;
|
||||
break;
|
||||
case 'int':
|
||||
type = sql.Int;
|
||||
break;
|
||||
case 'bit':
|
||||
type = sql.Bit;
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Unsupported parameter type: ${paramConfig.type} for parameter '${key}'`);
|
||||
}
|
||||
|
||||
formattedParams[key] = { type, value: params[key] };
|
||||
}
|
||||
return formattedParams;
|
||||
}
|
||||
|
||||
// ... rest of the file ...
|
||||
|
||||
|
||||
/**
|
||||
* Formats query parameters for Oracle.
|
||||
*
|
||||
* @param {Object} params - An object containing the parameters to format.
|
||||
* @param {Object} config - Database-specific configuration from JSON.
|
||||
* @returns {Object} Formatted parameters.
|
||||
*/
|
||||
function formatOracleParams(params) {
|
||||
function formatOracleParams(params, config) {
|
||||
const formattedParams = {};
|
||||
for (const key in params) {
|
||||
if (key === 'ID') {
|
||||
formattedParams[key] = { type: oracledb.STRING, value: params[key] }; // UUID can be handled as a string
|
||||
} else if (
|
||||
['Name', 'Description', 'Building', 'Owner', 'Role', 'Location', 'Route', 'Email', 'DisplayName', 'Team'].includes(key)
|
||||
) {
|
||||
formattedParams[key] = { type: oracledb.STRING, value: params[key] };
|
||||
} else if (key === 'Username' || key === 'AuthenticatedUsername') {
|
||||
formattedParams[key] = { type: oracledb.STRING, value: params[key].toLowerCase() }; // Normalize to lowercase
|
||||
} else if (key === 'UITheme' || key === 'UITHeme') {
|
||||
formattedParams[key] = { type: oracledb.STRING, value: params[key] };
|
||||
} else if (['Bio', 'PasswordHash', 'Image', 'AvatarURL'].includes(key)) {
|
||||
formattedParams[key] = { type: oracledb.CLOB, value: params[key] };
|
||||
} else if (key === 'SQL_USER') {
|
||||
formattedParams[key] = { type: oracledb.BOOLEAN, value: params[key] }; // Support for bit data type
|
||||
} else if (typeof params[key] === 'string') {
|
||||
formattedParams[key] = { type: oracledb.STRING, value: params[key] };
|
||||
} else if (typeof params[key] === 'number') {
|
||||
formattedParams[key] = { type: oracledb.NUMBER, value: params[key] };
|
||||
if (!config[key]) {
|
||||
console.warn(`Parameter '${key}' not defined in the configuration.`);
|
||||
continue;
|
||||
}
|
||||
|
||||
const paramConfig = config[key];
|
||||
let type;
|
||||
|
||||
switch (paramConfig.type.toLowerCase()) {
|
||||
case 'string':
|
||||
type = oracledb.STRING;
|
||||
break;
|
||||
case 'varchar2':
|
||||
if (!paramConfig.maxLength) {
|
||||
throw new Error(`Parameter '${key}' is missing maxLength in configuration.`);
|
||||
}
|
||||
type = oracledb.VARCHAR2(paramConfig.maxLength);
|
||||
break;
|
||||
case 'clob':
|
||||
type = oracledb.CLOB;
|
||||
break;
|
||||
case 'number':
|
||||
type = oracledb.NUMBER;
|
||||
break;
|
||||
case 'boolean':
|
||||
type = oracledb.BOOLEAN;
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Unsupported parameter type: ${paramConfig.type} for parameter '${key}'`);
|
||||
}
|
||||
|
||||
formattedParams[key] = { type, value: params[key] };
|
||||
}
|
||||
return formattedParams;
|
||||
}
|
||||
@@ -109,30 +141,47 @@ function formatOracleParams(params) {
|
||||
* Formats query parameters for MariaDB.
|
||||
*
|
||||
* @param {Object} params - An object containing the parameters to format.
|
||||
* @param {Object} config - Database-specific configuration from JSON.
|
||||
* @returns {Object} Formatted parameters.
|
||||
*/
|
||||
function formatMariaDBParams(params) {
|
||||
function formatMariaDBParams(params, config) {
|
||||
const formattedParams = {};
|
||||
for (const key in params) {
|
||||
if (key === 'ID') {
|
||||
formattedParams[key] = { type: 'char', value: params[key] }; // UUID can be handled as a string
|
||||
} else if (
|
||||
['Name', 'Description', 'Building', 'Owner', 'Role', 'Location', 'Route', 'Email', 'DisplayName', 'Team'].includes(key)
|
||||
) {
|
||||
formattedParams[key] = { type: 'string', value: params[key] };
|
||||
} else if (key === 'Username' || key === 'AuthenticatedUsername') {
|
||||
formattedParams[key] = { type: 'string', value: params[key].toLowerCase() }; // Normalize to lowercase
|
||||
} else if (key === 'UITheme' || key === 'UITHeme') {
|
||||
formattedParams[key] = { type: 'string', value: params[key] };
|
||||
} else if (['Bio', 'PasswordHash', 'Image', 'AvatarURL'].includes(key)) {
|
||||
formattedParams[key] = { type: 'text', value: params[key] };
|
||||
} else if (key === 'SQL_USER') {
|
||||
formattedParams[key] = { type: 'boolean', value: params[key] }; // Support for bit data type
|
||||
} else if (typeof params[key] === 'string') {
|
||||
formattedParams[key] = { type: 'string', value: params[key] };
|
||||
} else if (typeof params[key] === 'number') {
|
||||
formattedParams[key] = { type: 'int', value: params[key] };
|
||||
if (!config[key]) {
|
||||
console.warn(`Parameter '${key}' not defined in the configuration.`);
|
||||
continue;
|
||||
}
|
||||
|
||||
const paramConfig = config[key];
|
||||
let type;
|
||||
|
||||
switch (paramConfig.type.toLowerCase()) {
|
||||
case 'char':
|
||||
if (!paramConfig.length) {
|
||||
throw new Error(`Parameter '${key}' is missing length in configuration.`);
|
||||
}
|
||||
type = { type: 'CHAR', length: paramConfig.length };
|
||||
break;
|
||||
case 'uuid':
|
||||
type = 'uuid';
|
||||
break;
|
||||
case 'string':
|
||||
type = 'string';
|
||||
break;
|
||||
case 'text':
|
||||
type = 'text';
|
||||
break;
|
||||
case 'int':
|
||||
type = 'int';
|
||||
break;
|
||||
case 'boolean':
|
||||
type = 'boolean';
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Unsupported parameter type: ${paramConfig.type} for parameter '${key}'`);
|
||||
}
|
||||
|
||||
formattedParams[key] = { type, value: params[key] };
|
||||
}
|
||||
return formattedParams;
|
||||
}
|
||||
@@ -141,32 +190,47 @@ function formatMariaDBParams(params) {
|
||||
* Formats query parameters for PostgreSQL.
|
||||
*
|
||||
* @param {Object} params - An object containing the parameters to format.
|
||||
* @param {Object} config - Database-specific configuration from JSON.
|
||||
* @returns {Object} Formatted parameters.
|
||||
*/
|
||||
function formatPostgresParams(params) {
|
||||
function formatPostgresParams(params, config) {
|
||||
const formattedParams = {};
|
||||
for (const key in params) {
|
||||
if (key === 'ID') {
|
||||
formattedParams[key] = { type: 'uuid', value: params[key] };
|
||||
} else if (
|
||||
['Name', 'Description', 'Building', 'Owner', 'Role', 'Location', 'Route', 'Email', 'DisplayName', 'Team'].includes(key)
|
||||
) {
|
||||
formattedParams[key] = { type: 'varchar', value: params[key] };
|
||||
} else if (key === 'Username' || key === 'AuthenticatedUsername') {
|
||||
formattedParams[key] = { type: 'varchar', value: params[key].toLowerCase() }; // Normalize to lowercase
|
||||
} else if (key === 'UITheme' || key === 'UITHeme') {
|
||||
formattedParams[key] = { type: 'varchar', value: params[key] };
|
||||
} else if (['Bio', 'PasswordHash', 'Image', 'AvatarURL'].includes(key)) {
|
||||
formattedParams[key] = { type: 'text', value: params[key] };
|
||||
} else if (key === 'SQL_USER') {
|
||||
formattedParams[key] = { type: 'boolean', value: params[key] }; // Support for bit data type
|
||||
} else if (typeof params[key] === 'string') {
|
||||
formattedParams[key] = { type: 'varchar', value: params[key] };
|
||||
} else if (typeof params[key] === 'number') {
|
||||
formattedParams[key] = { type: 'int', value: params[key] };
|
||||
if (!config[key]) {
|
||||
console.warn(`Parameter '${key}' not defined in the configuration.`);
|
||||
continue;
|
||||
}
|
||||
|
||||
const paramConfig = config[key];
|
||||
let type;
|
||||
|
||||
switch (paramConfig.type.toLowerCase()) {
|
||||
case 'uuid':
|
||||
type = 'uuid';
|
||||
break;
|
||||
case 'varchar':
|
||||
if (!paramConfig.length) {
|
||||
throw new Error(`Parameter '${key}' is missing length in configuration.`);
|
||||
}
|
||||
type = { type: 'VARCHAR', length: paramConfig.length };
|
||||
break;
|
||||
case 'text':
|
||||
type = 'text';
|
||||
break;
|
||||
case 'int':
|
||||
type = 'int';
|
||||
break;
|
||||
case 'boolean':
|
||||
type = 'boolean';
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Unsupported parameter type: ${paramConfig.type} for parameter '${key}'`);
|
||||
}
|
||||
|
||||
formattedParams[key] = { type, value: params[key] };
|
||||
}
|
||||
return formattedParams;
|
||||
}
|
||||
|
||||
module.exports = { formatQueryParams };
|
||||
|
||||
|
||||
90
services/dbconnector/paramsConfig.json
Normal file
90
services/dbconnector/paramsConfig.json
Normal file
@@ -0,0 +1,90 @@
|
||||
{
|
||||
"mssql": {
|
||||
"ID": { "type": "uniqueidentifier" },
|
||||
"Name": { "type": "nvarchar", "maxLength": 255 },
|
||||
"Description": { "type": "nvarchar", "maxLength": 255 },
|
||||
"Building": { "type": "nvarchar", "maxLength": 255 },
|
||||
"Owner": { "type": "nvarchar", "maxLength": 255 },
|
||||
"Role": { "type": "nvarchar", "maxLength": 255 },
|
||||
"Location": { "type": "nvarchar", "maxLength": 255 },
|
||||
"Route": { "type": "nvarchar", "maxLength": 255 },
|
||||
"Email": { "type": "nvarchar", "maxLength": 255 },
|
||||
"DisplayName": { "type": "nvarchar", "maxLength": 255 },
|
||||
"Team": { "type": "nvarchar", "maxLength": 255 },
|
||||
"Username": { "type": "nvarchar", "maxLength": 50 },
|
||||
"AuthenticatedUsername": { "type": "nvarchar", "maxLength": 50 },
|
||||
"UITheme": { "type": "nvarchar", "maxLength": 50 },
|
||||
"Bio": { "type": "text" },
|
||||
"PasswordHash": { "type": "text" },
|
||||
"Image": { "type": "text" },
|
||||
"AvatarURL": { "type": "text" },
|
||||
"SQL_USER": { "type": "bit" },
|
||||
"Text": { "type": "nvarchar", "maxLength": 255 }
|
||||
},
|
||||
"oracle": {
|
||||
"ID": { "type": "string" },
|
||||
"Name": { "type": "varchar2", "maxLength": 255 },
|
||||
"Description": { "type": "varchar2", "maxLength": 255 },
|
||||
"Text": { "type": "varchar2", "maxLength": 255 },
|
||||
"Building": { "type": "varchar2", "maxLength": 255 },
|
||||
"Owner": { "type": "varchar2", "maxLength": 255 },
|
||||
"Role": { "type": "varchar2", "maxLength": 255 },
|
||||
"Location": { "type": "varchar2", "maxLength": 255 },
|
||||
"Route": { "type": "varchar2", "maxLength": 255 },
|
||||
"Email": { "type": "varchar2", "maxLength": 255 },
|
||||
"DisplayName": { "type": "varchar2", "maxLength": 255 },
|
||||
"Team": { "type": "varchar2", "maxLength": 255 },
|
||||
"Username": { "type": "varchar2", "maxLength": 50 },
|
||||
"AuthenticatedUsername": { "type": "varchar2", "maxLength": 50 },
|
||||
"UITheme": { "type": "varchar2", "maxLength": 50 },
|
||||
"Bio": { "type": "clob" },
|
||||
"PasswordHash": { "type": "clob" },
|
||||
"Image": { "type": "clob" },
|
||||
"AvatarURL": { "type": "clob" },
|
||||
"SQL_USER": { "type": "boolean" }
|
||||
},
|
||||
"mariaDB": {
|
||||
"ID": { "type": "uuid" },
|
||||
"Name": { "type": "string" },
|
||||
"Description": { "type": "string" },
|
||||
"Text": { "type": "string" },
|
||||
"Building": { "type": "string" },
|
||||
"Owner": { "type": "string" },
|
||||
"Role": { "type": "string" },
|
||||
"Location": { "type": "string" },
|
||||
"Route": { "type": "string" },
|
||||
"Email": { "type": "string" },
|
||||
"DisplayName": { "type": "string" },
|
||||
"Team": { "type": "string" },
|
||||
"Username": { "type": "string" },
|
||||
"AuthenticatedUsername": { "type": "string" },
|
||||
"UITheme": { "type": "string" },
|
||||
"Bio": { "type": "text" },
|
||||
"PasswordHash": { "type": "text" },
|
||||
"Image": { "type": "text" },
|
||||
"AvatarURL": { "type": "text" },
|
||||
"SQL_USER": { "type": "boolean" }
|
||||
},
|
||||
"postgres": {
|
||||
"ID": { "type": "uuid" },
|
||||
"Name": { "type": "varchar", "length": 255 },
|
||||
"Description": { "type": "varchar", "length": 255 },
|
||||
"Text": { "type": "varchar", "length": 255 },
|
||||
"Building": { "type": "varchar", "length": 255 },
|
||||
"Owner": { "type": "varchar", "length": 255 },
|
||||
"Role": { "type": "varchar", "length": 255 },
|
||||
"Location": { "type": "varchar", "length": 255 },
|
||||
"Route": { "type": "varchar", "length": 255 },
|
||||
"Email": { "type": "varchar", "length": 255 },
|
||||
"DisplayName": { "type": "varchar", "length": 255 },
|
||||
"Team": { "type": "varchar", "length": 255 },
|
||||
"Username": { "type": "varchar", "length": 50 },
|
||||
"AuthenticatedUsername": { "type": "varchar", "length": 50 },
|
||||
"UITheme": { "type": "varchar", "length": 50 },
|
||||
"Bio": { "type": "text" },
|
||||
"PasswordHash": { "type": "text" },
|
||||
"Image": { "type": "text" },
|
||||
"AvatarURL": { "type": "text" },
|
||||
"SQL_USER": { "type": "boolean" }
|
||||
}
|
||||
}
|
||||
@@ -93,7 +93,7 @@ function validateCompareParams(params) {
|
||||
if (!params || typeof params !== 'object' || !params.compareTable || !params.idField) {
|
||||
throw new Error('Missing or invalid parameters for COMPARE operation. Please provide an object with "compareTable" and "idField" fields.');
|
||||
}
|
||||
}*/
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Generates a CREATE SQL query string based on database type, table, and parameters.
|
||||
@@ -144,22 +144,43 @@ function generateReadQuery(dbType, table, params) {
|
||||
// Prepare an array to hold WHERE conditions
|
||||
const whereConditions = [];
|
||||
|
||||
// Iterate over each parameter in params
|
||||
for (const key in params) {
|
||||
if (params.hasOwnProperty(key)) {
|
||||
const value = params[key];
|
||||
|
||||
// Construct the condition based on dbType
|
||||
if (params[key]) {
|
||||
let condition;
|
||||
if (key === 'partialMatch') continue; // Skip the partialSearch flag
|
||||
|
||||
switch (dbType.toUpperCase()) {
|
||||
case 'MSSQL':
|
||||
condition = `${key} = @${key}`;
|
||||
if (params.partialMatch) {
|
||||
condition = `${key} LIKE '%' + @${key} + '%'`;
|
||||
params[key] = `%${params[key]}%`; // Add % wildcard in params
|
||||
} else {
|
||||
condition = `${key} = @${key}`;
|
||||
}
|
||||
break;
|
||||
case 'ORACLE':
|
||||
if (params.partialMatch) {
|
||||
condition = `${key} LIKE '%' || :${key} || '%'`;
|
||||
params[key] = `%${params[key]}%`; // Add % wildcard in params
|
||||
} else {
|
||||
condition = `${key} = :${key}`;
|
||||
}
|
||||
break;
|
||||
case 'POSTGRES':
|
||||
condition = `${key} = $1`;
|
||||
if (params.partialMatch) {
|
||||
condition = `${key} LIKE $1`;
|
||||
params[key] = `%${params[key]}%`; // Add % wildcard in params
|
||||
} else {
|
||||
condition = `${key} = $1`;
|
||||
}
|
||||
break;
|
||||
case 'MARIADB':
|
||||
condition = `${key} = ?`;
|
||||
if (params.partialMatch) {
|
||||
condition = `${key} LIKE ?`;
|
||||
params[key] = `%${params[key]}%`; // Add % wildcard in params
|
||||
} else {
|
||||
condition = `${key} = ?`;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new Error('Unsupported database type');
|
||||
@@ -177,7 +198,6 @@ function generateReadQuery(dbType, table, params) {
|
||||
return query;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generates a UPDATE SQL query string based on database type, table, and parameters.
|
||||
*
|
||||
@@ -221,8 +241,6 @@ async function generateUpdateQuery(dbType, table, params) {
|
||||
return `UPDATE ${table} SET ${updateClause} ${whereClause};`;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Generates a DELETE SQL query string based on database type, table, and parameters.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user