Merge pull request #4888 from Budibase/fix/sql-queries

Fixing SQL constant character usage in queries with bindings
This commit is contained in:
Michael Drury 2022-03-13 10:45:00 +00:00 committed by GitHub
commit c247832231
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 39 additions and 2 deletions

View File

@ -8,5 +8,6 @@ export interface DatasourcePlus extends IntegrationBase {
// if the datasource supports the use of bindings directly (to protect against SQL injection) // if the datasource supports the use of bindings directly (to protect against SQL injection)
// this returns the format of the identifier // this returns the format of the identifier
getBindingIdentifier(): string getBindingIdentifier(): string
getStringConcat(parts: string[]): string
buildSchema(datasourceId: string, entities: Record<string, Table>): any buildSchema(datasourceId: string, entities: Record<string, Table>): any
} }

View File

@ -115,6 +115,10 @@ module GoogleSheetsModule {
return "" return ""
} }
getStringConcat(parts: string[]) {
return ""
}
/** /**
* Pull the spreadsheet ID out from a valid google sheets URL * Pull the spreadsheet ID out from a valid google sheets URL
* @param spreadsheetId - the URL or standard spreadsheetId of the google sheet * @param spreadsheetId - the URL or standard spreadsheetId of the google sheet

View File

@ -126,7 +126,11 @@ module MSSQLModule {
} }
getBindingIdentifier(): string { getBindingIdentifier(): string {
return `(@p${this.index++})` return `@p${this.index++}`
}
getStringConcat(parts: string[]): string {
return `concat(${parts.join(", ")})`
} }
async connect() { async connect() {

View File

@ -99,6 +99,10 @@ module MySQLModule {
return "?" return "?"
} }
getStringConcat(parts: string[]): string {
return `concat(${parts.join(", ")})`
}
async connect() { async connect() {
this.client = await mysql.createConnection(this.config) this.client = await mysql.createConnection(this.config)
} }

View File

@ -179,6 +179,10 @@ module OracleModule {
return `:${this.index++}` return `:${this.index++}`
} }
getStringConcat(parts: string[]): string {
return parts.join(" || ")
}
/** /**
* Map the flat tabular columns and constraints data into a nested object * Map the flat tabular columns and constraints data into a nested object
*/ */

View File

@ -148,6 +148,10 @@ module PostgresModule {
return `$${this.index++}` return `$${this.index++}`
} }
getStringConcat(parts: string[]): string {
return parts.join(" || ")
}
async internalQuery(query: SqlQuery) { async internalQuery(query: SqlQuery) {
const client = this.client const client = this.client
this.index = 1 this.index = 1

View File

@ -37,7 +37,23 @@ class QueryRunner {
for (let binding of bindings) { for (let binding of bindings) {
let variable = integration.getBindingIdentifier() let variable = integration.getBindingIdentifier()
variables.push(binding) variables.push(binding)
sql = sql.replace(binding, variable) // check if the variable was used as part of a string concat e.g. 'Hello {{binding}}'
const charConstRegex = new RegExp(`'[^']*${binding}[^']*'`)
const charConstMatch = sql.match(charConstRegex)
if (charConstMatch) {
let [part1, part2] = charConstMatch[0].split(binding)
part1 = `'${part1.substring(1)}'`
part2 = `'${part2.substring(0, part2.length - 1)}'`
sql = sql.replace(
charConstMatch[0],
integration.getStringConcat([part1, variable, part2])
)
} else {
sql = sql.replace(binding, variable)
}
// const indexOfBinding = sql.indexOf(binding)
// const constantStr = `'${binding}'`
// sql = sql.replace(sql.indexOf(constantStr) === indexOfBinding - 1 ? constantStr : binding, variable)
} }
// replicate the knex structure // replicate the knex structure
fields.sql = sql fields.sql = sql