From 26c41b10dbc6e5251a22dfb772db0c5559aa2a83 Mon Sep 17 00:00:00 2001 From: Connor Fitzgerald Date: Mon, 19 Aug 2019 19:25:49 +0100 Subject: [PATCH] oracledb - Implemented generics for DB results (#37747) * WIP updating oracledb typings to 3.1.2 * WIP * SODA WIP * .d.ts done. Needs tests writing * Finished * Added pool stats methods. Fixed bug with BindParameter being string or number * Making _enableStats optional * Allow parameters to be nulled * Capitalise namespace * Update contribution URL * Revert "Update contribution URL" This reverts commit f329d293dceaf44832ae3424753c1ccb98378df2. * Update contribution URL * Change poolAlias to string. SODA not in preview. Add BindParameters interface * getRows should not return void * Added pino-std-serializers * Adding @types/clear * Upgrading oracledb to 4.0 * Retained oracledb v3 files. Made requested changes * Added Buffer to BindParameters * Implemented generics * Added tests --- types/oracledb/index.d.ts | 78 ++++++++++++++++---------------- types/oracledb/oracledb-tests.ts | 65 ++++++++++++++++++++------ types/oracledb/v3/index.d.ts | 3 ++ 3 files changed, 93 insertions(+), 53 deletions(-) diff --git a/types/oracledb/index.d.ts b/types/oracledb/index.d.ts index 9adc45135e..2b2298e8dc 100644 --- a/types/oracledb/index.d.ts +++ b/types/oracledb/index.d.ts @@ -513,8 +513,6 @@ declare namespace OracleDB { */ const versionSuffix: string; - type Row = any[] | Record; - interface BindParameter { /** * The direction of the bind. One of the Execute Bind Direction Constants. @@ -753,12 +751,12 @@ declare namespace OracleDB { * @see https://oracle.github.io/node-oracledb/doc/api.html#sqlexecution * @see https://oracle.github.io/node-oracledb/doc/api.html#querystream For an alternative */ - execute(sql: string, bindParams: BindParameters, options: ExecuteOptions): Promise; - execute( + execute(sql: string, bindParams: BindParameters, options: ExecuteOptions): Promise>; + execute( sql: string, bindParams: BindParameters, options: ExecuteOptions, - callback: (error: DBError, result: Result) => void, + callback: (error: DBError, result: Result) => void, ): void; /** @@ -770,11 +768,11 @@ declare namespace OracleDB { * @see https://oracle.github.io/node-oracledb/doc/api.html#sqlexecution * @see https://oracle.github.io/node-oracledb/doc/api.html#querystream For an alternative */ - execute(sql: string, bindParams: BindParameters): Promise; - execute( + execute(sql: string, bindParams: BindParameters): Promise>; + execute( sql: string, bindParams: BindParameters, - callback: (error: DBError, result: Result) => void, + callback: (error: DBError, result: Result) => void, ): void; /** @@ -785,8 +783,8 @@ declare namespace OracleDB { * @see https://oracle.github.io/node-oracledb/doc/api.html#sqlexecution * @see https://oracle.github.io/node-oracledb/doc/api.html#querystream For an alternative */ - execute(sql: string): Promise; - execute(sql: string, callback: (error: DBError, result: Result) => void): void; + execute(sql: string): Promise>; + execute(sql: string, callback: (error: DBError, result: Result) => void): void; /** * This method allows sets of data values to be bound to one DML or PL/SQL statement for execution. @@ -827,26 +825,26 @@ declare namespace OracleDB { * * @since 2.2 */ - executeMany( + executeMany( sql: string, - binds: Row[], + binds: BindParameters[], options: ExecuteManyOptions, - ): Promise; - executeMany( + ): Promise>; + executeMany( sql: string, - binds: Row[], + binds: BindParameters[], options: ExecuteManyOptions, - callback: (error: DBError, result: Results) => void, + callback: (error: DBError, result: Results) => void, ): void; - executeMany( + executeMany( sql: string, - binds: Row[], - ): Promise; - executeMany( + binds: BindParameters[], + ): Promise>; + executeMany( sql: string, - binds: Row[], - callback: (error: DBError, result: Results) => void, + binds: BindParameters[], + callback: (error: DBError, result: Results) => void, ): void; /** @@ -865,19 +863,19 @@ declare namespace OracleDB { * @param iterations The number of times the SQL should be executed. * @param options Optional parameter to control the execution. */ - executeMany(sql: string, iterations: number, options: ExecuteManyOptions): Promise; - executeMany( + executeMany(sql: string, iterations: number, options: ExecuteManyOptions): Promise>; + executeMany( sql: string, iterations: number, options: ExecuteManyOptions, - callback: (error: DBError, result: Results) => void, + callback: (error: DBError, result: Results) => void, ): void; - executeMany(sql: string, iterations: number): Promise; - executeMany( + executeMany(sql: string, iterations: number): Promise>; + executeMany( sql: string, iterations: number, - callback: (error: DBError, result: Results) => void, + callback: (error: DBError, result: Results) => void, ): void; /** @@ -2119,7 +2117,7 @@ declare namespace OracleDB { /** * Contains information regarding the outcome of a successful connection.execute(). */ - interface Result { + interface Result { /** * This property will be defined if the executed statement returned Implicit Results. Depending on the value of resultSet it will either be an array, * each element containing an array of rows from one query, or an array of ResultSets each corresponding to a query. @@ -2127,7 +2125,7 @@ declare namespace OracleDB { * @see https://oracle.github.io/node-oracledb/doc/api.html#implicitresults * @since 4.0 */ - implicitResults?: (Row[] | ResultSet)[]; + implicitResults?: (T[] | ResultSet)[]; /** * For SELECT statements, this contains an array of objects describing details of columns for the select list. * For non queries, this property is undefined. @@ -2141,7 +2139,7 @@ declare namespace OracleDB { * then outBinds is returned as an array. If bindParams is passed as an object, * then outBinds is returned as an object. If there are no OUT or IN OUT binds, the value is undefined. */ - outBinds: Row; + outBinds: T; /** * For SELECT statements when the resultSet option is true, use the resultSet object to fetch rows. * @@ -2151,7 +2149,7 @@ declare namespace OracleDB { * @see https://oracle.github.io/node-oracledb/doc/api.html#resultsetclass * @see https://oracle.github.io/node-oracledb/doc/api.html#resultsethandling */ - resultSet: ResultSet; + resultSet: ResultSet; /** * For SELECT statements using direct fetches, rows contains an array of fetched rows. * It will be NULL if there is an error or the SQL statement was not a SELECT statement. @@ -2162,7 +2160,7 @@ declare namespace OracleDB { * The number of rows returned is limited by oracledb.maxRows or the maxRows option in an execute() call. * If maxRows is 0, then the number of rows is limited by Node.js memory constraints. */ - rows: Row[]; + rows: T[]; /** * For DML statements (including SELECT FOR UPDATE) this contains the number of rows affected, * for example the number of rows inserted. For non-DML statements such as queries and PL/SQL statements, @@ -2174,7 +2172,7 @@ declare namespace OracleDB { /** * Contains information regarding the outcome of a successful connection.executeMany(). */ - interface Results { + interface Results { /** * An array of error objects that were reported during execution. * @@ -2199,7 +2197,7 @@ declare namespace OracleDB { * the array passed as the binds parameter. It will be present only if there is at least one OUT bind * variable identified. */ - outBinds: Row[]; + outBinds: T[]; /** * An integer identifying the total number of database rows affected by the processing of all records * of the binds parameter. It is only present if a DML statement was executed. @@ -2220,7 +2218,7 @@ declare namespace OracleDB { * * @see https://oracle.github.io/node-oracledb/doc/api.html#resultsethandling */ - interface ResultSet { + interface ResultSet { /** * Contains an array of objects with metadata about the query or REF CURSOR columns. * @@ -2245,11 +2243,11 @@ declare namespace OracleDB { * Performance of getRow() can be tuned by adjusting the value of oracledb.fetchArraySize or * the execute() option fetchArraySize. */ - getRow(): Promise; + getRow(): Promise; getRow( callback: ( error: DBError, - row: Row, + row: T, ) => void, ): void; @@ -2264,8 +2262,8 @@ declare namespace OracleDB { * * @param numRows The number of rows to fetch */ - getRows(numRows: number): Promise; - getRows(numRows: number, callback: (error: DBError, rows: Row[]) => void): void; + getRows(numRows: number): Promise; + getRows(numRows: number, callback: (error: DBError, rows: T[]) => void): void; /** * This synchronous method converts a ResultSet into a stream. diff --git a/types/oracledb/oracledb-tests.ts b/types/oracledb/oracledb-tests.ts index 4e80b1a2e9..a379387522 100644 --- a/types/oracledb/oracledb-tests.ts +++ b/types/oracledb/oracledb-tests.ts @@ -298,6 +298,10 @@ const runPromiseTests = async (): Promise => { } }; +interface One { + one: string; +} + const version4Tests = async () => { console.log(oracledb.OUT_FORMAT_ARRAY, oracledb.OUT_FORMAT_OBJECT); @@ -305,15 +309,21 @@ const version4Tests = async () => { const connection = await pool.getConnection(); - const implicitResults = (await connection.execute('SELECT 1 FROM DUAL')).implicitResults as oracledb.ResultSet[]; + const implicitResults = (await connection.execute( + 'SELECT 1 FROM DUAL', + )).implicitResults as oracledb.ResultSet[]; + + (await implicitResults[0].getRow()).one; await implicitResults[0].close() - const implicitResults2 = (await connection.execute('SELECT 1 FROM DUAL')).implicitResults as oracledb.Row[][]; + const implicitResults2 = (await connection.execute( + 'SELECT 1 FROM DUAL', + )).implicitResults as One[][]; - const results = implicitResults2[0][0] as any[]; + const results = implicitResults2[0][0]; - console.log(results[0]); + console.log(results.one); const GeomType = await connection.getDbObjectClass("MDSYS.SDO_GEOMETRY"); @@ -407,14 +417,14 @@ const version4Tests = async () => { result = await connection.execute(plsql, [], { resultSet: true }); for (let i = 0; i < result.implicitResults.length; i++) { - console.log(" Implicit Result Set", i + 1); - const rs = result.implicitResults[i] as oracledb.ResultSet; // get the next ResultSet - let row; - while ((row = await rs.getRow())) { - console.log(" ", row); - } - - await rs.close(); + console.log(' Implicit Result Set', i + 1); + const rs = result.implicitResults[i] as oracledb.ResultSet; // get the next ResultSet + let row; + while ((row = await rs.getRow())) { + console.log(' ', row); + } + + await rs.close(); } const queueName = "DEMO_RAW_QUEUE"; @@ -442,4 +452,33 @@ const version4Tests = async () => { await connection.commit(); } -runPromiseTests(); +interface MyTableRow { + firstColumn: string; + secondColumn: number; +} + +const testGenerics = async () => { + const connection = await oracledb.getConnection({ + user: 'test' + }); + + const result = await connection.execute('SELECT 1 FROM DUAL'); + + console.log(result.rows[0].firstColumn); + console.log(result.rows[0].secondColumn); + + const result2 = await connection.execute<{test: string}>(' BEGIN DO_SOMETHING END;', { + test: { + dir: oracledb.BIND_OUT, + val: 'something' + } + }) + + console.log(result2.outBinds.test); + + const sql = `SELECT FIRST_COLUMN, SECOND_COLUMN FROM SOMEWHERE`; + + const result3 = await connection.executeMany(sql, 5); + + console.log(result3.outBinds[0].firstColumn); +} diff --git a/types/oracledb/v3/index.d.ts b/types/oracledb/v3/index.d.ts index 8dd1b5a834..727cd242fd 100644 --- a/types/oracledb/v3/index.d.ts +++ b/types/oracledb/v3/index.d.ts @@ -9,6 +9,9 @@ import { Duplex, Readable } from 'stream'; +/** + * @deprecated These types are no longer maintained. Please upgrade to oracledb version 4. + */ declare namespace OracleDB { /** Constant for the query result outFormat option. */ const ARRAY: number;