1
0
Fork 0
mirror of synced 2024-09-10 14:35:47 +12:00

Merge pull request #5240 from Budibase/fix/4978

Fix for IN SQL query parsing - handling parentheses and string interpolation
This commit is contained in:
Michael Drury 2022-04-05 14:32:16 +01:00 committed by GitHub
commit d1a08f6530

View file

@ -9,6 +9,8 @@ const {
const { doInAppContext, getAppDB } = require("@budibase/backend-core/context") const { doInAppContext, getAppDB } = require("@budibase/backend-core/context")
const { isSQL } = require("../integrations/utils") const { isSQL } = require("../integrations/utils")
const CONST_CHAR_REGEX = new RegExp("'[^']*'", "g")
class QueryRunner { class QueryRunner {
constructor(input, flags = { noRecursiveQuery: false }) { constructor(input, flags = { noRecursiveQuery: false }) {
this.datasource = input.datasource this.datasource = input.datasource
@ -37,17 +39,22 @@ class QueryRunner {
arrays = [] arrays = []
for (let binding of bindings) { for (let binding of bindings) {
// look for array/list operations in the SQL statement, which will need handled later // look for array/list operations in the SQL statement, which will need handled later
const listRegex = new RegExp(`(in|IN|In|iN)( )+${binding}`) const listRegexMatch = sql.match(
const listRegexMatch = sql.match(listRegex) new RegExp(`(in|IN|In|iN)( )+[(]?${binding}[)]?`)
)
// check if the variable was used as part of a string concat e.g. 'Hello {{binding}}' // check if the variable was used as part of a string concat e.g. 'Hello {{binding}}'
const charConstRegex = new RegExp(`'[^']*${binding}[^']*'`) // start by finding all the instances of const character strings
const charConstMatch = sql.match(charConstRegex) const charConstMatch = sql.match(CONST_CHAR_REGEX) || []
if (charConstMatch) { // now look within them to see if a binding is used
let [part1, part2] = charConstMatch[0].split(binding) const charConstBindingMatch = charConstMatch.find(string =>
string.match(new RegExp(`'[^']*${binding}[^']*'`))
)
if (charConstBindingMatch) {
let [part1, part2] = charConstBindingMatch.split(binding)
part1 = `'${part1.substring(1)}'` part1 = `'${part1.substring(1)}'`
part2 = `'${part2.substring(0, part2.length - 1)}'` part2 = `'${part2.substring(0, part2.length - 1)}'`
sql = sql.replace( sql = sql.replace(
charConstMatch[0], charConstBindingMatch,
integration.getStringConcat([ integration.getStringConcat([
part1, part1,
integration.getBindingIdentifier(), integration.getBindingIdentifier(),
@ -63,12 +70,14 @@ class QueryRunner {
"," ","
) )
// build a string like ($1, $2, $3) // build a string like ($1, $2, $3)
sql = sql.replace( let replacement = `${Array.apply(null, Array(value.length))
binding, .map(() => integration.getBindingIdentifier())
`(${Array.apply(null, Array(value.length)) .join(",")}`
.map(() => integration.getBindingIdentifier()) // check if parentheses are needed
.join(",")})` if (!listRegexMatch[0].includes(`(${binding})`)) {
) replacement = `(${replacement})`
}
sql = sql.replace(binding, replacement)
} else { } else {
sql = sql.replace(binding, integration.getBindingIdentifier()) sql = sql.replace(binding, integration.getBindingIdentifier())
} }