jeep-sqlite
Version:
Browser SQLite Stencil Component
229 lines (228 loc) • 9.33 kB
JavaScript
export class UtilsSQLStatement {
static extractTableName(statement) {
const pattern = /(?:INSERT\s+INTO|UPDATE|DELETE\s+FROM)\s+([^\s]+)/i;
const match = statement.match(pattern);
if (match && match[1]) {
const tableName = match[1];
return tableName;
}
return null;
}
static extractWhereClause(statement) {
const pattern = /WHERE(.+?)(?:ORDER\s+BY|LIMIT|$)/i;
const match = statement.match(pattern);
if (match && match[1]) {
const whereClause = match[1].trim();
return whereClause;
}
return null;
}
static addPrefixToWhereClause(whereClause, colNames, refNames, prefix) {
let columnValuePairs;
// TODO "OR" and "NOT"
if (whereClause.includes("AND")) {
// Split the WHERE clause based on the "AND" keyword
const subSequenceArray = whereClause.split("AND");
columnValuePairs = subSequenceArray.map((pair) => pair.trim());
}
else {
columnValuePairs = [whereClause];
}
const modifiedPairs = columnValuePairs.map((pair) => {
const match = pair.match(/(\w+)\s*(=|<|<=|<>|>|>=|IN|BETWEEN|LIKE)\s*(.+)/);
if (!match) {
return pair;
}
const column = match[1].trim();
const operator = match[2].trim();
let value = match[3].trim();
let newColumn = column;
const index = UtilsSQLStatement.findIndexOfStringInArray(column, refNames);
if (index !== -1) {
newColumn = UtilsSQLStatement.getStringAtIndex(colNames, index);
}
const modifiedColumn = `${prefix}${newColumn}`;
const ret = `${modifiedColumn} ${operator} ${value}`;
return ret;
});
return modifiedPairs.join(" AND ");
}
static findIndexOfStringInArray(target, array) {
return array.indexOf(target);
}
static getStringAtIndex(array, index) {
if (index >= 0 && index < array.length) {
return array[index];
}
else {
return undefined;
}
}
static extractForeignKeyInfo(sqlStatement) {
// Define the regular expression pattern for extracting the FOREIGN KEY clause
const foreignKeyPattern = /\bFOREIGN\s+KEY\s*\(([^)]+)\)\s+REFERENCES\s+(\w+)\s*\(([^)]+)\)\s+(ON\s+DELETE\s+(RESTRICT|CASCADE|SET\s+NULL|SET\s+DEFAULT|NO\s+ACTION))?/;
const matches = sqlStatement.match(foreignKeyPattern);
if (matches) {
const foreignKeyInfo = {
forKeys: matches[1].split(",").map(key => key.trim()),
tableName: matches[2],
refKeys: matches[3].split(",").map(key => key.trim()),
action: matches[5] ? matches[5] : "NO ACTION"
};
return foreignKeyInfo;
}
else {
throw new Error("extractForeignKeyInfo: No FOREIGN KEY found");
}
}
static extractColumnNames(whereClause) {
const keywords = new Set([
"AND", "OR", "IN", "VALUES", "LIKE", "BETWEEN", "NOT"
]);
const regex = /\b[a-zA-Z]\w*\b(?=\s*(?:<=?|>=?|<>?|=|AND|OR|BETWEEN|NOT|IN|LIKE))|\b[a-zA-Z]\w*\b\s+BETWEEN\s+'[^']+'\s+AND\s+'[^']+'|\(([^)]+)\)\s+IN\s+\(?\s*VALUES\s*\(/g;
let match;
const columns = [];
while ((match = regex.exec(whereClause)) !== null) {
const columnList = match[1];
if (columnList) {
const columnNamesArray = columnList.split(',');
for (const columnName of columnNamesArray) {
columns.push(columnName.trim());
}
}
else {
const matchedText = match[0];
if (!keywords.has(matchedText.trim().toUpperCase())) {
columns.push(matchedText.trim());
}
}
}
return columns;
}
static flattenMultilineString(input) {
const lines = input.split(/\r?\n/);
return lines.join(" ");
}
static getStmtAndRetColNames(sqlStmt, retMode) {
const retWord = "RETURNING";
const retStmtNames = { stmt: sqlStmt, names: "" };
const retWordIndex = sqlStmt.toUpperCase().indexOf(retWord);
if (retWordIndex !== -1) {
const prefix = sqlStmt.substring(0, retWordIndex);
retStmtNames.stmt = `${prefix};`;
if (retMode.substring(0, 2) === "wA") {
const suffix = sqlStmt.substring(retWordIndex + retWord.length);
const names = suffix.trim();
if (names.endsWith(";")) {
retStmtNames.names = names.substring(0, names.length - 1);
}
else {
retStmtNames.names = names;
}
}
}
return retStmtNames;
}
static extractCombinedPrimaryKey(whereClause) {
const pattern = /WHERE\s*\((.+?)\)\s*(?:=|IN)\s*\((.+?)\)/g;
const regex = new RegExp(pattern);
const matches = whereClause.matchAll(regex);
const primaryKeySets = [];
for (const match of matches) {
const keysString = match[1].trim();
const keys = keysString.split(",").map((key) => key.trim());
primaryKeySets.push(keys);
}
return primaryKeySets.length === 0 ? null : primaryKeySets;
}
static getWhereStmtForCombinedPK(whStmt, withRefs, colNames, keys) {
let retWhere = whStmt;
for (const grpKeys of keys) {
const repKeys = grpKeys.join(",") === withRefs.join(",") ? colNames : withRefs;
for (const [index, key] of grpKeys.entries()) {
retWhere = UtilsSQLStatement.replaceAllString(retWhere, key, repKeys[index]);
}
}
return retWhere;
}
static replaceAllString(originalStr, searchStr, replaceStr) {
return originalStr.split(searchStr).join(replaceStr);
}
static indicesOf(str, searchStr, fromIndex = 0) {
// Helper function to find indices of a substring within a string
const indices = [];
let currentIndex = str.indexOf(searchStr, fromIndex);
while (currentIndex !== -1) {
indices.push(currentIndex);
currentIndex = str.indexOf(searchStr, currentIndex + 1);
}
return indices;
}
static getWhereStmtForNonCombinedPK(whStmt, withRefs, colNames) {
let whereStmt = "";
let stmt = whStmt.substring(6);
for (let idx = 0; idx < withRefs.length; idx++) {
let colType = "withRefsNames";
let idxs = UtilsSQLStatement.indicesOf(stmt, withRefs[idx]);
if (idxs.length === 0) {
idxs = UtilsSQLStatement.indicesOf(stmt, colNames[idx]);
colType = "colNames";
}
if (idxs.length > 0) {
let valStr = "";
const indicesEqual = UtilsSQLStatement.indicesOf(stmt, "=", idxs[0]);
if (indicesEqual.length > 0) {
const indicesAnd = UtilsSQLStatement.indicesOf(stmt, "AND", indicesEqual[0]);
if (indicesAnd.length > 0) {
valStr = stmt.substring(indicesEqual[0] + 1, indicesAnd[0] - 1);
stmt = stmt.substring(indicesAnd[0] + 3);
}
else {
valStr = stmt.substring(indicesEqual[0] + 1);
}
if (idx > 0) {
whereStmt += " AND ";
}
if (colType === "withRefsNames") {
whereStmt += colNames[idx] + " = " + valStr;
}
else {
whereStmt += withRefs[idx] + " = " + valStr;
}
}
}
}
whereStmt = "WHERE " + whereStmt;
return whereStmt;
}
static updateWhere(whStmt, withRefs, colNames) {
let whereStmt = "";
if (whStmt.length <= 0) {
return whereStmt;
}
if (whStmt.toUpperCase().substring(0, 5) !== "WHERE") {
return whereStmt;
}
if (withRefs.length === colNames.length) {
// get whereStmt for primary combined key
const keys = UtilsSQLStatement.extractCombinedPrimaryKey(whStmt);
if (keys) {
whereStmt = UtilsSQLStatement.getWhereStmtForCombinedPK(whStmt, withRefs, colNames, keys);
}
else {
// get for non primary combined key
whereStmt = UtilsSQLStatement.getWhereStmtForNonCombinedPK(whStmt, withRefs, colNames);
}
}
return whereStmt;
}
}
UtilsSQLStatement.replaceString = (originalStr, searchStr, replaceStr) => {
const range = originalStr.indexOf(searchStr);
if (range !== -1) {
const modifiedStr = originalStr.substring(0, range) + replaceStr + originalStr.substring(range + searchStr.length);
return modifiedStr;
}
return originalStr;
};
//# sourceMappingURL=utils-sqlstatement.js.map