Skip to content

Commit dd487c0

Browse files
committed
Added new error message to handle the case when executeMany() is used with SELECT statement and WITH SQL clause
1 parent 483a211 commit dd487c0

File tree

5 files changed

+167
-4
lines changed

5 files changed

+167
-4
lines changed

doc/src/release_notes.rst

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ Common Changes
4444
`vault-azure` to `ocivault` and `azurevault` respectively for consistency
4545
with other Oracle Database drivers.
4646

47-
#) Remove the 'Critical Dependency' warning from webpack builds.
48-
See `Issue #1678 <https://github.com/oracle/node-oracledb/issues/1678>`__.
47+
#) Remove the 'Critical Dependency' warning from webpack builds.
48+
See `Issue #1678 <https://github.com/oracle/node-oracledb/issues/1678>`__.
4949

5050
Thin Mode Changes
5151
+++++++++++++++++
@@ -56,7 +56,7 @@ Thin Mode Changes
5656

5757
#) Fixed bug that did not allow connection to Oracle Database 23ai instances
5858
that have fast authentication disabled.
59-
See `Issue #1697<https://github.com/oracle/node-oracledb/issues/1697>`__.
59+
See `Issue #1697 <https://github.com/oracle/node-oracledb/issues/1697>`__.
6060

6161
#) Fixed bug with statement cache which threw an ``NJS-111`` error when select
6262
SQL is run on CLOB columns fetched as string.
@@ -70,11 +70,15 @@ Thin Mode Changes
7070
#) Error ``NJS-125`` is now raised when an empty connect string is provided
7171
for creating pools.
7272

73-
#) Provide additional error details when an invalid wallet is used.
73+
#) Provide additional error details when an invalid wallet is used.
7474

7575
#) Improved bind error message ``NJS-098`` with cleaner description that is
7676
thrown for all bind mismatch scenarios.
7777

78+
#) Added new error message to handle the case when
79+
:meth:`connection.executeMany()` is used with SELECT statement and WITH
80+
SQL clause.
81+
7882
Thick Mode changes
7983
++++++++++++++++++
8084

lib/errors.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ const ERR_INVALID_TRANSACTION_SIZE = 153;
163163
const ERR_INVALID_BRANCH_SIZE = 154;
164164
const ERR_OPERATION_NOT_SUPPORTED_ON_BFILE = 155;
165165
const ERR_OPERATION_ONLY_SUPPORTED_ON_BFILE = 156;
166+
const ERR_EXECMANY_NOT_ALLOWED_ON_QUERIES = 157;
166167

167168
// Oracle Net layer errors start from 500
168169
const ERR_CONNECTION_CLOSED = 500;
@@ -463,6 +464,8 @@ messages.set(ERR_OPERATION_NOT_SUPPORTED_ON_BFILE, // NJS-155
463464
'operation is not supported on BFILE LOBs');
464465
messages.set(ERR_OPERATION_ONLY_SUPPORTED_ON_BFILE, // NJS-156
465466
'operation is only supported on BFILE LOBs');
467+
messages.set(ERR_EXECMANY_NOT_ALLOWED_ON_QUERIES, // NJS-157
468+
'executeMany() cannot be used with SELECT statement or WITH SQL clause');
466469

467470
// Oracle Net layer errors
468471

@@ -900,6 +903,7 @@ module.exports = {
900903
ERR_CONNECTION_CLOSED_CODE: `${ERR_PREFIX}-${ERR_CONNECTION_CLOSED}`,
901904
ERR_OPERATION_NOT_SUPPORTED_ON_BFILE,
902905
ERR_OPERATION_ONLY_SUPPORTED_ON_BFILE,
906+
ERR_EXECMANY_NOT_ALLOWED_ON_QUERIES,
903907
WRN_COMPILATION_CREATE,
904908
assert,
905909
assertArgCount,

lib/thin/connection.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,10 @@ class ThinConnectionImpl extends ConnectionImpl {
169169
//---------------------------------------------------------------------------
170170
async _execute(statement, numIters, binds, options, executeManyFlag) {
171171

172+
// Throw error if executeMany is not called on a DML statement or PL/SQL
173+
if (executeManyFlag && statement.isQuery) {
174+
errors.throwErr(errors.ERR_EXECMANY_NOT_ALLOWED_ON_QUERIES);
175+
}
172176
// perform binds
173177
const numStmtBinds = statement.bindInfoList.length;
174178
const numUserBinds = binds.length;

test/executeMany1.js

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,149 @@ describe('163. executeMany1.js', function() {
524524
await doDropProc();
525525
}); // 163.17
526526

527+
it('163.18 Negative - executeMany with SELECT query, positional bind', async function() {
528+
529+
if (testsUtil.getClientVersion < 1201000200) {
530+
return this.skip();
531+
}
532+
533+
const sql = "SELECT :1 FROM DUAL";
534+
const binds = [ [3] ];
535+
536+
await assert.rejects(
537+
async () => await conn.executeMany(sql, binds),
538+
// Thick mode - DPI-1013: not supported
539+
// Thin mode - NJS-157: executeMany() cannot be used with
540+
// SELECT statement or WITH SQL clause
541+
/DPI-1013:|NJS-157:/
542+
);
543+
}); // 163.18
544+
545+
it('163.19 Negative - executeMany with SELECT query, named bind', async function() {
546+
547+
if (testsUtil.getClientVersion < 1201000200) {
548+
return this.skip();
549+
}
550+
551+
const sql = "SELECT :num FROM DUAL";
552+
const binds = [{ num: 3 }];
553+
554+
await assert.rejects(
555+
async () => await conn.executeMany(sql, binds),
556+
// Thick mode - DPI-1013: not supported
557+
// Thin mode - NJS-157: executeMany() cannot be used with
558+
// SELECT statement or WITH SQL clause
559+
/DPI-1013:|NJS-157:/
560+
);
561+
}); // 163.19
562+
563+
it('163.20 Negative - executeMany with WITH SQL clause, positional bind', async function() {
564+
565+
if (testsUtil.getClientVersion < 1201000200) {
566+
return this.skip();
567+
}
568+
569+
const sql = "WITH data as (SELECT 1 as Num1, 2 as Num2 from dual) SELECT :1 from data";
570+
const binds = [ [1] ];
571+
572+
await assert.rejects(
573+
async () => await conn.executeMany(sql, binds),
574+
// Thick mode - DPI-1013: not supported
575+
// Thin mode - NJS-157: executeMany() cannot be used with
576+
// SELECT statement or WITH SQL clause
577+
/DPI-1013:|NJS-157:/
578+
);
579+
}); // 163.20
580+
581+
it('163.21 Negative - executeMany with WITH SQL clause, named bind', async function() {
582+
583+
if (testsUtil.getClientVersion < 1201000200) {
584+
return this.skip();
585+
}
586+
587+
const sql = "WITH data as (SELECT 1 as Num1, 2 as Num2 from dual) SELECT :Num1 from data";
588+
const binds = [ { Num1: 3 } ];
589+
590+
await assert.rejects(
591+
async () => await conn.executeMany(sql, binds),
592+
// Thick mode - DPI-1013: not supported
593+
// Thin mode - NJS-157: executeMany() cannot be used with
594+
// SELECT statement or WITH SQL clause
595+
/DPI-1013:|NJS-157:/
596+
);
597+
}); // 163.21
598+
599+
it('163.22 Negative - executeMany with SELECT query, multiple positional binds', async function() {
600+
601+
if (testsUtil.getClientVersion < 1201000200) {
602+
return this.skip();
603+
}
604+
605+
const sql = "SELECT :1, :2 FROM DUAL";
606+
const binds = [ [1, 2] ];
607+
608+
await assert.rejects(
609+
async () => await conn.executeMany(sql, binds),
610+
// Thick mode - DPI-1013: not supported
611+
// Thin mode - NJS-157: executeMany() cannot be used with
612+
// SELECT statement or WITH SQL clause
613+
/DPI-1013:|NJS-157:/
614+
);
615+
}); // 163.22
616+
617+
it('163.23 Negative - executeMany with WITH SQL clause and multiple positional binds', async function() {
618+
619+
if (testsUtil.getClientVersion < 1201000200) {
620+
return this.skip();
621+
}
622+
623+
const sql = "WITH data as (SELECT 1 as Num1, 2 as Num2 from dual) SELECT :1, :2 FROM data";
624+
const binds = [ [1, 2] ];
625+
626+
await assert.rejects(
627+
async () => await conn.executeMany(sql, binds),
628+
// Thick mode - DPI-1013: not supported
629+
// Thin mode - NJS-157: executeMany() cannot be used with
630+
// SELECT statement or WITH SQL clause
631+
/DPI-1013:|NJS-157:/
632+
);
633+
}); // 163.23
634+
635+
it('163.24 Negative - executeMany with SELECT query and invalid bind variable', async function() {
636+
637+
if (testsUtil.getClientVersion < 1201000200) {
638+
return this.skip();
639+
}
640+
641+
const sql = "SELECT :invalidBind FROM DUAL";
642+
const binds = [ [3] ];
643+
644+
await assert.rejects(
645+
async () => await conn.executeMany(sql, binds),
646+
// Thick mode - DPI-1013: not supported
647+
// Thin mode - NJS-157: executeMany() cannot be used with
648+
// SELECT statement or WITH SQL clause
649+
/DPI-1013:|NJS-157:/
650+
);
651+
}); // 163.24
652+
653+
it('163.25 Negative - executeMany with DDL - CREATE TABLE', async function() {
654+
655+
// Does not throw the proper error in Thin mode yet
656+
if (testsUtil.getClientVersion < 1201000200 || oracledb.thin) {
657+
return this.skip();
658+
}
659+
660+
const sql = "CREATE TABLE :tblname (:id NUMBER, :name VARCHAR2(30))";
661+
const binds = [ ["tbl1", "ID", "NAME"] ];
662+
663+
await assert.rejects(
664+
async () => await conn.executeMany(sql, binds),
665+
// Thick mode - DPI-1059: bind variables are not supported in DDL statements
666+
/DPI-1059:/
667+
);
668+
}); // 163.25
669+
527670
const doCreateProc = async function() {
528671
const proc = "CREATE OR REPLACE PROCEDURE nodb_proc_em (a_num IN NUMBER, " +
529672
" a_outnum OUT NUMBER, a_outstr OUT VARCHAR2) \n" +

test/list.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4261,6 +4261,14 @@ oracledb.OUT_FORMAT_OBJECT and resultSet = true
42614261
163.15 getting dmlrowcounts after executemany with dmlrowcounts=False
42624262
163.16 executemany() with an invalid row
42634263
163.17 calls PL/SQL, with round trip count check
4264+
163.18 Negative - executeMany with SELECT query, positional bind
4265+
163.19 Negative - executeMany with SELECT query, named bind
4266+
163.20 Negative - executeMany with WITH SQL clause, positional bind
4267+
163.21 Negative - executeMany with WITH SQL clause, named bind
4268+
163.22 Negative - executeMany with SELECT query, multiple positional binds
4269+
163.23 Negative - executeMany with WITH SQL clause and multiple positional binds
4270+
163.24 Negative - executeMany with SELECT query and invalid bind variable
4271+
163.25 Negative - executeMany with DDL - CREATE TABLE
42644272

42654273
164. soda1.js
42664274
164.1 getSodaDatabase() creates a sodaDatabase Object

0 commit comments

Comments
 (0)