Skip to content

Commit da5150b

Browse files
committed
Fix issue with getStmtInfo() function to process metadata attributes correctly
1 parent dfcdba3 commit da5150b

File tree

4 files changed

+110
-4
lines changed

4 files changed

+110
-4
lines changed

doc/src/release_notes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@ Thick Mode Changes
6565

6666
#) Internal code refactoring to optimize handling of SODA functions.
6767

68+
#) Fixed bug to ensure that :meth:`connection.getStmtInfo()` processes the
69+
query metadata correctly.
70+
6871
node-oracledb `v6.9.0 <https://github.com/oracle/node-oracledb/compare/v6.8.0...v6.9.0>`__ (18 Jul 2025)
6972
---------------------------------------------------------------------------------------------------------
7073

src/njsConnection.c

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1745,7 +1745,7 @@ static bool njsConnection_getStatementInfoAsync(njsBaton *baton)
17451745
static bool njsConnection_getStatementInfoPostAsync(njsBaton *baton,
17461746
napi_env env, napi_value *result)
17471747
{
1748-
napi_value bindNames, metadata, temp;
1748+
napi_value bindNames, metadata, temp, options, callingObj;
17491749
uint32_t i;
17501750

17511751
// create object for the result
@@ -1756,9 +1756,27 @@ static bool njsConnection_getStatementInfoPostAsync(njsBaton *baton,
17561756
if (!njsVariable_initForQueryJS(baton->queryVars, baton->numQueryVars,
17571757
env, baton))
17581758
return false;
1759-
if (!njsVariable_getMetadataMany(baton->queryVars, baton->numQueryVars,
1760-
env, &metadata))
1759+
1760+
// Setup the options parameter for "_setup" call in JavaScript
1761+
NJS_CHECK_NAPI(env, napi_create_object(env, &options))
1762+
NJS_CHECK_NAPI(env, napi_get_reference_value(env, baton->jsCallingObjRef,
1763+
&callingObj))
1764+
NJS_CHECK_NAPI(env, napi_set_named_property(env, options, "connection",
1765+
callingObj))
1766+
NJS_CHECK_NAPI(env, napi_create_reference(env, options, 1,
1767+
&baton->jsExecuteOptionsRef))
1768+
1769+
// return result set
1770+
if (!njsResultSet_new(baton, env,
1771+
(njsConnection*) baton->callingInstance, baton->dpiStmtHandle,
1772+
baton->queryVars, baton->numQueryVars, &temp))
17611773
return false;
1774+
1775+
baton->dpiStmtHandle = NULL;
1776+
baton->queryVars = NULL;
1777+
baton->numQueryVars = 0;
1778+
NJS_CHECK_NAPI(env, napi_get_named_property(env, temp, "metaData",
1779+
&metadata))
17621780
NJS_CHECK_NAPI(env, napi_set_named_property(env, *result, "metaData",
17631781
metadata))
17641782
}

test/getStmtInfo.js

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright (c) 2018, 2023, Oracle and/or its affiliates. */
1+
/* Copyright (c) 2018, 2025, Oracle and/or its affiliates. */
22

33
/******************************************************************************
44
*
@@ -494,4 +494,81 @@ describe('162. getStmtInfo.js', function() {
494494
const result = await conn.execute(sql, expectedRes);
495495
assert.deepStrictEqual(result.rows[0], expectedRes);
496496
});
497+
498+
it('162.37 Duplicate column aliases', async function() {
499+
const sql = `SELECT 1 a, 'abc' a FROM dual`;
500+
501+
const info = await conn.getStatementInfo(sql);
502+
assert.strictEqual(info.metaData[0].name, 'A');
503+
assert.strictEqual(info.metaData[1].name, 'A_1');
504+
const result = await conn.execute(sql);
505+
assert.deepStrictEqual(result.rows[0], [1, 'abc']);
506+
});
507+
508+
it('162.38 Simple table columns without aliases', async function() {
509+
const sql = `SELECT num, content FROM ${tableName}`;
510+
511+
const info = await conn.getStatementInfo(sql);
512+
assert.strictEqual(info.metaData[0].name, 'NUM');
513+
assert.strictEqual(info.metaData[1].name, 'CONTENT');
514+
});
515+
516+
it('162.39 Mixed aliases and table columns', async function() {
517+
const sql = `SELECT num, content AS value, 'literal' AS lit FROM ${tableName}`;
518+
519+
const info = await conn.getStatementInfo(sql);
520+
assert.strictEqual(info.metaData[0].name, 'NUM');
521+
assert.strictEqual(info.metaData[1].name, 'VALUE');
522+
assert.strictEqual(info.metaData[2].name, 'LIT');
523+
});
524+
525+
it('162.40 Very long column alias names', async function() {
526+
const longName = 'A'.repeat(30);
527+
528+
const sql = `SELECT 1 AS "${longName}", 2 AS "${longName}" FROM dual`;
529+
const info = await conn.getStatementInfo(sql);
530+
assert.notStrictEqual(info.metaData[0].name, info.metaData[1].name);
531+
});
532+
533+
it('162.41 Single character duplicate aliases', async function() {
534+
const sql = `SELECT 1 AS "A", 2 AS "A" FROM dual`;
535+
536+
const info = await conn.getStatementInfo(sql);
537+
assert.strictEqual(info.metaData[0].name, 'A');
538+
assert.strictEqual(info.metaData[1].name, 'A_1');
539+
});
540+
541+
it('162.42 Numeric aliases converted to strings', async function() {
542+
const sql = `SELECT 1 AS "1", 2 AS "1" FROM dual`;
543+
544+
const info = await conn.getStatementInfo(sql);
545+
assert.strictEqual(info.metaData[0].name, '1');
546+
assert.strictEqual(info.metaData[1].name, '1_1');
547+
});
548+
549+
it('162.43 Special character aliases', async function() {
550+
const sql = `SELECT 1 AS "@#$", 2 AS "@#$" FROM dual`;
551+
552+
const info = await conn.getStatementInfo(sql);
553+
assert.strictEqual(info.metaData[0].name, '@#$');
554+
assert.strictEqual(info.metaData[1].name, '@#$_1');
555+
});
556+
557+
it('162.44 Metadata consistency between output formats - duplicate aliases', async function() {
558+
const sql = `SELECT sysdate as A, sysdate as A FROM dual`;
559+
560+
// Test with array format
561+
const infoArray = await conn.getStatementInfo(sql);
562+
const resultArray = await conn.execute(sql, [], { outFormat: oracledb.OUT_FORMAT_ARRAY });
563+
564+
// Test with object format
565+
const infoObject = await conn.getStatementInfo(sql);
566+
const resultObject = await conn.execute(sql, [], { outFormat: oracledb.OUT_FORMAT_OBJECT });
567+
568+
assert.deepStrictEqual(infoArray.metaData, infoObject.metaData);
569+
assert.deepStrictEqual(resultArray.metaData, resultObject.metaData);
570+
571+
assert.strictEqual(infoArray.metaData[0].name, 'A');
572+
assert.strictEqual(infoArray.metaData[1].name, 'A_1');
573+
});
497574
});

test/list.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4272,6 +4272,14 @@ oracledb.OUT_FORMAT_OBJECT and resultSet = true
42724272
162.34 ignore literals only during bind processing
42734273
162.35 Parse and Execute twice
42744274
162.36 Multiple line and Multiple Asterisks
4275+
162.37 Duplicate column aliases
4276+
162.38 Simple table columns without aliases
4277+
162.39 Mixed aliases and table columns
4278+
162.40 Very long column alias names
4279+
162.41 Single character duplicate aliases
4280+
162.42 Numeric aliases converted to strings
4281+
162.43 Special character aliases
4282+
162.44 Metadata consistency between output formats - duplicate aliases
42754283

42764284
163. executeMany1.js
42774285
163.1 inserts many rows with bind by name

0 commit comments

Comments
 (0)