dsql-admin/dsql-app/package-shared/functions/dsql/sql/sql-generator.ts

283 lines
9.8 KiB
TypeScript
Raw Normal View History

2025-01-13 08:00:21 +00:00
import {
ServerQueryParam,
ServerQueryParamsJoin,
ServerQueryQueryObject,
} from "../../../types";
2025-01-28 18:43:16 +00:00
type Param<T extends { [key: string]: any } = { [key: string]: any }> = {
genObject?: ServerQueryParam<T>;
2025-01-13 08:00:21 +00:00
tableName: string;
2025-01-28 18:43:16 +00:00
dbFullName?: string;
2025-01-13 08:00:21 +00:00
};
type Return =
| {
string: string;
values: string[];
}
| undefined;
2024-12-06 13:24:26 +00:00
/**
* # SQL Query Generator
* @description Generates an SQL Query for node module `mysql` or `serverless-mysql`
*/
2025-01-28 18:43:16 +00:00
export default function sqlGenerator<
T extends { [key: string]: any } = { [key: string]: any }
>({ tableName, genObject, dbFullName }: Param<T>): Return {
2024-12-06 13:24:26 +00:00
if (!genObject) return undefined;
const finalQuery = genObject.query ? genObject.query : undefined;
const queryKeys = finalQuery ? Object.keys(finalQuery) : undefined;
2025-01-13 08:00:21 +00:00
const sqlSearhValues: string[] = [];
2024-12-06 13:24:26 +00:00
2025-01-28 18:43:16 +00:00
const finalDbName = dbFullName ? `${dbFullName}.` : "";
2025-01-13 08:00:21 +00:00
/**
* # Generate Query
*/
function genSqlSrchStr({
queryObj,
join,
field,
}: {
queryObj: ServerQueryQueryObject[string];
join?: ServerQueryParamsJoin[];
field?: string;
}) {
2024-12-06 13:24:26 +00:00
const finalFieldName = (() => {
if (queryObj?.tableName) {
2025-01-28 18:43:16 +00:00
return `${finalDbName}${queryObj.tableName}.${field}`;
2024-12-06 13:24:26 +00:00
}
2025-01-13 08:00:21 +00:00
if (join) {
2025-01-28 18:43:16 +00:00
return `${finalDbName}${tableName}.${field}`;
2024-12-06 13:24:26 +00:00
}
return field;
})();
let str = `${finalFieldName}=?`;
if (
typeof queryObj.value == "string" ||
typeof queryObj.value == "number"
) {
const valueParsed = String(queryObj.value);
2025-01-13 08:00:21 +00:00
2024-12-06 13:24:26 +00:00
if (queryObj.equality == "LIKE") {
str = `LOWER(${finalFieldName}) LIKE LOWER('%${valueParsed}%')`;
2025-01-13 08:00:21 +00:00
} else if (queryObj.equality == "NOT EQUAL") {
str = `${finalFieldName} != ?`;
sqlSearhValues.push(valueParsed);
2024-12-06 13:24:26 +00:00
} else {
sqlSearhValues.push(valueParsed);
}
} else if (Array.isArray(queryObj.value)) {
2025-01-13 08:00:21 +00:00
const strArray: string[] = [];
2024-12-06 13:24:26 +00:00
queryObj.value.forEach((val) => {
const valueParsed = val;
if (queryObj.equality == "LIKE") {
strArray.push(
`LOWER(${finalFieldName}) LIKE LOWER('%${valueParsed}%')`
);
2025-01-13 08:00:21 +00:00
} else if (queryObj.equality == "NOT EQUAL") {
strArray.push(`${finalFieldName} != ?`);
sqlSearhValues.push(valueParsed);
2024-12-06 13:24:26 +00:00
} else {
strArray.push(`${finalFieldName} = ?`);
sqlSearhValues.push(valueParsed);
}
});
str = "(" + strArray.join(` ${queryObj.operator || "AND"} `) + ")";
}
return str;
2025-01-13 08:00:21 +00:00
}
const sqlSearhString = queryKeys?.map((field) => {
2025-02-12 16:56:44 +00:00
const queryObj = finalQuery?.[field];
2025-01-13 08:00:21 +00:00
if (!queryObj) return;
if (queryObj.__query) {
2025-02-12 16:56:44 +00:00
const subQueryGroup = queryObj.__query;
2025-01-13 08:00:21 +00:00
const subSearchKeys = Object.keys(subQueryGroup);
const subSearchString = subSearchKeys.map((_field) => {
const newSubQueryObj = subQueryGroup?.[_field];
return genSqlSrchStr({
queryObj: newSubQueryObj,
field: _field,
join: genObject.join,
});
});
return (
"(" +
subSearchString.join(` ${queryObj.operator || "AND"} `) +
")"
);
}
return genSqlSrchStr({ queryObj, field, join: genObject.join });
2024-12-06 13:24:26 +00:00
});
function generateJoinStr(
2025-01-13 08:00:21 +00:00
/** @type {import("../../../types").ServerQueryParamsJoinMatchObject} */ mtch: import("../../../types").ServerQueryParamsJoinMatchObject,
/** @type {import("../../../types").ServerQueryParamsJoin} */ join: import("../../../types").ServerQueryParamsJoin
2024-12-06 13:24:26 +00:00
) {
2025-01-28 18:43:16 +00:00
return `${finalDbName}${
2024-12-06 13:24:26 +00:00
typeof mtch.source == "object" ? mtch.source.tableName : tableName
}.${
typeof mtch.source == "object" ? mtch.source.fieldName : mtch.source
}=${(() => {
if (mtch.targetLiteral) {
return `'${mtch.targetLiteral}'`;
}
2025-01-13 08:00:21 +00:00
if (join.alias) {
2025-01-28 18:43:16 +00:00
return `${finalDbName}${
2025-01-13 08:00:21 +00:00
typeof mtch.target == "object"
? mtch.target.tableName
: join.alias
}.${
typeof mtch.target == "object"
? mtch.target.fieldName
: mtch.target
}`;
}
2025-01-28 18:43:16 +00:00
return `${finalDbName}${
2024-12-06 13:24:26 +00:00
typeof mtch.target == "object"
? mtch.target.tableName
: join.tableName
}.${
typeof mtch.target == "object"
? mtch.target.fieldName
: mtch.target
}`;
})()}`;
}
let queryString = (() => {
let str = "SELECT";
if (genObject.selectFields?.[0]) {
if (genObject.join) {
str += ` ${genObject.selectFields
2025-01-28 18:43:16 +00:00
?.map((fld) => `${finalDbName}${tableName}.${fld}`)
2024-12-06 13:24:26 +00:00
.join(",")}`;
} else {
str += ` ${genObject.selectFields?.join(",")}`;
}
} else {
if (genObject.join) {
2025-01-28 18:43:16 +00:00
str += ` ${finalDbName}${tableName}.*`;
2024-12-06 13:24:26 +00:00
} else {
str += " *";
}
}
if (genObject.join) {
/** @type {string[]} */
2025-01-13 08:00:21 +00:00
const existingJoinTableNames: string[] = [tableName];
2024-12-06 13:24:26 +00:00
str +=
"," +
genObject.join
.map((joinObj) => {
2025-01-13 08:00:21 +00:00
const joinTableName = joinObj.alias
? joinObj.alias
: joinObj.tableName;
if (existingJoinTableNames.includes(joinTableName))
2024-12-06 13:24:26 +00:00
return null;
2025-01-13 08:00:21 +00:00
existingJoinTableNames.push(joinTableName);
2024-12-06 13:24:26 +00:00
if (joinObj.selectFields) {
return joinObj.selectFields
2025-01-13 08:00:21 +00:00
.map((selectField) => {
if (typeof selectField == "string") {
2025-01-28 18:43:16 +00:00
return `${finalDbName}${joinTableName}.${selectField}`;
2025-01-13 08:00:21 +00:00
} else if (typeof selectField == "object") {
let aliasSelectField = selectField.count
2025-01-28 18:43:16 +00:00
? `COUNT(${finalDbName}${joinTableName}.${selectField.field})`
: `${finalDbName}${joinTableName}.${selectField.field}`;
2025-01-13 08:00:21 +00:00
if (selectField.alias)
aliasSelectField += ` AS ${selectField.alias}`;
return aliasSelectField;
2024-12-06 13:24:26 +00:00
}
})
.join(",");
} else {
2025-01-28 18:43:16 +00:00
return `${finalDbName}${joinTableName}.*`;
2024-12-06 13:24:26 +00:00
}
})
.filter((_) => Boolean(_))
.join(",");
}
2025-01-28 18:43:16 +00:00
str += ` FROM ${finalDbName}${tableName}`;
2024-12-06 13:24:26 +00:00
if (genObject.join) {
str +=
" " +
genObject.join
.map((join) => {
return (
join.joinType +
" " +
2025-01-13 08:00:21 +00:00
(join.alias
2025-01-28 18:43:16 +00:00
? `${finalDbName}${join.tableName}` +
" " +
join.alias
: `${finalDbName}${join.tableName}`) +
2024-12-06 13:24:26 +00:00
" ON " +
(() => {
if (Array.isArray(join.match)) {
return (
"(" +
join.match
.map((mtch) =>
generateJoinStr(mtch, join)
)
2025-01-13 08:00:21 +00:00
.join(
join.operator
? ` ${join.operator} `
: " AND "
) +
2024-12-06 13:24:26 +00:00
")"
);
} else if (typeof join.match == "object") {
return generateJoinStr(join.match, join);
}
})()
);
})
.join(" ");
}
return str;
})();
2025-01-13 08:00:21 +00:00
if (sqlSearhString?.[0] && sqlSearhString.find((str) => str)) {
2024-12-06 13:24:26 +00:00
const stringOperator = genObject?.searchOperator || "AND";
queryString += ` WHERE ${sqlSearhString.join(` ${stringOperator} `)} `;
}
if (genObject.order)
queryString += ` ORDER BY ${
genObject.join
2025-01-28 18:43:16 +00:00
? `${finalDbName}${tableName}.${String(genObject.order.field)}`
: String(genObject.order.field)
2024-12-06 13:24:26 +00:00
} ${genObject.order.strategy}`;
2025-01-13 08:00:21 +00:00
2024-12-06 13:24:26 +00:00
if (genObject.limit) queryString += ` LIMIT ${genObject.limit}`;
2025-01-13 08:00:21 +00:00
if (genObject.offset) queryString += ` OFFSET ${genObject.offset}`;
2024-12-06 13:24:26 +00:00
return {
string: queryString,
values: sqlSearhValues,
};
}