From b631c8c624b877ad994d31715acd887404e479ec Mon Sep 17 00:00:00 2001 From: Rory Powell Date: Tue, 23 Nov 2021 13:27:38 +0000 Subject: [PATCH] Add returning --- packages/server/src/integrations/base/sql.ts | 2 + packages/server/src/integrations/oracle.ts | 42 ++++++++++++-------- packages/server/src/integrations/utils.ts | 1 + 3 files changed, 29 insertions(+), 16 deletions(-) diff --git a/packages/server/src/integrations/base/sql.ts b/packages/server/src/integrations/base/sql.ts index ea8e33af33..3014a76807 100644 --- a/packages/server/src/integrations/base/sql.ts +++ b/packages/server/src/integrations/base/sql.ts @@ -416,6 +416,8 @@ class SqlQueryBuilder extends SqlTableQueryBuilder { id = results?.[0].id } else if (sqlClient === SqlClients.MY_SQL) { id = results?.insertId + } else if (sqlClient === SqlClients.ORACLE) { + id = response.outBinds[0][0] } row = processFn( await this.getReturningRow(queryFn, this.checkLookupKeys(id, json)) diff --git a/packages/server/src/integrations/oracle.ts b/packages/server/src/integrations/oracle.ts index 532a1befd1..c74977bece 100644 --- a/packages/server/src/integrations/oracle.ts +++ b/packages/server/src/integrations/oracle.ts @@ -4,12 +4,14 @@ import { QueryTypes, SqlQuery, QueryJson, + Operation, } from "../definitions/datasource" import { finaliseExternalTables, getSqlQuery, buildExternalTableId, convertSqlType, + SqlClients, } from "./utils" import oracledb, { ExecuteOptions, @@ -168,7 +170,7 @@ module OracleModule { OR cons.status IS NULL) ` constructor(config: OracleConfig) { - super("oracledb") + super(SqlClients.ORACLE) this.config = config } @@ -346,13 +348,29 @@ module OracleModule { this.schemaErrors = final.errors } - private async internalQuery(query: SqlQuery): Promise> { + /** + * 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(query: SqlQuery, returnColum?: string, operation?: string): Promise> { let connection try { connection = await this.getConnection() const options: ExecuteOptions = { autoCommit: true } const bindings: BindParameters = query.bindings || [] + + if (returnColum && (operation === Operation.CREATE || operation === Operation.UPDATE)) { + this.addReturning(query, bindings, returnColum) + } + const result: Result = await connection.execute( query.sql, bindings, @@ -411,20 +429,12 @@ module OracleModule { } async query(json: QueryJson) { - const operation = this._operation(json).toLowerCase() - const input = this._query(json, { disableReturning: true }) - if (Array.isArray(input)) { - const responses = [] - for (let query of input) { - responses.push(await this.internalQuery(query)) - } - return responses - } else { - const response = await this.internalQuery(input) - return response.rows && response.rows.length - ? response.rows - : [{ [operation]: true }] - } + const primaryKeys = json.meta!.table!.primary + const primaryKey = primaryKeys ? primaryKeys[0] : undefined + const queryFn = (query: any, operation: string) => this.internalQuery(query, primaryKey, operation) + const processFn = (response: any) => response.rows ? response.rows : [] + const output = await this.queryWithReturning(json, queryFn, processFn) + return output } } diff --git a/packages/server/src/integrations/utils.ts b/packages/server/src/integrations/utils.ts index 594fee1b65..07cf0505bf 100644 --- a/packages/server/src/integrations/utils.ts +++ b/packages/server/src/integrations/utils.ts @@ -42,6 +42,7 @@ export enum SqlClients { MS_SQL = "mssql", POSTGRES = "pg", MY_SQL = "mysql", + ORACLE = "oracledb" } export function isExternalTable(tableId: string) {