Add returning

This commit is contained in:
Rory Powell 2021-11-23 13:27:38 +00:00
parent 1a0c66beb6
commit 7135599295
3 changed files with 29 additions and 16 deletions

View File

@ -416,6 +416,8 @@ 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))

View File

@ -4,12 +4,14 @@ import {
QueryTypes, QueryTypes,
SqlQuery, SqlQuery,
QueryJson, QueryJson,
Operation,
} from "../definitions/datasource" } from "../definitions/datasource"
import { import {
finaliseExternalTables, finaliseExternalTables,
getSqlQuery, getSqlQuery,
buildExternalTableId, buildExternalTableId,
convertSqlType, convertSqlType,
SqlClients,
} from "./utils" } from "./utils"
import oracledb, { import oracledb, {
ExecuteOptions, ExecuteOptions,
@ -168,7 +170,7 @@ module OracleModule {
OR cons.status IS NULL) OR cons.status IS NULL)
` `
constructor(config: OracleConfig) { constructor(config: OracleConfig) {
super("oracledb") super(SqlClients.ORACLE)
this.config = config this.config = config
} }
@ -346,13 +348,29 @@ 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()
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,
@ -411,20 +429,12 @@ module OracleModule {
} }
async query(json: QueryJson) { async query(json: QueryJson) {
const operation = this._operation(json).toLowerCase() const primaryKeys = json.meta!.table!.primary
const input = this._query(json, { disableReturning: true }) const primaryKey = primaryKeys ? primaryKeys[0] : undefined
if (Array.isArray(input)) { const queryFn = (query: any, operation: string) => 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 {
const response = await this.internalQuery(input)
return response.rows && response.rows.length
? response.rows
: [{ [operation]: true }]
}
} }
} }

View File

@ -42,6 +42,7 @@ export enum SqlClients {
MS_SQL = "mssql", MS_SQL = "mssql",
POSTGRES = "pg", POSTGRES = "pg",
MY_SQL = "mysql", MY_SQL = "mysql",
ORACLE = "oracledb"
} }
export function isExternalTable(tableId: string) { export function isExternalTable(tableId: string) {