diff --git a/packages/server/scripts/integrations/oracle/docker-compose.yml b/packages/server/scripts/integrations/oracle/docker-compose.yml index 5cd5e02f81..c54cd0a40b 100644 --- a/packages/server/scripts/integrations/oracle/docker-compose.yml +++ b/packages/server/scripts/integrations/oracle/docker-compose.yml @@ -4,7 +4,7 @@ version: "3.8" services: db: - container_name: oracle-xe + restart: always platform: linux/x86_64 image: container-registry.oracle.com/database/express:18.4.0-xe environment: diff --git a/packages/server/src/integrations/base/sql.ts b/packages/server/src/integrations/base/sql.ts index 1f733ac135..df4f2d511b 100644 --- a/packages/server/src/integrations/base/sql.ts +++ b/packages/server/src/integrations/base/sql.ts @@ -435,8 +435,6 @@ 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 13658399db..bf8e83350e 100644 --- a/packages/server/src/integrations/oracle.ts +++ b/packages/server/src/integrations/oracle.ts @@ -348,27 +348,7 @@ module OracleModule { this.schemaErrors = final.errors } - /** - * 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> { + private async internalQuery(query: SqlQuery): Promise> { let connection try { connection = await this.getConnection() @@ -376,13 +356,6 @@ module OracleModule { 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, @@ -441,13 +414,46 @@ module OracleModule { } async query(json: QueryJson) { - 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 + const operation = this._operation(json) + 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 { + // 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 }] + } + } + } } }