@visactor/vmind
Version:
<div align="center"> <a href="https://github.com/VisActor#gh-light-mode-only" target="_blank"> <img alt="VisActor Logo" width="200" src="https://github.com/VisActor/.github/blob/main/profile/logo_500_200_light.svg"/> </a> <a href="https://githu
177 lines (144 loc) • 8.81 kB
JavaScript
;
var __importDefault = this && this.__importDefault || function(mod) {
return mod && mod.__esModule ? mod : {
default: mod
};
};
Object.defineProperty(exports, "__esModule", {
value: !0
}), exports.parseRespondField = exports.convertGroupByToString = exports.sumAllMeasureFields = exports.replaceBlankSpace = exports.matchColumnName = exports.mergeMap = exports.replaceInvalidWords = exports.getValueByAttributeName = exports.replaceDataset = exports.replaceString = exports.replaceByMap = exports.swapMap = exports.removeEmptyLines = exports.parseSQLResponse = exports.generateRandomString = void 0;
const json5_1 = __importDefault(require("json5")), vutils_1 = require("@visactor/vutils"), text_1 = require("../../utils/text"), const_1 = require("./const"), types_1 = require("../../types"), alasql_1 = __importDefault(require("alasql")), field_1 = require("../../utils/field");
function generateRandomString(len) {
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
let result = "";
for (let i = 0; i < len; i++) result += chars.charAt(Math.floor(52 * Math.random()));
return result;
}
exports.generateRandomString = generateRandomString;
const operatorList = [ [ "+", `_${generateRandomString(3)}_PLUS_${generateRandomString(3)}_` ], [ "-", `_${generateRandomString(3)}_DASH_${generateRandomString(3)}_` ], [ "*", `_${generateRandomString(3)}_ASTERISK_${generateRandomString(3)}_` ], [ "/", `_${generateRandomString(3)}_SLASH_${generateRandomString(3)}_` ] ], operators = operatorList.map((op => op[0])), RESERVE_REPLACE_MAP = new Map([ ...operatorList, ...const_1.alasqlKeywordList.map((keyword => [ keyword, generateRandomString(10) ])) ]), parseSQLResponse = response => {
const sql = response.match(/sql:\n?```(.*?)```/s)[1], fieldInfoStr = response.match(/fieldInfo:\n?```(.*?)```/s)[1];
let fieldInfo = [];
try {
const tempFieldInfo = json5_1.default.parse(fieldInfoStr);
fieldInfo = (0, vutils_1.isArray)(tempFieldInfo) ? tempFieldInfo : tempFieldInfo.fieldInfo;
} catch (e) {
fieldInfo = json5_1.default.parse(`[${fieldInfoStr}]`);
}
return {
sql: sql,
llmFieldInfo: fieldInfo,
thoughts: ""
};
};
function removeEmptyLines(str) {
return str.replace(/\n\s*\n/g, "\n");
}
exports.parseSQLResponse = parseSQLResponse, exports.removeEmptyLines = removeEmptyLines;
const swapMap = map => {
const swappedMap = new Map;
return map.forEach(((value, key) => {
swappedMap.set(value, key);
})), swappedMap;
};
exports.swapMap = swapMap;
const replaceByMap = (str, replaceMap) => [ ...replaceMap.keys() ].reduce(((prev, cur) => {
const originColumnName = cur, validColumnName = replaceMap.get(cur);
return (0, text_1.replaceAll)(prev, originColumnName, validColumnName);
}), str);
exports.replaceByMap = replaceByMap;
const replaceNonASCIICharacters = str => {
const nonAsciiCharMap = new Map;
return {
validStr: str.replace(/([^\x00-\x7F]+)/g, (m => {
let replacement;
return nonAsciiCharMap.has(m) ? replacement = nonAsciiCharMap.get(m) : (replacement = generateRandomString(10),
nonAsciiCharMap.set(m, replacement)), replacement;
})),
replaceMap: nonAsciiCharMap
};
}, replaceString = (str, replaceMap) => {
if (!(0, vutils_1.isString)(str)) return str;
if (replaceMap.has(str)) return replaceMap.get(str);
return [ ...replaceMap.keys() ].sort(((a, b) => b.length - a.length)).reduce(((prev, cur) => (0,
text_1.replaceAll)(prev, cur, replaceMap.get(cur))), str);
};
exports.replaceString = replaceString;
const replaceDataset = (dataset, replaceMap, keysOnly) => dataset.map((d => Object.keys(d).reduce(((prev, cur) => {
const replacedKey = (0, exports.replaceString)(cur, replaceMap), replacedValue = (0,
exports.replaceString)(d[cur], replaceMap);
return prev[replacedKey] = keysOnly ? d[cur] : replacedValue, prev;
}), {})));
exports.replaceDataset = replaceDataset;
const getValueByAttributeName = (obj, outterKey) => {
const values = [];
for (const key in obj) if (key === outterKey && "string" == typeof obj[key]) values.push(obj[key]); else if ("object" == typeof obj[key]) {
const childValues = (0, exports.getValueByAttributeName)(obj[key], outterKey);
values.push(...childValues);
}
return (0, vutils_1.uniqArray)(values);
};
exports.getValueByAttributeName = getValueByAttributeName;
const replaceInvalidWords = (sql, columns) => {
const operatorReplaceMap = new Map, validColumnNames = columns.map((column => [ ...RESERVE_REPLACE_MAP.keys() ].reduce(((prev, cur) => {
const replaceStr = [ cur.toUpperCase(), cur.toLowerCase(), (0, text_1.capitalize)(cur) ].find((str => operators.includes(cur) ? prev.includes(str) : prev === str));
return replaceStr ? (operatorReplaceMap.has(replaceStr) || operatorReplaceMap.set(replaceStr, RESERVE_REPLACE_MAP.get(cur)),
(0, text_1.replaceAll)(prev, replaceStr, RESERVE_REPLACE_MAP.get(cur))) : prev;
}), column))), columnReplaceMap = new Map(columns.map(((column, index) => {
const validStr = validColumnNames[index];
if (column !== validStr) return [ column, validStr ];
})).filter(Boolean)), sqlWithoutOperator = (0, exports.replaceByMap)(sql, columnReplaceMap), {validStr: sqlWithoutAscii, replaceMap: asciiReplaceMap} = replaceNonASCIICharacters(sqlWithoutOperator);
return {
validStr: sqlWithoutAscii,
columnReplaceMap: operatorReplaceMap,
sqlReplaceMap: asciiReplaceMap
};
};
exports.replaceInvalidWords = replaceInvalidWords;
const mergeMap = (map1, map2) => (map2.forEach(((value, key) => {
map1.set(key, value);
})), map1);
exports.mergeMap = mergeMap;
const matchColumnName = (columnName, fieldName) => {
const fieldWithoutSpace = fieldName.replace(/\s/g, "");
return columnName.replace(/\s/g, "") === fieldWithoutSpace;
};
exports.matchColumnName = matchColumnName;
const replaceBlankSpace = (sql, fieldNames) => {
const ast = alasql_1.default.parse(sql), columnsInSql = (0, exports.getValueByAttributeName)(ast.statements[0], "columnid"), validColumnNames = columnsInSql.map((column => {
const matchedFieldName = fieldNames.find((field => (0, exports.matchColumnName)(column, field)));
return null != matchedFieldName ? matchedFieldName : column;
}));
return columnsInSql.reduce(((prev, _cur, index) => {
const originColumnName = columnsInSql[index], validColumnName = validColumnNames[index];
return validColumnName !== originColumnName ? (0, text_1.replaceAll)(prev, originColumnName, validColumnName) : prev;
}), sql);
};
exports.replaceBlankSpace = replaceBlankSpace;
const sumAllMeasureFields = (sql, fieldInfo, columnReplaceMap, sqlReplaceMap) => {
var _a;
const measureFieldsInSql = fieldInfo.filter((field => field.role === types_1.ROLE.MEASURE)).map((field => {
const {fieldName: fieldName} = field, replacedName1 = (0, exports.replaceString)(fieldName, columnReplaceMap);
return (0, exports.replaceString)(replacedName1, sqlReplaceMap);
})), ast = alasql_1.default.parse(sql), selectedColumns = ast.statements[0].columns, nonAggregatedColumns = selectedColumns.filter((column => !column.aggregatorid)).map((column => column.columnid)), groupByColumns = (null !== (_a = ast.statements[0].group) && void 0 !== _a ? _a : []).map((column => column.columnid));
let needAggregateColumns = [];
groupByColumns.length > 0 && nonAggregatedColumns.length !== selectedColumns.length && (needAggregateColumns = nonAggregatedColumns.filter((column => measureFieldsInSql.includes(column))).filter((column => !groupByColumns.includes(column))));
const patchedFields = needAggregateColumns.map((column => `SUM(\`${column}\`) as ${column}`));
return needAggregateColumns.reduce(((prev, cur, index) => {
const regex = new RegExp(`\`?${cur}\`?`, "g");
return prev.replace(regex, patchedFields[index]);
}), sql);
};
exports.sumAllMeasureFields = sumAllMeasureFields;
const convertGroupByToString = (sql, dataset) => {
const groupByColumns = alasql_1.default.parse(sql).statements[0].group.map((column => column.columnid));
dataset.forEach((item => {
groupByColumns.forEach((column => {
item[column] = item[column].toString();
}));
}));
};
exports.convertGroupByToString = convertGroupByToString;
const parseRespondField = (responseFieldInfo, dataset) => responseFieldInfo.map((field => Object.assign(Object.assign({}, field), (0,
field_1.detectFieldType)(dataset, field.fieldName))));
exports.parseRespondField = parseRespondField;
//# sourceMappingURL=utils.js.map