diff --git a/packages/nocodb/src/lib/db/sql-client/lib/oracle/OracleClient.ts b/packages/nocodb/src/lib/db/sql-client/lib/oracle/OracleClient.ts index e7ef13cd00..9a79ab5459 100644 --- a/packages/nocodb/src/lib/db/sql-client/lib/oracle/OracleClient.ts +++ b/packages/nocodb/src/lib/db/sql-client/lib/oracle/OracleClient.ts @@ -1568,10 +1568,15 @@ class OracleClient extends KnexClient { this.emit(`Success : ${upQuery}`); + const triggerStatements = await this.afterTableCreate(args); + /**************** return files *************** */ result.data.object = { - upStatement: [{ sql: upQuery }], - downStatement, + upStatement: [{ sql: upQuery }, ...triggerStatements.upStatement], + downStatement: [ + ...triggerStatements.downStatement, + { sql: downStatement }, + ], }; } catch (e) { log.ppe(e, _func); @@ -1581,6 +1586,63 @@ class OracleClient extends KnexClient { return result; } + // https://chartio.com/resources/tutorials/how-to-define-an-auto-increment-primary-key-in-oracle/ + // fallback for older version to auto generate auto incremented pk using sequence and trigger + async afterTableCreate(args) { + const result = { upStatement: [], downStatement: [] }; + let upQuery = ''; + let downQuery = ''; + + const pk = args.columns.find((c) => c.pk); + if (!pk || !this.useTriggerBasedAI) return result; + + for (let i = 0; i < args.columns.length; i++) { + const column = args.columns[i]; + if (column.ai) { + const triggerName = `nc_trigger_${args.table_name}_${column.column_name}_on_insert`; + const sequenceName = `nc_sequence_${args.table_name}_${column.column_name}`; + + const sequenceCreateQuery = this.genQuery(`CREATE SEQUENCE ??.??`, [ + this.schema, + sequenceName, + ]); + const triggerCreateQuery = this.genQuery( + `CREATE OR REPLACE TRIGGER ??.?? + BEFORE INSERT ON ??.?? + FOR EACH ROW + BEGIN + SELECT ??.nextval + INTO :new.?? + FROM dual; + END;`, + [ + this.schema, + triggerName, + this.schema, + args.table_name, + sequenceName, + column.column_name, + ] + ); + + upQuery += + sequenceCreateQuery + this.querySeparator() + triggerCreateQuery; + + await this.sqlClient.raw(sequenceCreateQuery); + await this.sqlClient.raw(triggerCreateQuery); + + downQuery += + this.querySeparator() + + this.genQuery(`DROP TRIGGER ??.??`, [this.schema, triggerName]) + + this.querySeparator() + + this.genQuery(`DROP SEQUENCE ??.??`, [this.schema, sequenceName]); + } + } + result.upStatement[0] = { sql: upQuery }; + result.downStatement[0] = { sql: downQuery }; + return result; + } + /** * * @param {Object} - args @@ -2034,9 +2096,11 @@ class OracleClient extends KnexClient { query += scale ? `,${scale}` : ''; query += n.dtxp && n.dtxp !== ' ' ? ')' : ''; } - // todo: `IDENTITY` is not supported in older version, - // add a fallback with sequence or trigger - if (n.ai) { + + // https://chartio.com/resources/tutorials/how-to-define-an-auto-increment-primary-key-in-oracle/ + // `IDENTITY` is not supported in older version, + // use trigger based ai a fallback with sequence or trigger + if (n.ai && !this.useTriggerBasedAI) { query += ' GENERATED BY DEFAULT ON NULL AS IDENTITY'; } else { query += n.rqd ? ' NOT NULL' : ' NULL'; @@ -2091,6 +2155,18 @@ class OracleClient extends KnexClient { return query; } + + get schema() { + return this.connectionConfig.connection?.user; + } + + // trigger based auto increment column + get useTriggerBasedAI() { + return ( + this.connectionConfig.useTriggerBasedAI ?? + this.connectionConfig.connection?.useTriggerBasedAI + ); + } } function getDefaultValue(n) { diff --git a/packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/functionMappings/oracle.ts b/packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/functionMappings/oracle.ts index 94a1023df6..b5082cab94 100644 --- a/packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/functionMappings/oracle.ts +++ b/packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/functionMappings/oracle.ts @@ -76,6 +76,21 @@ const pg = { )} + 7, 7) ${colAlias}` ); }, + // AND: (args: MapFnArgs) => { + // return args.knex.raw( + // `CASE WHEN ${commonFns.AND({ + // ...args, + // colAlias: '', + // })} THEN 1 ELSE 0 END${args.colAlias}` + // ); + // }, + // OR: (args: MapFnArgs) => { + // return args.knex.raw( + // `CASE WHEN ${commonFns.OR({ ...args, colAlias: '' })} THEN 1 ELSE 0 END${ + // args.colAlias + // }` + // ); + // }, }; export default pg;