node-oracledb/test/urowidDMLBindAsString2.js

557 lines
20 KiB
JavaScript
Executable File

/* Copyright (c) 2017, 2023, Oracle and/or its affiliates. */
/******************************************************************************
*
* 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.
*
* 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* NAME
* 115. urowidDMLBindAsString2.js
*
* DESCRIPTION
* Testing urowid binding as String with DML.
* The Universal ROWID (UROWID) is a datatype that can store both logical and physical rowids of Oracle tables. Logical rowids are primary key-based logical identifiers for the rows of Index-Organized Tables (IOTs).
* To use columns of the UROWID datatype, the value of the COMPATIBLE initialization parameter must be set to 8.1 or higher.
*
*****************************************************************************/
'use strict';
const oracledb = require('oracledb');
const assert = require('assert');
const dbConfig = require('./dbconfig.js');
const random = require('./random.js');
const testsUtil = require('./testsUtil.js');
describe('115. urowidDMLBindAsString2.js', function() {
let connection = null;
const tableName_indexed = "nodb_urowid_indexed";
const tableName_normal = "nodb_urowid_normal";
let insertID = 1;
const table_indexed = `BEGIN
DECLARE
e_table_missing EXCEPTION;
PRAGMA EXCEPTION_INIT(e_table_missing, -00942);
BEGIN
EXECUTE IMMEDIATE ('DROP TABLE ` + tableName_indexed + ` PURGE' );
EXCEPTION
WHEN e_table_missing
THEN NULL;
END;
EXECUTE IMMEDIATE ( '
CREATE TABLE ` + tableName_indexed + `(
c1 NUMBER,
c2 VARCHAR2(3000),
primary key(c1, c2)
) organization index
');
END;`;
const table_normal = `BEGIN
DECLARE
e_table_missing EXCEPTION;
PRAGMA EXCEPTION_INIT(e_table_missing, -00942);
BEGIN
EXECUTE IMMEDIATE ('DROP TABLE ` + tableName_normal + ` PURGE' );
EXCEPTION
WHEN e_table_missing
THEN NULL;
END;
EXECUTE IMMEDIATE ('
CREATE TABLE ` + tableName_normal + ` (
ID NUMBER,
content UROWID(4000)
)
');
END;`;
const drop_table_indexed = "DROP TABLE " + tableName_indexed + " PURGE";
const drop_table_normal = "DROP TABLE " + tableName_normal + " PURGE";
before('get connection and create table', async function() {
connection = await oracledb.getConnection(dbConfig);
await connection.execute(table_indexed);
await connection.execute(table_normal);
});
after('release connection', async function() {
await connection.execute(drop_table_indexed);
await connection.execute(drop_table_normal);
await connection.close();
});
beforeEach(function() {
insertID++;
});
describe('115.1 INSERT & SELECT', function() {
it('115.1.1 works with urowid length > 200', async function() {
await testBigUROWID(200, 200);
});
it('115.1.2 works with urowid length > 500', async function() {
await testBigUROWID(600, 500);
});
it('115.1.3 works with maxSize < 200', async function() {
await testBigUROWID_maxSize(300, 200);
});
});
describe('115.2 UPDATE', function() {
it('115.2.1 update null with urowid length > 200', async function() {
await testBigUROWID_update(null, 200, 200);
});
it('115.2.2 update enpty string with urowid length > 500', async function() {
await testBigUROWID_update("", 600, 500);
});
it('115.2.3 update with urowid length > 500', async function() {
await testBigUROWID_update("00000DD5.0000.0001", 600, 500);
});
it('115.2.4 works with maxSize < 200', async function() {
await testBigUROWID_update_maxSize("00000DD5.0000.0001", 300, 200);
});
});
describe('115.3 RETURNING INTO', function() {
it('115.3.1 urowid length > 200', async function() {
if (connection.oracleServerVersion < 1201000200) this.skip();
await testBigUROWID_returning(200, 200);
});
it('115.3.2 urowid length > 500', async function() {
await testBigUROWID_returning(600, 500);
});
});
describe('115.4 WHERE', function() {
it('115.4.1 urowid length > 200', async function() {
await testBigUROWID_where(200, 200);
});
it('115.4.2 urowid length > 500', async function() {
await testBigUROWID_where(600, 500);
});
});
describe('115.5 queryStream() and oracledb.maxRows = actual rows', function() {
it('115.5.1 urowid length > 200', async function() {
await testBigUROWID_stream(2, 200, 200);
});
it('115.5.2 urowid length > 500', async function() {
await testBigUROWID_stream(2, 600, 500);
});
});
describe('115.6 queryStream() and oracledb.maxRows > actual rows', function() {
it('115.6.1 urowid length > 200', async function() {
await testBigUROWID_stream(5, 200, 200);
});
it('115.6.2 urowid length > 500', async function() {
await testBigUROWID_stream(100, 600, 500);
});
});
describe('115.7 queryStream() and oracledb.maxRows < actual rows', function() {
it('115.7.1 urowid length > 200', async function() {
await testBigUROWID_stream(1, 200, 200);
});
it('115.7.2 urowid length > 500', async function() {
await testBigUROWID_stream(1, 600, 500);
});
});
const testBigUROWID = async function(strLength, rowidLenExpected) {
const str = random.getRandomLengthString(strLength);
let result;
const sql_insert = "insert into " + tableName_indexed + " values (" + insertID + ", '" + str + "')";
await connection.execute(sql_insert);
result = await connection.execute("select ROWID from " + tableName_indexed + " where c1 = " + insertID);
const urowid = result.rows[0][0];
const urowidLen = urowid.length;
await testsUtil.checkUrowidLength(urowidLen, rowidLenExpected);
const bindVar = {
i: { val: insertID, dir: oracledb.BIND_IN, type: oracledb.NUMBER },
c: { val: urowid, dir: oracledb.BIND_IN, type: oracledb.STRING }
};
try {
result = await connection.execute("insert into " + tableName_normal + " (ID, content) values (:i, :c)", bindVar);
} catch (err) {
if (urowidLen > 4000) {
assert.strictEqual(err.message, "ORA-01704: string literal too long");
}
}
if ((urowidLen <= 4000)) {
assert.strictEqual(result.rowsAffected, 1);
}
result = await connection.execute("select * from " + tableName_normal + " where ID = " + insertID);
if (urowidLen < 4000) {
assert.strictEqual(result.rows[0][1], urowid);
}
insertID++;
try {
result = await connection.execute("insert into " + tableName_normal + " (ID, content) values (" + insertID + ", '" + urowid + "')");
} catch (err) {
if (urowidLen > 4000) {
assert.strictEqual(err.message, "ORA-01704: string literal too long");
}
}
if ((urowidLen <= 4000)) {
assert.strictEqual(result.rowsAffected, 1);
}
result = await connection.execute("select * from " + tableName_normal + " where ID = " + insertID);
if (urowidLen < 4000) {
assert.strictEqual(result.rows[0][1], urowid);
}
};
const testBigUROWID_maxSize = async function(strLength, rowidLenExpected) {
const str = random.getRandomLengthString(strLength);
let result;
const sql_insert = "insert into " + tableName_indexed + " values (" + insertID + ", '" + str + "')";
await connection.execute(sql_insert);
result = await connection.execute("select ROWID from " + tableName_indexed + " where c1 = " + insertID);
const urowid = result.rows[0][0];
const urowidLen = urowid.length;
await testsUtil.checkUrowidLength(urowidLen, rowidLenExpected);
const bindVar = {
i: { val: insertID, dir: oracledb.BIND_IN, type: oracledb.NUMBER },
c: { val: urowid, dir: oracledb.BIND_IN, type: oracledb.STRING, maxSize: 100 }
};
try {
result = await connection.execute("insert into " + tableName_normal + " (ID, content) values (:i, :c)", bindVar);
} catch (err) {
if (urowidLen > 4000) {
assert.strictEqual(err.message, "ORA-01704: string literal too long");
}
}
if (urowidLen <= 4000) {
assert.strictEqual(result.rowsAffected, 1);
}
result = await connection.execute("select * from " + tableName_normal + " where ID = " + insertID);
if (urowidLen < 4000) {
assert.strictEqual(result.rows[0][1], urowid);
}
insertID++;
try {
result = await connection.execute("insert into " + tableName_normal + " (ID, content) values (" + insertID + ", '" + urowid + "')");
} catch (err) {
if (urowidLen > 4000) {
assert.strictEqual(err.message, "ORA-01704: string literal too long");
}
}
if (urowidLen <= 4000) {
assert.strictEqual(result.rowsAffected, 1);
}
result = await connection.execute("select * from " + tableName_normal + " where ID = " + insertID);
if (urowidLen < 4000) {
assert.strictEqual(result.rows[0][1], urowid);
}
};
const testBigUROWID_update = async function(rowid_org, strLength, rowidLenExpected) {
const str = random.getRandomLengthString(strLength);
let sql_insert, bindVar, result;
const id_1 = insertID++;
const id_2 = insertID++;
sql_insert = "insert into " + tableName_normal + " (ID, content) values (:i, :c)";
bindVar = {
i: { val: id_1, dir: oracledb.BIND_IN, type: oracledb.NUMBER },
c: { val: rowid_org, dir: oracledb.BIND_IN, type: oracledb.STRING }
};
await connection.execute(sql_insert, bindVar);
sql_insert = "insert into " + tableName_normal + " (ID, content) values (:i, :c)";
bindVar = {
i: { val: id_2, dir: oracledb.BIND_IN, type: oracledb.NUMBER },
c: { val: rowid_org, dir: oracledb.BIND_IN, type: oracledb.STRING }
};
await connection.execute(sql_insert, bindVar);
sql_insert = "insert into " + tableName_indexed + " values (" + insertID + ", '" + str + "')";
await connection.execute(sql_insert);
result = await connection.execute("select ROWID from " + tableName_indexed + " where c1 = " + insertID);
const urowid = result.rows[0][0];
const urowidLen = urowid.length;
await testsUtil.checkUrowidLength(urowidLen, rowidLenExpected);
bindVar = {
c: { val: urowid, dir: oracledb.BIND_IN, type: oracledb.STRING },
i: { val: id_1, dir: oracledb.BIND_IN, type: oracledb.NUMBER }
};
try {
result = await connection.execute("update " + tableName_normal + " set content = :c where ID = :i", bindVar);
} catch (err) {
if (urowidLen > 4000) {
assert.strictEqual(err.message, "ORA-01704: string literal too long");
}
}
if (urowidLen <= 4000) {
assert.strictEqual(result.rowsAffected, 1);
}
result = await connection.execute("select * from " + tableName_normal + " where ID = " + id_1);
if (urowidLen < 4000) {
assert.strictEqual(result.rows[0][1], urowid);
}
try {
result = await connection.execute("update " + tableName_normal + " set content = '" + urowid + "' where ID = " + id_2);
} catch (err) {
if (urowidLen > 4000) {
assert.strictEqual(err.message, "ORA-01704: string literal too long");
}
}
if (urowidLen <= 4000) {
assert(result.rowsAffected, 1);
}
result = await connection.execute("select * from " + tableName_normal + " where ID = " + id_2);
if (urowidLen < 4000) {
assert.strictEqual(result.rows[0][1], urowid);
}
};
const testBigUROWID_update_maxSize = async function(rowid_org, strLength, rowidLenExpected) {
const str = random.getRandomLengthString(strLength);
const id_1 = insertID++;
const id_2 = insertID++;
let sql_insert, bindVar, result;
sql_insert = "insert into " + tableName_normal + " (ID, content) values (:i, :c)";
bindVar = {
i: { val: id_1, dir: oracledb.BIND_IN, type: oracledb.NUMBER },
c: { val: rowid_org, dir: oracledb.BIND_IN, type: oracledb.STRING }
};
await connection.execute(sql_insert, bindVar);
sql_insert = "insert into " + tableName_normal + " (ID, content) values (:i, :c)";
bindVar = {
i: { val: id_2, dir: oracledb.BIND_IN, type: oracledb.NUMBER },
c: { val: rowid_org, dir: oracledb.BIND_IN, type: oracledb.STRING }
};
await connection.execute(sql_insert, bindVar);
sql_insert = "insert into " + tableName_indexed + " values (" + insertID + ", '" + str + "')";
await connection.execute(sql_insert);
result = await connection.execute("select ROWID from " + tableName_indexed + " where c1 = " + insertID);
assert(result);
const urowid = result.rows[0][0];
const urowidLen = urowid.length;
testsUtil.checkUrowidLength(urowidLen, rowidLenExpected);
bindVar = {
c: { val: urowid, dir: oracledb.BIND_IN, type: oracledb.STRING },
i: { val: id_1, dir: oracledb.BIND_IN, type: oracledb.NUMBER, maxSize: 100 }
};
result = await connection.execute("update " + tableName_normal + " set content = :c where ID = :i", bindVar);
assert(result);
assert(result.rowsAffected, 1);
result = await connection.execute("select * from " + tableName_normal + " where ID = " + id_1);
if (urowidLen < 4000) {
assert(result);
assert.strictEqual(result.rows[0][1], urowid);
}
result = await connection.execute("update " + tableName_normal + " set content = '" + urowid + "' where ID = " + id_2);
assert(result);
assert(result.rowsAffected, 1);
result = await connection.execute("select * from " + tableName_normal + " where ID = " + id_2);
assert(result);
assert.strictEqual(result.rows[0][1], urowid);
};
const testBigUROWID_returning = async function(strLength, rowidLenExpected) {
const str = random.getRandomLengthString(strLength);
let result, bindVar;
const sql_insert = "insert into " + tableName_indexed + " values (" + insertID + ", '" + str + "')";
await connection.execute(sql_insert);
result = await connection.execute("select ROWID from " + tableName_indexed + " where c1 = " + insertID);
assert(result);
const urowid = result.rows[0][0];
const urowidLen = urowid.length;
testsUtil.checkUrowidLength(urowidLen, rowidLenExpected);
bindVar = {
i: { val: insertID, dir: oracledb.BIND_IN, type: oracledb.NUMBER },
c: { val: urowid, dir: oracledb.BIND_IN, type: oracledb.STRING },
o: { dir: oracledb.BIND_OUT, type: oracledb.STRING, maxSize: urowidLen }
};
result = await connection.execute("insert into " + tableName_normal + " (ID, content) values (:i, :c) returning content into :o", bindVar);
assert(result);
let resultVal;
if (typeof (result.outBinds.o) === 'undefined') resultVal = result.outBinds[0][0];
else resultVal = result.outBinds.o[0];
assert.strictEqual(resultVal, urowid);
bindVar = {
i: { val: insertID, dir: oracledb.BIND_IN, type: oracledb.NUMBER },
c: { val: urowid, dir: oracledb.BIND_IN, type: oracledb.STRING },
o: { dir: oracledb.BIND_OUT, type: oracledb.STRING, maxSize: 100 }
};
try {
await connection.execute("insert into " + tableName_normal + " (ID, content) values (:i, :c) returning content into :o", bindVar);
} catch (err) {
assert.strictEqual(err.message, "NJS-016: buffer is too small for OUT binds");
}
};
const testBigUROWID_where = async function(strLength, rowidLenExpected) {
const str = random.getRandomLengthString(strLength);
let result, bindVar;
const sql_insert = "insert into " + tableName_indexed + " values (" + insertID + ", '" + str + "')";
await connection.execute(sql_insert);
result = await connection.execute("select ROWID from " + tableName_indexed + " where c1 = " + insertID);
assert(result);
const urowid = result.rows[0][0];
const urowidLen = urowid.length;
testsUtil.checkUrowidLength(urowidLen, rowidLenExpected);
bindVar = {
c: { val: urowid, dir: oracledb.BIND_IN, type: oracledb.STRING }
};
result = await connection.execute("select * from " + tableName_indexed + " where ROWID = :c", bindVar);
assert(result);
assert.strictEqual(result.rows[0][0], insertID);
assert.strictEqual(result.rows[0][1], str);
bindVar = {
c: { val: urowid, dir: oracledb.BIND_IN, type: oracledb.STRING, maxSize: 100 }
};
result = await connection.execute("select * from " + tableName_indexed + " where ROWID = :c", bindVar);
assert(result);
assert.strictEqual(result.rows[0][0], insertID);
assert.strictEqual(result.rows[0][1], str);
};
const testBigUROWID_stream = async function(maxRows, strLength, rowidLenExpected) {
const str = random.getRandomLengthString(strLength);
const id_1 = insertID++;
const id_2 = insertID++;
const maxRowsBak = oracledb.maxRows;
oracledb.maxRows = maxRows;
let sql_insert, result;
sql_insert = "insert into " + tableName_indexed + " values (" + id_1 + ", '" + str + "')";
await connection.execute(sql_insert);
sql_insert = "insert into " + tableName_indexed + " values (" + id_2 + ", '" + str + "')";
await connection.execute(sql_insert);
result = await connection.execute("select ROWID from " + tableName_indexed + " where c1 = " + id_1);
const urowid_1 = result.rows[0][0];
const urowidLen_1 = urowid_1.length;
testsUtil.checkUrowidLength(urowidLen_1, rowidLenExpected);
result = await connection.execute("select ROWID from " + tableName_indexed + " where c1 = " + id_2);
const urowid_2 = result.rows[0][0];
const urowidLen_2 = urowid_2.length;
testsUtil.checkUrowidLength(urowidLen_2, rowidLenExpected);
let counter = 0;
const sql_select = "select c1, c2, ROWID from " + tableName_indexed + " where ROWID = :i1 or ROWID = :i2 order by c1";
const bindVar = {
i1: { val: urowid_1, dir: oracledb.BIND_IN, type: oracledb.STRING },
i2: { val: urowid_2, dir: oracledb.BIND_IN, type: oracledb.STRING }
};
const stream = await connection.queryStream(sql_select, bindVar);
stream.on('error', function() {
});
stream.on('data', function(data) {
assert(data != null);
counter++;
const result_id = data[0];
if (result_id === id_1) {
assert.deepStrictEqual(data, [ id_1, str, urowid_1 ]);
} else {
assert.deepStrictEqual(data, [ id_2, str, urowid_2 ]);
}
});
stream.on('metadata', function(metadata) {
counter++;
assert(metadata != null);
assert.deepStrictEqual(metadata, [ { name: 'C1' }, { name: 'C2' }, { name: 'ROWID' } ]);
});
stream.on('end', function(err) {
assert(err == null);
assert.equal(counter, 3); // 3 events seen
oracledb.maxRows = maxRowsBak;
stream.destroy();
});
stream.on('close', function() {
});
};
});