2022-04-19 08:06:36 +08:00
|
|
|
/* Copyright (c) 2018, 2022, Oracle and/or its affiliates. */
|
2018-04-03 05:45:58 +08:00
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
*
|
2023-02-21 09:43:43 +08:00
|
|
|
* This software is dual-licensed to you under the Universal Permissive License
|
|
|
|
* (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License
|
|
|
|
* 2.0 as shown at https://www.apache.org/licenses/LICENSE-2.0. You may choose
|
|
|
|
* either license.
|
2018-04-03 05:45:58 +08:00
|
|
|
*
|
2023-02-21 09:43:43 +08:00
|
|
|
* If you elect to accept the software under the Apache License, Version 2.0,
|
|
|
|
* the following applies:
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
2018-04-03 05:45:58 +08:00
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
2023-02-21 09:43:43 +08:00
|
|
|
* https://www.apache.org/licenses/LICENSE-2.0
|
2018-04-03 05:45:58 +08:00
|
|
|
*
|
2023-02-21 09:43:43 +08:00
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
2018-04-03 05:45:58 +08:00
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*
|
|
|
|
* NAME
|
2018-11-15 13:14:40 +08:00
|
|
|
* 163. executeMany1.js
|
2018-04-03 05:45:58 +08:00
|
|
|
*
|
|
|
|
* DESCRIPTION
|
|
|
|
* Test connection.executeMany() method.
|
|
|
|
*
|
|
|
|
*****************************************************************************/
|
|
|
|
'use strict';
|
|
|
|
|
2023-02-21 11:27:04 +08:00
|
|
|
const oracledb = require('oracledb');
|
|
|
|
const assert = require('assert');
|
|
|
|
const dbConfig = require('./dbconfig.js');
|
2023-02-21 11:20:36 +08:00
|
|
|
const testsUtil = require('./testsUtil.js');
|
2018-04-03 05:45:58 +08:00
|
|
|
|
2018-11-15 13:14:40 +08:00
|
|
|
describe('163. executeMany1.js', function() {
|
2018-04-03 05:45:58 +08:00
|
|
|
|
2023-02-21 11:27:04 +08:00
|
|
|
let conn;
|
|
|
|
|
|
|
|
before(async function() {
|
|
|
|
conn = await oracledb.getConnection(dbConfig);
|
|
|
|
const proc = "BEGIN \n" +
|
|
|
|
" DECLARE \n" +
|
|
|
|
" e_table_missing EXCEPTION; \n" +
|
|
|
|
" PRAGMA EXCEPTION_INIT(e_table_missing, -00942); \n" +
|
|
|
|
" BEGIN \n" +
|
|
|
|
" EXECUTE IMMEDIATE('DROP TABLE nodb_tab_xmany PURGE'); \n" +
|
|
|
|
" EXCEPTION \n" +
|
|
|
|
" WHEN e_table_missing \n" +
|
|
|
|
" THEN NULL; \n" +
|
|
|
|
" END; \n" +
|
|
|
|
" EXECUTE IMMEDIATE (' \n" +
|
|
|
|
" CREATE TABLE nodb_tab_xmany ( \n" +
|
|
|
|
" id NUMBER, \n" +
|
|
|
|
" val VARCHAR2(100) \n" +
|
|
|
|
" ) \n" +
|
|
|
|
" '); \n" +
|
|
|
|
"END; ";
|
|
|
|
await conn.execute(proc);
|
2018-04-03 05:45:58 +08:00
|
|
|
}); // before()
|
|
|
|
|
2023-02-21 11:27:04 +08:00
|
|
|
after(async function() {
|
|
|
|
const sql = "DROP TABLE nodb_tab_xmany PURGE";
|
|
|
|
await conn.execute(sql);
|
|
|
|
await conn.close();
|
2018-04-03 05:45:58 +08:00
|
|
|
}); // after
|
|
|
|
|
2023-02-21 11:27:04 +08:00
|
|
|
it('163.1 inserts many rows with bind by name', async function() {
|
2018-04-03 05:45:58 +08:00
|
|
|
|
2023-02-21 11:27:04 +08:00
|
|
|
const binds = [
|
|
|
|
{ a: 1, b: "Test 1 (One)" },
|
|
|
|
{ a: 2, b: "Test 2 (Two)" },
|
|
|
|
{ a: 3, b: "Test 3 (Three)" },
|
|
|
|
{ a: 4 },
|
|
|
|
{ a: 5, b: "Test 5 (Five)" }
|
|
|
|
];
|
|
|
|
let sql = "INSERT INTO nodb_tab_xmany VALUES (:a, :b)";
|
|
|
|
let options = {
|
|
|
|
autoCommit: true,
|
|
|
|
bindDefs: {
|
|
|
|
a: { type: oracledb.NUMBER },
|
|
|
|
b: { type: oracledb.STRING, maxSize: 15 }
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
let result = await conn.executeMany(sql, binds, options);
|
|
|
|
assert.strictEqual(result.rowsAffected, binds.length);
|
|
|
|
sql = "SELECT * FROM nodb_tab_xmany ORDER BY ID";
|
|
|
|
const expectVal = [
|
|
|
|
[ 1, 'Test 1 (One)' ],
|
|
|
|
[ 2, 'Test 2 (Two)' ],
|
|
|
|
[ 3, 'Test 3 (Three)' ],
|
|
|
|
[ 4, null ],
|
|
|
|
[ 5, 'Test 5 (Five)' ]
|
|
|
|
];
|
|
|
|
result = await conn.execute(sql);
|
|
|
|
assert.deepEqual(result.rows, expectVal);
|
|
|
|
await dotruncate();
|
2018-04-03 05:45:58 +08:00
|
|
|
}); // 163.1
|
|
|
|
|
2023-02-21 11:27:04 +08:00
|
|
|
it('163.2 inserts rows with bind by position', async function() {
|
|
|
|
const binds = [
|
2018-04-03 05:45:58 +08:00
|
|
|
[1, "Test 1 (One)"],
|
|
|
|
[2, "Test 2 (Two)"],
|
|
|
|
[3, "Test 3 (Three)"],
|
|
|
|
[4, null],
|
|
|
|
[5, "Test 5 (Five)"]
|
|
|
|
];
|
2023-02-21 11:27:04 +08:00
|
|
|
let sql = "INSERT INTO nodb_tab_xmany VALUES (:1, :2)";
|
|
|
|
const options = {
|
|
|
|
autoCommit: true,
|
|
|
|
bindDefs: [
|
|
|
|
{ type: oracledb.NUMBER },
|
|
|
|
{ type: oracledb.STRING, maxSize: 15 }
|
|
|
|
]
|
|
|
|
};
|
|
|
|
let result = await conn.executeMany(sql, binds, options);
|
|
|
|
assert.strictEqual(result.rowsAffected, binds.length);
|
|
|
|
sql = "SELECT * FROM nodb_tab_xmany ORDER BY ID";
|
|
|
|
result = await conn.execute(sql);
|
|
|
|
assert.deepEqual(result.rows, binds);
|
|
|
|
await dotruncate();
|
2018-04-03 05:45:58 +08:00
|
|
|
}); // 163.2
|
|
|
|
|
2023-02-21 11:27:04 +08:00
|
|
|
it('163.3 DML RETURNING that returns single value', async function() {
|
|
|
|
const sql = "INSERT INTO nodb_tab_xmany VALUES (:1, :2) RETURNING id, val INTO :3, :4";
|
|
|
|
const binds = [
|
|
|
|
[1, "Test 1 (One)"],
|
|
|
|
[2, "Test 2 (Two)"],
|
|
|
|
[3, "Test 3 (Three)"],
|
|
|
|
[4, null],
|
|
|
|
[5, "Test 5 (Five)"]
|
|
|
|
];
|
|
|
|
const options = {
|
|
|
|
bindDefs: [
|
|
|
|
{ type: oracledb.NUMBER },
|
|
|
|
{ type: oracledb.STRING, maxSize: 20 },
|
|
|
|
{ type: oracledb.NUMBER, dir: oracledb.BIND_OUT },
|
|
|
|
{ type: oracledb.STRING, maxSize: 25, dir: oracledb.BIND_OUT }
|
|
|
|
]
|
|
|
|
};
|
|
|
|
|
|
|
|
const result = await conn.executeMany(sql, binds, options);
|
|
|
|
assert.strictEqual(result.rowsAffected, binds.length);
|
|
|
|
for (let i = 0; i < result.outBinds.length; i++) {
|
|
|
|
assert.strictEqual(result.outBinds[i][0][0], binds[i][0]);
|
|
|
|
assert.strictEqual(result.outBinds[i][1][0], binds[i][1]);
|
|
|
|
}
|
|
|
|
await dotruncate();
|
2018-04-03 05:45:58 +08:00
|
|
|
}); // 163.3
|
|
|
|
|
2023-02-21 11:27:04 +08:00
|
|
|
it('163.4 DML RETURNING that returns multiple values', async function() {
|
|
|
|
let sql = "INSERT INTO nodb_tab_xmany VALUES(:1, :2)";
|
|
|
|
let binds = [
|
|
|
|
[1, "Test 1 (One)"],
|
|
|
|
[2, "Test 2 (Two)"],
|
|
|
|
[3, "Test 3 (Three)"],
|
|
|
|
[4, "Test 4 (Four)"],
|
|
|
|
[5, "Test 5 (Five)"],
|
|
|
|
[6, "Test 6 (Six)"],
|
|
|
|
[7, "Test 7 (Seven)"],
|
|
|
|
[8, "Test 8 (Eight)"]
|
|
|
|
];
|
|
|
|
let options = {
|
|
|
|
bindDefs: [
|
|
|
|
{ type: oracledb.NUMBER },
|
|
|
|
{ type: oracledb.STRING, maxSize: 20 }
|
|
|
|
]
|
|
|
|
};
|
|
|
|
let result = await conn.executeMany(sql, binds, options);
|
|
|
|
assert.strictEqual(result.rowsAffected, binds.length);
|
|
|
|
|
|
|
|
sql = "DELETE FROM nodb_tab_xmany WHERE id < :1 RETURNING id, val INTO :2, :3";
|
|
|
|
binds = [ [2], [6], [8] ];
|
|
|
|
options = {
|
|
|
|
bindDefs: [
|
|
|
|
{ type: oracledb.NUMBER },
|
|
|
|
{ type: oracledb.NUMBER, dir: oracledb.BIND_OUT },
|
|
|
|
{ type: oracledb.STRING, maxSize: 25, dir: oracledb.BIND_OUT }
|
|
|
|
]
|
|
|
|
};
|
|
|
|
result = await conn.executeMany(sql, binds, options);
|
|
|
|
assert.strictEqual(result.rowsAffected, 7);
|
|
|
|
assert.strictEqual(result.outBinds.length, 3);
|
|
|
|
assert.deepEqual(
|
|
|
|
result.outBinds[0],
|
|
|
|
[ [ 1 ], [ 'Test 1 (One)' ] ]
|
|
|
|
);
|
|
|
|
assert.deepEqual(
|
|
|
|
result.outBinds[1],
|
|
|
|
[ [ 2, 3, 4, 5 ], [ 'Test 2 (Two)', 'Test 3 (Three)', 'Test 4 (Four)', 'Test 5 (Five)' ]]
|
|
|
|
);
|
|
|
|
assert.deepEqual(
|
|
|
|
result.outBinds[2],
|
|
|
|
[ [ 6, 7 ], [ 'Test 6 (Six)', 'Test 7 (Seven)' ] ]
|
|
|
|
);
|
|
|
|
await dotruncate();
|
2018-04-03 05:45:58 +08:00
|
|
|
}); // 163.4
|
|
|
|
|
2023-02-21 11:27:04 +08:00
|
|
|
it('163.5 calls PL/SQL', async function() {
|
|
|
|
await doCreateProc();
|
|
|
|
const plsql = "BEGIN nodb_proc_em(:1, :2, :3); END;";
|
|
|
|
const binds = [ [1], [2], [3], [4], [6] ];
|
|
|
|
const options = {
|
|
|
|
bindDefs: [
|
|
|
|
{ type: oracledb.NUMBER },
|
|
|
|
{ type: oracledb.NUMBER, dir: oracledb.BIND_OUT },
|
|
|
|
{ type: oracledb.STRING, dir: oracledb.BIND_OUT, maxSize: 20 }
|
|
|
|
]
|
|
|
|
};
|
|
|
|
const result = await conn.executeMany(plsql, binds, options);
|
|
|
|
assert.deepEqual(
|
|
|
|
result.outBinds,
|
|
|
|
[ [ 2, 'X' ], [ 4, 'XX' ], [ 6, 'XXX' ], [ 8, 'XXXX' ], [ 12, 'XXXXXX' ] ]
|
|
|
|
);
|
|
|
|
await doDropProc();
|
2018-04-03 05:45:58 +08:00
|
|
|
}); // 163.5
|
|
|
|
|
2023-02-21 11:27:04 +08:00
|
|
|
it('163.6 shows dmlRowCounts', async function() {
|
2018-04-03 05:45:58 +08:00
|
|
|
|
2023-02-21 11:20:36 +08:00
|
|
|
if ((testsUtil.getClientVersion < 1201000200)
|
2021-04-01 12:48:37 +08:00
|
|
|
|| (conn.oracleServerVersion < 1201000200)) {
|
2023-02-21 11:27:04 +08:00
|
|
|
return this.skip();
|
2018-09-29 06:16:05 +08:00
|
|
|
}
|
2018-04-03 05:45:58 +08:00
|
|
|
|
2023-02-21 11:27:04 +08:00
|
|
|
const childTable = "nodb_tab_child_one";
|
|
|
|
const parentTable = "nodb_tab_parent_one";
|
|
|
|
|
|
|
|
await makeParentChildTables(childTable, parentTable);
|
|
|
|
const sql = "DELETE FROM " + childTable + " WHERE parentid = :1";
|
|
|
|
const binds = [ [20], [30], [50] ];
|
|
|
|
const options = { dmlRowCounts: true };
|
|
|
|
const result = await conn.executeMany(sql, binds, options);
|
|
|
|
assert.strictEqual(result.rowsAffected, 9);
|
|
|
|
assert.deepEqual(result.dmlRowCounts, [ 3, 2, 4 ]);
|
|
|
|
await dropParentChildTables(childTable, parentTable);
|
2018-04-03 05:45:58 +08:00
|
|
|
}); // 163.6
|
|
|
|
|
2023-02-21 11:27:04 +08:00
|
|
|
it('163.7 shows batchErrors behavior', async function() {
|
2018-04-03 05:45:58 +08:00
|
|
|
|
2023-02-21 11:20:36 +08:00
|
|
|
if ((testsUtil.getClientVersion < 1201000200)
|
2021-04-01 12:48:37 +08:00
|
|
|
|| (conn.oracleServerVersion < 1201000200)) {
|
2023-02-21 11:27:04 +08:00
|
|
|
return this.skip();
|
2018-09-29 06:16:05 +08:00
|
|
|
}
|
2018-04-03 05:45:58 +08:00
|
|
|
|
2023-02-21 11:27:04 +08:00
|
|
|
const childTable = "nodb_tab_child_two";
|
|
|
|
const parentTable = "nodb_tab_parent_two";
|
|
|
|
|
|
|
|
await makeParentChildTables(childTable, parentTable);
|
|
|
|
const sql = "INSERT INTO " + childTable + " VALUES (:1, :2, :3)";
|
|
|
|
const binds = [
|
|
|
|
[1016, 10, "Child 2 of Parent A"],
|
|
|
|
[1017, 10, "Child 3 of Parent A"],
|
|
|
|
[1018, 20, "Child 4 of Parent B"],
|
|
|
|
[1018, 20, "Child 4 of Parent B"], // duplicate key
|
|
|
|
[1019, 30, "Child 3 of Parent C"],
|
|
|
|
[1020, 40, "Child 4 of Parent D"],
|
|
|
|
[1021, 75, "Child 1 of Parent F"], // parent does not exist
|
|
|
|
[1022, 40, "Child 6 of Parent D"]
|
|
|
|
];
|
|
|
|
const options = {
|
|
|
|
autoCommit: true,
|
|
|
|
batchErrors: true,
|
|
|
|
dmlRowCounts: true,
|
|
|
|
bindDefs: [
|
|
|
|
{ type: oracledb.NUMBER },
|
|
|
|
{ type: oracledb.NUMBER },
|
|
|
|
{ type: oracledb.STRING, maxSize: 20 }
|
|
|
|
]
|
|
|
|
};
|
|
|
|
const result = await conn.executeMany(sql, binds, options);
|
|
|
|
assert.strictEqual(result.rowsAffected, 6);
|
|
|
|
assert.deepEqual(result.dmlRowCounts, [ 1, 1, 1, 0, 1, 1, 0, 1 ]);
|
|
|
|
assert(result.batchErrors[0].message.startsWith('ORA-00001: '));
|
|
|
|
// ORA-00001: unique constraint (HR.CHILDTAB_PK) violated
|
|
|
|
assert(result.batchErrors[1].message.startsWith('ORA-02291: '));
|
|
|
|
// ORA-02291: integrity constraint (HR.CHILDTAB_FK) violated - parent key not found
|
|
|
|
await dropParentChildTables(childTable, parentTable);
|
2018-04-03 05:45:58 +08:00
|
|
|
}); // 163.7
|
|
|
|
|
2023-02-21 11:27:04 +08:00
|
|
|
it('163.8 Negative - batchErrors with non-DML statement', async function() {
|
2018-05-22 12:45:11 +08:00
|
|
|
|
2023-02-21 11:20:36 +08:00
|
|
|
if (testsUtil.getClientVersion < 1201000200) {
|
2023-02-21 11:27:04 +08:00
|
|
|
return this.skip();
|
2021-04-01 12:48:37 +08:00
|
|
|
}
|
2018-05-22 12:45:11 +08:00
|
|
|
|
2023-02-21 11:27:04 +08:00
|
|
|
await doCreateProc();
|
|
|
|
|
|
|
|
const plsql = "BEGIN nodb_proc_em(:1, :2, :3); END;";
|
|
|
|
const binds = [ [1], [2], [3], [4], [6] ];
|
|
|
|
const options = {
|
|
|
|
batchErrors: true,
|
|
|
|
bindDefs: [
|
|
|
|
{ type: oracledb.NUMBER },
|
|
|
|
{ type: oracledb.NUMBER, dir: oracledb.BIND_OUT },
|
|
|
|
{ type: oracledb.STRING, dir: oracledb.BIND_OUT, maxSize: 20 }
|
|
|
|
]
|
|
|
|
};
|
|
|
|
|
2023-02-21 11:45:10 +08:00
|
|
|
await assert.rejects(
|
2023-02-21 11:27:04 +08:00
|
|
|
async () => await conn.executeMany(plsql, binds, options),
|
2023-02-21 11:36:19 +08:00
|
|
|
/NJS-095:/
|
2023-02-21 11:27:04 +08:00
|
|
|
);
|
|
|
|
await doDropProc();
|
2018-05-22 12:45:11 +08:00
|
|
|
}); // 163.8
|
|
|
|
|
2023-02-21 11:27:04 +08:00
|
|
|
it('163.9 if batchErrors is disabled', async function() {
|
2018-05-22 12:45:11 +08:00
|
|
|
|
2023-02-21 11:20:36 +08:00
|
|
|
if (testsUtil.getClientVersion < 1201000200) {
|
2023-02-21 11:27:04 +08:00
|
|
|
return this.skip();
|
2021-04-01 12:48:37 +08:00
|
|
|
}
|
2018-05-22 12:45:11 +08:00
|
|
|
|
2023-02-21 11:27:04 +08:00
|
|
|
const childTable = "nodb_tab_child_three";
|
|
|
|
const parentTable = "nodb_tab_parent_three";
|
|
|
|
|
|
|
|
await makeParentChildTables(childTable, parentTable);
|
|
|
|
const sql = "INSERT INTO " + childTable + " VALUES (:1, :2, :3)";
|
|
|
|
const binds = [
|
|
|
|
[1016, 10, "Child 2 of Parent A"],
|
|
|
|
[1017, 10, "Child 3 of Parent A"],
|
|
|
|
[1018, 20, "Child 4 of Parent B"],
|
|
|
|
[1018, 20, "Child 4 of Parent B"], // duplicate key
|
|
|
|
[1019, 30, "Child 3 of Parent C"],
|
|
|
|
[1020, 40, "Child 4 of Parent D"],
|
|
|
|
[1021, 75, "Child 1 of Parent F"], // parent does not exist
|
|
|
|
[1022, 40, "Child 6 of Parent D"]
|
|
|
|
];
|
|
|
|
const options = {
|
|
|
|
autoCommit: true,
|
|
|
|
batchErrors: false,
|
|
|
|
dmlRowCounts: true,
|
|
|
|
bindDefs: [
|
|
|
|
{ type: oracledb.NUMBER },
|
|
|
|
{ type: oracledb.NUMBER },
|
|
|
|
{ type: oracledb.STRING, maxSize: 20 }
|
|
|
|
]
|
|
|
|
};
|
2023-02-21 11:45:10 +08:00
|
|
|
await assert.rejects(
|
2023-02-21 11:27:04 +08:00
|
|
|
async () => await conn.executeMany(sql, binds, options),
|
|
|
|
/ORA-00001:/
|
|
|
|
);
|
|
|
|
await dropParentChildTables(childTable, parentTable);
|
2018-05-22 12:45:11 +08:00
|
|
|
}); // 163.9
|
|
|
|
|
2023-02-21 11:27:04 +08:00
|
|
|
it('163.10 Negative - dmlRowCounts with non-DML statement', async function() {
|
2023-02-21 11:20:36 +08:00
|
|
|
if (testsUtil.getClientVersion < 1201000200) {
|
2023-02-21 11:27:04 +08:00
|
|
|
return this.skip();
|
2021-04-01 12:48:37 +08:00
|
|
|
}
|
2018-05-22 12:45:11 +08:00
|
|
|
|
2023-02-21 11:27:04 +08:00
|
|
|
await doCreateProc();
|
|
|
|
const plsql = "BEGIN nodb_proc_em(:1, :2, :3); END;";
|
|
|
|
const binds = [ [1], [2], [3], [4], [6] ];
|
|
|
|
const options = {
|
|
|
|
dmlRowCounts: true,
|
|
|
|
bindDefs: [
|
|
|
|
{ type: oracledb.NUMBER },
|
|
|
|
{ type: oracledb.NUMBER, dir: oracledb.BIND_OUT },
|
|
|
|
{ type: oracledb.STRING, dir: oracledb.BIND_OUT, maxSize: 20 }
|
|
|
|
]
|
|
|
|
};
|
2023-02-21 11:45:10 +08:00
|
|
|
await assert.rejects(
|
2023-02-21 11:27:04 +08:00
|
|
|
async () => await conn.executeMany(plsql, binds, options),
|
2023-02-21 11:36:19 +08:00
|
|
|
/NJS-095:/
|
2023-02-21 11:27:04 +08:00
|
|
|
);
|
|
|
|
await doDropProc();
|
2018-05-22 12:45:11 +08:00
|
|
|
}); // 163.10
|
|
|
|
|
2023-02-21 11:27:04 +08:00
|
|
|
it('163.11 numIterations - only OUT parameters', async function() {
|
|
|
|
const sql =
|
|
|
|
`declare
|
|
|
|
t_Id number;
|
|
|
|
begin
|
|
|
|
select nvl(count(*), 0) + 1 into t_Id
|
|
|
|
from nodb_tab_xmany;
|
|
|
|
|
|
|
|
insert into nodb_tab_xmany
|
|
|
|
values (t_Id, 'Test String ' || t_Id);
|
|
|
|
|
|
|
|
select sum(Id) into :1
|
|
|
|
from nodb_tab_xmany;
|
|
|
|
end;`;
|
|
|
|
const bindDefs = [
|
|
|
|
{ type : oracledb.NUMBER, dir : oracledb.BIND_OUT }
|
|
|
|
];
|
|
|
|
const options = { bindDefs: bindDefs };
|
|
|
|
const numIterations = 8;
|
|
|
|
const result = await conn.executeMany(sql, numIterations, options);
|
|
|
|
assert.deepEqual(
|
|
|
|
result.outBinds,
|
|
|
|
[ [ 1 ], [ 3 ], [ 6 ], [ 10 ], [ 15 ], [ 21 ], [ 28 ], [ 36 ] ]
|
|
|
|
);
|
|
|
|
await dotruncate();
|
2018-08-22 11:30:48 +08:00
|
|
|
}); // 163.11
|
2018-08-22 11:10:37 +08:00
|
|
|
|
2023-02-21 11:27:04 +08:00
|
|
|
it('163.12 numIterations - No parameters', async function() {
|
|
|
|
const sql = `
|
|
|
|
declare
|
|
|
|
t_Id number;
|
|
|
|
begin
|
|
|
|
select nvl(count(*), 0) + 1 into t_Id
|
|
|
|
from nodb_tab_xmany;
|
|
|
|
|
|
|
|
insert into nodb_tab_xmany
|
|
|
|
values (t_Id, 'Test String ' || t_Id);
|
|
|
|
end;`;
|
|
|
|
|
|
|
|
const numIterations = 8;
|
|
|
|
await conn.executeMany(sql, numIterations);
|
|
|
|
await dotruncate();
|
2018-08-22 11:30:48 +08:00
|
|
|
}); // 163.12
|
2018-08-22 11:10:37 +08:00
|
|
|
|
2023-02-21 11:27:04 +08:00
|
|
|
it('163.13 numIterations - DML RETURNING', async function() {
|
|
|
|
const sql = `
|
|
|
|
insert into nodb_tab_xmany (val)
|
|
|
|
values (to_char(systimestamp, 'YYYY-MM-DD HH24:MI:SS.FF'))
|
|
|
|
returning id, val into :1, :2`;
|
|
|
|
|
|
|
|
const bindDefs = [
|
|
|
|
{ type : oracledb.NUMBER, dir : oracledb.BIND_OUT },
|
|
|
|
{ type : oracledb.STRING, dir : oracledb.BIND_OUT, maxSize : 30 }
|
|
|
|
];
|
|
|
|
|
|
|
|
const options = { bindDefs : bindDefs };
|
|
|
|
const numIterations = 8;
|
|
|
|
const result = await conn.executeMany(sql, numIterations, options);
|
|
|
|
assert.strictEqual(result.outBinds.length, numIterations);
|
|
|
|
await dotruncate();
|
2018-08-22 11:10:37 +08:00
|
|
|
}); // 164.13
|
|
|
|
|
2023-02-21 11:27:04 +08:00
|
|
|
it('163.14 Negative - set numIterations to be negative value', async function() {
|
|
|
|
const sql = `
|
|
|
|
declare
|
|
|
|
t_Id number;
|
|
|
|
begin
|
|
|
|
select nvl(count(*), 0) + 1 into t_Id
|
|
|
|
from nodb_tab_xmany;
|
|
|
|
|
|
|
|
insert into nodb_tab_xmany
|
|
|
|
values (t_Id, 'Test String ' || t_Id);
|
|
|
|
end;`;
|
|
|
|
|
|
|
|
const numIterations = -8;
|
2023-02-21 11:45:10 +08:00
|
|
|
await assert.rejects(
|
2023-02-21 11:27:04 +08:00
|
|
|
async () => await conn.executeMany(sql, numIterations),
|
|
|
|
/NJS-005:/
|
|
|
|
);
|
|
|
|
await dotruncate();
|
2020-02-16 08:06:45 +08:00
|
|
|
}); // 163.14
|
2018-08-22 11:10:37 +08:00
|
|
|
|
2023-02-21 12:04:16 +08:00
|
|
|
it('163.15 getting dmlrowcounts after executemany with dmlrowcounts=False', async function() {
|
|
|
|
|
|
|
|
const binds = [
|
|
|
|
{ a: 6, b: "Test 6 (Six)" },
|
|
|
|
{ a: 7, b: "Test 7 (Seven)" },
|
|
|
|
{ a: 8, b: "Test 8 (Eight)" },
|
|
|
|
{ a: 9 },
|
|
|
|
{ a: 10, b: "Test 10 (Ten)" }
|
|
|
|
];
|
|
|
|
let sql = "INSERT INTO nodb_tab_xmany VALUES (:a, :b)";
|
|
|
|
|
|
|
|
let result = await conn.executeMany(sql, binds, { dmlRowCounts: false });
|
|
|
|
assert.strictEqual(result.rowsAffected, binds.length);
|
|
|
|
sql = "SELECT * FROM nodb_tab_xmany ORDER BY ID";
|
|
|
|
const expectVal = [
|
|
|
|
[ 6, 'Test 6 (Six)' ],
|
|
|
|
[ 7, 'Test 7 (Seven)' ],
|
|
|
|
[ 8, 'Test 8 (Eight)' ],
|
|
|
|
[ 9, null ],
|
|
|
|
[ 10, 'Test 10 (Ten)' ]
|
|
|
|
];
|
|
|
|
result = await conn.execute(sql);
|
|
|
|
assert.deepEqual(result.rows, expectVal);
|
|
|
|
await dotruncate();
|
|
|
|
}); // 163.15
|
|
|
|
|
|
|
|
it('163.16 executemany() with an invalid row', async function() {
|
|
|
|
|
|
|
|
const binds = [
|
|
|
|
{ a: 6, b: "Test 6 (Six)" },
|
|
|
|
{ a: 7, b: "Test 7 (Seven)" },
|
|
|
|
{ a: 8, b: 8 }
|
|
|
|
];
|
|
|
|
let sql = "INSERT INTO nodb_tab_xmany VALUES (:a, :b)";
|
|
|
|
|
|
|
|
await assert.rejects(
|
|
|
|
async () => await conn.executeMany(sql, binds, { dmlRowCounts: true }),
|
|
|
|
/NJS-011:/
|
|
|
|
);
|
|
|
|
await dotruncate();
|
|
|
|
}); // 163.16
|
|
|
|
|
2023-02-21 11:27:04 +08:00
|
|
|
const doCreateProc = async function() {
|
|
|
|
const proc = "CREATE OR REPLACE PROCEDURE nodb_proc_em (a_num IN NUMBER, " +
|
2018-05-22 12:45:11 +08:00
|
|
|
" a_outnum OUT NUMBER, a_outstr OUT VARCHAR2) \n" +
|
|
|
|
"AS \n" +
|
|
|
|
"BEGIN \n" +
|
|
|
|
" a_outnum := a_num * 2; \n" +
|
|
|
|
" FOR i IN 1..a_num LOOP \n" +
|
|
|
|
" a_outstr := a_outstr || 'X'; \n" +
|
|
|
|
" END LOOP; \n" +
|
|
|
|
"END nodb_proc_em;";
|
2023-02-21 11:27:04 +08:00
|
|
|
await conn.execute(proc);
|
2018-05-22 12:45:11 +08:00
|
|
|
}; // doCreateProc()
|
|
|
|
|
2023-02-21 11:27:04 +08:00
|
|
|
const doDropProc = async function() {
|
|
|
|
const sql = "DROP PROCEDURE nodb_proc_em";
|
|
|
|
await conn.execute(sql);
|
2018-05-22 12:45:11 +08:00
|
|
|
}; // doDropProc()
|
|
|
|
|
2023-02-21 11:27:04 +08:00
|
|
|
const dotruncate = async function() {
|
|
|
|
await conn.execute("TRUNCATE TABLE nodb_tab_xmany");
|
2018-04-03 05:45:58 +08:00
|
|
|
}; // dotruncate()
|
|
|
|
|
2023-02-21 11:27:04 +08:00
|
|
|
const makeParentChildTables = async function(cTab, pTab) {
|
|
|
|
let proc = "BEGIN EXECUTE IMMEDIATE 'DROP TABLE " + cTab + "'; " +
|
|
|
|
"EXCEPTION WHEN OTHERS THEN IF SQLCODE <> -942 THEN RAISE; END IF; END;";
|
|
|
|
await conn.execute(proc);
|
|
|
|
proc = "BEGIN EXECUTE IMMEDIATE 'DROP TABLE " + pTab + "'; " +
|
|
|
|
"EXCEPTION WHEN OTHERS THEN IF SQLCODE <> -942 THEN RAISE; END IF; END;";
|
|
|
|
await conn.execute(proc);
|
|
|
|
let sql = "CREATE TABLE " + pTab + " ( \n" +
|
|
|
|
" parentid NUMBER NOT NULL, \n" +
|
|
|
|
" description VARCHAR2(60) NOT NULL, \n" +
|
|
|
|
" CONSTRAINT " + pTab + "_pk PRIMARY KEY (parentid) \n" +
|
|
|
|
") ";
|
|
|
|
await conn.execute(sql);
|
|
|
|
sql = "CREATE TABLE " + cTab + " ( \n" +
|
|
|
|
" childid NUMBER NOT NULL, \n" +
|
|
|
|
" parentid NUMBER NOT NULL, \n" +
|
|
|
|
" description VARCHAR2(30) NOT NULL, \n" +
|
|
|
|
" CONSTRAINT " + cTab + "_pk PRIMARY KEY (childid), \n" +
|
|
|
|
" CONSTRAINT " + cTab + "_fk FOREIGN KEY (parentid) REFERENCES " + pTab + " \n" +
|
|
|
|
") ";
|
|
|
|
await conn.execute(sql);
|
|
|
|
sql = "INSERT INTO " + pTab + " VALUES (:1, :2)";
|
|
|
|
let binds = [
|
|
|
|
[10, "Parent 10"],
|
|
|
|
[20, "Parent 20"],
|
|
|
|
[30, "Parent 30"],
|
|
|
|
[40, "Parent 40"],
|
|
|
|
[50, "Parent 50"]
|
|
|
|
];
|
|
|
|
let options = {
|
|
|
|
autoCommit: true,
|
|
|
|
bindDefs: [
|
|
|
|
{ type: oracledb.NUMBER },
|
|
|
|
{ type: oracledb.STRING, maxSize: 15 }
|
|
|
|
]
|
|
|
|
};
|
|
|
|
let result = await conn.executeMany(sql, binds, options);
|
|
|
|
assert.strictEqual(result.rowsAffected, binds.length);
|
|
|
|
sql = "INSERT INTO " + cTab + " VALUES (:1, :2, :3)";
|
|
|
|
binds = [
|
|
|
|
[1001, 10, "Child 1001 of Parent 10"],
|
|
|
|
[1002, 20, "Child 1001 of Parent 20"],
|
|
|
|
[1003, 20, "Child 1001 of Parent 20"],
|
|
|
|
[1004, 20, 'Child 1004 of Parent 20'],
|
|
|
|
[1005, 30, 'Child 1005 of Parent 30'],
|
|
|
|
[1006, 30, 'Child 1006 of Parent 30'],
|
|
|
|
[1007, 40, 'Child 1007 of Parent 40'],
|
|
|
|
[1008, 40, 'Child 1008 of Parent 40'],
|
|
|
|
[1009, 40, "Child 1009 of Parent 40"],
|
|
|
|
[1010, 40, "Child 1010 of Parent 40"],
|
|
|
|
[1011, 40, "Child 1011 of Parent 40"],
|
|
|
|
[1012, 50, 'Child 1012 of Parent 50'],
|
|
|
|
[1013, 50, 'Child 1013 of Parent 50'],
|
|
|
|
[1014, 50, 'Child 1014 of Parent 50'],
|
|
|
|
[1015, 50, 'Child 1015 of Parent 50'],
|
|
|
|
];
|
|
|
|
options = {
|
|
|
|
autoCommit: true,
|
|
|
|
bindDefs: [
|
|
|
|
{ type: oracledb.NUMBER },
|
|
|
|
{ type: oracledb.NUMBER },
|
|
|
|
{ type: oracledb.STRING, maxSize: 500 }
|
|
|
|
]
|
|
|
|
};
|
|
|
|
result = await conn.executeMany(sql, binds, options);
|
|
|
|
assert.strictEqual(result.rowsAffected, binds.length);
|
2018-04-03 05:45:58 +08:00
|
|
|
}; // makeParentChildTables()
|
|
|
|
|
2023-02-21 11:27:04 +08:00
|
|
|
const dropParentChildTables = async function(cTab, pTab) {
|
|
|
|
let sql = "drop table " + cTab + " purge";
|
|
|
|
await conn.execute(sql);
|
|
|
|
sql = "drop table " + pTab + " purge";
|
|
|
|
await conn.execute(sql);
|
2018-04-03 05:45:58 +08:00
|
|
|
}; // dropParentChildTables()
|
|
|
|
|
2019-03-18 10:58:21 +08:00
|
|
|
});
|