I have a dynamic string that is generated like one of the following:
var q = "FROM Table SELECT avg(1), avg(2), avg(3) where x='y'
var q = "SELECT avg(1), avg(2), avg(3) FROM Table where z='x' since x days ago
The values after the select are also dynamic where there could be 1 select option, or 10. I'm trying to create some logic to always pluck whatever is selected into an array, but having trouble dealing with the dynamic nature (string being constructed dynamically AND the # of selects being dynamic).
Basically, end result something like this:
['avg(1)', 'avg(2)', 'avg(3)']
Currently I'm doing something like the following, but it always expects the string to be formatted in a certain order (always starting with SELECT
and where
after the fields to pluck):
let splitQ = q.match(".*SELECT(.*)where");
let selects = splitQ[1].trim().split(",");
CodePudding user response:
Here is a working solution. It makes these assumptions about the query (after lowercased).
- the values come after the first instance of the word 'select '
- if the query starts with 'from', values end before the first instance of ' where'
- if the query starts with 'select', values end before the first instance of ' from'
const test1 = "FROM Table SELECT avg(1), avg(2), avg(3) where x='y'";
const test2 = "SELECT avg(1), avg(2), avg(3) FROM Table where z='x' since x days ago";
function extractValues(query) {
// in both scenarios, the values always come directly after 'select '
const valuesComeAfterMe = 'select ';
query = query.toLowerCase();
let valuesEndBeforeMe;
// conditionally handle both query syntaxes
if (query.startsWith('from')) {
valuesEndBeforeMe = ' where';
} else if (query.startsWith('select')) {
valuesEndBeforeMe = ' from';
} else {
throw Error('query not handled');
}
// remove start
query = query.slice(query.indexOf(valuesComeAfterMe) valuesComeAfterMe.length);
// remove end
query = query.slice(0, query.indexOf(valuesEndBeforeMe));
// split values and trim whitespace
return query.split(',').map(item => item.trim());
}
console.log(extractValues(test1));
console.log(extractValues(test2));