Adding a mechanism to concat strings in queries, there was a problem when char const strings were wrapping bindings, this should find instances of that and replace with a datasource specific method of concating the constant with the variable.

This commit is contained in:
Michael Drury 2022-03-11 00:19:26 +00:00
parent 92bf490066
commit 07bcaf2d0a
7 changed files with 38 additions and 1 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)
// this returns the format of the identifier
getBindingIdentifier(): string
getStringConcat(parts: string[]): string
buildSchema(datasourceId: string, entities: Record<string, Table>): any
}

View File

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

View File

@ -129,6 +129,10 @@ module MSSQLModule {
return `(@p${this.index++})`
}
getStringConcat(parts: string[]): string {
return `concat(${parts.join(", ")})`
}
async connect() {
try {
this.client = await this.pool.connect()

View File

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

View File

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

View File

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

View File

@ -37,7 +37,23 @@ class QueryRunner {
for (let binding of bindings) {
let variable = integration.getBindingIdentifier()
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
fields.sql = sql