autosql
Version:
An auto-parser of JSON into SQL.
150 lines (149 loc) • 6.97 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.MySQLInsertQueryBuilder = void 0;
const mysqlConfig_1 = require("../../config/mysqlConfig");
const utilities_1 = require("../../../helpers/utilities");
const dialectConfig = mysqlConfig_1.mysqlConfig;
class MySQLInsertQueryBuilder {
static getInsertStatementQuery(tableOrInput, data, metaData, databaseConfig, inputInsertType) {
let table;
let rows;
let header;
let insertType;
const schemaPrefix = databaseConfig?.schema ? `\`${databaseConfig.schema}\`.` : "";
if (typeof tableOrInput === "object" && "table" in tableOrInput) {
table = tableOrInput.table;
rows = tableOrInput.data;
header = tableOrInput.comparedMetaData?.updatedMetaData || tableOrInput.metaData;
insertType = tableOrInput?.insertType || databaseConfig?.insertType || "UPDATE";
}
else {
table = tableOrInput;
rows = data;
header = metaData;
insertType = inputInsertType || databaseConfig?.insertType || "UPDATE";
}
if (!rows || rows.length === 0) {
throw new Error(`No data provided for insert into table "${table}"`);
}
const columns = Object.keys(header);
// Flatten values
let params = [];
if (typeof rows[0] === "object" && !Array.isArray(rows[0])) {
const normalisedChunk = rows.map(row => (0, utilities_1.getInsertValues)(header, row, undefined, undefined, false) // ⬅ false = flatten
);
params = normalisedChunk.flat();
}
else {
params = rows.flat();
}
const escapedCols = columns.map(col => `\`${col}\``).join(", ");
const valuePlaceholders = rows
.map(() => `(${columns.map(() => `?`).join(", ")})`)
.join(", ");
let query = `INSERT INTO ${schemaPrefix}\`${table}\` (${escapedCols}) VALUES ${valuePlaceholders}`;
if (insertType === "UPDATE") {
// Get primary key columns
const primaryKeys = Object.keys(header).filter((col) => header[col].primary === true);
const updateCols = columns.filter((col) => {
const colMeta = header[col];
// Exclude primary keys and protected calculated fields
const isPrimary = primaryKeys.includes(col);
const isProtectedCalc = colMeta.calculated === true && colMeta.updatedCalculated === false;
return !isPrimary && !isProtectedCalc;
});
if (updateCols.length > 0) {
const updateSet = updateCols
.map(col => `\`${col}\` = VALUES(\`${col}\`)`)
.join(", ");
query += ` ON DUPLICATE KEY UPDATE ${updateSet}`;
}
}
const result = {
query,
params
};
return result;
}
static getInsertFromStagingQuery(tableOrInput, metaData, databaseConfig, inputInsertType) {
let table;
let header;
let insertType;
const schemaPrefix = databaseConfig?.schema ? `\`${databaseConfig.schema}\`.` : "";
if (typeof tableOrInput === "object" && "table" in tableOrInput) {
table = tableOrInput.table;
header = tableOrInput.comparedMetaData?.updatedMetaData || tableOrInput.metaData;
insertType = tableOrInput?.insertType || databaseConfig?.insertType || "UPDATE";
}
else {
table = tableOrInput;
header = metaData;
insertType = inputInsertType || databaseConfig?.insertType || "UPDATE";
}
const tempTable = (0, utilities_1.getTempTableName)(table);
const columns = Object.keys(header);
const escapedCols = columns.map(col => `\`${col}\``).join(", ");
const selectCols = columns.map(col => `\`${col}\``).join(", ");
let query = `INSERT INTO ${schemaPrefix}\`${table}\` (${escapedCols}) SELECT ${selectCols} FROM ${schemaPrefix}\`${tempTable}\``;
if (insertType === "UPDATE") {
const primaryKeys = Object.keys(header).filter(col => header[col].primary === true);
const updateCols = columns.filter((col) => {
const colMeta = header[col];
const isPrimary = primaryKeys.includes(col);
const isProtectedCalc = colMeta.calculated === true && colMeta.updatedCalculated === false;
return !isPrimary && !isProtectedCalc;
});
if (updateCols.length > 0) {
const updateSet = updateCols
.map(col => `\`${col}\` = VALUES(\`${col}\`)`)
.join(", ");
query += ` ON DUPLICATE KEY UPDATE ${updateSet}`;
}
}
return {
query,
params: []
};
}
static getInsertChangedRowsToHistoryQuery(tableOrInput, metaData, databaseConfig) {
let table;
let header;
const schemaPrefix = databaseConfig?.schema ? `\`${databaseConfig.schema}\`.` : "";
if (typeof tableOrInput === "object" && "table" in tableOrInput) {
table = (0, utilities_1.getTrueTableName)(tableOrInput.table);
header = tableOrInput.comparedMetaData?.updatedMetaData || tableOrInput.metaData;
}
else {
table = (0, utilities_1.getTrueTableName)(tableOrInput);
header = metaData;
}
const historyTable = (0, utilities_1.getHistoryTableName)(table);
const tempTable = (0, utilities_1.getTempTableName)(table);
const filteredCols = Object.keys(header).filter(col => col !== "dwh_as_at");
const primaryKeys = filteredCols.filter(col => header[col].primary);
const nonPrimaryCols = filteredCols.filter(col => !header[col].primary && header[col].calculated !== true);
const t1 = "t1";
const t2 = "t2";
const valuesCols = filteredCols.map(col => `\`${col}\``).join(", ");
const selectCols = filteredCols.map(col => `${t1}.\`${col}\``).join(", ");
const joinCondition = primaryKeys
.map(pk => `${t1}.\`${pk}\` = ${t2}.\`${pk}\``)
.join(" AND ");
const diffCondition = nonPrimaryCols
.map(col => `${t1}.\`${col}\` <=> ${t2}.\`${col}\` = FALSE`)
.join(" OR ");
const query = `
INSERT INTO ${schemaPrefix}\`${historyTable}\` (${valuesCols}, \`dwh_as_at\`)
SELECT ${selectCols}, NOW()
FROM ${schemaPrefix}\`${table}\` ${t1}
LEFT JOIN ${schemaPrefix}\`${tempTable}\` ${t2}
ON ${joinCondition}
WHERE ${diffCondition};
`.trim();
return {
query,
params: []
};
}
}
exports.MySQLInsertQueryBuilder = MySQLInsertQueryBuilder;