Merge pull request #3555 from Budibase/oracle/returning
Improve returning logic for oracle
This commit is contained in:
commit
301938eaa0
|
@ -4,7 +4,7 @@
|
||||||
version: "3.8"
|
version: "3.8"
|
||||||
services:
|
services:
|
||||||
db:
|
db:
|
||||||
container_name: oracle-xe
|
restart: always
|
||||||
platform: linux/x86_64
|
platform: linux/x86_64
|
||||||
image: container-registry.oracle.com/database/express:18.4.0-xe
|
image: container-registry.oracle.com/database/express:18.4.0-xe
|
||||||
environment:
|
environment:
|
||||||
|
|
|
@ -435,8 +435,6 @@ class SqlQueryBuilder extends SqlTableQueryBuilder {
|
||||||
id = results?.[0].id
|
id = results?.[0].id
|
||||||
} else if (sqlClient === SqlClients.MY_SQL) {
|
} else if (sqlClient === SqlClients.MY_SQL) {
|
||||||
id = results?.insertId
|
id = results?.insertId
|
||||||
} else if (sqlClient === SqlClients.ORACLE) {
|
|
||||||
id = response.outBinds[0][0]
|
|
||||||
}
|
}
|
||||||
row = processFn(
|
row = processFn(
|
||||||
await this.getReturningRow(queryFn, this.checkLookupKeys(id, json))
|
await this.getReturningRow(queryFn, this.checkLookupKeys(id, json))
|
||||||
|
|
|
@ -348,27 +348,7 @@ module OracleModule {
|
||||||
this.schemaErrors = final.errors
|
this.schemaErrors = final.errors
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private async internalQuery<T>(query: SqlQuery): Promise<Result<T>> {
|
||||||
* Knex default returning behaviour does not work with oracle
|
|
||||||
* Manually add the behaviour for the return column
|
|
||||||
*/
|
|
||||||
private addReturning(
|
|
||||||
query: SqlQuery,
|
|
||||||
bindings: BindParameters,
|
|
||||||
returnColumn: string
|
|
||||||
) {
|
|
||||||
if (bindings instanceof Array) {
|
|
||||||
bindings.push({ dir: oracledb.BIND_OUT })
|
|
||||||
query.sql =
|
|
||||||
query.sql + ` returning \"${returnColumn}\" into :${bindings.length}`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async internalQuery<T>(
|
|
||||||
query: SqlQuery,
|
|
||||||
returnColum?: string,
|
|
||||||
operation?: string
|
|
||||||
): Promise<Result<T>> {
|
|
||||||
let connection
|
let connection
|
||||||
try {
|
try {
|
||||||
connection = await this.getConnection()
|
connection = await this.getConnection()
|
||||||
|
@ -376,13 +356,6 @@ module OracleModule {
|
||||||
const options: ExecuteOptions = { autoCommit: true }
|
const options: ExecuteOptions = { autoCommit: true }
|
||||||
const bindings: BindParameters = query.bindings || []
|
const bindings: BindParameters = query.bindings || []
|
||||||
|
|
||||||
if (
|
|
||||||
returnColum &&
|
|
||||||
(operation === Operation.CREATE || operation === Operation.UPDATE)
|
|
||||||
) {
|
|
||||||
this.addReturning(query, bindings, returnColum)
|
|
||||||
}
|
|
||||||
|
|
||||||
const result: Result<T> = await connection.execute<T>(
|
const result: Result<T> = await connection.execute<T>(
|
||||||
query.sql,
|
query.sql,
|
||||||
bindings,
|
bindings,
|
||||||
|
@ -441,13 +414,46 @@ module OracleModule {
|
||||||
}
|
}
|
||||||
|
|
||||||
async query(json: QueryJson) {
|
async query(json: QueryJson) {
|
||||||
const primaryKeys = json.meta!.table!.primary
|
const operation = this._operation(json)
|
||||||
const primaryKey = primaryKeys ? primaryKeys[0] : undefined
|
const input = this._query(json, { disableReturning: true })
|
||||||
const queryFn = (query: any, operation: string) =>
|
if (Array.isArray(input)) {
|
||||||
this.internalQuery(query, primaryKey, operation)
|
const responses = []
|
||||||
const processFn = (response: any) => (response.rows ? response.rows : [])
|
for (let query of input) {
|
||||||
const output = await this.queryWithReturning(json, queryFn, processFn)
|
responses.push(await this.internalQuery(query))
|
||||||
return output
|
}
|
||||||
|
return responses
|
||||||
|
} else {
|
||||||
|
// read the row to be deleted up front for the return
|
||||||
|
let deletedRows
|
||||||
|
if (operation === Operation.DELETE) {
|
||||||
|
const queryFn = (query: any) => this.internalQuery(query)
|
||||||
|
deletedRows = await this.getReturningRow(queryFn, json)
|
||||||
|
}
|
||||||
|
|
||||||
|
// run the query
|
||||||
|
const response = await this.internalQuery(input)
|
||||||
|
|
||||||
|
// get the results or return the created / updated / deleted row
|
||||||
|
if (deletedRows?.rows?.length) {
|
||||||
|
return deletedRows.rows
|
||||||
|
} else if (response.rows?.length) {
|
||||||
|
return response.rows
|
||||||
|
} else {
|
||||||
|
// get the last row that was updated
|
||||||
|
if (
|
||||||
|
response.lastRowid &&
|
||||||
|
json.endpoint?.entityId &&
|
||||||
|
operation !== Operation.DELETE
|
||||||
|
) {
|
||||||
|
const lastRow = await this.internalQuery({
|
||||||
|
sql: `SELECT * FROM \"${json.endpoint.entityId}\" WHERE ROWID = '${response.lastRowid}'`,
|
||||||
|
})
|
||||||
|
return lastRow.rows
|
||||||
|
} else {
|
||||||
|
return [{ [ operation.toLowerCase() ]: true }]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue