465 lines
19 KiB
JavaScript
465 lines
19 KiB
JavaScript
/* Copyright (c) 2017, 2022, 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
|
|
* 114. urowidDMLBindAsString1.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');
|
|
|
|
describe('114. urowidDMLBindAsString1.js', function() {
|
|
let connection;
|
|
const tableName = "nodb_bind_urowid";
|
|
let insertID = 1;
|
|
|
|
const proc_create_table = "BEGIN \n" +
|
|
" DECLARE \n" +
|
|
" e_table_missing EXCEPTION; \n" +
|
|
" PRAGMA EXCEPTION_INIT(e_table_missing, -00942);\n" +
|
|
" BEGIN \n" +
|
|
" EXECUTE IMMEDIATE ('DROP TABLE " + tableName + " PURGE' ); \n" +
|
|
" EXCEPTION \n" +
|
|
" WHEN e_table_missing \n" +
|
|
" THEN NULL; \n" +
|
|
" END; \n" +
|
|
" EXECUTE IMMEDIATE ( ' \n" +
|
|
" CREATE TABLE " + tableName + " ( \n" +
|
|
" ID NUMBER, \n" +
|
|
" content UROWID(4000) \n" +
|
|
" ) \n" +
|
|
" '); \n" +
|
|
"END; ";
|
|
const drop_table = "DROP TABLE " + tableName + " PURGE";
|
|
|
|
before('get connection and create table', async function() {
|
|
connection = await oracledb.getConnection(dbConfig);
|
|
await connection.execute(proc_create_table);
|
|
});
|
|
|
|
after('release connection', async function() {
|
|
await connection.execute(drop_table);
|
|
await connection.close();
|
|
});
|
|
|
|
beforeEach(function() {
|
|
insertID++;
|
|
});
|
|
|
|
describe('114.1 INSERT & SELECT', function() {
|
|
|
|
it('114.1.1 works with null', async function() {
|
|
const content = null;
|
|
const bindVar = {
|
|
i: { val: insertID, dir: oracledb.BIND_IN, type: oracledb.NUMBER },
|
|
c: { val: content, dir: oracledb.BIND_IN, type: oracledb.STRING }
|
|
};
|
|
await dmlInsert(bindVar, content);
|
|
});
|
|
|
|
it('114.1.2 works with empty string', async function() {
|
|
const content = "";
|
|
const expected = null;
|
|
const bindVar = {
|
|
i: { val: insertID, dir: oracledb.BIND_IN, type: oracledb.NUMBER },
|
|
c: { val: content, dir: oracledb.BIND_IN, type: oracledb.STRING }
|
|
};
|
|
await dmlInsert(bindVar, expected);
|
|
});
|
|
|
|
it('114.1.3 works with extended rowid', async function() {
|
|
const content = "AAABoqAADAAAAwPAAA";
|
|
const bindVar = {
|
|
i: { val: insertID, dir: oracledb.BIND_IN, type: oracledb.NUMBER },
|
|
c: { val: content, dir: oracledb.BIND_IN, type: oracledb.STRING }
|
|
};
|
|
await dmlInsert(bindVar, content);
|
|
});
|
|
|
|
it('114.1.4 works with restricted rowid', async function() {
|
|
if (oracledb.thin)
|
|
return this.skip();
|
|
const content = "00000DD5.0000.0001";
|
|
const bindVar = {
|
|
i: { val: insertID, dir: oracledb.BIND_IN, type: oracledb.NUMBER },
|
|
c: { val: content, dir: oracledb.BIND_IN, type: oracledb.STRING }
|
|
};
|
|
await dmlInsert(bindVar, content);
|
|
});
|
|
|
|
it('114.1.5 throws error with number 0', async function() {
|
|
const content = 0;
|
|
const sql_insert = "insert into " + tableName + "(id, content) values (:i, CHARTOROWID(:c))";
|
|
const bindVar = {
|
|
i: { val: insertID, dir: oracledb.BIND_IN, type: oracledb.NUMBER },
|
|
c: { val: content, dir: oracledb.BIND_IN, type: oracledb.STRING }
|
|
};
|
|
|
|
await assert.rejects(
|
|
async () => await connection.execute(sql_insert, bindVar),
|
|
/NJS-011:/
|
|
);
|
|
});
|
|
|
|
it('114.1.6 works with string 0', async function() {
|
|
if (oracledb.thin)
|
|
return this.skip();
|
|
const content = "0";
|
|
const expected = "00000000.0000.0000";
|
|
const bindVar = {
|
|
i: { val: insertID, dir: oracledb.BIND_IN, type: oracledb.NUMBER },
|
|
c: { val: content, dir: oracledb.BIND_IN, type: oracledb.STRING }
|
|
};
|
|
await dmlInsert(bindVar, expected);
|
|
});
|
|
|
|
it('114.1.7 works with substr', async function() {
|
|
const content = "AAAA8+AALAAAAQ/AAA";
|
|
await dmlInsert_substr(content);
|
|
});
|
|
|
|
it('114.1.8 bind null with default type/dir - named bind', async function() {
|
|
const content = null;
|
|
const bindVar_1 = {
|
|
i: insertID,
|
|
c: content
|
|
};
|
|
await dmlInsert(bindVar_1, content);
|
|
});
|
|
|
|
it('114.1.9 bind null with default type/dir - positional bind', async function() {
|
|
const content = null;
|
|
const bindVar_1 = [ insertID, content ];
|
|
await dmlInsert(bindVar_1, content);
|
|
});
|
|
|
|
it('114.1.10 bind extented rowid with default type/dir - named bind', async function() {
|
|
const content = "AAAA8+AALAAAAQ/AAA";
|
|
const bindVar_1 = {
|
|
i: insertID,
|
|
c: content
|
|
};
|
|
await dmlInsert(bindVar_1, content);
|
|
});
|
|
|
|
it('114.1.11 bind extented rowid with default type/dir - positional bind', async function() {
|
|
const content = "AAAA8+AALAAAAQ/AAA";
|
|
const bindVar_1 = [ insertID, content ];
|
|
await dmlInsert(bindVar_1, content);
|
|
});
|
|
|
|
it('114.1.12 works with undefined', async function() {
|
|
const content = undefined;
|
|
const bindVar = {
|
|
i: { val: insertID, dir: oracledb.BIND_IN, type: oracledb.NUMBER },
|
|
c: { val: content, dir: oracledb.BIND_IN, type: oracledb.STRING }
|
|
};
|
|
await dmlInsert(bindVar, null);
|
|
});
|
|
|
|
it('114.1.13 bind undefined with default type/dir - named bind', async function() {
|
|
const content = undefined;
|
|
const bindVar_1 = {
|
|
i: insertID,
|
|
c: content
|
|
};
|
|
await dmlInsert(bindVar_1, null);
|
|
});
|
|
|
|
it('114.1.14 bind undefined with default type/dir - positional bind', async function() {
|
|
const content = undefined;
|
|
const bindVar_1 = [ insertID, content ];
|
|
await dmlInsert(bindVar_1, null);
|
|
});
|
|
|
|
it('114.1.15 works with NaN', async function() {
|
|
const content = NaN;
|
|
const sql_insert = "insert into " + tableName + "(id, content) values (:i, CHARTOROWID(:c))";
|
|
const bindVar = {
|
|
i: { val: insertID, dir: oracledb.BIND_IN, type: oracledb.NUMBER },
|
|
c: { val: content, dir: oracledb.BIND_IN, type: oracledb.STRING }
|
|
};
|
|
|
|
await assert.rejects(
|
|
async () => await connection.execute(sql_insert, bindVar),
|
|
/NJS-011:/
|
|
);
|
|
});
|
|
|
|
});
|
|
|
|
describe('114.2 UPDATE', function() {
|
|
|
|
it('114.2.1 UPDATE null column', async function() {
|
|
const content_insert = null;
|
|
const content_update = "AAABiqAADAAAAwPAAA";
|
|
await dmlUpdate(content_insert, content_update, content_update);
|
|
});
|
|
|
|
it('114.2.1 UPDATE extented rowid with restricted rowid', async function() {
|
|
if (oracledb.thin)
|
|
return this.skip();
|
|
const content_insert = "AAABioAADAAAAwPAAA";
|
|
const content_update = "00000DD5.0010.0001";
|
|
await dmlUpdate(content_insert, content_update, content_update);
|
|
});
|
|
|
|
it('114.2.3 UPDATE restricted rowid with null', async function() {
|
|
const content_insert = "00000DD5.0010.0002";
|
|
const content_update = null;
|
|
await dmlUpdate(content_insert, content_update, content_update);
|
|
});
|
|
});
|
|
|
|
describe('114.3 RETURNING INTO', function() {
|
|
|
|
it('114.3.1 INSERT null', async function() {
|
|
const content = null;
|
|
const bindVar = {
|
|
i: { val: insertID, dir: oracledb.BIND_IN, type: oracledb.NUMBER },
|
|
c: { val: content, dir: oracledb.BIND_IN, type: oracledb.STRING },
|
|
o: { dir: oracledb.BIND_OUT, type: oracledb.STRING }
|
|
};
|
|
await insert_returning(bindVar, content);
|
|
});
|
|
|
|
it('114.3.2 INSERT extented rowid', async function() {
|
|
const content = "AAAA++AALAAAAQ/AAA";
|
|
const bindVar = {
|
|
i: { val: insertID, dir: oracledb.BIND_IN, type: oracledb.NUMBER },
|
|
c: { val: content, dir: oracledb.BIND_IN, type: oracledb.STRING },
|
|
o: { dir: oracledb.BIND_OUT, type: oracledb.STRING }
|
|
};
|
|
await insert_returning(bindVar, content);
|
|
});
|
|
|
|
it('114.3.3 INSERT restricted rowid', async function() {
|
|
const content = "00000000.0100.0100";
|
|
const bindVar = {
|
|
i: { val: insertID, dir: oracledb.BIND_IN, type: oracledb.NUMBER },
|
|
c: { val: content, dir: oracledb.BIND_IN, type: oracledb.STRING },
|
|
o: { dir: oracledb.BIND_OUT, type: oracledb.STRING }
|
|
};
|
|
await insert_returning(bindVar, content);
|
|
});
|
|
|
|
it('114.3.7 UPDATE null with extented rowid', async function() {
|
|
const content_insert = null;
|
|
const content_update = "AAABiqAADAAAAwPAAA";
|
|
const bindVar_update = {
|
|
i: { val: insertID, dir: oracledb.BIND_IN, type: oracledb.NUMBER },
|
|
c: { val: content_update, dir: oracledb.BIND_IN, type: oracledb.STRING },
|
|
o: { dir: oracledb.BIND_OUT, type: oracledb.STRING }
|
|
};
|
|
await update_returning(content_insert, bindVar_update, content_update);
|
|
});
|
|
|
|
it('114.3.8 UPDATE extented rowid with null', async function() {
|
|
const content_insert = "AAABiqAADAAAAwPAAA";
|
|
const content_update = null;
|
|
const bindVar_update = {
|
|
i: { val: insertID, dir: oracledb.BIND_IN, type: oracledb.NUMBER },
|
|
c: { val: content_update, dir: oracledb.BIND_IN, type: oracledb.STRING },
|
|
o: { dir: oracledb.BIND_OUT, type: oracledb.STRING }
|
|
};
|
|
await update_returning(content_insert, bindVar_update, content_update);
|
|
});
|
|
|
|
it('114.3.9 UPDATE restricted rowid with empty string', async function() {
|
|
const content_insert = "00000000.0100.0100";
|
|
const content_update = "";
|
|
const bindVar_update = {
|
|
i: { val: insertID, dir: oracledb.BIND_IN, type: oracledb.NUMBER },
|
|
c: { val: content_update, dir: oracledb.BIND_IN, type: oracledb.STRING },
|
|
o: { dir: oracledb.BIND_OUT, type: oracledb.STRING }
|
|
};
|
|
await update_returning(content_insert, bindVar_update, null);
|
|
});
|
|
|
|
it('114.3.10 UPDATE restricted rowid with extented rowid', async function() {
|
|
const content_insert = "00000000.0100.0100";
|
|
const content_update = "AAABiqAADAAAAwPAAA";
|
|
const bindVar_update = {
|
|
i: { val: insertID, dir: oracledb.BIND_IN, type: oracledb.NUMBER },
|
|
c: { val: content_update, dir: oracledb.BIND_IN, type: oracledb.STRING },
|
|
o: { dir: oracledb.BIND_OUT, type: oracledb.STRING }
|
|
};
|
|
await update_returning(content_insert, bindVar_update, content_update);
|
|
});
|
|
|
|
it('114.3.11 INSERT with default type/dir - named bind', async function() {
|
|
const content = "00000000.0100.0100";
|
|
const bindVar = {
|
|
i: insertID,
|
|
c: content,
|
|
o: { dir: oracledb.BIND_OUT, type: oracledb.STRING }
|
|
};
|
|
await insert_returning(bindVar, content);
|
|
});
|
|
|
|
it('114.3.12 INSERT with default type/dir - positional bind', async function() {
|
|
const content = "00000000.0100.0100";
|
|
const bindVar = [ insertID, content, { dir: oracledb.BIND_OUT, type: oracledb.STRING } ];
|
|
await insert_returning(bindVar, content);
|
|
});
|
|
|
|
it('114.3.13 UPDATE with default type/dir - named bind', async function() {
|
|
const content_insert = "00000000.0100.0100";
|
|
const content_update = "AAABiqAADAAAAwPAAA";
|
|
const bindVar_update = {
|
|
i: insertID,
|
|
c: content_update,
|
|
o: { dir: oracledb.BIND_OUT, type: oracledb.STRING }
|
|
};
|
|
await update_returning(content_insert, bindVar_update, content_update);
|
|
});
|
|
|
|
it('114.3.14 UPDATE with default type/dir - positional bind', async function() {
|
|
const content_insert = "00000000.0100.0100";
|
|
const content_update = "AAABiqAADAAAAwPAAA";
|
|
const bindVar_update = [ content_update, insertID, { dir: oracledb.BIND_OUT, type: oracledb.STRING } ];
|
|
await update_returning(content_insert, bindVar_update, content_update);
|
|
});
|
|
});
|
|
|
|
describe('107.4 WHERE', function() {
|
|
it('107.4.1 can bind in WHERE clause', async function() {
|
|
await where_select();
|
|
});
|
|
});
|
|
|
|
const dmlInsert = async function(bindVar, expected) {
|
|
const sql_insert = "insert into " + tableName + "(id, content) values (:i, CHARTOROWID(:c))";
|
|
const sql_select = "select * from " + tableName + " where id = :i";
|
|
let result = await connection.execute(sql_insert, bindVar);
|
|
assert.strictEqual(result.rowsAffected, 1);
|
|
result = await connection.execute(sql_select, { i: insertID });
|
|
const resultVal = result.rows[0][1];
|
|
assert.strictEqual(resultVal, expected);
|
|
};
|
|
|
|
const dmlInsert_substr = async function(content) {
|
|
const id = insertID++;
|
|
const sql_insert = "insert into " + tableName + "(id, content) values (" + id + ", CHARTOROWID(:c))";
|
|
const sql_select = "select content, SUBSTR(content,1,6) , SUBSTR(content,7,3), SUBSTR(content,10,6), SUBSTR(content,16,3) from " + tableName + " where id = " + id;
|
|
const bindVar = { c: { val: content, dir: oracledb.BIND_IN, type: oracledb.STRING }};
|
|
let result = await connection.execute(sql_insert, bindVar);
|
|
assert.strictEqual(result.rowsAffected, 1);
|
|
result = await connection.execute(sql_select);
|
|
const resultVal_rowid = result.rows[0][0];
|
|
const resultVal_object = result.rows[0][1];
|
|
const resultVal_file = result.rows[0][2];
|
|
const resultVal_block = result.rows[0][3];
|
|
const resultVal_row = result.rows[0][4];
|
|
assert.strictEqual(typeof resultVal_rowid, "string");
|
|
assert.strictEqual(typeof resultVal_block, "string");
|
|
assert.strictEqual(typeof resultVal_row, "string");
|
|
assert.strictEqual(typeof resultVal_file, "string");
|
|
assert.strictEqual(typeof resultVal_object, "string");
|
|
assert.strictEqual(resultVal_rowid, content);
|
|
assert.strictEqual(resultVal_object, content.substring(0, 6));
|
|
assert.strictEqual(resultVal_file, content.substring(6, 9));
|
|
assert.strictEqual(resultVal_block, content.substring(9, 15));
|
|
assert.strictEqual(resultVal_row, content.substring(15, 18));
|
|
};
|
|
|
|
const dmlUpdate = async function(content_insert, content_update, expected) {
|
|
const sql_insert = "insert into " + tableName + "(id, content) values (:i, CHARTOROWID(:c))";
|
|
const sql_update = "update " + tableName + " set content = :c where id = :i";
|
|
const sql_select = "select * from " + tableName + " where id = :i";
|
|
const bindVar_insert = {
|
|
i: { val: insertID, dir: oracledb.BIND_IN, type: oracledb.NUMBER },
|
|
c: { val: content_insert, dir: oracledb.BIND_IN, type: oracledb.STRING }
|
|
};
|
|
const bindVar_update = {
|
|
i: { val: insertID, dir: oracledb.BIND_IN, type: oracledb.NUMBER },
|
|
c: { val: content_update, dir: oracledb.BIND_IN, type: oracledb.STRING }
|
|
};
|
|
let result = await connection.execute(sql_insert, bindVar_insert);
|
|
assert.strictEqual(result.rowsAffected, 1);
|
|
result = await connection.execute(sql_update, bindVar_update);
|
|
assert.strictEqual(result.rowsAffected, 1);
|
|
result = await connection.execute(sql_select, { i: insertID });
|
|
const resultVal = result.rows[0][1];
|
|
assert.strictEqual(resultVal, expected);
|
|
};
|
|
|
|
const insert_returning = async function(bindVar, expected) {
|
|
const sql_returning = "insert into " + tableName + "(id, content) values (:i, CHARTOROWID(:c)) returning content into :o";
|
|
const result = await connection.execute(sql_returning, bindVar);
|
|
let resultVal;
|
|
if (typeof (result.outBinds.o) === 'undefined') resultVal = result.outBinds[0][0];
|
|
else resultVal = result.outBinds.o[0];
|
|
assert.strictEqual(resultVal, expected);
|
|
};
|
|
|
|
const update_returning = async function(content_insert, bindVar_update, expected) {
|
|
const sql_insert = "insert into " + tableName + "(id, content) values (:i, CHARTOROWID(:c))";
|
|
const sql_update = "update " + tableName + " set content = :c where id = :i returning content into :o";
|
|
const bindVar_insert = {
|
|
i: { val: insertID, dir: oracledb.BIND_IN, type: oracledb.NUMBER },
|
|
c: { val: content_insert, dir: oracledb.BIND_IN, type: oracledb.STRING }
|
|
};
|
|
let result = await connection.execute(sql_insert, bindVar_insert);
|
|
assert.strictEqual(result.rowsAffected, 1);
|
|
result = await connection.execute(sql_update, bindVar_update);
|
|
let resultVal;
|
|
if (typeof (result.outBinds.o) === 'undefined') resultVal = result.outBinds[0][0];
|
|
else resultVal = result.outBinds.o[0];
|
|
assert.strictEqual(resultVal, expected);
|
|
};
|
|
|
|
const where_select = async function() {
|
|
let sql = `insert into ${tableName} T (ID) values (${insertID})`;
|
|
let result = await connection.execute(sql);
|
|
assert.strictEqual(result.rowsAffected, 1);
|
|
sql = `UPDATE ${tableName} T SET content = T.ROWID where ID = ${insertID}`;
|
|
result = await connection.execute(sql);
|
|
assert.strictEqual(result.rowsAffected, 1);
|
|
sql = `select content from ${tableName} where ID = ${insertID}`;
|
|
result = await connection.execute(sql);
|
|
const resultVal = result.rows[0][0];
|
|
sql = `select * from ${tableName} where ROWID = CHARTOROWID(:c)`;
|
|
const binds = {
|
|
c: {
|
|
val: resultVal, dir: oracledb.BIND_IN, type: oracledb.STRING
|
|
}
|
|
};
|
|
result = await connection.execute(sql, binds);
|
|
const resultVal_1 = result.rows[0][0];
|
|
const resultVal_2 = result.rows[0][1];
|
|
assert.strictEqual(resultVal_1, insertID);
|
|
assert.strictEqual(resultVal_2, resultVal);
|
|
};
|
|
|
|
});
|