socio
Version:
A WebSocket Real-Time Communication (RTC) API framework.
45 lines (44 loc) • 2.14 kB
JavaScript
import { soft_error } from './logging.js';
export function socio(strings, ...vars) { return ''; }
export const socio_string_regex = /socio`(?<sql>.*?)`/igs;
const table_extract_regex = '(?<tables>[\\w\\s\\.,_]+?)';
const Verb2TableRegex = {
SELECT: RegExp('FROM' + table_extract_regex + '(?:WHERE|ON|USING|;|$)', 'mi'),
INSERT: RegExp('INTO' + table_extract_regex + '(?:\\(|VALUES|DEFAULT)', 'i'),
UPDATE: RegExp('UPDATE\\s+(?:OR\\s+(?:ABORT|FAIL|IGNORE|REPLACE|ROLLBACK))?' + table_extract_regex + 'SET', 'i'),
DROP: RegExp('TABLE(?:\\s+IF EXISTS)?\\s+' + table_extract_regex + '(?:$|;)', 'mi'),
CREATE: RegExp('TABLE(?:\\s+IF NOT EXISTS)?\\s+' + table_extract_regex + '(?:AS|\\(|;|$)', 'mi'),
ALTER: RegExp('TABLE(?:\\s+IF NOT EXISTS)?\\s+' + table_extract_regex + '(?:RENAME|ADD|DROP)', 'i'),
};
export function QueryIsSelect(sql) {
return /^(\s+)?SELECT/im.test(sql);
}
export function ParseQueryTables(q) {
const verb = ParseQueryVerb(q);
if (!verb) {
soft_error(`Couldnt parse SQL verb.`, { sql_string: q, parsed_verb: verb });
return [];
}
;
if (!Object.keys(Verb2TableRegex).includes(verb)) {
soft_error(`Parsed SQL verb not supported for table extraction!`, { sql_string: q, parsed_verb: verb, supported: Object.keys(Verb2TableRegex) });
return [];
}
let tables_str = q.match(Verb2TableRegex[verb])?.groups?.tables;
if (!tables_str) {
soft_error(`SQL table extraction regex didnt match anything!`, { sql_string: q, parsed_verb: verb });
return [];
}
if (verb === 'SELECT')
tables_str = tables_str.replaceAll(/(\s+)?(NATURAL|LEFT|RIGHT|FULL|INNER|CROSS|OUTER|JOIN)(\s+)?/gi, ',').replaceAll(/,+/g, ' , ').replaceAll(/\s+/g, ' ');
tables_str = tables_str.replaceAll(/AS\s+\w+/g, '').trim();
if (tables_str.includes(','))
return tables_str
.split(/,[\s]*/mig)
.map((t) => t.split(/\s/mi)[0].trim()) || [];
else
return [tables_str];
}
export function ParseQueryVerb(q) {
return q.match(/^(\s+)?(?<verb>\w+)/mi)?.groups?.verb?.toUpperCase() || null;
}