Sync tests and fix missed merges
This commit is contained in:
parent
db600cb016
commit
8db863f6d6
|
@ -0,0 +1,755 @@
|
|||
/* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. */
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* You may not use the identified files except in compliance with the Apache
|
||||
* License, Version 2.0 (the "License.")
|
||||
*
|
||||
* You may obtain a copy of the License at
|
||||
* http://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.
|
||||
*
|
||||
* The node-oracledb test suite uses 'mocha', 'should' and 'async'.
|
||||
* See LICENSE.md for relevant licenses.
|
||||
*
|
||||
* NAME
|
||||
* 82. blobDMLBindAsBuffer.js
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Testing BLOB binding as Buffer with DML.
|
||||
*
|
||||
* NUMBERING RULE
|
||||
* Test numbers follow this numbering rule:
|
||||
* 1 - 20 are reserved for basic functional tests
|
||||
* 21 - 50 are reserved for data type supporting tests
|
||||
* 51 onwards are for other tests
|
||||
*
|
||||
*****************************************************************************/
|
||||
'use strict';
|
||||
|
||||
var oracledb = require('oracledb');
|
||||
var should = require('should');
|
||||
var async = require('async');
|
||||
var dbConfig = require('./dbconfig.js');
|
||||
var random = require('./random.js');
|
||||
var fs = require('fs');
|
||||
var assist = require('./dataTypeAssist.js');
|
||||
|
||||
describe('82.blobDMLBindAsBuffer.js', function() {
|
||||
this.timeout(100000);
|
||||
|
||||
var connection = null;
|
||||
var node6plus = false; // assume node runtime version is lower than 6
|
||||
var insertID = 1; // assume id for insert into db starts from 1
|
||||
|
||||
var proc_blob_1 = "BEGIN \n" +
|
||||
" DECLARE \n" +
|
||||
" e_table_missing EXCEPTION; \n" +
|
||||
" PRAGMA EXCEPTION_INIT(e_table_missing, -00942); \n" +
|
||||
" BEGIN \n" +
|
||||
" EXECUTE IMMEDIATE('DROP TABLE nodb_dml_blob_1 PURGE'); \n" +
|
||||
" EXCEPTION \n" +
|
||||
" WHEN e_table_missing \n" +
|
||||
" THEN NULL; \n" +
|
||||
" END; \n" +
|
||||
" EXECUTE IMMEDIATE (' \n" +
|
||||
" CREATE TABLE nodb_dml_blob_1 ( \n" +
|
||||
" id NUMBER, \n" +
|
||||
" blob BLOB \n" +
|
||||
" ) \n" +
|
||||
" '); \n" +
|
||||
"END; ";
|
||||
var sql2DropTable1 = "DROP TABLE nodb_dml_blob_1 PURGE";
|
||||
|
||||
before(function(done) {
|
||||
oracledb.getConnection(dbConfig, function(err, conn) {
|
||||
should.not.exist(err);
|
||||
connection = conn;
|
||||
// Check whether node runtime version is >= 6 or not
|
||||
if ( process.versions["node"].substring (0, 1) >= "6")
|
||||
node6plus = true;
|
||||
|
||||
done();
|
||||
});
|
||||
}); // before
|
||||
|
||||
after(function(done) {
|
||||
connection.release(function(err) {
|
||||
should.not.exist(err);
|
||||
done();
|
||||
});
|
||||
}); // after
|
||||
|
||||
var executeSQL = function(sql, callback) {
|
||||
connection.execute(
|
||||
sql,
|
||||
function(err) {
|
||||
should.not.exist(err);
|
||||
return callback();
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
var insertIntoBlobTable1 = function(id, content, callback) {
|
||||
if(content == "EMPTY_BLOB") {
|
||||
connection.execute(
|
||||
"INSERT INTO nodb_dml_blob_1 VALUES (:ID, EMPTY_BLOB())",
|
||||
[ id ],
|
||||
function(err, result) {
|
||||
should.not.exist(err);
|
||||
should.strictEqual(result.rowsAffected, 1);
|
||||
callback();
|
||||
}
|
||||
);
|
||||
} else {
|
||||
connection.execute(
|
||||
"INSERT INTO nodb_dml_blob_1 VALUES (:ID, :C)",
|
||||
{
|
||||
ID : { val : id },
|
||||
C : { val : content, dir : oracledb.BIND_IN, type : oracledb.BUFFER }
|
||||
},
|
||||
function(err, result) {
|
||||
should.not.exist(err);
|
||||
should.strictEqual(result.rowsAffected, 1);
|
||||
callback();
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
var updateBlobTable1 = function(id, content, callback) {
|
||||
if(content == "EMPTY_BLOB") {
|
||||
connection.execute(
|
||||
"UPDATE nodb_dml_blob_1 set blob = EMPTY_BLOB() where id = :ID",
|
||||
{ ID: id },
|
||||
function(err, result){
|
||||
should.not.exist(err);
|
||||
should.strictEqual(result.rowsAffected, 1);
|
||||
callback();
|
||||
}
|
||||
);
|
||||
} else {
|
||||
connection.execute(
|
||||
"UPDATE nodb_dml_blob_1 set blob = :C where id = :ID",
|
||||
{ ID: id, C: content },
|
||||
function(err, result){
|
||||
should.not.exist(err);
|
||||
should.strictEqual(result.rowsAffected, 1);
|
||||
callback();
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
// compare the inserted blob with orginal content
|
||||
var verifyBlobValueWithBuffer = function(selectSql, originalBuffer, specialStr, callback) {
|
||||
connection.execute(
|
||||
selectSql,
|
||||
function(err, result) {
|
||||
should.not.exist(err);
|
||||
var lob = result.rows[0][0];
|
||||
if(originalBuffer == '' || originalBuffer == undefined) {
|
||||
should.not.exist(lob);
|
||||
return callback();
|
||||
} else {
|
||||
should.exist(lob);
|
||||
var blobData = node6plus ? Buffer.alloc(0) : new Buffer(0);
|
||||
var totalLength = 0;
|
||||
|
||||
lob.on('data', function(chunk) {
|
||||
totalLength = totalLength + chunk.length;
|
||||
blobData = Buffer.concat([blobData, chunk], totalLength);
|
||||
});
|
||||
|
||||
lob.on('error', function(err) {
|
||||
should.not.exist(err, "lob.on 'error' event.");
|
||||
});
|
||||
|
||||
lob.on('end', function() {
|
||||
if(originalBuffer == "EMPTY_BLOB") {
|
||||
var nullBuffer = node6plus ? Buffer.from('', "utf-8") : new Buffer('', "utf-8");
|
||||
should.strictEqual(assist.compare2Buffers(blobData, nullBuffer), true);
|
||||
} else {
|
||||
should.strictEqual(totalLength, originalBuffer.length);
|
||||
var specStrLength = specialStr.length;
|
||||
should.strictEqual(blobData.toString('utf8', 0, specStrLength), specialStr);
|
||||
should.strictEqual(blobData.toString('utf8', (totalLength - specStrLength), totalLength), specialStr);
|
||||
should.strictEqual(assist.compare2Buffers(blobData, originalBuffer), true);
|
||||
}
|
||||
return callback();
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
var checkInsertResult = function(id, content, specialStr, callback) {
|
||||
var sql = "select blob from nodb_dml_blob_1 where id = " + id;
|
||||
verifyBlobValueWithBuffer(sql, content, specialStr, callback);
|
||||
};
|
||||
|
||||
describe('82.1 BLOB, INSERT', function() {
|
||||
before(function(done) {
|
||||
executeSQL(proc_blob_1, done);
|
||||
}); // before
|
||||
|
||||
after(function(done) {
|
||||
executeSQL(sql2DropTable1, done);
|
||||
}); // after
|
||||
|
||||
it('82.1.1 works with EMPTY_BLOB', function(done) {
|
||||
var id = insertID++;
|
||||
var content = "EMPTY_BLOB";
|
||||
|
||||
async.series([
|
||||
function(cb) {
|
||||
insertIntoBlobTable1(id, content, cb);
|
||||
},
|
||||
function(cb) {
|
||||
checkInsertResult(id, content, null, cb);
|
||||
}
|
||||
], done);
|
||||
}); // 82.1.1
|
||||
|
||||
it('82.1.2 works with empty buffer', function(done) {
|
||||
var id = insertID++;
|
||||
var bigStr = '';
|
||||
var content = node6plus ? Buffer.from(bigStr, "utf-8") : new Buffer(bigStr, "utf-8");
|
||||
|
||||
async.series([
|
||||
function(cb) {
|
||||
insertIntoBlobTable1(id, content, cb);
|
||||
},
|
||||
function(cb) {
|
||||
checkInsertResult(id, content, null, cb);
|
||||
}
|
||||
], done);
|
||||
}); // 82.1.2
|
||||
|
||||
it('82.1.3 works with empty buffer and bind in maxSize set to 32767', function(done) {
|
||||
var id = insertID++;
|
||||
var bigStr = '';
|
||||
var content = node6plus ? Buffer.from(bigStr, "utf-8") : new Buffer(bigStr, "utf-8");
|
||||
|
||||
async.series([
|
||||
function(cb) {
|
||||
connection.execute(
|
||||
"INSERT INTO nodb_dml_blob_1 VALUES (:ID, :C)",
|
||||
{
|
||||
ID : { val : id },
|
||||
C : { val : content, dir : oracledb.BIND_IN, type : oracledb.BUFFER, maxSize: 32767 }
|
||||
},
|
||||
function(err, result) {
|
||||
should.not.exist(err);
|
||||
should.strictEqual(result.rowsAffected, 1);
|
||||
cb();
|
||||
}
|
||||
);
|
||||
},
|
||||
function(cb) {
|
||||
checkInsertResult(id, content, null, cb);
|
||||
}
|
||||
], done);
|
||||
}); // 82.1.3
|
||||
|
||||
it('82.1.4 works with empty buffer and bind in maxSize set to 50000', function(done) {
|
||||
var id = insertID++;
|
||||
var bigStr = '';
|
||||
var content = node6plus ? Buffer.from(bigStr, "utf-8") : new Buffer(bigStr, "utf-8");
|
||||
|
||||
async.series([
|
||||
function(cb) {
|
||||
connection.execute(
|
||||
"INSERT INTO nodb_dml_blob_1 VALUES (:ID, :C)",
|
||||
{
|
||||
ID : { val : id },
|
||||
C : { val : content, dir : oracledb.BIND_IN, type : oracledb.BUFFER, maxSize: 50000 }
|
||||
},
|
||||
function(err, result) {
|
||||
should.not.exist(err);
|
||||
should.strictEqual(result.rowsAffected, 1);
|
||||
cb();
|
||||
}
|
||||
);
|
||||
},
|
||||
function(cb) {
|
||||
checkInsertResult(id, content, null, cb);
|
||||
}
|
||||
], done);
|
||||
}); // 82.1.4
|
||||
|
||||
it('82.1.5 works with undefined', function(done) {
|
||||
var id = insertID++;
|
||||
var content = undefined;
|
||||
|
||||
async.series([
|
||||
function(cb) {
|
||||
insertIntoBlobTable1(id, content, cb);
|
||||
},
|
||||
function(cb) {
|
||||
checkInsertResult(id, content, null, cb);
|
||||
}
|
||||
], done);
|
||||
}); // 82.1.5
|
||||
|
||||
it('82.1.6 works with null', function(done) {
|
||||
var id = insertID++;
|
||||
var content = null;
|
||||
|
||||
async.series([
|
||||
function(cb) {
|
||||
insertIntoBlobTable1(id, content, cb);
|
||||
},
|
||||
function(cb) {
|
||||
checkInsertResult(id, content, null, cb);
|
||||
}
|
||||
], done);
|
||||
}); // 82.1.6
|
||||
|
||||
it('82.1.7 works with null and bind in maxSize set to 32767', function(done) {
|
||||
var id = insertID++;
|
||||
var content = null;
|
||||
|
||||
async.series([
|
||||
function(cb) {
|
||||
connection.execute(
|
||||
"INSERT INTO nodb_dml_blob_1 VALUES (:ID, :C)",
|
||||
{
|
||||
ID : { val : id },
|
||||
C : { val : content, dir : oracledb.BIND_IN, type : oracledb.BUFFER, maxSize: 32767 }
|
||||
},
|
||||
function(err, result) {
|
||||
should.not.exist(err);
|
||||
should.strictEqual(result.rowsAffected, 1);
|
||||
cb();
|
||||
}
|
||||
);
|
||||
},
|
||||
function(cb) {
|
||||
checkInsertResult(id, content, null, cb);
|
||||
}
|
||||
], done);
|
||||
}); // 82.1.7
|
||||
|
||||
it('82.1.8 works with null and bind in maxSize set to 50000', function(done) {
|
||||
var id = insertID++;
|
||||
var content = null;
|
||||
|
||||
async.series([
|
||||
function(cb) {
|
||||
connection.execute(
|
||||
"INSERT INTO nodb_dml_blob_1 VALUES (:ID, :C)",
|
||||
{
|
||||
ID : { val : id },
|
||||
C : { val : content, dir : oracledb.BIND_IN, type : oracledb.BUFFER, maxSize: 50000 }
|
||||
},
|
||||
function(err, result) {
|
||||
should.not.exist(err);
|
||||
should.strictEqual(result.rowsAffected, 1);
|
||||
cb();
|
||||
}
|
||||
);
|
||||
},
|
||||
function(cb) {
|
||||
checkInsertResult(id, content, null, cb);
|
||||
}
|
||||
], done);
|
||||
}); // 82.1.8
|
||||
|
||||
it('82.1.9 works with NaN', function(done) {
|
||||
var id = insertID++;
|
||||
var content = NaN;
|
||||
|
||||
connection.execute(
|
||||
"INSERT INTO nodb_dml_blob_1 VALUES (:ID, :C)",
|
||||
{
|
||||
ID : { val : id },
|
||||
C : { val : content, dir : oracledb.BIND_IN, type : oracledb.BUFFER }
|
||||
},
|
||||
function(err) {
|
||||
should.exist(err);
|
||||
// NJS-011: encountered bind value and type mismatch in parameter 2
|
||||
(err.message).should.startWith('NJS-011:');
|
||||
done();
|
||||
}
|
||||
);
|
||||
}); // 82.1.9
|
||||
|
||||
it('82.1.10 works with 0', function(done) {
|
||||
var id = insertID++;
|
||||
var content = 0;
|
||||
|
||||
connection.execute(
|
||||
"INSERT INTO nodb_dml_blob_1 VALUES (:ID, :C)",
|
||||
{
|
||||
ID : { val : id },
|
||||
C : { val : content, dir : oracledb.BIND_IN, type : oracledb.BUFFER }
|
||||
},
|
||||
function(err) {
|
||||
should.exist(err);
|
||||
// NJS-011: encountered bind value and type mismatch in parameter 2
|
||||
(err.message).should.startWith('NJS-011:');
|
||||
done();
|
||||
}
|
||||
);
|
||||
}); // 82.1.10
|
||||
|
||||
it('82.1.11 works with Buffer length 32K', function(done) {
|
||||
var id = insertID++;
|
||||
var contentLength = 32768;
|
||||
var specialStr = "82.1.11";
|
||||
var bigStr = random.getRandomString(contentLength, specialStr);
|
||||
var content = node6plus ? Buffer.from(bigStr, "utf-8") : new Buffer(bigStr, "utf-8");
|
||||
|
||||
async.series([
|
||||
function(cb) {
|
||||
insertIntoBlobTable1(id, content, cb);
|
||||
},
|
||||
function(cb) {
|
||||
checkInsertResult(id, content, specialStr, cb);
|
||||
}
|
||||
], done);
|
||||
}); // 82.1.11
|
||||
|
||||
it('82.1.12 works with Buffer length (64K - 1)', function(done) {
|
||||
var id = insertID++;
|
||||
var contentLength = 65535;
|
||||
var specialStr = "82.1.12";
|
||||
var bigStr = random.getRandomString(contentLength, specialStr);
|
||||
var content = node6plus ? Buffer.from(bigStr, "utf-8") : new Buffer(bigStr, "utf-8");
|
||||
|
||||
async.series([
|
||||
function(cb) {
|
||||
insertIntoBlobTable1(id, content, cb);
|
||||
},
|
||||
function(cb) {
|
||||
checkInsertResult(id, content, specialStr, cb);
|
||||
}
|
||||
], done);
|
||||
}); // 82.1.12
|
||||
|
||||
it('82.1.13 works with Buffer length (64K + 1)', function(done) {
|
||||
var id = insertID++;
|
||||
var contentLength = 65537;
|
||||
var specialStr = "82.1.13";
|
||||
var bigStr = random.getRandomString(contentLength, specialStr);
|
||||
var content = node6plus ? Buffer.from(bigStr, "utf-8") : new Buffer(bigStr, "utf-8");
|
||||
|
||||
async.series([
|
||||
function(cb) {
|
||||
insertIntoBlobTable1(id, content, cb);
|
||||
},
|
||||
function(cb) {
|
||||
checkInsertResult(id, content, specialStr, cb);
|
||||
}
|
||||
], done);
|
||||
}); // 82.1.13
|
||||
|
||||
it('82.1.14 works with Buffer length (1MB + 1)', function(done) {
|
||||
var id = insertID++;
|
||||
var contentLength = 1048577; // 1 * 1024 * 1024 + 1;
|
||||
var specialStr = "82.1.14";
|
||||
var bigStr = random.getRandomString(contentLength, specialStr);
|
||||
var content = node6plus ? Buffer.from(bigStr, "utf-8") : new Buffer(bigStr, "utf-8");
|
||||
|
||||
async.series([
|
||||
function(cb) {
|
||||
insertIntoBlobTable1(id, content, cb);
|
||||
},
|
||||
function(cb) {
|
||||
checkInsertResult(id, content, specialStr, cb);
|
||||
}
|
||||
], done);
|
||||
}); // 82.1.14
|
||||
|
||||
it('82.1.15 bind value and type mismatch', function(done) {
|
||||
var id = insertID++;
|
||||
var content = 100;
|
||||
|
||||
connection.execute(
|
||||
"INSERT INTO nodb_dml_blob_1 VALUES (:ID, :C)",
|
||||
{
|
||||
ID : { val : id },
|
||||
C : { val : content, dir : oracledb.BIND_IN, type : oracledb.BUFFER }
|
||||
},
|
||||
function(err) {
|
||||
should.exist(err);
|
||||
// NJS-011: encountered bind value and type mismatch in parameter 2
|
||||
(err.message).should.startWith('NJS-011:');
|
||||
done();
|
||||
}
|
||||
);
|
||||
}); // 82.1.15
|
||||
|
||||
it('82.1.16 mixing named with positional binding', function(done) {
|
||||
var id = insertID++;
|
||||
var contentLength = 40000;
|
||||
var specialStr = "82.1.16";
|
||||
var bigStr = random.getRandomString(contentLength, specialStr);
|
||||
var content = node6plus ? Buffer.from(bigStr, "utf-8") : new Buffer(bigStr, "utf-8");
|
||||
|
||||
async.series([
|
||||
function(cb) {
|
||||
connection.execute(
|
||||
"INSERT INTO nodb_dml_blob_1 VALUES (:1, :2)",
|
||||
[
|
||||
id, { val : content, dir : oracledb.BIND_IN, type : oracledb.BUFFER }
|
||||
],
|
||||
function(err, result) {
|
||||
should.not.exist(err);
|
||||
should.strictEqual(result.rowsAffected, 1);
|
||||
cb();
|
||||
}
|
||||
);
|
||||
},
|
||||
function(cb) {
|
||||
checkInsertResult(id, content, specialStr, cb);
|
||||
}
|
||||
], done);
|
||||
}); // 82.1.16
|
||||
|
||||
it('82.1.17 bind with invalid BLOB', function(done) {
|
||||
var id = insertID++;
|
||||
|
||||
connection.execute(
|
||||
"INSERT INTO nodb_dml_blob_1 VALUES (:1, :2)",
|
||||
[
|
||||
id, { val : {}, dir : oracledb.BIND_IN, type : oracledb.BUFFER }
|
||||
],
|
||||
function(err) {
|
||||
should.exist(err);
|
||||
// NJS-011: encountered bind value and type mismatch in parameter 2
|
||||
(err.message).should.startWith('NJS-011:');
|
||||
done();
|
||||
}
|
||||
);
|
||||
}); // 82.1.17
|
||||
|
||||
it('82.1.18 Negative: RETURNING INTO with bind type BUFFER', function(done) {
|
||||
var id = insertID++;
|
||||
var contentLength = 400;
|
||||
var specialStr = "82.1.18";
|
||||
var bigStr = random.getRandomString(contentLength, specialStr);
|
||||
var content = node6plus ? Buffer.from(bigStr, "utf-8") : new Buffer(bigStr, "utf-8");
|
||||
var sql = "INSERT INTO nodb_dml_blob_1 (id, blob) VALUES (:i, :c) RETURNING blob INTO :lobbv";
|
||||
|
||||
connection.execute(
|
||||
sql,
|
||||
{
|
||||
i: id,
|
||||
c: { val: content, type: oracledb.BUFFER, dir: oracledb.BIND_IN },
|
||||
lobbv: { type: oracledb.BUFFER, dir: oracledb.BIND_OUT, maxSize: contentLength }
|
||||
},
|
||||
function(err) {
|
||||
should.exist(err);
|
||||
// NJS-028: RAW database type is not supported with DML Returning statements
|
||||
(err.message).should.startWith('NJS-028:');
|
||||
done();
|
||||
}
|
||||
);
|
||||
}); // 82.1.18
|
||||
|
||||
it('82.1.19 Negative: RETURNING INTO with autocommit on', function(done) {
|
||||
var id = insertID++;
|
||||
var sql = "INSERT INTO nodb_dml_blob_1 (id, blob) VALUES (:i, EMPTY_BLOB()) RETURNING blob INTO :lobbv";
|
||||
var inFileName = './test/tree.jpg';
|
||||
|
||||
connection.execute(
|
||||
sql,
|
||||
{
|
||||
i: id,
|
||||
lobbv: { type: oracledb.BLOB, dir: oracledb.BIND_OUT }
|
||||
},
|
||||
{ autoCommit: true },
|
||||
function(err, result) {
|
||||
should.not.exist(err);
|
||||
var inStream = fs.createReadStream(inFileName);
|
||||
var lob = result.outBinds.lobbv[0];
|
||||
|
||||
lob.on('error', function(err) {
|
||||
should.exist(err);
|
||||
// ORA-22990: LOB locators cannot span transactions
|
||||
(err.message).should.startWith('ORA-22990:');
|
||||
});
|
||||
|
||||
inStream.on('error', function(err) {
|
||||
should.not.exist(err, "inStream.on 'error' event");
|
||||
});
|
||||
|
||||
lob.on('close', function(err) {
|
||||
should.not.exist(err);
|
||||
done();
|
||||
});
|
||||
|
||||
inStream.pipe(lob); // copies the text to the CLOB
|
||||
}
|
||||
);
|
||||
}); // 82.1.19
|
||||
|
||||
it('82.1.20 works with bind in maxSize smaller than buffer size', function(done) {
|
||||
var id = insertID++;
|
||||
var contentLength = 32768;
|
||||
var specialStr = "82.1.20";
|
||||
var bigStr = random.getRandomString(contentLength, specialStr);
|
||||
var content = node6plus ? Buffer.from(bigStr, "utf-8") : new Buffer(bigStr, "utf-8");
|
||||
|
||||
async.series([
|
||||
function(cb) {
|
||||
connection.execute(
|
||||
"INSERT INTO nodb_dml_blob_1 VALUES (:ID, :C)",
|
||||
{
|
||||
ID : { val : id },
|
||||
C : { val : content, dir : oracledb.BIND_IN, type : oracledb.BUFFER, maxSize: 1 }
|
||||
},
|
||||
function(err, result) {
|
||||
should.not.exist(err);
|
||||
should.strictEqual(result.rowsAffected, 1);
|
||||
cb();
|
||||
}
|
||||
);
|
||||
},
|
||||
function(cb) {
|
||||
checkInsertResult(id, content, specialStr, cb);
|
||||
}
|
||||
], done);
|
||||
}); // 82.1.20
|
||||
|
||||
}); // 82.1
|
||||
|
||||
describe('82.2 BLOB, UPDATE', function() {
|
||||
insertID = 0;
|
||||
|
||||
before(function(done) {
|
||||
executeSQL(proc_blob_1, done);
|
||||
}); // before
|
||||
|
||||
after(function(done) {
|
||||
executeSQL(sql2DropTable1, done);
|
||||
}); // after
|
||||
|
||||
it('82.2.1 update EMPTY_BLOB column', function(done) {
|
||||
var id = insertID++;
|
||||
var content_1 = "EMPTY_BLOB";
|
||||
var contentLength_2 = 32768;
|
||||
var specialStr_2 = "82.2.1";
|
||||
var bigStr_2 = random.getRandomString(contentLength_2, specialStr_2);
|
||||
var content_2 = node6plus ? Buffer.from(bigStr_2, "utf-8") : new Buffer(bigStr_2, "utf-8");
|
||||
|
||||
async.series([
|
||||
function(cb) {
|
||||
insertIntoBlobTable1(id, content_1, cb);
|
||||
},
|
||||
function(cb) {
|
||||
checkInsertResult(id, content_1, null, cb);
|
||||
},
|
||||
function(cb) {
|
||||
updateBlobTable1(id, content_2, cb);
|
||||
},
|
||||
function(cb) {
|
||||
checkInsertResult(id, content_2, specialStr_2, cb);
|
||||
}
|
||||
], done);
|
||||
}); // 82.2.1
|
||||
|
||||
it('82.2.2 update a cloumn with EMPTY_BLOB', function(done) {
|
||||
var id = insertID++;
|
||||
var contentLength_1 = 50000;
|
||||
var specialStr_1 = "82.2.2";
|
||||
var bigStr_1 = random.getRandomString(contentLength_1, specialStr_1);
|
||||
var content_1 = node6plus ? Buffer.from(bigStr_1, "utf-8") : new Buffer(bigStr_1, "utf-8");
|
||||
var content_2 = "EMPTY_BLOB";
|
||||
|
||||
async.series([
|
||||
function(cb) {
|
||||
insertIntoBlobTable1(id, content_1, cb);
|
||||
},
|
||||
function(cb) {
|
||||
checkInsertResult(id, content_1, specialStr_1, cb);
|
||||
},
|
||||
function(cb) {
|
||||
updateBlobTable1(id, content_2, cb);
|
||||
},
|
||||
function(cb) {
|
||||
checkInsertResult(id, content_2, null, cb);
|
||||
}
|
||||
], done);
|
||||
}); // 82.2.2
|
||||
|
||||
it('82.2.3 update EMPTY_BLOB column with empty buffer', function(done) {
|
||||
var id = insertID++;
|
||||
var content_1 = "EMPTY_BLOB";
|
||||
var content_2 = "";
|
||||
|
||||
async.series([
|
||||
function(cb) {
|
||||
insertIntoBlobTable1(id, content_1, cb);
|
||||
},
|
||||
function(cb) {
|
||||
checkInsertResult(id, content_1, null, cb);
|
||||
},
|
||||
function(cb) {
|
||||
updateBlobTable1(id, content_2, cb);
|
||||
},
|
||||
function(cb) {
|
||||
checkInsertResult(id, content_2, null, cb);
|
||||
}
|
||||
], done);
|
||||
}); // 82.2.3
|
||||
|
||||
it('82.2.4 update empty buffer column', function(done) {
|
||||
var id = insertID++;
|
||||
var bigStr_1 = "";
|
||||
var content_1 = node6plus ? Buffer.from(bigStr_1, "utf-8") : new Buffer(bigStr_1, "utf-8");
|
||||
var contentLength_2 = 54321;
|
||||
var specialStr_2 = "82.2.4";
|
||||
var bigStr_2 = random.getRandomString(contentLength_2, specialStr_2);
|
||||
var content_2 = node6plus ? Buffer.from(bigStr_2, "utf-8") : new Buffer(bigStr_2, "utf-8");
|
||||
|
||||
async.series([
|
||||
function(cb) {
|
||||
insertIntoBlobTable1(id, content_1, cb);
|
||||
},
|
||||
function(cb) {
|
||||
checkInsertResult(id, content_1, null, cb);
|
||||
},
|
||||
function(cb) {
|
||||
updateBlobTable1(id, content_2, cb);
|
||||
},
|
||||
function(cb) {
|
||||
checkInsertResult(id, content_2, specialStr_2, cb);
|
||||
}
|
||||
], done);
|
||||
}); // 82.2.4
|
||||
|
||||
it('82.2.5 update a column with empty buffer', function(done) {
|
||||
var id = insertID++;
|
||||
var contentLength_1 = 50000;
|
||||
var specialStr_1 = "82.2.2";
|
||||
var bigStr_1 = random.getRandomString(contentLength_1, specialStr_1);
|
||||
var content_1 = node6plus ? Buffer.from(bigStr_1, "utf-8") : new Buffer(bigStr_1, "utf-8");
|
||||
var content_2 = "";
|
||||
|
||||
async.series([
|
||||
function(cb) {
|
||||
insertIntoBlobTable1(id, content_1, cb);
|
||||
},
|
||||
function(cb) {
|
||||
checkInsertResult(id, content_1, specialStr_1, cb);
|
||||
},
|
||||
function(cb) {
|
||||
updateBlobTable1(id, content_2, cb);
|
||||
},
|
||||
function(cb) {
|
||||
checkInsertResult(id, content_2, null, cb);
|
||||
}
|
||||
], done);
|
||||
}); // 82.2.5
|
||||
|
||||
}); // 82.2
|
||||
});
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,742 @@
|
|||
/* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. */
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* You may not use the identified files except in compliance with the Apache
|
||||
* License, Version 2.0 (the "License.")
|
||||
*
|
||||
* You may obtain a copy of the License at
|
||||
* http://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.
|
||||
*
|
||||
* The node-oracledb test suite uses 'mocha', 'should' and 'async'.
|
||||
* See LICENSE.md for relevant licenses.
|
||||
*
|
||||
* NAME
|
||||
* 81. clobDMLBindAsString.js
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Testing CLOB binding as String with DML.
|
||||
*
|
||||
* NUMBERING RULE
|
||||
* Test numbers follow this numbering rule:
|
||||
* 1 - 20 are reserved for basic functional tests
|
||||
* 21 - 50 are reserved for data type supporting tests
|
||||
* 51 onwards are for other tests
|
||||
*
|
||||
*****************************************************************************/
|
||||
'use strict';
|
||||
|
||||
var oracledb = require('oracledb');
|
||||
var should = require('should');
|
||||
var async = require('async');
|
||||
var fs = require('fs');
|
||||
var dbConfig = require('./dbconfig.js');
|
||||
var random = require('./random.js');
|
||||
|
||||
describe('81. clobDMLBindAsString.js', function() {
|
||||
this.timeout(100000);
|
||||
|
||||
var connection = null;
|
||||
var insertID = 1; // assume id for insert into db starts from 1
|
||||
|
||||
var proc_clob_1 = "BEGIN \n" +
|
||||
" DECLARE \n" +
|
||||
" e_table_missing EXCEPTION; \n" +
|
||||
" PRAGMA EXCEPTION_INIT(e_table_missing, -00942); \n" +
|
||||
" BEGIN \n" +
|
||||
" EXECUTE IMMEDIATE('DROP TABLE nodb_dml_clob_1 PURGE'); \n" +
|
||||
" EXCEPTION \n" +
|
||||
" WHEN e_table_missing \n" +
|
||||
" THEN NULL; \n" +
|
||||
" END; \n" +
|
||||
" EXECUTE IMMEDIATE (' \n" +
|
||||
" CREATE TABLE nodb_dml_clob_1 ( \n" +
|
||||
" id NUMBER, \n" +
|
||||
" clob CLOB \n" +
|
||||
" ) \n" +
|
||||
" '); \n" +
|
||||
"END; ";
|
||||
var sql2DropTable1 = "DROP TABLE nodb_dml_clob_1 PURGE";
|
||||
|
||||
before(function(done) {
|
||||
oracledb.getConnection(dbConfig, function(err, conn) {
|
||||
should.not.exist(err);
|
||||
connection = conn;
|
||||
done();
|
||||
});
|
||||
}); // before
|
||||
|
||||
after(function(done) {
|
||||
connection.release(function(err) {
|
||||
should.not.exist(err);
|
||||
done();
|
||||
});
|
||||
}); // after
|
||||
|
||||
var executeSQL = function(sql, callback) {
|
||||
connection.execute(
|
||||
sql,
|
||||
function(err) {
|
||||
should.not.exist(err);
|
||||
return callback();
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
var insertIntoClobTable1 = function(id, content, callback) {
|
||||
if(content == "EMPTY_CLOB") {
|
||||
connection.execute(
|
||||
"INSERT INTO nodb_dml_clob_1 VALUES (:ID, EMPTY_CLOB())",
|
||||
[ id ],
|
||||
function(err, result) {
|
||||
should.not.exist(err);
|
||||
should.strictEqual(result.rowsAffected, 1);
|
||||
callback();
|
||||
}
|
||||
);
|
||||
} else {
|
||||
connection.execute(
|
||||
"INSERT INTO nodb_dml_clob_1 VALUES (:ID, :C)",
|
||||
{
|
||||
ID : { val : id },
|
||||
C : { val : content, dir : oracledb.BIND_IN, type : oracledb.STRING }
|
||||
},
|
||||
function(err, result) {
|
||||
should.not.exist(err);
|
||||
should.strictEqual(result.rowsAffected, 1);
|
||||
callback();
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
var updateClobTable1 = function(id, content, callback) {
|
||||
if(content == "EMPTY_CLOB") {
|
||||
connection.execute(
|
||||
"UPDATE nodb_dml_clob_1 set clob = EMPTY_CLOB() where id = :ID",
|
||||
{ ID: id },
|
||||
function(err, result){
|
||||
should.not.exist(err);
|
||||
should.strictEqual(result.rowsAffected, 1);
|
||||
callback();
|
||||
}
|
||||
);
|
||||
} else {
|
||||
connection.execute(
|
||||
"UPDATE nodb_dml_clob_1 set clob = :C where id = :ID",
|
||||
{ ID: id, C: content },
|
||||
function(err, result){
|
||||
should.not.exist(err);
|
||||
should.strictEqual(result.rowsAffected, 1);
|
||||
callback();
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
// compare the inserted clob with orginal content
|
||||
var verifyClobValueWithString = function(selectSql, originalString, specialStr, callback) {
|
||||
connection.execute(
|
||||
selectSql,
|
||||
function(err, result) {
|
||||
should.not.exist(err);
|
||||
var lob = result.rows[0][0];
|
||||
if(originalString == '' || originalString == undefined || originalString == null) {
|
||||
should.not.exist(lob);
|
||||
return callback();
|
||||
} else {
|
||||
should.exist(lob);
|
||||
// set the encoding so we get a 'string' not a 'buffer'
|
||||
lob.setEncoding('utf8');
|
||||
var clobData = '';
|
||||
|
||||
lob.on('data', function(chunk) {
|
||||
clobData += chunk;
|
||||
});
|
||||
|
||||
lob.on('error', function(err) {
|
||||
should.not.exist(err, "lob.on 'error' event.");
|
||||
});
|
||||
|
||||
lob.on('end', function(err) {
|
||||
should.not.exist(err);
|
||||
if (originalString == "EMPTY_CLOB") {
|
||||
should.strictEqual(clobData, "");
|
||||
} else {
|
||||
var resultLength = clobData.length;
|
||||
var specStrLength = specialStr.length;
|
||||
should.strictEqual(resultLength, originalString.length);
|
||||
should.strictEqual(clobData.substring(0, specStrLength), specialStr);
|
||||
should.strictEqual(clobData.substring(resultLength - specStrLength, resultLength), specialStr);
|
||||
}
|
||||
return callback();
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
var checkInsertResult = function(id, content, specialStr, callback) {
|
||||
var sql = "select clob from nodb_dml_clob_1 where id = " + id;
|
||||
verifyClobValueWithString(sql, content, specialStr, callback);
|
||||
};
|
||||
|
||||
describe('81.1 CLOB, INSERT', function() {
|
||||
before(function(done) {
|
||||
executeSQL(proc_clob_1, done);
|
||||
}); // before
|
||||
|
||||
after(function(done) {
|
||||
executeSQL(sql2DropTable1, done);
|
||||
}); // after
|
||||
|
||||
it('81.1.1 works with EMPTY_CLOB', function(done) {
|
||||
var id = insertID++;
|
||||
var content = "EMPTY_CLOB";
|
||||
|
||||
async.series([
|
||||
function(cb) {
|
||||
insertIntoClobTable1(id, content, cb);
|
||||
},
|
||||
function(cb) {
|
||||
checkInsertResult(id, content, null, cb);
|
||||
}
|
||||
], done);
|
||||
}); // 81.1.1
|
||||
|
||||
it('81.1.2 works with empty string', function(done) {
|
||||
var id = insertID++;
|
||||
var content = '';
|
||||
|
||||
async.series([
|
||||
function(cb) {
|
||||
insertIntoClobTable1(id, content, cb);
|
||||
},
|
||||
function(cb) {
|
||||
checkInsertResult(id, content, null, cb);
|
||||
}
|
||||
], done);
|
||||
}); // 81.1.2
|
||||
|
||||
it('81.1.3 works with empty string and bind in maxSize set to 32767', function(done) {
|
||||
var id = insertID++;
|
||||
var content = "";
|
||||
|
||||
async.series([
|
||||
function(cb) {
|
||||
connection.execute(
|
||||
"INSERT INTO nodb_dml_clob_1 VALUES (:ID, :C)",
|
||||
{
|
||||
ID : { val : id },
|
||||
C : { val : content, dir : oracledb.BIND_IN, type : oracledb.STRING, maxSize: 32767 }
|
||||
},
|
||||
function(err, result) {
|
||||
should.not.exist(err);
|
||||
should.strictEqual(result.rowsAffected, 1);
|
||||
cb();
|
||||
}
|
||||
);
|
||||
},
|
||||
function(cb) {
|
||||
checkInsertResult(id, content, null, cb);
|
||||
}
|
||||
], done);
|
||||
}); // 81.1.3
|
||||
|
||||
it('81.1.4 works with empty string and bind in maxSize set to 50000', function(done) {
|
||||
var id = insertID++;
|
||||
var content = "";
|
||||
|
||||
async.series([
|
||||
function(cb) {
|
||||
connection.execute(
|
||||
"INSERT INTO nodb_dml_clob_1 VALUES (:ID, :C)",
|
||||
{
|
||||
ID : { val : id },
|
||||
C : { val : content, dir : oracledb.BIND_IN, type : oracledb.STRING, maxSize: 50000 }
|
||||
},
|
||||
function(err, result) {
|
||||
should.not.exist(err);
|
||||
should.strictEqual(result.rowsAffected, 1);
|
||||
cb();
|
||||
}
|
||||
);
|
||||
},
|
||||
function(cb) {
|
||||
checkInsertResult(id, content, null, cb);
|
||||
}
|
||||
], done);
|
||||
}); // 81.1.4
|
||||
|
||||
it('81.1.5 works with undefined', function(done) {
|
||||
var id = insertID++;
|
||||
var content = undefined;
|
||||
|
||||
async.series([
|
||||
function(cb) {
|
||||
insertIntoClobTable1(id, content, cb);
|
||||
},
|
||||
function(cb) {
|
||||
checkInsertResult(id, content, null, cb);
|
||||
}
|
||||
], done);
|
||||
}); // 81.1.5
|
||||
|
||||
it('81.1.6 works with null', function(done) {
|
||||
var id = insertID++;
|
||||
var content = null;
|
||||
|
||||
async.series([
|
||||
function(cb) {
|
||||
insertIntoClobTable1(id, content, cb);
|
||||
},
|
||||
function(cb) {
|
||||
checkInsertResult(id, content, null, cb);
|
||||
}
|
||||
], done);
|
||||
}); // 81.1.6
|
||||
|
||||
it('81.1.7 works with null and bind in maxSize set to 32767', function(done) {
|
||||
var id = insertID++;
|
||||
var content = null;
|
||||
|
||||
async.series([
|
||||
function(cb) {
|
||||
connection.execute(
|
||||
"INSERT INTO nodb_dml_clob_1 VALUES (:ID, :C)",
|
||||
{
|
||||
ID : { val : id },
|
||||
C : { val : content, dir : oracledb.BIND_IN, type : oracledb.STRING, maxSize: 32767 }
|
||||
},
|
||||
function(err, result) {
|
||||
should.not.exist(err);
|
||||
should.strictEqual(result.rowsAffected, 1);
|
||||
cb();
|
||||
}
|
||||
);
|
||||
},
|
||||
function(cb) {
|
||||
checkInsertResult(id, content, null, cb);
|
||||
}
|
||||
], done);
|
||||
}); // 81.1.7
|
||||
|
||||
it('81.1.8 works with null and bind in maxSize set to 50000', function(done) {
|
||||
var id = insertID++;
|
||||
var content = null;
|
||||
|
||||
async.series([
|
||||
function(cb) {
|
||||
connection.execute(
|
||||
"INSERT INTO nodb_dml_clob_1 VALUES (:ID, :C)",
|
||||
{
|
||||
ID : { val : id },
|
||||
C : { val : content, dir : oracledb.BIND_IN, type : oracledb.STRING, maxSize: 50000 }
|
||||
},
|
||||
function(err, result) {
|
||||
should.not.exist(err);
|
||||
should.strictEqual(result.rowsAffected, 1);
|
||||
cb();
|
||||
}
|
||||
);
|
||||
},
|
||||
function(cb) {
|
||||
checkInsertResult(id, content, null, cb);
|
||||
}
|
||||
], done);
|
||||
}); // 81.1.8
|
||||
|
||||
it('81.1.9 works with NaN', function(done) {
|
||||
var id = insertID++;
|
||||
var content = NaN;
|
||||
|
||||
connection.execute(
|
||||
"INSERT INTO nodb_dml_clob_1 VALUES (:ID, :C)",
|
||||
{
|
||||
ID : { val : id },
|
||||
C : { val : content, dir : oracledb.BIND_IN, type : oracledb.STRING }
|
||||
},
|
||||
function(err) {
|
||||
should.exist(err);
|
||||
// NJS-011: encountered bind value and type mismatch in parameter 2
|
||||
(err.message).should.startWith('NJS-011:');
|
||||
done();
|
||||
}
|
||||
);
|
||||
}); // 81.1.9
|
||||
|
||||
it('81.1.10 works with 0', function(done) {
|
||||
var id = insertID++;
|
||||
var content = 0;
|
||||
|
||||
connection.execute(
|
||||
"INSERT INTO nodb_dml_clob_1 VALUES (:ID, :C)",
|
||||
{
|
||||
ID : { val : id },
|
||||
C : { val : content, dir : oracledb.BIND_IN, type : oracledb.STRING }
|
||||
},
|
||||
function(err) {
|
||||
should.exist(err);
|
||||
// NJS-011: encountered bind value and type mismatch in parameter 2
|
||||
(err.message).should.startWith('NJS-011:');
|
||||
done();
|
||||
}
|
||||
);
|
||||
}); // 81.1.10
|
||||
|
||||
it('81.1.11 works with String length 32K', function(done) {
|
||||
var id = insertID++;
|
||||
var contentLength = 32768;
|
||||
var specialStr = "81.1.11";
|
||||
var content = random.getRandomString(contentLength, specialStr);
|
||||
|
||||
async.series([
|
||||
function(cb) {
|
||||
insertIntoClobTable1(id, content, cb);
|
||||
},
|
||||
function(cb) {
|
||||
checkInsertResult(id, content, specialStr, cb);
|
||||
}
|
||||
], done);
|
||||
}); // 81.1.11
|
||||
|
||||
it('81.1.12 works with String length (64K - 1)', function(done) {
|
||||
var id = insertID++;
|
||||
var contentLength = 65535;
|
||||
var specialStr = "81.1.12";
|
||||
var content = random.getRandomString(contentLength, specialStr);
|
||||
|
||||
async.series([
|
||||
function(cb) {
|
||||
insertIntoClobTable1(id, content, cb);
|
||||
},
|
||||
function(cb) {
|
||||
checkInsertResult(id, content, specialStr, cb);
|
||||
}
|
||||
], done);
|
||||
}); // 81.1.12
|
||||
|
||||
it('81.1.13 works with String length (64K + 1)', function(done) {
|
||||
var id = insertID++;
|
||||
var contentLength = 65537;
|
||||
var specialStr = "81.1.13";
|
||||
var content = random.getRandomString(contentLength, specialStr);
|
||||
|
||||
async.series([
|
||||
function(cb) {
|
||||
insertIntoClobTable1(id, content, cb);
|
||||
},
|
||||
function(cb) {
|
||||
checkInsertResult(id, content, specialStr, cb);
|
||||
}
|
||||
], done);
|
||||
}); // 81.1.13
|
||||
|
||||
it('81.1.14 works with String length (1MB + 1)', function(done) {
|
||||
var id = insertID++;
|
||||
var contentLength = 1048577; // 1 * 1024 * 1024 + 1;
|
||||
var specialStr = "81.1.14";
|
||||
var content = random.getRandomString(contentLength, specialStr);
|
||||
|
||||
async.series([
|
||||
function(cb) {
|
||||
insertIntoClobTable1(id, content, cb);
|
||||
},
|
||||
function(cb) {
|
||||
checkInsertResult(id, content, specialStr, cb);
|
||||
}
|
||||
], done);
|
||||
}); // 81.1.14
|
||||
|
||||
it('81.1.15 bind value and type mismatch', function(done) {
|
||||
var id = insertID++;
|
||||
var content = 100;
|
||||
|
||||
connection.execute(
|
||||
"INSERT INTO nodb_dml_clob_1 VALUES (:ID, :C)",
|
||||
{
|
||||
ID : { val : id },
|
||||
C : { val : content, dir : oracledb.BIND_IN, type : oracledb.STRING }
|
||||
},
|
||||
function(err) {
|
||||
should.exist(err);
|
||||
// NJS-011: encountered bind value and type mismatch in parameter 2
|
||||
(err.message).should.startWith('NJS-011:');
|
||||
done();
|
||||
}
|
||||
);
|
||||
}); // 81.1.15
|
||||
|
||||
it('81.1.16 mixing named with positional binding', function(done) {
|
||||
var id = insertID++;
|
||||
var contentLength = 40000;
|
||||
var specialStr = "81.1.16";
|
||||
var content = random.getRandomString(contentLength, specialStr);
|
||||
|
||||
async.series([
|
||||
function(cb) {
|
||||
connection.execute(
|
||||
"INSERT INTO nodb_dml_clob_1 VALUES (:1, :2)",
|
||||
[
|
||||
id, { val : content, dir : oracledb.BIND_IN, type : oracledb.STRING }
|
||||
],
|
||||
function(err, result) {
|
||||
should.not.exist(err);
|
||||
should.strictEqual(result.rowsAffected, 1);
|
||||
cb();
|
||||
}
|
||||
);
|
||||
},
|
||||
function(cb) {
|
||||
checkInsertResult(id, content, specialStr, cb);
|
||||
}
|
||||
], done);
|
||||
}); // 81.1.16
|
||||
|
||||
it('81.1.17 bind with invalid CLOB', function(done) {
|
||||
var id = insertID++;
|
||||
|
||||
connection.execute(
|
||||
"INSERT INTO nodb_dml_clob_1 VALUES (:1, :2)",
|
||||
[
|
||||
id, { val : {}, dir : oracledb.BIND_IN, type : oracledb.STRING }
|
||||
],
|
||||
function(err) {
|
||||
should.exist(err);
|
||||
// NJS-011: encountered bind value and type mismatch
|
||||
(err.message).should.startWith('NJS-011:');
|
||||
done();
|
||||
}
|
||||
);
|
||||
}); // 81.1.17
|
||||
|
||||
it('81.1.18 RETURNING INTO with bind type STRING', function(done) {
|
||||
var id = insertID++;
|
||||
var contentLength = 400;
|
||||
var specialStr = "81.1.18";
|
||||
var content = random.getRandomString(contentLength, specialStr);
|
||||
var sql = "INSERT INTO nodb_dml_clob_1 (id, clob) VALUES (:i, :c) RETURNING clob INTO :lobbv";
|
||||
|
||||
async.series([
|
||||
function(cb) {
|
||||
connection.execute(
|
||||
sql,
|
||||
{
|
||||
i: id,
|
||||
c: { val: content, type: oracledb.STRING, dir: oracledb.BIND_IN },
|
||||
lobbv: { type: oracledb.STRING, dir: oracledb.BIND_OUT, maxSize: contentLength }
|
||||
},
|
||||
{ autoCommit: false },
|
||||
function(err, result) {
|
||||
should.not.exist(err);
|
||||
(result.rowsAffected).should.be.exactly(1);
|
||||
(result.outBinds.lobbv.length).should.be.exactly(1);
|
||||
cb();
|
||||
}
|
||||
);
|
||||
},
|
||||
function(cb) {
|
||||
checkInsertResult(id, content, specialStr, cb);
|
||||
}
|
||||
], done);
|
||||
}); // 81.1.18
|
||||
|
||||
it('81.1.19 Negative: RETURNING INTO with autocommit on', function(done) {
|
||||
var id = insertID++;
|
||||
var sql = "INSERT INTO nodb_dml_clob_1 (id, clob) VALUES (:i, EMPTY_CLOB()) RETURNING clob INTO :lobbv";
|
||||
var inFileName = './test/clobexample.txt';
|
||||
|
||||
connection.execute(
|
||||
sql,
|
||||
{
|
||||
i: id,
|
||||
lobbv: { type: oracledb.CLOB, dir: oracledb.BIND_OUT }
|
||||
},
|
||||
{ autoCommit: true },
|
||||
function(err, result) {
|
||||
should.not.exist(err);
|
||||
var inStream = fs.createReadStream(inFileName);
|
||||
var lob = result.outBinds.lobbv[0];
|
||||
|
||||
lob.on('error', function(err) {
|
||||
should.exist(err);
|
||||
// ORA-22990: LOB locators cannot span transactions
|
||||
(err.message).should.startWith('ORA-22990:');
|
||||
});
|
||||
|
||||
inStream.on('error', function(err) {
|
||||
should.not.exist(err, "inStream.on 'error' event");
|
||||
});
|
||||
|
||||
lob.on('close', function(err) {
|
||||
should.not.exist(err);
|
||||
done();
|
||||
});
|
||||
|
||||
inStream.pipe(lob); // copies the text to the CLOB
|
||||
}
|
||||
);
|
||||
}); // 81.1.19
|
||||
|
||||
it('81.1.20 works with bind in maxSize smaller than string length', function(done) {
|
||||
var id = insertID++;
|
||||
var contentLength = 32768;
|
||||
var specialStr = "81.1.20";
|
||||
var content = random.getRandomString(contentLength, specialStr);
|
||||
|
||||
async.series([
|
||||
function(cb) {
|
||||
connection.execute(
|
||||
"INSERT INTO nodb_dml_clob_1 VALUES (:ID, :C)",
|
||||
{
|
||||
ID : { val : id },
|
||||
C : { val : content, dir : oracledb.BIND_IN, type : oracledb.STRING, maxSize: 1 }
|
||||
},
|
||||
function(err, result) {
|
||||
should.not.exist(err);
|
||||
should.strictEqual(result.rowsAffected, 1);
|
||||
cb();
|
||||
}
|
||||
);
|
||||
},
|
||||
function(cb) {
|
||||
checkInsertResult(id, content, specialStr, cb);
|
||||
}
|
||||
], done);
|
||||
}); // 81.1.20
|
||||
|
||||
}); // 81.1
|
||||
|
||||
describe('81.2 CLOB, UPDATE', function() {
|
||||
insertID = 0;
|
||||
|
||||
before(function(done) {
|
||||
executeSQL(proc_clob_1, done);
|
||||
}); // before
|
||||
|
||||
after(function(done) {
|
||||
executeSQL(sql2DropTable1, done);
|
||||
}); // after
|
||||
|
||||
it('81.2.1 update EMPTY_CLOB column', function(done) {
|
||||
var id = insertID++;
|
||||
var content_1 = "EMPTY_CLOB";
|
||||
var contentLength_2 = 32768;
|
||||
var specialStr_2 = "81.2.1";
|
||||
var content_2 = random.getRandomString(contentLength_2, specialStr_2);
|
||||
|
||||
async.series([
|
||||
function(cb) {
|
||||
insertIntoClobTable1(id, content_1, cb);
|
||||
},
|
||||
function(cb) {
|
||||
checkInsertResult(id, content_1, null, cb);
|
||||
},
|
||||
function(cb) {
|
||||
updateClobTable1(id, content_2, cb);
|
||||
},
|
||||
function(cb) {
|
||||
checkInsertResult(id, content_2, specialStr_2, cb);
|
||||
}
|
||||
], done);
|
||||
}); // 81.2.1
|
||||
|
||||
it('81.2.2 update a cloumn with EMPTY_CLOB', function(done) {
|
||||
var id = insertID++;
|
||||
var contentLength_1 = 50000;
|
||||
var specialStr_1 = "81.2.2";
|
||||
var content_1 = random.getRandomString(contentLength_1, specialStr_1);
|
||||
var content_2 = "EMPTY_CLOB";
|
||||
|
||||
async.series([
|
||||
function(cb) {
|
||||
insertIntoClobTable1(id, content_1, cb);
|
||||
},
|
||||
function(cb) {
|
||||
checkInsertResult(id, content_1, specialStr_1, cb);
|
||||
},
|
||||
function(cb) {
|
||||
updateClobTable1(id, content_2, cb);
|
||||
},
|
||||
function(cb) {
|
||||
checkInsertResult(id, content_2, null, cb);
|
||||
}
|
||||
], done);
|
||||
}); // 81.2.2
|
||||
|
||||
it('81.2.3 update EMPTY_CLOB column with empty string', function(done) {
|
||||
var id = insertID++;
|
||||
var content_1 = "EMPTY_CLOB";
|
||||
var content_2 = "";
|
||||
|
||||
async.series([
|
||||
function(cb) {
|
||||
insertIntoClobTable1(id, content_1, cb);
|
||||
},
|
||||
function(cb) {
|
||||
checkInsertResult(id, content_1, null, cb);
|
||||
},
|
||||
function(cb) {
|
||||
updateClobTable1(id, content_2, cb);
|
||||
},
|
||||
function(cb) {
|
||||
checkInsertResult(id, content_2, null, cb);
|
||||
}
|
||||
], done);
|
||||
}); // 81.2.3
|
||||
|
||||
it('81.2.4 update empty string column', function(done) {
|
||||
var id = insertID++;
|
||||
var content_1 = "";
|
||||
var contentLength_2 = 54321;
|
||||
var specialStr_2 = "81.2.4";
|
||||
var content_2 = random.getRandomString(contentLength_2, specialStr_2);
|
||||
|
||||
async.series([
|
||||
function(cb) {
|
||||
insertIntoClobTable1(id, content_1, cb);
|
||||
},
|
||||
function(cb) {
|
||||
checkInsertResult(id, content_1, null, cb);
|
||||
},
|
||||
function(cb) {
|
||||
updateClobTable1(id, content_2, cb);
|
||||
},
|
||||
function(cb) {
|
||||
checkInsertResult(id, content_2, specialStr_2, cb);
|
||||
}
|
||||
], done);
|
||||
}); // 81.2.4
|
||||
|
||||
it('81.2.5 update a column with empty string', function(done) {
|
||||
var id = insertID++;
|
||||
var contentLength_1 = 50000;
|
||||
var specialStr_1 = "81.2.2";
|
||||
var content_1 = random.getRandomString(contentLength_1, specialStr_1);
|
||||
var content_2 = "";
|
||||
|
||||
async.series([
|
||||
function(cb) {
|
||||
insertIntoClobTable1(id, content_1, cb);
|
||||
},
|
||||
function(cb) {
|
||||
checkInsertResult(id, content_1, specialStr_1, cb);
|
||||
},
|
||||
function(cb) {
|
||||
updateClobTable1(id, content_2, cb);
|
||||
},
|
||||
function(cb) {
|
||||
checkInsertResult(id, content_2, null, cb);
|
||||
}
|
||||
], done);
|
||||
}); // 81.2.5
|
||||
|
||||
}); // 81.2
|
||||
});
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,83 @@
|
|||
/* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. */
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* You may not use the identified files except in compliance with the Apache
|
||||
* License, Version 2.0 (the "License.")
|
||||
*
|
||||
* You may obtain a copy of the License at
|
||||
* http://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.
|
||||
*
|
||||
* The node-oracledb test suite uses 'mocha', 'should' and 'async'.
|
||||
* See LICENSE.md for relevant licenses.
|
||||
*
|
||||
* NAME
|
||||
* 18. constants.js
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Check the mapping between names and numbers of oracledb constants.
|
||||
*
|
||||
* NUMBERING RULE
|
||||
* Test numbers follow this numbering rule:
|
||||
* 1 - 20 are reserved for basic functional tests
|
||||
* 21 - 50 are reserved for data type supporting tests
|
||||
* 51 onwards are for other tests
|
||||
*
|
||||
*****************************************************************************/
|
||||
'use strict';
|
||||
|
||||
var oracledb = require('oracledb');
|
||||
var should = require('should');
|
||||
|
||||
describe('18. constants.js', function() {
|
||||
|
||||
it('18.1 dbTypes maps correctly between names and numbers', function() {
|
||||
|
||||
should.exist(oracledb);
|
||||
(oracledb.DB_TYPE_VARCHAR).should.be.exactly(1);
|
||||
(oracledb.DB_TYPE_NUMBER).should.be.exactly(2);
|
||||
(oracledb.DB_TYPE_DATE).should.be.exactly(12);
|
||||
(oracledb.DB_TYPE_RAW).should.be.exactly(23);
|
||||
(oracledb.DB_TYPE_CHAR).should.be.exactly(96);
|
||||
(oracledb.DB_TYPE_BINARY_FLOAT).should.be.exactly(100);
|
||||
(oracledb.DB_TYPE_BINARY_DOUBLE).should.be.exactly(101);
|
||||
(oracledb.DB_TYPE_ROWID).should.be.exactly(104);
|
||||
(oracledb.DB_TYPE_CLOB).should.be.exactly(112);
|
||||
(oracledb.DB_TYPE_BLOB).should.be.exactly(113);
|
||||
(oracledb.DB_TYPE_TIMESTAMP).should.be.exactly(187);
|
||||
(oracledb.DB_TYPE_TIMESTAMP_TZ).should.be.exactly(188);
|
||||
(oracledb.DB_TYPE_TIMESTAMP_LTZ).should.be.exactly(232);
|
||||
|
||||
});
|
||||
|
||||
it('18.2 jsTypes maps correctly', function() {
|
||||
|
||||
(oracledb.DEFAULT).should.be.exactly(0);
|
||||
(oracledb.STRING).should.be.exactly(2001);
|
||||
(oracledb.NUMBER).should.be.exactly(2002);
|
||||
(oracledb.DATE).should.be.exactly(2003);
|
||||
(oracledb.CURSOR).should.be.exactly(2004);
|
||||
(oracledb.BUFFER).should.be.exactly(2005);
|
||||
(oracledb.CLOB).should.be.exactly(2006);
|
||||
(oracledb.BLOB).should.be.exactly(2007);
|
||||
|
||||
});
|
||||
|
||||
it('18.3 binding contants maps correctly', function() {
|
||||
|
||||
(oracledb.BIND_IN).should.be.exactly(3001);
|
||||
(oracledb.BIND_INOUT).should.be.exactly(3002);
|
||||
(oracledb.BIND_OUT).should.be.exactly(3003);
|
||||
(oracledb.ARRAY).should.be.exactly(4001);
|
||||
(oracledb.OBJECT).should.be.exactly(4002);
|
||||
|
||||
});
|
||||
|
||||
});
|
|
@ -0,0 +1,50 @@
|
|||
/* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. */
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* You may not use the identified files except in compliance with the Apache
|
||||
* License, Version 2.0 (the "License.")
|
||||
*
|
||||
* You may obtain a copy of the License at
|
||||
* http://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.
|
||||
*
|
||||
* The node-oracledb test suite uses 'mocha', 'should' and 'async'.
|
||||
* See LICENSE.md for relevant licenses.
|
||||
*
|
||||
* NAME
|
||||
* devnull.js
|
||||
*
|
||||
* DESCRIPTION
|
||||
* /dev/null for Node streams
|
||||
*
|
||||
*****************************************************************************/
|
||||
'use strict';
|
||||
|
||||
var stream = require('stream');
|
||||
var util = require('util');
|
||||
|
||||
module.exports = DevNull;
|
||||
|
||||
// step 2 - to call the Writable constructor in our own constructor
|
||||
function DevNull(opts) {
|
||||
if ( !(this instanceof DevNull) ) return new DevNull(opts);
|
||||
|
||||
opts = opts || {};
|
||||
stream.Writable.call(this, opts);
|
||||
|
||||
}
|
||||
|
||||
// step 1 - to extend the Writable Class
|
||||
util.inherits(DevNull, stream.Writable);
|
||||
|
||||
// step 3 -define a '_write()' method in the prototype of our stream object
|
||||
DevNull.prototype._write = function(chunk, encoding, cb) {
|
||||
setImmediate(cb);
|
||||
};
|
|
@ -0,0 +1,106 @@
|
|||
/* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. */
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* You may not use the identified files except in compliance with the Apache
|
||||
* License, Version 2.0 (the "License.")
|
||||
*
|
||||
* You may obtain a copy of the License at
|
||||
* http://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.
|
||||
*
|
||||
* The node-oracledb test suite uses 'mocha', 'should' and 'async'.
|
||||
* See LICENSE.md for relevant licenses.
|
||||
*
|
||||
* NAME
|
||||
* 69. driverName.js
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Testing external authentication functionality.
|
||||
*
|
||||
* Note that enabling the externalAuth feature requires configuration on the
|
||||
* database besides setting "externalAuth" attribute to be true. Please refer
|
||||
* to api doc about the configuration.
|
||||
* https://github.com/oracle/node-oracledb/blob/master/doc/api.md#extauth
|
||||
*
|
||||
* NUMBERING RULE
|
||||
* Test numbers follow this numbering rule:
|
||||
* 1 - 20 are reserved for basic functional tests
|
||||
* 21 - 50 are reserved for data type supporting tests
|
||||
* 51 onwards are for other tests
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
'use strict';
|
||||
|
||||
var oracledb = require('oracledb');
|
||||
var should = require('should');
|
||||
var async = require('async');
|
||||
var dbConfig = require('./dbconfig.js');
|
||||
|
||||
describe('69. driverName.js', function() {
|
||||
|
||||
var getAddonVer = function() {
|
||||
var addonVer = oracledb.version;
|
||||
var major = Math.floor (addonVer / 10000);
|
||||
var minor = Math.floor(addonVer / 100) % 100;
|
||||
var update = addonVer % 100;
|
||||
|
||||
return (major + '.' + minor + '.' + update);
|
||||
};
|
||||
|
||||
it("69.1 checks the driver name", function(done) {
|
||||
|
||||
async.waterfall([
|
||||
function(cb) {
|
||||
oracledb.createPool(dbConfig, cb);
|
||||
},
|
||||
function(pool, cb) {
|
||||
pool.should.be.ok();
|
||||
pool.getConnection( function(err, connection) {
|
||||
cb(err, connection, pool);
|
||||
});
|
||||
},
|
||||
function(connection, pool, cb) {
|
||||
var sql = "select distinct client_driver from v$session_connect_info where sid = sys_context('USERENV', 'SID')";
|
||||
connection.should.be.ok();
|
||||
connection.execute(
|
||||
sql,
|
||||
function(err, result) {
|
||||
|
||||
var serverVer = connection.oracleServerVersion;
|
||||
|
||||
// Since 12.1.0.2, OCI_ATTR_DRIVER_NAME with 30 characters has been supported
|
||||
// Database server can then return the full driver name, e.g. 'node-oracledb 1.11'
|
||||
if(serverVer >= 1201000200) {
|
||||
var addonVer = getAddonVer();
|
||||
(result.rows[0][0].trim()).should.equal("node-oracledb : " + addonVer);
|
||||
}
|
||||
// previous databases only returns the first 8 characters of the driver name
|
||||
else {
|
||||
(result.rows[0][0]).should.equal("node-ora");
|
||||
}
|
||||
|
||||
cb(err, connection, pool);
|
||||
}
|
||||
);
|
||||
}
|
||||
], function(err, connection, pool) {
|
||||
should.not.exist(err);
|
||||
connection.close( function(err) {
|
||||
should.not.exist(err);
|
||||
pool.close(function(err) {
|
||||
should.not.exist(err);
|
||||
done();
|
||||
});
|
||||
});
|
||||
}); // async
|
||||
|
||||
});
|
||||
});
|
|
@ -0,0 +1,495 @@
|
|||
/* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. */
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* You may not use the identified files except in compliance with the Apache
|
||||
* License, Version 2.0 (the "License.")
|
||||
*
|
||||
* You may obtain a copy of the License at
|
||||
* http://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.
|
||||
*
|
||||
* The node-oracledb test suite uses 'mocha', 'should' and 'async'.
|
||||
* See LICENSE.md for relevant licenses.
|
||||
*
|
||||
* NAME
|
||||
* 5. externalAuth.js
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Testing external authentication functionality.
|
||||
*
|
||||
* Note that enabling the externalAuth feature requires configuration on the
|
||||
* database besides setting "externalAuth" attribute to be true. Please refer
|
||||
* to api doc about the configuration.
|
||||
* https://github.com/oracle/node-oracledb/blob/master/doc/api.md#extauth
|
||||
*
|
||||
* NUMBERING RULE
|
||||
* Test numbers follow this numbering rule:
|
||||
* 1 - 20 are reserved for basic functional tests
|
||||
* 21 - 50 are reserved for data type supporting tests
|
||||
* 51 onwards are for other tests
|
||||
*
|
||||
*****************************************************************************/
|
||||
'use strict';
|
||||
|
||||
var oracledb = require('oracledb');
|
||||
var should = require('should');
|
||||
var async = require('async');
|
||||
var dbConfig = require('./dbconfig.js');
|
||||
|
||||
describe('5. externalAuth.js', function() {
|
||||
|
||||
describe('5.1 tests that work both when DB has configured externalAuth and not configured', function() {
|
||||
|
||||
it('5.1.1 can get connection from oracledb with correct user/password when externalAuth is disabled', function(done) {
|
||||
|
||||
async.waterfall([
|
||||
function(callback) {
|
||||
oracledb.getConnection(
|
||||
{
|
||||
externalAuth: false,
|
||||
user: dbConfig.user,
|
||||
password: dbConfig.password,
|
||||
connectString: dbConfig.connectString
|
||||
},
|
||||
function(err, connection) {
|
||||
callback(err, connection);
|
||||
}
|
||||
);
|
||||
},
|
||||
function(connection, callback) {
|
||||
connection.execute(
|
||||
"select (7+8) from dual",
|
||||
function(err, result) {
|
||||
(result.rows[0][0]).should.equal(15);
|
||||
callback(err, connection);
|
||||
}
|
||||
);
|
||||
}
|
||||
], function(err, connection) {
|
||||
should.not.exist(err);
|
||||
connection.release( function(err) {
|
||||
should.not.exist(err);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
}); // 5.1.1
|
||||
|
||||
it('5.1.2 throws error when getting connection from oracledb with correct user/password when externalAuth is enabled', function(done) {
|
||||
|
||||
oracledb.getConnection(
|
||||
{
|
||||
externalAuth: true,
|
||||
user: dbConfig.user,
|
||||
password: dbConfig.password,
|
||||
connectString: dbConfig.connectString
|
||||
},
|
||||
function(err, conn){
|
||||
should.exist(err);
|
||||
(err.message).should.startWith("DPI-1032:");
|
||||
// DPI-1032: user and password should not be set when using external authentication
|
||||
should.not.exist(conn);
|
||||
done();
|
||||
}
|
||||
);
|
||||
|
||||
}); // 5.1.2
|
||||
|
||||
it("5.1.3 throws error when gettting connection from oracledb given only 'user' when externalAuth is enabled", function(done) {
|
||||
|
||||
oracledb.getConnection(
|
||||
{
|
||||
externalAuth: true,
|
||||
user: dbConfig.user,
|
||||
connectString: dbConfig.connectString
|
||||
},
|
||||
function(err, conn){
|
||||
should.exist(err);
|
||||
(err.message).should.startWith("DPI-1032:");
|
||||
// DPI-1032: user and password should not be set when using external authentication
|
||||
should.not.exist(conn);
|
||||
done();
|
||||
}
|
||||
);
|
||||
|
||||
}); // 5.1.3
|
||||
|
||||
it("5.1.4 throws error when gettting connection from oracledb given only 'password' when externalAuth is enabled", function(done) {
|
||||
|
||||
oracledb.getConnection(
|
||||
{
|
||||
externalAuth: true,
|
||||
password: dbConfig.password,
|
||||
connectString: dbConfig.connectString
|
||||
},
|
||||
function(err, conn){
|
||||
should.exist(err);
|
||||
(err.message).should.startWith("DPI-1032:");
|
||||
// DPI-1032: user and password should not be set when using external authentication
|
||||
|
||||
should.not.exist(conn);
|
||||
done();
|
||||
}
|
||||
);
|
||||
|
||||
}); // 5.1.4
|
||||
|
||||
it("5.1.5 can get pool from oracledb with user/password when externalAuth is disabled", function(done) {
|
||||
|
||||
async.waterfall([
|
||||
function(callback) {
|
||||
oracledb.createPool(
|
||||
{
|
||||
externalAuth: false,
|
||||
user: dbConfig.user,
|
||||
password: dbConfig.password,
|
||||
connectString: dbConfig.connectString
|
||||
},
|
||||
function(err, pool) {
|
||||
callback(err, pool);
|
||||
}
|
||||
);
|
||||
},
|
||||
function(pool, callback) {
|
||||
pool.getConnection(function(err, connection) {
|
||||
callback(err, connection, pool);
|
||||
});
|
||||
},
|
||||
function(connection, pool, callback) {
|
||||
connection.execute(
|
||||
"select (3+5) from dual",
|
||||
function(err, result) {
|
||||
(result.rows[0][0]).should.equal(8);
|
||||
callback(err, connection, pool);
|
||||
}
|
||||
);
|
||||
}
|
||||
], function(err, connection, pool) {
|
||||
should.not.exist(err);
|
||||
connection.close( function(err) {
|
||||
should.not.exist(err);
|
||||
pool.close( function(err) {
|
||||
should.not.exist(err);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
}); // 5.1.5
|
||||
|
||||
it("5.1.6 throws error when getting pool from oracledb given user/password when externalAuth is enabled", function(done) {
|
||||
|
||||
oracledb.createPool(
|
||||
{
|
||||
externalAuth: true,
|
||||
user: dbConfig.user,
|
||||
password: dbConfig.password,
|
||||
connectString: dbConfig.connectString
|
||||
},
|
||||
function(err, pool) {
|
||||
should.exist(err);
|
||||
(err.message).should.startWith("DPI-1032:");
|
||||
// DPI-1032: user and password should not be set when using external authentication
|
||||
should.not.exist(pool);
|
||||
done();
|
||||
}
|
||||
);
|
||||
|
||||
}); // 5.1.6
|
||||
|
||||
it("5.1.7 throws error when getting pool from oracledb only given username when externalAuth is enabled", function(done) {
|
||||
|
||||
oracledb.createPool(
|
||||
{
|
||||
externalAuth: true,
|
||||
user: dbConfig.user,
|
||||
connectString: dbConfig.connectString
|
||||
},
|
||||
function(err, pool) {
|
||||
should.exist(err);
|
||||
(err.message).should.startWith("DPI-1032:");
|
||||
should.not.exist(pool);
|
||||
done();
|
||||
}
|
||||
);
|
||||
|
||||
});
|
||||
|
||||
it("5.1.8 throws error when getting pool from oracledb only given password when externalAuth is enabled", function(done) {
|
||||
|
||||
oracledb.createPool(
|
||||
{
|
||||
externalAuth: true,
|
||||
password: dbConfig.password,
|
||||
connectString: dbConfig.connectString
|
||||
},
|
||||
function(err, pool) {
|
||||
should.exist(err);
|
||||
(err.message).should.startWith("DPI-1032:");
|
||||
should.not.exist(pool);
|
||||
done();
|
||||
}
|
||||
);
|
||||
|
||||
});
|
||||
|
||||
}); // 5.1
|
||||
|
||||
describe('5.2 tests only work when externalAuth is configured on DB', function() {
|
||||
|
||||
before(function() {
|
||||
if ( !(process.env.NODE_ORACLEDB_EXTERNALAUTH) ) this.skip();
|
||||
});
|
||||
|
||||
it("5.2.1 can get connection from oracledb with external authentication", function(done) {
|
||||
|
||||
async.waterfall([
|
||||
function(callback) {
|
||||
oracledb.getConnection(
|
||||
{
|
||||
externalAuth: true,
|
||||
connectString: dbConfig.connectString
|
||||
},
|
||||
function(err, connection) {
|
||||
callback(err, connection);
|
||||
}
|
||||
);
|
||||
},
|
||||
function(connection, callback) {
|
||||
connection.execute(
|
||||
"select (7+8) from dual",
|
||||
function(err, result) {
|
||||
(result.rows[0][0]).should.equal(15);
|
||||
callback(err, connection);
|
||||
}
|
||||
);
|
||||
}
|
||||
], function(err, connection) {
|
||||
should.not.exist(err);
|
||||
connection.release( function(err) {
|
||||
should.not.exist(err);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
}); // 5.2.1
|
||||
|
||||
it("5.2.2 can get pool from oracledb with external authentication", function(done) {
|
||||
|
||||
async.waterfall([
|
||||
function(callback) {
|
||||
oracledb.createPool(
|
||||
{
|
||||
externalAuth: true,
|
||||
connectString: dbConfig.connectString
|
||||
},
|
||||
function(err, pool) {
|
||||
// verify poolMin value
|
||||
(pool.connectionsOpen).should.be.exactly(0);
|
||||
callback(err, pool);
|
||||
}
|
||||
);
|
||||
},
|
||||
function(pool, callback) {
|
||||
pool.getConnection( function(err, connection) {
|
||||
callback(err, connection, pool);
|
||||
});
|
||||
},
|
||||
function(connection, pool, callback) {
|
||||
connection.execute(
|
||||
"select (3+5) from dual",
|
||||
function(err, result) {
|
||||
(result.rows[0][0]).should.equal(8);
|
||||
callback(err, connection, pool);
|
||||
}
|
||||
);
|
||||
}
|
||||
], function(err, connection, pool) {
|
||||
should.not.exist(err);
|
||||
connection.close( function(err) {
|
||||
should.not.exist(err);
|
||||
pool.close(function(err) {
|
||||
should.not.exist(err);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
}); // 5.2.2
|
||||
|
||||
it("5.2.3 gets multiple connections from oracledb", function(done) {
|
||||
|
||||
var getConns = function(id, callback) {
|
||||
oracledb.getConnection(
|
||||
{
|
||||
externalAuth: true,
|
||||
connectString: dbConfig.connectString
|
||||
},
|
||||
function(err, connection) {
|
||||
callback(err, {
|
||||
num: id,
|
||||
inst: connection
|
||||
});
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
var closeConns = function(conns, cb) {
|
||||
async.map(conns, function(item, callback) {
|
||||
// console.log("-- close conn " + item.num);
|
||||
var connection = item.inst;
|
||||
connection.execute(
|
||||
"select (5+7) from dual",
|
||||
function(err, result) {
|
||||
should.not.exist(err);
|
||||
(result.rows[0][0]).should.equal(12);
|
||||
connection.close(callback);
|
||||
}
|
||||
);
|
||||
}, function(err) {
|
||||
should.not.exist(err);
|
||||
cb();
|
||||
});
|
||||
};
|
||||
|
||||
// Main function of this case
|
||||
async.times(9, function(n, next) {
|
||||
getConns(n, function(err, conn) {
|
||||
next(err, conn);
|
||||
});
|
||||
}, function(err, arr) {
|
||||
should.not.exist(err);
|
||||
closeConns(arr, done);
|
||||
});
|
||||
|
||||
}); // 5.2.3
|
||||
|
||||
it("5.2.4 gets multiple pools from oracledb", function(done) {
|
||||
|
||||
var getPools = function(id, callback) {
|
||||
oracledb.createPool(
|
||||
{
|
||||
externalAuth: true,
|
||||
connectString: dbConfig.connectString
|
||||
},
|
||||
function(err, pool) {
|
||||
callback(err, {
|
||||
num: id,
|
||||
inst: pool
|
||||
});
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
var closePools = function(pools, cb) {
|
||||
async.map(pools, function(item, callback) {
|
||||
// console.log("-- close pool " + item.num);
|
||||
var pool = item.inst;
|
||||
pool.getConnection(function(err, connection) {
|
||||
should.not.exist(err);
|
||||
connection.execute(
|
||||
"select (8+9) from dual",
|
||||
function(err, result) {
|
||||
should.not.exist(err);
|
||||
(result.rows[0][0]).should.equal(17);
|
||||
connection.close(function(err) {
|
||||
should.not.exist(err);
|
||||
pool.close(callback);
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
}, function(err) {
|
||||
should.not.exist(err);
|
||||
cb();
|
||||
});
|
||||
};
|
||||
|
||||
// Main function of this case
|
||||
async.times(9, function(n, next) {
|
||||
getPools(n, function(err, poolInst) {
|
||||
next(err, poolInst);
|
||||
});
|
||||
}, function(err, arr) {
|
||||
should.not.exist(err);
|
||||
closePools(arr, done);
|
||||
});
|
||||
|
||||
}); // 5.2.4
|
||||
|
||||
it("5.2.5 poolMin no longer takes effect under externalAuth", function(done) {
|
||||
|
||||
oracledb.createPool(
|
||||
{
|
||||
externalAuth: true,
|
||||
connectString: dbConfig.connectString,
|
||||
poolMin: 5,
|
||||
poolMax: 20,
|
||||
poolIncrement: 2
|
||||
},
|
||||
function(err, pool) {
|
||||
(pool.connectionsOpen).should.be.exactly(0);
|
||||
|
||||
pool.close(function(err) {
|
||||
should.not.exist(err);
|
||||
done();
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
});
|
||||
|
||||
it("5.2.6 poolIncrement no longer takes effect", function(done) {
|
||||
|
||||
async.waterfall([
|
||||
function(callback) {
|
||||
oracledb.createPool(
|
||||
{
|
||||
externalAuth: true,
|
||||
connectString: dbConfig.connectString,
|
||||
poolMin: 5,
|
||||
poolMax: 20,
|
||||
poolIncrement: 2
|
||||
},
|
||||
function(err, pool) {
|
||||
callback(err, pool);
|
||||
}
|
||||
);
|
||||
},
|
||||
function(pool, callback) {
|
||||
pool.getConnection( function(err, conn1) {
|
||||
(pool.connectionsOpen).should.be.exactly(1);
|
||||
callback(err, conn1, pool);
|
||||
});
|
||||
},
|
||||
function(conn1, pool, callback) {
|
||||
pool.getConnection( function(err, conn2) {
|
||||
(pool.connectionsOpen).should.be.exactly(2);
|
||||
callback(err, conn1, conn2, pool);
|
||||
});
|
||||
}
|
||||
], function(err, conn1, conn2, pool) {
|
||||
should.not.exist(err);
|
||||
conn1.close( function(err) {
|
||||
should.not.exist(err);
|
||||
conn2.close(function(err) {
|
||||
should.not.exist(err);
|
||||
pool.close(function(err) {
|
||||
should.not.exist(err);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
}); // 5.2
|
||||
|
||||
});
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,414 @@
|
|||
/* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. */
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* You may not use the identified files except in compliance with the Apache
|
||||
* License, Version 2.0 (the "License.")
|
||||
*
|
||||
* You may obtain a copy of the License at
|
||||
* http://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.
|
||||
*
|
||||
* The node-oracledb test suite uses 'mocha', 'should' and 'async'.
|
||||
* See LICENSE.md for relevant licenses.
|
||||
*
|
||||
* NAME
|
||||
* 89. fetchBlobAsBuffer3.js
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Testing Oracle data type support - BLOB.
|
||||
* To fetch BLOB columns as buffer
|
||||
*
|
||||
* NUMBERING RULE
|
||||
* Test numbers follow this numbering rule:
|
||||
* 1 - 20 are reserved for basic functional tests
|
||||
* 21 - 50 are reserved for data type supporting tests
|
||||
* 51 onwards are for other tests
|
||||
*
|
||||
*****************************************************************************/
|
||||
'use strict';
|
||||
|
||||
var oracledb = require('oracledb');
|
||||
var async = require('async');
|
||||
var should = require('should');
|
||||
var dbConfig = require('./dbconfig.js');
|
||||
var random = require('./random.js');
|
||||
var assist = require('./dataTypeAssist.js');
|
||||
|
||||
describe('89. fetchBlobAsBuffer3.js', function() {
|
||||
this.timeout(100000);
|
||||
var connection = null;
|
||||
var node6plus = false; // assume node runtime version is lower than 6
|
||||
var insertID = 1; // assume id for insert into db starts from 1
|
||||
|
||||
var proc_create_table2 = "BEGIN \n" +
|
||||
" DECLARE \n" +
|
||||
" e_table_missing EXCEPTION; \n" +
|
||||
" PRAGMA EXCEPTION_INIT(e_table_missing, -00942); \n" +
|
||||
" BEGIN \n" +
|
||||
" EXECUTE IMMEDIATE('DROP TABLE nodb_blob2 PURGE'); \n" +
|
||||
" EXCEPTION \n" +
|
||||
" WHEN e_table_missing \n" +
|
||||
" THEN NULL; \n" +
|
||||
" END; \n" +
|
||||
" EXECUTE IMMEDIATE (' \n" +
|
||||
" CREATE TABLE nodb_blob2 ( \n" +
|
||||
" ID NUMBER, \n" +
|
||||
" B1 BLOB, \n" +
|
||||
" B2 BLOB \n" +
|
||||
" ) \n" +
|
||||
" '); \n" +
|
||||
"END; ";
|
||||
var drop_table2 = "DROP TABLE nodb_blob2 PURGE";
|
||||
|
||||
before('get one connection', function(done) {
|
||||
oracledb.stmtCacheSize = 0;
|
||||
oracledb.getConnection(dbConfig, function(err, conn) {
|
||||
should.not.exist(err);
|
||||
connection = conn;
|
||||
if(process.versions["node"].substring(0,1) >= "6")
|
||||
node6plus = true;
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
}); // before
|
||||
|
||||
after('release connection', function(done) {
|
||||
connection.release(function(err) {
|
||||
should.not.exist(err);
|
||||
done();
|
||||
});
|
||||
}); // after
|
||||
|
||||
var insertIntoBlobTable2 = function(id, content1, content2, callback) {
|
||||
connection.execute(
|
||||
"INSERT INTO nodb_blob2 VALUES (:ID, :B1, :B2)",
|
||||
[ id, content1, content2 ],
|
||||
function(err, result){
|
||||
should.not.exist(err);
|
||||
should.strictEqual(result.rowsAffected, 1);
|
||||
callback();
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
// compare fetch result
|
||||
var compareClientFetchResult = function(err, resultVal, specialStr, content, contentLength) {
|
||||
should.not.exist(err);
|
||||
compareBuffers(resultVal, specialStr, content, contentLength);
|
||||
};
|
||||
|
||||
// compare two buffers
|
||||
var compareBuffers = function(resultVal, specialStr, content, contentLength) {
|
||||
should.equal(resultVal.length, contentLength);
|
||||
var compareBuffer = assist.compare2Buffers(resultVal, content);
|
||||
should.strictEqual(compareBuffer, true);
|
||||
};
|
||||
|
||||
describe('89.1 fetch multiple BLOBs', function() {
|
||||
|
||||
before('create Table and populate', function(done) {
|
||||
connection.execute(
|
||||
proc_create_table2,
|
||||
function(err){
|
||||
should.not.exist(err);
|
||||
done() ;
|
||||
}
|
||||
);
|
||||
}); // before
|
||||
|
||||
after('drop table', function(done) {
|
||||
connection.execute(
|
||||
drop_table2,
|
||||
function(err){
|
||||
should.not.exist(err);
|
||||
done();
|
||||
}
|
||||
);
|
||||
}); // after
|
||||
|
||||
beforeEach('set oracledb.fetchAsBuffer', function(done) {
|
||||
oracledb.fetchAsBuffer = [ oracledb.BLOB ];
|
||||
done();
|
||||
}); // beforeEach
|
||||
|
||||
afterEach('clear the By type specification', function(done) {
|
||||
oracledb.fetchAsBuffer = [];
|
||||
done();
|
||||
}); // afterEach
|
||||
|
||||
it('89.1.1 fetch multiple BLOB columns as Buffer', function(done) {
|
||||
var id = insertID++;
|
||||
var specialStr_1 = '89.1.1_1';
|
||||
var contentLength_1 = 26;
|
||||
var strBuf_1 = random.getRandomString(contentLength_1, specialStr_1);
|
||||
var content_1 = node6plus ? Buffer.from(strBuf_1, "utf-8") : new Buffer(strBuf_1, "utf-8");
|
||||
var specialStr_2 = '89.1.1_2';
|
||||
var contentLength_2 = 100;
|
||||
var strBuf_2 = random.getRandomString(contentLength_2, specialStr_2);
|
||||
var content_2 = node6plus ? Buffer.from(strBuf_2, "utf-8") : new Buffer(strBuf_2, "utf-8");
|
||||
|
||||
async.series([
|
||||
function(cb) {
|
||||
insertIntoBlobTable2(id, content_1, content_2, cb);
|
||||
},
|
||||
function(cb) {
|
||||
connection.execute(
|
||||
"SELECT ID, B1, B2 from nodb_blob2",
|
||||
function(err, result){
|
||||
should.not.exist(err);
|
||||
var resultVal = result.rows[0][1];
|
||||
compareClientFetchResult(err, resultVal, specialStr_1, content_1, contentLength_1);
|
||||
resultVal = result.rows[0][2];
|
||||
compareClientFetchResult(err, resultVal, specialStr_2, content_2, contentLength_2);
|
||||
cb();
|
||||
}
|
||||
);
|
||||
}
|
||||
], done);
|
||||
|
||||
}); // 89.1.1
|
||||
|
||||
it('89.1.2 fetch two BLOB columns, one as string, another streamed', function(done) {
|
||||
var id = insertID++;
|
||||
var specialStr_1 = '89.1.2_1';
|
||||
var contentLength_1 = 30;
|
||||
var strBuf_1 = random.getRandomString(contentLength_1, specialStr_1);
|
||||
var content_1 = node6plus ? Buffer.from(strBuf_1, "utf-8") : new Buffer(strBuf_1, "utf-8");
|
||||
var specialStr_2 = '89.1.2_2';
|
||||
var contentLength_2 = 50;
|
||||
var strBuf_2 = random.getRandomString(contentLength_2, specialStr_2);
|
||||
var content_2 = node6plus ? Buffer.from(strBuf_2, "utf-8") : new Buffer(strBuf_2, "utf-8");
|
||||
|
||||
async.series([
|
||||
function(cb) {
|
||||
insertIntoBlobTable2(id, content_1, content_2, cb);
|
||||
},
|
||||
function(cb) {
|
||||
connection.execute(
|
||||
"SELECT ID, B1 from nodb_blob2 where ID = :id",
|
||||
{ id : id },
|
||||
function(err, result){
|
||||
should.not.exist(err);
|
||||
var resultVal = result.rows[0][1];
|
||||
compareClientFetchResult(err, resultVal, specialStr_1, content_1, contentLength_1);
|
||||
cb();
|
||||
}
|
||||
);
|
||||
},
|
||||
function(cb) {
|
||||
oracledb.fetchAsBuffer = [];
|
||||
|
||||
connection.execute(
|
||||
"SELECT B2 from nodb_blob2 where ID = :id",
|
||||
{ id : id },
|
||||
function(err, result){
|
||||
should.not.exist(err);
|
||||
(result.rows.length).should.not.eql(0);
|
||||
var lob = result.rows[0][0];
|
||||
should.exist(lob);
|
||||
|
||||
// set the encoding so we get a 'string' not a 'buffer'
|
||||
lob.setEncoding('utf8');
|
||||
var clobData = '';
|
||||
|
||||
lob.on('data', function(chunk) {
|
||||
clobData += chunk;
|
||||
});
|
||||
|
||||
lob.on('error', function(err) {
|
||||
should.not.exist(err, "lob.on 'error' event.");
|
||||
});
|
||||
|
||||
lob.on('end', function() {
|
||||
should.not.exist(err);
|
||||
var specialStrLen_2 = specialStr_2.length;
|
||||
var resultLen_2 = clobData.length;
|
||||
should.equal(clobData.length, contentLength_2);
|
||||
should.strictEqual(clobData.substring(0, specialStrLen_2), specialStr_2);
|
||||
should.strictEqual(clobData.substring(resultLen_2 - specialStrLen_2, resultLen_2), specialStr_2);
|
||||
|
||||
cb();
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
], done);
|
||||
|
||||
}); // 89.1.2
|
||||
|
||||
}); // 89.1
|
||||
|
||||
describe('89.2 types support for fetchAsBuffer property', function() {
|
||||
|
||||
afterEach ('clear the by-type specification', function ( done ) {
|
||||
oracledb.fetchAsBuffer = [];
|
||||
done ();
|
||||
});
|
||||
|
||||
it('89.2.1 String not supported in fetchAsBuffer', function(done) {
|
||||
should.throws(
|
||||
function() {
|
||||
oracledb.fetchAsBuffer = [ oracledb.STRING ];
|
||||
},
|
||||
/NJS-021: invalid type for conversion specified/
|
||||
);
|
||||
done();
|
||||
}); // 89.2.1
|
||||
|
||||
|
||||
it('89.2.2 CLOB not supported in fetchAsBuffer', function(done) {
|
||||
should.throws(
|
||||
function() {
|
||||
oracledb.fetchAsBuffer = [ oracledb.CLOB ];
|
||||
},
|
||||
/NJS-021: invalid type for conversion specified/
|
||||
);
|
||||
done();
|
||||
}); // 89.2.2
|
||||
|
||||
|
||||
it('89.2.3 Number not supported in fetchAsBuffer', function(done) {
|
||||
should.throws(
|
||||
function() {
|
||||
oracledb.fetchAsBuffer = [ oracledb.NUMBER ];
|
||||
},
|
||||
/NJS-021: invalid type for conversion specified/
|
||||
);
|
||||
done();
|
||||
}); // 89.2.3
|
||||
|
||||
|
||||
it('89.2.4 Date not supported in fetchAsBuffer', function(done) {
|
||||
should.throws(
|
||||
function() {
|
||||
oracledb.fetchAsBuffer = [ oracledb.DATE ];
|
||||
},
|
||||
/NJS-021: invalid type for conversion specified/
|
||||
);
|
||||
done();
|
||||
}); // 89.2.4
|
||||
|
||||
|
||||
it('89.2.5 Cursor not supported in fetchAsBuffer', function(done) {
|
||||
should.throws(
|
||||
function() {
|
||||
oracledb.fetchAsBuffer = [ oracledb.CURSOR ];
|
||||
},
|
||||
/NJS-021: invalid type for conversion specified/
|
||||
);
|
||||
done();
|
||||
}); // 89.2.5
|
||||
|
||||
|
||||
it('89.2.6 Buffer not supported in fetchAsBuffer', function(done) {
|
||||
should.throws(
|
||||
function() {
|
||||
oracledb.fetchAsBuffer = [ oracledb.BUFFER ];
|
||||
},
|
||||
/NJS-021: invalid type for conversion specified/
|
||||
);
|
||||
done();
|
||||
}); // 89.2.6
|
||||
|
||||
|
||||
it('89.2.7 BLOB supported in fetchAsBuffer', function(done) {
|
||||
should.doesNotThrow(
|
||||
function() {
|
||||
oracledb.fetchAsBuffer = [ oracledb.BLOB ];
|
||||
}
|
||||
);
|
||||
should.strictEqual(oracledb.fetchAsBuffer.length, 1);
|
||||
should.strictEqual(oracledb.fetchAsBuffer[0], oracledb.BLOB);
|
||||
done();
|
||||
}); // 89.2.7
|
||||
|
||||
|
||||
it.skip('89.2.8 negative null value for fetchAsBuffer', function(done) {
|
||||
should.throws(
|
||||
function() {
|
||||
oracledb.fetchAsBuffer = null;
|
||||
},
|
||||
/NJS-004: invalid value for property [\w]/
|
||||
);
|
||||
done();
|
||||
}); // 89.2.8
|
||||
|
||||
|
||||
it.skip('89.2.9 negative undefined value for fetchAsBuffer', function(done) {
|
||||
should.throws(
|
||||
function() {
|
||||
oracledb.fetchAsBuffer = undefined;
|
||||
},
|
||||
/NJS-004: invalid value for property [\w]/
|
||||
);
|
||||
done();
|
||||
}); // 89.2.9
|
||||
|
||||
|
||||
it.skip('89.2.10 negative numeric value for fetchAsBuffer', function(done) {
|
||||
should.throws(
|
||||
function() {
|
||||
oracledb.fetchAsBuffer = 89210;
|
||||
},
|
||||
/NJS-004: invalid value for property [\w]/
|
||||
);
|
||||
done();
|
||||
}); // 89.2.10
|
||||
|
||||
|
||||
it.skip('89.2.11 negative emtpy string value for fetchAsBuffer', function(done) {
|
||||
should.throws(
|
||||
function() {
|
||||
oracledb.fetchAsBuffer = ' ';
|
||||
},
|
||||
/NJS-004: invalid value for property [\w]/
|
||||
);
|
||||
done();
|
||||
}); // 89.2.11
|
||||
|
||||
|
||||
it.skip('89.2.12 negative arbitary string value for fetchAsBuffer', function(done) {
|
||||
should.throws(
|
||||
function() {
|
||||
oracledb.fetchAsBuffer = "89.2.12";
|
||||
},
|
||||
/NJS-004: invalid value for property [\w]/
|
||||
);
|
||||
done();
|
||||
}); // 89.2.12
|
||||
|
||||
|
||||
it.skip('89.2.13 negative date value for fetchAsBuffer', function(done) {
|
||||
should.throws(
|
||||
function() {
|
||||
var dt = new Date ();
|
||||
oracledb.fetchAsBuffer = dt;
|
||||
},
|
||||
/NJS-004: invalid value for property [\w]/
|
||||
);
|
||||
done();
|
||||
}); // 89.2.13
|
||||
|
||||
|
||||
it.skip('89.2.14 negative arbitary buffer value for fetchAsBuffer', function(done) {
|
||||
should.throws(
|
||||
function() {
|
||||
var buf = assist.createBuffer ( 10 ) ;
|
||||
oracledb.fetchAsBuffer = buf;
|
||||
},
|
||||
/NJS-004: invalid value for property [\w]/
|
||||
);
|
||||
done();
|
||||
}); // 89.2.14
|
||||
|
||||
}); // 89.2
|
||||
|
||||
});
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,318 @@
|
|||
/* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. */
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* You may not use the identified files except in compliance with the Apache
|
||||
* License, Version 2.0 (the "License.")
|
||||
*
|
||||
* You may obtain a copy of the License at
|
||||
* http://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.
|
||||
*
|
||||
* The node-oracledb test suite uses 'mocha', 'should' and 'async'.
|
||||
* See LICENSE.md for relevant licenses.
|
||||
*
|
||||
* NAME
|
||||
* 86. fetchClobAsString.js
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Testing Oracle data type support - CLOB.
|
||||
* To fetch CLOB columns as strings
|
||||
* This could be very useful for smaller CLOB size as it can be fetched as string and processed in memory itself.
|
||||
*
|
||||
* NUMBERING RULE
|
||||
* Test numbers follow this numbering rule:
|
||||
* 1 - 20 are reserved for basic functional tests
|
||||
* 21 - 50 are reserved for data type supporting tests
|
||||
* 51 onwards are for other tests
|
||||
*
|
||||
*****************************************************************************/
|
||||
'use strict';
|
||||
|
||||
var oracledb = require('oracledb');
|
||||
var async = require('async');
|
||||
var should = require('should');
|
||||
var dbConfig = require('./dbconfig.js');
|
||||
var random = require('./random.js');
|
||||
|
||||
describe('86. fetchClobAsString3.js', function() {
|
||||
this.timeout(100000);
|
||||
var connection = null;
|
||||
var insertID = 1; // assume id for insert into db starts from 1
|
||||
var proc_create_table2 = "BEGIN \n" +
|
||||
" DECLARE \n" +
|
||||
" e_table_missing EXCEPTION; \n" +
|
||||
" PRAGMA EXCEPTION_INIT(e_table_missing, -00942); \n" +
|
||||
" BEGIN \n" +
|
||||
" EXECUTE IMMEDIATE('DROP TABLE nodb_clob2 PURGE'); \n" +
|
||||
" EXCEPTION \n" +
|
||||
" WHEN e_table_missing \n" +
|
||||
" THEN NULL; \n" +
|
||||
" END; \n" +
|
||||
" EXECUTE IMMEDIATE (' \n" +
|
||||
" CREATE TABLE nodb_clob2 ( \n" +
|
||||
" ID NUMBER, \n" +
|
||||
" C1 CLOB, \n" +
|
||||
" C2 CLOB \n" +
|
||||
" ) \n" +
|
||||
" '); \n" +
|
||||
"END; ";
|
||||
var drop_table2 = "DROP TABLE nodb_clob2 PURGE";
|
||||
|
||||
before('get one connection', function(done) {
|
||||
oracledb.stmtCacheSize = 0;
|
||||
oracledb.getConnection(dbConfig, function(err, conn) {
|
||||
should.not.exist(err);
|
||||
connection = conn;
|
||||
done();
|
||||
});
|
||||
}); // before
|
||||
|
||||
after('release connection', function(done) {
|
||||
connection.release(function(err) {
|
||||
should.not.exist(err);
|
||||
done();
|
||||
});
|
||||
}); // after
|
||||
|
||||
var insertIntoClobTable2 = function(id, content1, content2, callback) {
|
||||
connection.execute(
|
||||
"INSERT INTO nodb_clob2 VALUES (:ID, :C1, :C2)",
|
||||
[ id, content1, content2 ],
|
||||
function(err, result){
|
||||
should.not.exist(err);
|
||||
should.strictEqual(result.rowsAffected, 1);
|
||||
callback();
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
describe('86.1 fetch multiple CLOBs', function() {
|
||||
before('create Table and populate', function(done) {
|
||||
connection.execute(
|
||||
proc_create_table2,
|
||||
function(err){
|
||||
should.not.exist(err);
|
||||
done() ;
|
||||
}
|
||||
);
|
||||
}); // before
|
||||
|
||||
after('drop table', function(done) {
|
||||
oracledb.fetchAsString = [];
|
||||
connection.execute(
|
||||
drop_table2,
|
||||
function(err){
|
||||
should.not.exist(err);
|
||||
done();
|
||||
}
|
||||
);
|
||||
}); // after
|
||||
|
||||
beforeEach('set oracledb.fetchAsString', function(done) {
|
||||
oracledb.fetchAsString = [ oracledb.CLOB ];
|
||||
done();
|
||||
}); // beforeEach
|
||||
|
||||
afterEach('clear the By type specification', function(done) {
|
||||
oracledb.fetchAsString = [];
|
||||
done();
|
||||
}); // afterEach
|
||||
|
||||
it('86.1.1 fetch multiple CLOB columns as String', function(done) {
|
||||
var id = insertID++;
|
||||
var specialStr_1 = '86.1.1_1';
|
||||
var contentLength_1 = 26;
|
||||
var content_1 = random.getRandomString(contentLength_1, specialStr_1);
|
||||
var specialStr_2 = '86.1.1_2';
|
||||
var contentLength_2 = 100;
|
||||
var content_2 = random.getRandomString(contentLength_2, specialStr_2);
|
||||
|
||||
async.series([
|
||||
function(cb) {
|
||||
insertIntoClobTable2(id, content_1, content_2, cb);
|
||||
},
|
||||
function(cb) {
|
||||
connection.execute(
|
||||
"SELECT ID, C1, C2 from nodb_clob2",
|
||||
function(err, result){
|
||||
should.not.exist(err);
|
||||
var specialStrLen_1 = specialStr_1.length;
|
||||
var resultLen_1 = result.rows[0][1].length;
|
||||
should.equal(result.rows[0][1].length, contentLength_1);
|
||||
should.strictEqual(result.rows[0][1].substring(0, specialStrLen_1), specialStr_1);
|
||||
should.strictEqual(result.rows[0][1].substring(resultLen_1 - specialStrLen_1, resultLen_1), specialStr_1);
|
||||
|
||||
var specialStrLen_2 = specialStr_2.length;
|
||||
var resultLen_2 = result.rows[0][2].length;
|
||||
should.equal(result.rows[0][2].length, contentLength_2);
|
||||
should.strictEqual(result.rows[0][2].substring(0, specialStrLen_2), specialStr_2);
|
||||
should.strictEqual(result.rows[0][2].substring(resultLen_2 - specialStrLen_2, resultLen_2), specialStr_2);
|
||||
cb();
|
||||
}
|
||||
);
|
||||
}
|
||||
], done);
|
||||
|
||||
}); // 86.1.1
|
||||
|
||||
it('86.1.2 fetch two CLOB columns, one as string, another streamed', function(done) {
|
||||
var id = insertID++;
|
||||
var specialStr_1 = '86.1.2_1';
|
||||
var contentLength_1 = 30;
|
||||
var content_1 = random.getRandomString(contentLength_1, specialStr_1);
|
||||
var specialStr_2 = '86.1.2_2';
|
||||
var contentLength_2 = 50;
|
||||
var content_2 = random.getRandomString(contentLength_2, specialStr_2);
|
||||
|
||||
async.series([
|
||||
function(cb) {
|
||||
insertIntoClobTable2(id, content_1, content_2, cb);
|
||||
},
|
||||
function(cb) {
|
||||
connection.execute(
|
||||
"SELECT ID, C1 from nodb_clob2 where ID = :id",
|
||||
{ id: id },
|
||||
function(err, result){
|
||||
should.not.exist(err);
|
||||
var specialStrLen_1 = specialStr_1.length;
|
||||
var resultLen_1 = result.rows[0][1].length;
|
||||
should.equal(result.rows[0][1].length, contentLength_1);
|
||||
should.strictEqual(result.rows[0][1].substring(0, specialStrLen_1), specialStr_1);
|
||||
should.strictEqual(result.rows[0][1].substring(resultLen_1 - specialStrLen_1, resultLen_1), specialStr_1);
|
||||
cb();
|
||||
}
|
||||
);
|
||||
},
|
||||
function(cb) {
|
||||
oracledb.fetchAsString = [];
|
||||
|
||||
connection.execute(
|
||||
"SELECT C2 from nodb_clob2 where ID = :id",
|
||||
{ id: id },
|
||||
function(err, result){
|
||||
should.not.exist(err);
|
||||
(result.rows.length).should.not.eql(0);
|
||||
var lob = result.rows[0][0];
|
||||
should.exist(lob);
|
||||
|
||||
// set the encoding so we get a 'string' not a 'String'
|
||||
lob.setEncoding('utf8');
|
||||
var clobData = '';
|
||||
|
||||
lob.on('data', function(chunk) {
|
||||
clobData += chunk;
|
||||
});
|
||||
|
||||
lob.on('error', function(err) {
|
||||
should.not.exist(err, "lob.on 'error' event.");
|
||||
});
|
||||
|
||||
lob.on('end', function() {
|
||||
should.not.exist(err);
|
||||
var specialStrLen_2 = specialStr_2.length;
|
||||
var resultLen_2 = clobData.length;
|
||||
should.equal(clobData.length, contentLength_2);
|
||||
should.strictEqual(clobData.substring(0, specialStrLen_2), specialStr_2);
|
||||
should.strictEqual(clobData.substring(resultLen_2 - specialStrLen_2, resultLen_2), specialStr_2);
|
||||
|
||||
cb();
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
], done);
|
||||
|
||||
}); // 86.1.2
|
||||
|
||||
}); // 86.1
|
||||
|
||||
describe('86.2 types support for fetchAsString property', function() {
|
||||
|
||||
afterEach ('clear the by-type specification', function ( done ) {
|
||||
oracledb.fetchAsString = [];
|
||||
done ();
|
||||
});
|
||||
|
||||
it('86.2.1 String not supported in fetchAsString', function(done) {
|
||||
should.throws(
|
||||
function() {
|
||||
oracledb.fetchAsString = [ oracledb.STRING ];
|
||||
},
|
||||
/NJS-021: invalid type for conversion specified/
|
||||
);
|
||||
done();
|
||||
}); // 86.2.1
|
||||
|
||||
it('86.2.2 BLOB not supported in fetchAsString', function(done) {
|
||||
should.throws(
|
||||
function() {
|
||||
oracledb.fetchAsString = [ oracledb.BLOB ];
|
||||
},
|
||||
/NJS-021: invalid type for conversion specified/
|
||||
);
|
||||
done();
|
||||
}); // 86.2.2
|
||||
|
||||
it('86.2.3 Cursor not supported in fetchAsString', function(done) {
|
||||
should.throws(
|
||||
function() {
|
||||
oracledb.fetchAsString = [ oracledb.CURSOR ];
|
||||
},
|
||||
/NJS-021: invalid type for conversion specified/
|
||||
);
|
||||
done();
|
||||
}); // 86.2.3
|
||||
|
||||
it('86.2.4 Buffer not supported in fetchAsString', function(done) {
|
||||
should.throws(
|
||||
function() {
|
||||
oracledb.fetchAsString = [ oracledb.Buffer ];
|
||||
},
|
||||
/NJS-021: invalid type for conversion specified/
|
||||
);
|
||||
done();
|
||||
}); // 86.2.4
|
||||
|
||||
it('86.2.5 Number supported in fetchAsString', function(done) {
|
||||
should.doesNotThrow(
|
||||
function() {
|
||||
oracledb.fetchAsString = [ oracledb.NUMBER ];
|
||||
}
|
||||
);
|
||||
should.strictEqual(oracledb.fetchAsString.length, 1);
|
||||
should.strictEqual(oracledb.fetchAsString[0], oracledb.NUMBER);
|
||||
done();
|
||||
}); // 86.2.5
|
||||
|
||||
it('86.2.6 Date supported in fetchAsString', function(done) {
|
||||
should.doesNotThrow(
|
||||
function() {
|
||||
oracledb.fetchAsString = [ oracledb.DATE ];
|
||||
}
|
||||
);
|
||||
should.strictEqual(oracledb.fetchAsString.length, 1);
|
||||
should.strictEqual(oracledb.fetchAsString[0], oracledb.DATE);
|
||||
done();
|
||||
}); // 86.2.6
|
||||
|
||||
it('86.2.7 CLOB supported in fetchAsString', function(done) {
|
||||
should.doesNotThrow(
|
||||
function() {
|
||||
oracledb.fetchAsString = [ oracledb.CLOB ];
|
||||
}
|
||||
);
|
||||
should.strictEqual(oracledb.fetchAsString.length, 1);
|
||||
should.strictEqual(oracledb.fetchAsString[0], oracledb.CLOB);
|
||||
done();
|
||||
}); // 86.2.7
|
||||
|
||||
}); // 86.2
|
||||
|
||||
});
|
|
@ -0,0 +1,50 @@
|
|||
/* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. */
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* You may not use the identified files except in compliance with the Apache
|
||||
* License, Version 2.0 (the "License.")
|
||||
*
|
||||
* You may obtain a copy of the License at
|
||||
* http://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.
|
||||
*
|
||||
* The node-oracledb test suite uses 'mocha', 'should' and 'async'.
|
||||
* See LICENSE.md for relevant licenses.
|
||||
*
|
||||
* NAME
|
||||
* file.js
|
||||
*
|
||||
* DESCRIPTION
|
||||
* file manipulate
|
||||
*****************************************************************************/
|
||||
'use strict';
|
||||
var should = require('should');
|
||||
var fs = require('fs');
|
||||
|
||||
var file = exports;
|
||||
module.exports = file;
|
||||
|
||||
file.create = function(filePath) {
|
||||
fs.closeSync(fs.openSync(filePath, 'w'));
|
||||
};
|
||||
|
||||
file.write = function(filePath, content) {
|
||||
var stream = fs.createWriteStream(filePath, { flags: 'w', defaultEncoding: 'utf8', autoClose: true });
|
||||
stream.write(content);
|
||||
stream.end();
|
||||
};
|
||||
|
||||
file.delete = function(filePath) {
|
||||
if(fs.existsSync(filePath) === true) {
|
||||
fs.unlink(filePath, function(err) {
|
||||
should.not.exist(err);
|
||||
});
|
||||
}
|
||||
};
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,812 @@
|
|||
/* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. */
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* You may not use the identified files except in compliance with the Apache
|
||||
* License, Version 2.0 (the "License.")
|
||||
*
|
||||
* You may obtain a copy of the License at
|
||||
* http://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.
|
||||
*
|
||||
* The node-oracledb test suite uses 'mocha', 'should' and 'async'.
|
||||
* See LICENSE.md for relevant licenses.
|
||||
*
|
||||
* NAME
|
||||
* 80. lobBindAsStringBuffer.js
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Testing CLOB/BLOB binding as String/Buffer.
|
||||
*
|
||||
* NUMBERING RULE
|
||||
* Test numbers follow this numbering rule:
|
||||
* 1 - 20 are reserved for basic functional tests
|
||||
* 21 - 50 are reserved for data type supporting tests
|
||||
* 51 onwards are for other tests
|
||||
*
|
||||
*****************************************************************************/
|
||||
'use strict';
|
||||
|
||||
var oracledb = require('oracledb');
|
||||
var should = require('should');
|
||||
var async = require('async');
|
||||
var dbConfig = require('./dbconfig.js');
|
||||
var fs = require('fs');
|
||||
var random = require('./random.js');
|
||||
|
||||
describe('80. lobBindAsStringBuffer.js', function() {
|
||||
var connection = null;
|
||||
var node6plus = false; // assume node runtime version is lower than 6
|
||||
|
||||
var proc_lobs_in_tab = "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_lobs_in PURGE'); \n" +
|
||||
" EXCEPTION \n" +
|
||||
" WHEN e_table_missing \n" +
|
||||
" THEN NULL; \n" +
|
||||
" END; \n" +
|
||||
" EXECUTE IMMEDIATE (' \n" +
|
||||
" CREATE TABLE nodb_tab_lobs_in ( \n" +
|
||||
" id NUMBER, \n" +
|
||||
" clob CLOB, \n" +
|
||||
" blob BLOB \n" +
|
||||
" ) \n" +
|
||||
" '); \n" +
|
||||
"END; ";
|
||||
|
||||
before(function(done) {
|
||||
async.series([
|
||||
function(cb) {
|
||||
oracledb.getConnection(dbConfig, function(err, conn) {
|
||||
should.not.exist(err);
|
||||
connection = conn;
|
||||
|
||||
// Check whether node runtime version is >= 6 or not
|
||||
if ( process.versions["node"].substring (0, 1) >= "6")
|
||||
node6plus = true;
|
||||
|
||||
cb();
|
||||
});
|
||||
},
|
||||
function(cb) {
|
||||
setupAllTable(cb);
|
||||
}
|
||||
], done);
|
||||
|
||||
}); // before
|
||||
|
||||
after(function(done) {
|
||||
async.series([
|
||||
function(cb) {
|
||||
dropAllTable(cb);
|
||||
},
|
||||
function(cb) {
|
||||
connection.release(function(err) {
|
||||
should.not.exist(err);
|
||||
cb();
|
||||
});
|
||||
}
|
||||
], done);
|
||||
|
||||
}); // after
|
||||
|
||||
var setupAllTable = function(callback) {
|
||||
connection.execute(
|
||||
proc_lobs_in_tab,
|
||||
function(err) {
|
||||
should.not.exist(err);
|
||||
callback();
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
var dropAllTable = function(callback) {
|
||||
connection.execute(
|
||||
"DROP TABLE nodb_tab_lobs_in PURGE",
|
||||
function(err) {
|
||||
should.not.exist(err);
|
||||
callback();
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
var executeSQL = function(sql, callback) {
|
||||
connection.execute(
|
||||
sql,
|
||||
function(err) {
|
||||
should.not.exist(err);
|
||||
return callback();
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
var inFileName = './test/clobexample.txt';
|
||||
|
||||
var prepareTableWithClob = function(sql, id, callback) {
|
||||
var bindVar = { i: id, lobbv: { type: oracledb.CLOB, dir: oracledb.BIND_OUT } };
|
||||
|
||||
connection.execute(
|
||||
sql,
|
||||
bindVar,
|
||||
{ autoCommit: false }, // a transaction needs to span the INSERT and pipe()
|
||||
function(err, result) {
|
||||
should.not.exist(err);
|
||||
(result.rowsAffected).should.be.exactly(1);
|
||||
(result.outBinds.lobbv.length).should.be.exactly(1);
|
||||
|
||||
var inStream = fs.createReadStream(inFileName);
|
||||
var lob = result.outBinds.lobbv[0];
|
||||
|
||||
lob.on('error', function(err) {
|
||||
should.not.exist(err, "lob.on 'error' event");
|
||||
});
|
||||
|
||||
inStream.on('error', function(err) {
|
||||
should.not.exist(err, "inStream.on 'error' event");
|
||||
});
|
||||
|
||||
lob.on('close', function() {
|
||||
connection.commit( function(err) {
|
||||
should.not.exist(err);
|
||||
return callback();
|
||||
});
|
||||
});
|
||||
|
||||
inStream.pipe(lob); // copies the text to the CLOB
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
var jpgFileName = './test/fuzzydinosaur.jpg';
|
||||
|
||||
var prepareTableWithBlob = function(sql, id, callback) {
|
||||
var bindVar = { i: id, lobbv: { type: oracledb.BLOB, dir: oracledb.BIND_OUT } };
|
||||
|
||||
connection.execute(
|
||||
sql,
|
||||
bindVar,
|
||||
{ autoCommit: false }, // a transaction needs to span the INSERT and pipe()
|
||||
function(err, result) {
|
||||
should.not.exist(err);
|
||||
(result.rowsAffected).should.be.exactly(1);
|
||||
(result.outBinds.lobbv.length).should.be.exactly(1);
|
||||
|
||||
var inStream = fs.createReadStream(jpgFileName);
|
||||
var lob = result.outBinds.lobbv[0];
|
||||
|
||||
lob.on('error', function(err) {
|
||||
should.not.exist(err, "lob.on 'error' event");
|
||||
});
|
||||
|
||||
inStream.on('error', function(err) {
|
||||
should.not.exist(err, "inStream.on 'error' event");
|
||||
});
|
||||
|
||||
lob.on('close', function() {
|
||||
connection.commit( function(err) {
|
||||
should.not.exist(err);
|
||||
return callback();
|
||||
});
|
||||
});
|
||||
|
||||
inStream.pipe(lob);
|
||||
});
|
||||
};
|
||||
|
||||
var verifyClobValueWithFileData = function(selectSql, callback) {
|
||||
connection.execute(
|
||||
selectSql,
|
||||
function(err, result) {
|
||||
should.not.exist(err);
|
||||
var lob = result.rows[0][0];
|
||||
should.exist(lob);
|
||||
// set the encoding so we get a 'string' not a 'buffer'
|
||||
lob.setEncoding('utf8');
|
||||
var clobData = '';
|
||||
|
||||
lob.on('data', function(chunk) {
|
||||
clobData += chunk;
|
||||
});
|
||||
|
||||
lob.on('error', function(err) {
|
||||
should.not.exist(err, "lob.on 'error' event.");
|
||||
});
|
||||
|
||||
lob.on('end', function() {
|
||||
fs.readFile( inFileName, { encoding: 'utf8' }, function(err, originalData) {
|
||||
should.not.exist(err);
|
||||
should.strictEqual(clobData, originalData);
|
||||
return callback();
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
var verifyClobValueWithString = function(selectSql, originalString, specialStr, callback) {
|
||||
connection.execute(
|
||||
selectSql,
|
||||
function(err, result) {
|
||||
should.not.exist(err);
|
||||
var lob = result.rows[0][0];
|
||||
|
||||
if (originalString == null || originalString == undefined) {
|
||||
should.not.exist(lob);
|
||||
return callback();
|
||||
} else {
|
||||
should.exist(lob);
|
||||
// set the encoding so we get a 'string' not a 'buffer'
|
||||
lob.setEncoding('utf8');
|
||||
var clobData = '';
|
||||
|
||||
lob.on('data', function(chunk) {
|
||||
clobData += chunk;
|
||||
});
|
||||
|
||||
lob.on('error', function(err) {
|
||||
should.not.exist(err, "lob.on 'error' event.");
|
||||
});
|
||||
|
||||
lob.on('end', function() {
|
||||
var resultLength = clobData.length;
|
||||
var specStrLength = specialStr.length;
|
||||
should.strictEqual(resultLength, originalString.length);
|
||||
should.strictEqual(clobData.substring(0, specStrLength), specialStr);
|
||||
should.strictEqual(clobData.substring(resultLength - specStrLength, resultLength), specialStr);
|
||||
return callback();
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
var verifyBlobValueWithFileData = function(selectSql, callback) {
|
||||
connection.execute(
|
||||
selectSql,
|
||||
function(err, result) {
|
||||
should.not.exist(err);
|
||||
var lob = result.rows[0][0];
|
||||
should.exist(lob);
|
||||
|
||||
var blobData = 0;
|
||||
var totalLength = 0;
|
||||
blobData = node6plus ? Buffer.alloc(0) : new Buffer(0);
|
||||
|
||||
lob.on('data', function(chunk) {
|
||||
totalLength = totalLength + chunk.length;
|
||||
blobData = Buffer.concat([blobData, chunk], totalLength);
|
||||
});
|
||||
|
||||
lob.on('error', function(err) {
|
||||
should.not.exist(err, "lob.on 'error' event.");
|
||||
});
|
||||
|
||||
lob.on('end', function() {
|
||||
fs.readFile( jpgFileName, function(err, originalData) {
|
||||
should.not.exist(err);
|
||||
should.strictEqual(totalLength, originalData.length);
|
||||
originalData.should.eql(blobData);
|
||||
return callback();
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
var verifyBlobValueWithBuffer = function(selectSql, oraginalBuffer, specialStr, callback) {
|
||||
connection.execute(
|
||||
selectSql,
|
||||
function(err, result) {
|
||||
should.not.exist(err);
|
||||
var lob = result.rows[0][0];
|
||||
if (oraginalBuffer == null | oraginalBuffer == '' || oraginalBuffer == undefined) {
|
||||
should.not.exist(lob);
|
||||
return callback();
|
||||
} else {
|
||||
should.exist(lob);
|
||||
var blobData = node6plus ? Buffer.alloc(0) : new Buffer(0);
|
||||
var totalLength = 0;
|
||||
|
||||
lob.on('data', function(chunk) {
|
||||
totalLength = totalLength + chunk.length;
|
||||
blobData = Buffer.concat([blobData, chunk], totalLength);
|
||||
});
|
||||
|
||||
lob.on('error', function(err) {
|
||||
should.not.exist(err, "lob.on 'error' event.");
|
||||
});
|
||||
|
||||
lob.on('end', function() {
|
||||
should.strictEqual(totalLength, oraginalBuffer.length);
|
||||
var specStrLength = specialStr.length;
|
||||
should.strictEqual(blobData.toString('utf8', 0, specStrLength), specialStr);
|
||||
should.strictEqual(blobData.toString('utf8', (totalLength - specStrLength), totalLength), specialStr);
|
||||
return callback();
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
describe('80.1 Multiple LOBs, BIND_IN', function() {
|
||||
var proc = "CREATE OR REPLACE PROCEDURE nodb_lobs_in_781 (id IN NUMBER, clob_in IN CLOB, blob_in IN BLOB)\n" +
|
||||
"AS \n" +
|
||||
"BEGIN \n" +
|
||||
" insert into nodb_tab_lobs_in (id, clob, blob) values (id, clob_in, blob_in); \n" +
|
||||
"END nodb_lobs_in_781; ";
|
||||
var sqlRun = "BEGIN nodb_lobs_in_781 (:i, :c, :b); END;";
|
||||
var proc_drop = "DROP PROCEDURE nodb_lobs_in_781";
|
||||
|
||||
before(function(done) {
|
||||
executeSQL(proc, done);
|
||||
}); // before
|
||||
|
||||
after(function(done) {
|
||||
executeSQL(proc_drop, done);
|
||||
}); // after
|
||||
|
||||
it('80.1.1 PLSQL, CLOB&BLOB, bind a string and a buffer', function(done) {
|
||||
var specialStr = "80.1.1";
|
||||
var length = 50000;
|
||||
var bigStr = random.getRandomString(length, specialStr);
|
||||
var bigBuffer = node6plus ? Buffer.from(bigStr, "utf-8") : new Buffer(bigStr, "utf-8");
|
||||
var sequence = 700;
|
||||
var bindVar = {
|
||||
i: { val: sequence, type: oracledb.NUMBER, dir: oracledb.BIND_IN },
|
||||
c: { val: bigStr, type: oracledb.STRING, dir: oracledb.BIND_IN, maxSize: length },
|
||||
b: { val: bigBuffer, type: oracledb.BUFFER, dir: oracledb.BIND_IN, maxSize: length }
|
||||
};
|
||||
|
||||
async.series([
|
||||
function(cb) {
|
||||
connection.execute(
|
||||
sqlRun,
|
||||
bindVar,
|
||||
{ autoCommit: true },
|
||||
function(err) {
|
||||
should.not.exist(err);
|
||||
cb();
|
||||
}
|
||||
);
|
||||
},
|
||||
function(cb) {
|
||||
var sql_1 = "select clob from nodb_tab_lobs_in where id = " + sequence;
|
||||
verifyClobValueWithString(sql_1, bigStr, specialStr, cb);
|
||||
},
|
||||
function(cb) {
|
||||
var sql_2 = "select blob from nodb_tab_lobs_in where id = " + sequence;
|
||||
verifyBlobValueWithBuffer(sql_2, bigBuffer, specialStr, cb);
|
||||
}
|
||||
], done);
|
||||
}); // 80.1.1
|
||||
|
||||
it('80.1.2 PLSQL, CLOB&BLOB, bind a string and a JPG file', function(done) {
|
||||
var preparedCLOBID = 701;
|
||||
var sequence = 2;
|
||||
var size = 40000;
|
||||
var specialStr = "80.1.2";
|
||||
var bigStr = random.getRandomString(size, specialStr);
|
||||
|
||||
async.series([
|
||||
function(cb) {
|
||||
var sql = "INSERT INTO nodb_tab_lobs_in (id, blob) VALUES (:i, EMPTY_BLOB()) RETURNING blob INTO :lobbv";
|
||||
prepareTableWithBlob(sql, preparedCLOBID, cb);
|
||||
},
|
||||
function(cb) {
|
||||
connection.execute(
|
||||
"select blob from nodb_tab_lobs_in where id = :id",
|
||||
{ id: preparedCLOBID },
|
||||
function(err, result) {
|
||||
should.not.exist(err);
|
||||
(result.rows.length).should.not.eql(0);
|
||||
var blob = result.rows[0][0];
|
||||
|
||||
connection.execute(
|
||||
sqlRun,
|
||||
{
|
||||
i: { val: sequence, type: oracledb.NUMBER, dir: oracledb.BIND_IN },
|
||||
c: { val: bigStr, type: oracledb.STRING, dir: oracledb.BIND_IN, maxSize: size },
|
||||
b: { val: blob, type: oracledb.BLOB, dir: oracledb.BIND_IN }
|
||||
},
|
||||
{ autoCommit: true },
|
||||
function(err) {
|
||||
should.not.exist(err);
|
||||
cb();
|
||||
});
|
||||
});
|
||||
},
|
||||
function(cb) {
|
||||
var sql_1 = "select clob from nodb_tab_lobs_in where id = " + sequence;
|
||||
verifyClobValueWithString(sql_1, bigStr, specialStr, cb);
|
||||
},
|
||||
function(cb) {
|
||||
var sql_2 = "select blob from nodb_tab_lobs_in where id = " + sequence;
|
||||
verifyBlobValueWithFileData(sql_2, cb);
|
||||
}
|
||||
], done);
|
||||
}); // 80.1.2
|
||||
|
||||
it('80.1.3 PLSQL, CLOB&BLOB, bind a txt file and a Buffer', function(done) {
|
||||
var preparedCLOBID = 200;
|
||||
var sequence = 303;
|
||||
var size = 40000;
|
||||
var specialStr = "80.1.3";
|
||||
var bigStr = random.getRandomString(size, specialStr);
|
||||
var bigBuffer = node6plus ? Buffer.from(bigStr, "utf-8") : new Buffer(bigStr, "utf-8");
|
||||
|
||||
async.series([
|
||||
function(cb) {
|
||||
var sql = "INSERT INTO nodb_tab_lobs_in (id, clob) VALUES (:i, EMPTY_CLOB()) RETURNING clob INTO :lobbv";
|
||||
prepareTableWithClob(sql, preparedCLOBID, cb);
|
||||
},
|
||||
function(cb) {
|
||||
connection.execute(
|
||||
"select clob from nodb_tab_lobs_in where id = :id",
|
||||
{ id: preparedCLOBID },
|
||||
function(err, result) {
|
||||
should.not.exist(err);
|
||||
(result.rows.length).should.not.eql(0);
|
||||
var clob = result.rows[0][0];
|
||||
|
||||
connection.execute(
|
||||
sqlRun,
|
||||
{
|
||||
i: { val: sequence, type: oracledb.NUMBER, dir: oracledb.BIND_IN },
|
||||
c: { val: clob, type: oracledb.CLOB, dir: oracledb.BIND_IN },
|
||||
b: { val: bigBuffer, type: oracledb.BUFFER, dir: oracledb.BIND_IN }
|
||||
},
|
||||
{ autoCommit: true },
|
||||
function(err) {
|
||||
should.not.exist(err);
|
||||
cb();
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
},
|
||||
function(cb) {
|
||||
var sql_1 = "select clob from nodb_tab_lobs_in where id = " + sequence;
|
||||
verifyClobValueWithFileData(sql_1, cb);
|
||||
},
|
||||
function(cb) {
|
||||
var sql_2 = "select blob from nodb_tab_lobs_in where id = " + sequence;
|
||||
verifyBlobValueWithBuffer(sql_2, bigBuffer, specialStr,cb);
|
||||
}
|
||||
], done);
|
||||
}); // 80.1.3
|
||||
|
||||
}); // 80.1
|
||||
|
||||
describe('80.2 Multiple LOBs, BIND_OUT', function() {
|
||||
var proc = "CREATE OR REPLACE PROCEDURE nodb_lobs_out_782 (lob_id IN NUMBER, clob OUT CLOB, blob OUT BLOB) \n" +
|
||||
"AS \n" +
|
||||
"BEGIN \n" +
|
||||
" select clob, blob into clob, blob from nodb_tab_lobs_in where id = lob_id; \n" +
|
||||
"END nodb_lobs_out_782; ";
|
||||
var sqlRun = "BEGIN nodb_lobs_out_782 (:i, :c, :b); END;";
|
||||
var proc_drop = "DROP PROCEDURE nodb_lobs_out_782";
|
||||
|
||||
before(function(done) {
|
||||
executeSQL(proc, done);
|
||||
}); // before
|
||||
|
||||
after(function(done) {
|
||||
executeSQL(proc_drop, done);
|
||||
}); // after
|
||||
|
||||
var insertLobs = function(id, insertStr1, insertStr2, callback) {
|
||||
var sql = "INSERT INTO nodb_tab_lobs_in (id, clob, blob) VALUES (:i, :c, :b)";
|
||||
var bindVar = {
|
||||
i: { val: id, dir: oracledb.BIND_IN, type: oracledb.NUMBER },
|
||||
c: { val: insertStr1, dir: oracledb.BIND_IN, type: oracledb.STRING },
|
||||
b: { val: insertStr2, dir: oracledb.BIND_IN, type: oracledb.BUFFER }
|
||||
};
|
||||
|
||||
connection.execute(
|
||||
sql,
|
||||
bindVar,
|
||||
function(err, result) {
|
||||
should.not.exist(err);
|
||||
should.strictEqual(result.rowsAffected, 1);
|
||||
callback();
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
it('80.2.1 PLSQL, CLOB&BLOB, bind a string and a buffer', function(done) {
|
||||
var length = 50000;
|
||||
var specialStr = "80.2.1";
|
||||
var sequence = 311;
|
||||
var bigStr = random.getRandomString(length, specialStr);
|
||||
var bigBuffer = node6plus ? Buffer.from(bigStr, "utf-8") : new Buffer(bigStr, "utf-8");
|
||||
var bindVar = {
|
||||
i: { val: sequence, type: oracledb.NUMBER, dir: oracledb.BIND_IN },
|
||||
c: { type: oracledb.STRING, dir: oracledb.BIND_OUT, maxSize: length },
|
||||
b: { type: oracledb.BUFFER, dir: oracledb.BIND_OUT, maxSize: length }
|
||||
};
|
||||
|
||||
async.series([
|
||||
function(cb) {
|
||||
insertLobs(sequence, bigStr, bigBuffer, cb);
|
||||
},
|
||||
function(cb) {
|
||||
var sql = "select clob from nodb_tab_lobs_in where id = " + sequence;
|
||||
verifyClobValueWithString(sql, bigStr, specialStr, cb);
|
||||
},
|
||||
function(cb) {
|
||||
var sql = "select blob from nodb_tab_lobs_in where id = " + sequence;
|
||||
verifyBlobValueWithBuffer(sql, bigBuffer, specialStr, cb);
|
||||
},
|
||||
function(cb) {
|
||||
connection.execute(
|
||||
sqlRun,
|
||||
bindVar,
|
||||
function(err, result) {
|
||||
should.not.exist(err);
|
||||
var specStrLength = specialStr.length;
|
||||
var resultLength1 = result.outBinds.c.length;
|
||||
should.strictEqual(resultLength1, length);
|
||||
should.strictEqual(result.outBinds.c.substring(0, specStrLength), specialStr);
|
||||
should.strictEqual(result.outBinds.c.substring(resultLength1 - specStrLength, resultLength1), specialStr);
|
||||
var resultLength2 = result.outBinds.b.length;
|
||||
should.strictEqual(resultLength2, length);
|
||||
should.strictEqual(result.outBinds.b.toString('utf8', 0, specStrLength), specialStr);
|
||||
should.strictEqual(result.outBinds.b.toString('utf8', (resultLength2 - specStrLength), resultLength2), specialStr);
|
||||
cb();
|
||||
});
|
||||
}
|
||||
], done);
|
||||
|
||||
}); // 80.2.1
|
||||
|
||||
it('80.2.2 PLSQL, CLOB&BLOB, bind a string and a JPG file', function(done) {
|
||||
var size = 40000;
|
||||
var specialStr = "80.2.2";
|
||||
var bigStr = random.getRandomString(size, specialStr);
|
||||
var sequence = 312;
|
||||
var bindVar = {
|
||||
i: { val: sequence, type: oracledb.NUMBER, dir: oracledb.BIND_IN },
|
||||
c: { type: oracledb.STRING, dir: oracledb.BIND_OUT, maxSize: size },
|
||||
b: { type: oracledb.BLOB, dir: oracledb.BIND_OUT }
|
||||
};
|
||||
|
||||
async.series([
|
||||
function(cb) {
|
||||
var sql = "INSERT INTO nodb_tab_lobs_in (id, blob) VALUES (:i, EMPTY_BLOB()) RETURNING blob INTO :lobbv";
|
||||
prepareTableWithBlob(sql, sequence, cb);
|
||||
},
|
||||
function(cb) {
|
||||
var sql = "select blob from nodb_tab_lobs_in where id = " + sequence;
|
||||
verifyBlobValueWithFileData(sql, cb);
|
||||
},
|
||||
function(cb) {
|
||||
var sql = "update nodb_tab_lobs_in set clob = :c where id = :i";
|
||||
var bindVar_1 = {
|
||||
i: { val: sequence, type: oracledb.NUMBER, dir: oracledb.BIND_IN },
|
||||
c: { val: bigStr, type: oracledb.STRING, dir: oracledb.BIND_IN, maxSize: size }
|
||||
};
|
||||
connection.execute(
|
||||
sql,
|
||||
bindVar_1,
|
||||
function(err, result) {
|
||||
should.not.exist(err);
|
||||
should.strictEqual(result.rowsAffected, 1);
|
||||
cb();
|
||||
});
|
||||
},
|
||||
function(cb) {
|
||||
var sql = "select clob from nodb_tab_lobs_in where id = " + sequence;
|
||||
verifyClobValueWithString(sql, bigStr, specialStr, cb);
|
||||
},
|
||||
function(cb) {
|
||||
connection.execute(
|
||||
sqlRun,
|
||||
bindVar,
|
||||
function(err, result) {
|
||||
should.not.exist(err);
|
||||
var resultLength = result.outBinds.c.length;
|
||||
var specStrLength = specialStr.length;
|
||||
should.strictEqual(resultLength, size);
|
||||
should.strictEqual(result.outBinds.c.substring(0, specStrLength), specialStr);
|
||||
should.strictEqual(result.outBinds.c.substring(resultLength - specStrLength, resultLength), specialStr);
|
||||
|
||||
var lob = result.outBinds.b;
|
||||
var blobData = node6plus ? Buffer.alloc(0) : new Buffer(0);
|
||||
var totalLength = 0;
|
||||
|
||||
lob.on('data', function(chunk) {
|
||||
totalLength = totalLength + chunk.length;
|
||||
blobData = Buffer.concat([blobData, chunk], totalLength);
|
||||
});
|
||||
|
||||
lob.on('error', function(err) {
|
||||
should.not.exist(err, "lob.on 'error' event.");
|
||||
});
|
||||
|
||||
lob.on('end', function() {
|
||||
fs.readFile( jpgFileName, function(err, originalData) {
|
||||
should.not.exist(err);
|
||||
should.strictEqual(totalLength, originalData.length);
|
||||
originalData.should.eql(blobData);
|
||||
cb();
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
], done);
|
||||
|
||||
}); // 80.2.2
|
||||
|
||||
it('80.2.3 PLSQL, CLOB&BLOB, bind a txt file and a buffer', function(done) {
|
||||
var size = 40000;
|
||||
var specialStr = "80.2.3";
|
||||
var bigStr = random.getRandomString(size, specialStr);
|
||||
var bigBuffer = node6plus ? Buffer.from(bigStr, "utf-8") : new Buffer(bigStr, "utf-8");
|
||||
var sequence = 313;
|
||||
var bindVar = {
|
||||
i: { val: sequence, type: oracledb.NUMBER, dir: oracledb.BIND_IN },
|
||||
c: { type: oracledb.CLOB, dir: oracledb.BIND_OUT },
|
||||
b: { type: oracledb.BUFFER, dir: oracledb.BIND_OUT, maxSize: size }
|
||||
};
|
||||
|
||||
async.series([
|
||||
function(cb) {
|
||||
var sql = "INSERT INTO nodb_tab_lobs_in (id, clob) VALUES (:i, EMPTY_CLOB()) RETURNING clob INTO :lobbv";
|
||||
prepareTableWithClob(sql, sequence, cb);
|
||||
},
|
||||
function(cb) {
|
||||
var sql = "select clob from nodb_tab_lobs_in where id = " + sequence;
|
||||
verifyClobValueWithFileData(sql, cb);
|
||||
},
|
||||
function(cb) {
|
||||
var sql = "UPDATE nodb_tab_lobs_in set blob = :b where id = :i";
|
||||
var bindVar_1 = {
|
||||
i: { val: sequence, type: oracledb.NUMBER, dir: oracledb.BIND_IN },
|
||||
b: { val: bigBuffer, type: oracledb.BUFFER, dir: oracledb.BIND_IN, maxSize: size }
|
||||
};
|
||||
connection.execute(
|
||||
sql,
|
||||
bindVar_1,
|
||||
function(err, result) {
|
||||
should.not.exist(err);
|
||||
should.strictEqual(result.rowsAffected, 1);
|
||||
cb();
|
||||
});
|
||||
},
|
||||
function(cb) {
|
||||
var sql = "select blob from nodb_tab_lobs_in where id = " + sequence;
|
||||
verifyBlobValueWithBuffer(sql, bigBuffer, specialStr, cb);
|
||||
},
|
||||
function(cb) {
|
||||
connection.execute(
|
||||
sqlRun,
|
||||
bindVar,
|
||||
function(err, result) {
|
||||
should.not.exist(err);
|
||||
var specStrLength = specialStr.length;
|
||||
var resultLength1 = result.outBinds.b.length;
|
||||
should.strictEqual(resultLength1, size);
|
||||
should.strictEqual(result.outBinds.b.toString('utf8', 0, specStrLength), specialStr);
|
||||
should.strictEqual(result.outBinds.b.toString('utf8', (resultLength1 - specStrLength), resultLength1), specialStr);
|
||||
var lob = result.outBinds.c;
|
||||
should.exist(lob);
|
||||
lob.setEncoding("utf8");
|
||||
var clobData = '';
|
||||
lob.on('data', function(chunk) {
|
||||
clobData += chunk;
|
||||
});
|
||||
|
||||
lob.on('error', function(err) {
|
||||
should.not.exist(err, "lob.on 'error' event.");
|
||||
});
|
||||
|
||||
lob.on('end', function() {
|
||||
fs.readFile( inFileName, { encoding: 'utf8' }, function(err, originalData) {
|
||||
should.not.exist(err);
|
||||
should.strictEqual(clobData, originalData);
|
||||
cb();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
], done);
|
||||
}); // 80.2.3
|
||||
|
||||
}); // 80.2
|
||||
|
||||
describe('80.3 Multiple LOBs, BIND_INOUT', function() {
|
||||
var lobs_proc_inout = "CREATE OR REPLACE PROCEDURE nodb_lobs_in_out_783 (clob IN OUT CLOB, blob IN OUT BLOB) \n" +
|
||||
"AS \n" +
|
||||
"BEGIN \n" +
|
||||
" clob := clob; \n" +
|
||||
" blob := blob; \n" +
|
||||
"END nodb_lobs_in_out_783;";
|
||||
var sqlRun = "begin nodb_lobs_in_out_783(:clob, :blob); end;";
|
||||
var proc_drop = "DROP PROCEDURE nodb_lobs_in_out_783";
|
||||
|
||||
before(function(done) {
|
||||
executeSQL(lobs_proc_inout, done);
|
||||
}); // before
|
||||
|
||||
after(function(done) {
|
||||
executeSQL(proc_drop, done);
|
||||
}); // after
|
||||
|
||||
it('80.3.1 PLSQL, BIND_INOUT, bind a 32K string and a 32K buffer', function(done) {
|
||||
var specialStr = "80.3.1";
|
||||
var size = 32768;
|
||||
var bigStr = random.getRandomString(size, specialStr);
|
||||
var bufferStr = node6plus ? Buffer.from(bigStr, "utf-8") : new Buffer(bigStr, "utf-8");
|
||||
var bindVar = {
|
||||
clob: { dir: oracledb.BIND_INOUT, type: oracledb.STRING, val: bigStr, maxSize: size },
|
||||
blob: { dir: oracledb.BIND_INOUT, type: oracledb.BUFFER, val: bufferStr, maxSize: size }
|
||||
};
|
||||
|
||||
async.series([
|
||||
function(cb) {
|
||||
connection.execute(
|
||||
sqlRun,
|
||||
bindVar,
|
||||
function(err, result) {
|
||||
should.not.exist(err);
|
||||
var specStrLength = specialStr.length;
|
||||
var resultLength1 = result.outBinds.clob.length;
|
||||
should.strictEqual(resultLength1, size);
|
||||
should.strictEqual(result.outBinds.clob.substring(0, specStrLength), specialStr);
|
||||
should.strictEqual(result.outBinds.clob.substring(resultLength1 - specStrLength, resultLength1), specialStr);
|
||||
var resultLength2 = result.outBinds.blob.length;
|
||||
should.strictEqual(resultLength2, size);
|
||||
should.strictEqual(result.outBinds.blob.toString('utf8', 0, specStrLength), specialStr);
|
||||
should.strictEqual(result.outBinds.blob.toString('utf8', (resultLength2 - specStrLength), resultLength2), specialStr);
|
||||
cb();
|
||||
}
|
||||
);
|
||||
}
|
||||
], done);
|
||||
}); // 80.3.1
|
||||
|
||||
it('80.3.2 PLSQL, BIND_INOUT, bind a (64K - 1) string and a (64K - 1) buffer', function(done) {
|
||||
var specialStr = "80.3.2";
|
||||
var size = 65535;
|
||||
var bigStr = random.getRandomString(size, specialStr);
|
||||
var bufferStr = node6plus ? Buffer.from(bigStr, "utf-8") : new Buffer(bigStr, "utf-8");
|
||||
var bindVar = {
|
||||
clob: { dir: oracledb.BIND_INOUT, type: oracledb.STRING, val: bigStr, maxSize: size },
|
||||
blob: { dir: oracledb.BIND_INOUT, type: oracledb.BUFFER, val: bufferStr, maxSize: size }
|
||||
};
|
||||
|
||||
async.series([
|
||||
function(cb) {
|
||||
connection.execute(
|
||||
sqlRun,
|
||||
bindVar,
|
||||
function(err, result) {
|
||||
should.not.exist(err);
|
||||
var specStrLength = specialStr.length;
|
||||
var resultLength1 = result.outBinds.clob.length;
|
||||
should.strictEqual(resultLength1, size);
|
||||
should.strictEqual(result.outBinds.clob.substring(0, specStrLength), specialStr);
|
||||
should.strictEqual(result.outBinds.clob.substring(resultLength1 - specStrLength, resultLength1), specialStr);
|
||||
var resultLength2 = result.outBinds.blob.length;
|
||||
should.strictEqual(resultLength2, size);
|
||||
should.strictEqual(result.outBinds.blob.toString('utf8', 0, specStrLength), specialStr);
|
||||
should.strictEqual(result.outBinds.blob.toString('utf8', (resultLength2 - specStrLength), resultLength2), specialStr);
|
||||
cb();
|
||||
}
|
||||
);
|
||||
}
|
||||
], done);
|
||||
}); // 80.3.2
|
||||
|
||||
}); // 80.3
|
||||
|
||||
});
|
|
@ -0,0 +1,478 @@
|
|||
/* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. */
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* You may not use the identified files except in compliance with the Apache
|
||||
* License, Version 2.0 (the "License.")
|
||||
*
|
||||
* You may obtain a copy of the License at
|
||||
* http://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.
|
||||
*
|
||||
* The node-oracledb test suite uses 'mocha', 'should' and 'async'.
|
||||
* See LICENSE.md for relevant licenses.
|
||||
*
|
||||
* NAME
|
||||
* 62. lobProperties1.js
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Testing getters and setters for LOB class.
|
||||
* This test aims to increase the code coverage rate.
|
||||
*
|
||||
* NUMBERING RULE
|
||||
* Test numbers follow this numbering rule:
|
||||
* 1 - 20 are reserved for basic functional tests
|
||||
* 21 - 50 are reserved for data type supporting tests
|
||||
* 51 onwards are for other tests
|
||||
*
|
||||
*****************************************************************************/
|
||||
'use strict';
|
||||
|
||||
var oracledb = require('oracledb');
|
||||
var fs = require('fs');
|
||||
var should = require('should');
|
||||
var async = require('async');
|
||||
var dbConfig = require('./dbconfig.js');
|
||||
|
||||
describe('62. lobProperties1.js', function() {
|
||||
|
||||
var tableName = "nodb_tab_mylobprops";
|
||||
var connection = null;
|
||||
var sqlSelect = "SELECT * FROM " + tableName + " WHERE id = :i";
|
||||
var defaultChunkSize = null;
|
||||
|
||||
before('prepare table and LOB data', function(done) {
|
||||
|
||||
var sqlCreateTab =
|
||||
" BEGIN "
|
||||
+ " DECLARE "
|
||||
+ " e_table_missing EXCEPTION; "
|
||||
+ " PRAGMA EXCEPTION_INIT(e_table_missing, -00942); "
|
||||
+ " BEGIN "
|
||||
+ " EXECUTE IMMEDIATE ('DROP TABLE " + tableName + " PURGE'); "
|
||||
+ " EXCEPTION "
|
||||
+ " WHEN e_table_missing "
|
||||
+ " THEN NULL; "
|
||||
+ " END; "
|
||||
+ " EXECUTE IMMEDIATE (' "
|
||||
+ " CREATE TABLE " + tableName + " ( "
|
||||
+ " id NUMBER, c CLOB, b BLOB "
|
||||
+ " ) "
|
||||
+ " '); "
|
||||
+ " END; ";
|
||||
|
||||
var sqlInsert = "INSERT INTO " + tableName + " VALUES (:i, EMPTY_CLOB(), EMPTY_BLOB()) "
|
||||
+ " RETURNING c, b INTO :clob, :blob";
|
||||
|
||||
var bindVar =
|
||||
{
|
||||
i: 1,
|
||||
clob: { type: oracledb.CLOB, dir: oracledb.BIND_OUT },
|
||||
blob: { type: oracledb.BLOB, dir: oracledb.BIND_OUT }
|
||||
};
|
||||
var clobFileName = './test/clobexample.txt';
|
||||
var blobFileName = './test/fuzzydinosaur.jpg';
|
||||
|
||||
async.series([
|
||||
function(cb) {
|
||||
oracledb.getConnection(
|
||||
{
|
||||
user: dbConfig.user,
|
||||
password: dbConfig.password,
|
||||
connectString: dbConfig.connectString
|
||||
},
|
||||
function(err, conn) {
|
||||
should.not.exist(err);
|
||||
connection = conn;
|
||||
cb();
|
||||
}
|
||||
);
|
||||
},
|
||||
function(cb) {
|
||||
connection.execute(
|
||||
sqlCreateTab,
|
||||
function(err) {
|
||||
should.not.exist(err);
|
||||
cb();
|
||||
}
|
||||
);
|
||||
},
|
||||
function insertLobData(cb) {
|
||||
connection.execute(
|
||||
sqlInsert,
|
||||
bindVar,
|
||||
function(err, result) {
|
||||
should.not.exist(err);
|
||||
|
||||
var clob = result.outBinds.clob[0];
|
||||
var blob = result.outBinds.blob[0];
|
||||
var clobStream = fs.createReadStream(clobFileName);
|
||||
var blobStream = fs.createReadStream(blobFileName);
|
||||
|
||||
clobStream.on('error', function(err) {
|
||||
should.not.exist(err);
|
||||
});
|
||||
|
||||
blobStream.on('error', function(err) {
|
||||
should.not.exist(err);
|
||||
});
|
||||
|
||||
clob.on('error', function(err) {
|
||||
should.not.exist(err);
|
||||
});
|
||||
|
||||
blob.on('error', function(err) {
|
||||
should.not.exist(err);
|
||||
});
|
||||
|
||||
async.parallel([
|
||||
function(callback) {
|
||||
clob.on('finish', function() {
|
||||
callback();
|
||||
});
|
||||
},
|
||||
function(callback) {
|
||||
blob.on('finish', function() {
|
||||
callback();
|
||||
});
|
||||
}
|
||||
], function() {
|
||||
connection.commit( function(err) {
|
||||
should.not.exist(err);
|
||||
cb();
|
||||
});
|
||||
});
|
||||
|
||||
clobStream.pipe(clob);
|
||||
blobStream.pipe(blob);
|
||||
}
|
||||
);
|
||||
},
|
||||
function saveDefaultChunkSize(cb) {
|
||||
connection.execute(
|
||||
sqlSelect,
|
||||
{ i: 1 },
|
||||
function(err, result) {
|
||||
should.not.exist(err);
|
||||
var clob = result.rows[0][1];
|
||||
|
||||
defaultChunkSize = clob.chunkSize;
|
||||
cb();
|
||||
}
|
||||
);
|
||||
}
|
||||
], done);
|
||||
}); // before
|
||||
|
||||
after(function(done) {
|
||||
|
||||
async.series([
|
||||
function(cb) {
|
||||
connection.execute(
|
||||
"DROP TABLE " + tableName + " PURGE",
|
||||
function(err) {
|
||||
should.not.exist(err);
|
||||
cb();
|
||||
}
|
||||
);
|
||||
},
|
||||
function(cb) {
|
||||
connection.release( function(err) {
|
||||
should.not.exist(err);
|
||||
cb();
|
||||
});
|
||||
}
|
||||
], done);
|
||||
}); // after
|
||||
|
||||
it('62.1 chunkSize (read-only)', function(done) {
|
||||
connection.execute(
|
||||
sqlSelect,
|
||||
{ i: 1 },
|
||||
function(err, result) {
|
||||
should.not.exist(err);
|
||||
var clob = result.rows[0][1],
|
||||
blob = result.rows[0][2];
|
||||
|
||||
var t1 = clob.chunkSize,
|
||||
t2 = blob.chunkSize;
|
||||
|
||||
t1.should.be.a.Number();
|
||||
t2.should.be.a.Number();
|
||||
t1.should.eql(t2);
|
||||
defaultChunkSize = clob.chunkSize;
|
||||
|
||||
try {
|
||||
clob.chunkSize = t1 + 1;
|
||||
} catch(err) {
|
||||
should.exist(err);
|
||||
// console.log(err.message);
|
||||
// Cannot assign to read only property 'chunkSize' of #<Lob>
|
||||
}
|
||||
|
||||
try {
|
||||
blob.chunkSize = t2 + 1;
|
||||
} catch(err) {
|
||||
should.exist(err);
|
||||
// console.log(err.message);
|
||||
// Cannot assign to read only property 'chunkSize' of #<Lob>
|
||||
}
|
||||
done();
|
||||
}
|
||||
);
|
||||
}); // 62.1
|
||||
|
||||
it('62.2 length (read-only)', function(done) {
|
||||
connection.execute(
|
||||
sqlSelect,
|
||||
{ i: 1 },
|
||||
function(err, result) {
|
||||
should.not.exist(err);
|
||||
var clob = result.rows[0][1],
|
||||
blob = result.rows[0][2];
|
||||
|
||||
var t1 = clob.length,
|
||||
t2 = blob.length;
|
||||
|
||||
t1.should.be.a.Number();
|
||||
t2.should.be.a.Number();
|
||||
t1.should.not.eql(t2);
|
||||
|
||||
try {
|
||||
clob.length = t1 + 1;
|
||||
} catch(err) {
|
||||
should.exist(err);
|
||||
//console.log(err.message);
|
||||
// Cannot set property length of #<Lob> which has only a getter
|
||||
}
|
||||
|
||||
try {
|
||||
blob.length = t2 + 1;
|
||||
} catch(err) {
|
||||
should.exist(err);
|
||||
//console.log(err.message);
|
||||
// Cannot set property length of #<Lob> which has only a getter
|
||||
}
|
||||
done();
|
||||
}
|
||||
);
|
||||
}); // 62.2
|
||||
|
||||
it('62.3 pieceSize -default value is chunkSize', function(done) {
|
||||
connection.execute(
|
||||
sqlSelect,
|
||||
{ i: 1 },
|
||||
function(err, result) {
|
||||
should.not.exist(err);
|
||||
var clob = result.rows[0][1],
|
||||
blob = result.rows[0][2];
|
||||
|
||||
var t1 = clob.pieceSize,
|
||||
t2 = blob.pieceSize;
|
||||
t1.should.eql(defaultChunkSize);
|
||||
t2.should.eql(defaultChunkSize);
|
||||
done();
|
||||
}
|
||||
);
|
||||
}); // 62.3
|
||||
|
||||
it('62.4 pieceSize - can be increased', function(done) {
|
||||
connection.execute(
|
||||
sqlSelect,
|
||||
{ i: 1 },
|
||||
function(err, result) {
|
||||
should.not.exist(err);
|
||||
var clob = result.rows[0][1],
|
||||
blob = result.rows[0][2];
|
||||
|
||||
var newValue = clob.pieceSize * 5;
|
||||
|
||||
clob.pieceSize = clob.pieceSize * 5;
|
||||
blob.pieceSize = blob.pieceSize * 5;
|
||||
|
||||
(clob.pieceSize).should.eql(newValue);
|
||||
(blob.pieceSize).should.eql(newValue);
|
||||
|
||||
// Remember to restore the value
|
||||
clob.pieceSize = defaultChunkSize;
|
||||
blob.pieceSize = defaultChunkSize;
|
||||
|
||||
done();
|
||||
}
|
||||
);
|
||||
}); // 62.4
|
||||
|
||||
it('62.5 pieceSize - can be decreased', function(done) {
|
||||
if (defaultChunkSize <= 500) {
|
||||
console.log('As default chunkSize is too small, this case is not applicable');
|
||||
done();
|
||||
} else {
|
||||
connection.execute(
|
||||
sqlSelect,
|
||||
{ i: 1 },
|
||||
function(err, result) {
|
||||
should.not.exist(err);
|
||||
var clob = result.rows[0][1],
|
||||
blob = result.rows[0][2];
|
||||
|
||||
var newValue = clob.pieceSize - 500;
|
||||
|
||||
clob.pieceSize -= 500;
|
||||
blob.pieceSize -= 500;
|
||||
(clob.pieceSize).should.eql(newValue);
|
||||
(blob.pieceSize).should.eql(newValue);
|
||||
|
||||
// Restore
|
||||
clob.pieceSize = defaultChunkSize;
|
||||
blob.pieceSize = defaultChunkSize;
|
||||
|
||||
done();
|
||||
}
|
||||
);
|
||||
}
|
||||
}); // 62.5
|
||||
|
||||
it('62.6 pieceSize - can be zero', function(done) {
|
||||
connection.execute(
|
||||
sqlSelect,
|
||||
{ i: 1 },
|
||||
function(err, result) {
|
||||
should.not.exist(err);
|
||||
var clob = result.rows[0][1],
|
||||
blob = result.rows[0][2];
|
||||
|
||||
clob.pieceSize = 0;
|
||||
blob.pieceSize = 0;
|
||||
|
||||
(clob.pieceSize).should.eql(0);
|
||||
(blob.pieceSize).should.eql(0);
|
||||
|
||||
// Remember to restore the value
|
||||
clob.pieceSize = defaultChunkSize;
|
||||
blob.pieceSize = defaultChunkSize;
|
||||
|
||||
done();
|
||||
}
|
||||
);
|
||||
}); // 62.6
|
||||
|
||||
it('62.7 pieceSize - cannot be less than zero', function(done) {
|
||||
connection.execute(
|
||||
sqlSelect,
|
||||
{ i: 1 },
|
||||
function(err, result) {
|
||||
should.not.exist(err);
|
||||
var clob = result.rows[0][1],
|
||||
blob = result.rows[0][2];
|
||||
|
||||
try {
|
||||
clob.pieceSize = -100;
|
||||
} catch(err) {
|
||||
should.exist(err);
|
||||
(err.message).should.startWith('NJS-004:');
|
||||
// NJS-004: invalid value for property pieceSize
|
||||
}
|
||||
|
||||
// Remember to restore the value
|
||||
clob.pieceSize = defaultChunkSize;
|
||||
blob.pieceSize = defaultChunkSize;
|
||||
|
||||
done();
|
||||
}
|
||||
);
|
||||
}); // 62.7
|
||||
|
||||
it('62.8 pieceSize - cannot be null', function(done) {
|
||||
connection.execute(
|
||||
sqlSelect,
|
||||
{ i: 1 },
|
||||
function(err, result) {
|
||||
should.not.exist(err);
|
||||
var clob = result.rows[0][1],
|
||||
blob = result.rows[0][2];
|
||||
|
||||
try {
|
||||
clob.pieceSize = null;
|
||||
} catch(err) {
|
||||
should.exist(err);
|
||||
(err.message).should.startWith('NJS-004:');
|
||||
// NJS-004: invalid value for property pieceSize
|
||||
}
|
||||
|
||||
// Remember to restore the value
|
||||
clob.pieceSize = defaultChunkSize;
|
||||
blob.pieceSize = defaultChunkSize;
|
||||
|
||||
done();
|
||||
}
|
||||
);
|
||||
}); // 62.8
|
||||
|
||||
it('62.9 pieceSize - must be a number', function(done) {
|
||||
connection.execute(
|
||||
sqlSelect,
|
||||
{ i: 1 },
|
||||
function(err, result) {
|
||||
should.not.exist(err);
|
||||
var clob = result.rows[0][1],
|
||||
blob = result.rows[0][2];
|
||||
|
||||
try {
|
||||
clob.pieceSize = NaN;
|
||||
} catch(err) {
|
||||
should.exist(err);
|
||||
(err.message).should.startWith('NJS-004:');
|
||||
// NJS-004: invalid value for property pieceSize
|
||||
}
|
||||
|
||||
// Remember to restore the value
|
||||
clob.pieceSize = defaultChunkSize;
|
||||
blob.pieceSize = defaultChunkSize;
|
||||
|
||||
done();
|
||||
}
|
||||
);
|
||||
}); // 62.9
|
||||
|
||||
it('62.10 type (read-only)', function(done) {
|
||||
connection.execute(
|
||||
sqlSelect,
|
||||
{ i: 1 },
|
||||
function(err, result) {
|
||||
should.not.exist(err);
|
||||
var clob = result.rows[0][1],
|
||||
blob = result.rows[0][2];
|
||||
|
||||
var t1 = clob.type,
|
||||
t2 = blob.type;
|
||||
|
||||
t1.should.eql(oracledb.CLOB);
|
||||
t2.should.eql(oracledb.BLOB);
|
||||
|
||||
try {
|
||||
clob.type = t2;
|
||||
} catch(err) {
|
||||
should.exist(err);
|
||||
// console.log(err);
|
||||
// [TypeError: Cannot set property type of #<Lob> which has only a getter]
|
||||
}
|
||||
|
||||
try {
|
||||
blob.type = t1;
|
||||
} catch(err) {
|
||||
should.exist(err);
|
||||
// console.log(err);
|
||||
// [TypeError: Cannot set property type of #<Lob> which has only a getter]
|
||||
}
|
||||
|
||||
done();
|
||||
}
|
||||
);
|
||||
}); // 62.10
|
||||
});
|
|
@ -0,0 +1,294 @@
|
|||
/* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. */
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* You may not use the identified files except in compliance with the Apache
|
||||
* License, Version 2.0 (the "License.")
|
||||
*
|
||||
* You may obtain a copy of the License at
|
||||
* http://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.
|
||||
*
|
||||
* The node-oracledb test suite uses 'mocha', 'should' and 'async'.
|
||||
* See LICENSE.md for relevant licenses.
|
||||
*
|
||||
* NAME
|
||||
* 83. lobProperties2.js
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Testing the properties of LOB that created by createLob().
|
||||
*
|
||||
* NUMBERING RULE
|
||||
* Test numbers follow this numbering rule:
|
||||
* 1 - 20 are reserved for basic functional tests
|
||||
* 21 - 50 are reserved for data type supporting tests
|
||||
* 51 onwards are for other tests
|
||||
*
|
||||
*****************************************************************************/
|
||||
'use strict';
|
||||
|
||||
var oracledb = require('oracledb');
|
||||
var should = require('should');
|
||||
var async = require('async');
|
||||
var dbConfig = require('./dbconfig.js');
|
||||
|
||||
describe("83. lobProperties2.js", function() {
|
||||
|
||||
var connection;
|
||||
|
||||
before(function(done) {
|
||||
oracledb.getConnection(dbConfig, function(err, conn) {
|
||||
should.not.exist(err);
|
||||
connection = conn;
|
||||
done();
|
||||
});
|
||||
}); // before
|
||||
|
||||
after(function(done) {
|
||||
connection.close(function(err) {
|
||||
should.not.exist(err);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
var checkChunkSize = function(type, callback) {
|
||||
|
||||
connection.createLob(type, function(err, lob) {
|
||||
should.not.exist(err);
|
||||
|
||||
var t = lob.chunkSize;
|
||||
t.should.be.a.Number();
|
||||
|
||||
try {
|
||||
lob.chunkSize = t + 1;
|
||||
} catch(err) {
|
||||
should.exist(err);
|
||||
// Cannot assign to read only property 'chunkSize' of object '#<Lob>'
|
||||
}
|
||||
|
||||
lob.close(function(err) {
|
||||
should.not.exist(err);
|
||||
return callback();
|
||||
});
|
||||
|
||||
});
|
||||
}; // checkChunkSize
|
||||
|
||||
it("83.1 CLOB: chunkSize (read-only)", function(done) {
|
||||
checkChunkSize(oracledb.CLOB, done);
|
||||
});
|
||||
|
||||
it("83.2 BLOB: chunkSize (read-only)", function(done) {
|
||||
checkChunkSize(oracledb.BLOB, done);
|
||||
});
|
||||
|
||||
var checkLength = function(type, callback) {
|
||||
|
||||
connection.createLob(type, function(err, lob) {
|
||||
should.not.exist(err);
|
||||
|
||||
var t = lob.length;
|
||||
t.should.be.a.Number();
|
||||
|
||||
try {
|
||||
lob.length = t + 1;
|
||||
} catch(err) {
|
||||
should.exist(err);
|
||||
// Cannot set property length of #<Lob> which has only a getter
|
||||
}
|
||||
|
||||
lob.close(function(err) {
|
||||
should.not.exist(err);
|
||||
return callback();
|
||||
});
|
||||
});
|
||||
}; // checkLength
|
||||
|
||||
it("83.3 CLOB: length (read-only)", function(done) {
|
||||
checkLength(oracledb.CLOB, done);
|
||||
});
|
||||
|
||||
it("83.4 BLOB: length (read-only)", function(done) {
|
||||
checkLength(oracledb.BLOB, done);
|
||||
});
|
||||
|
||||
var checkType = function(lobtype, callback) {
|
||||
|
||||
connection.createLob(lobtype, function(err, lob) {
|
||||
should.not.exist(err);
|
||||
|
||||
var t = lob.type;
|
||||
t.should.eql(lobtype);
|
||||
|
||||
try {
|
||||
lob.type = oracledb.BUFFER;
|
||||
} catch(err) {
|
||||
should.exist(err);
|
||||
// Cannot set property type of #<Lob> which has only a getter
|
||||
}
|
||||
|
||||
lob.close(function(err) {
|
||||
should.not.exist(err);
|
||||
return callback();
|
||||
});
|
||||
});
|
||||
}; // checkType
|
||||
|
||||
it("83.5 CLOB: type (read-only)", function(done) {
|
||||
checkType(oracledb.CLOB, done);
|
||||
});
|
||||
|
||||
it("83.6 BLOB: type (read-only)", function(done) {
|
||||
checkType(oracledb.CLOB, done);
|
||||
});
|
||||
|
||||
describe("83.7 pieceSize", function() {
|
||||
|
||||
var defaultChunkSize;
|
||||
var clob, blob;
|
||||
|
||||
before("get the lobs", function(done) {
|
||||
async.parallel([
|
||||
function(cb) {
|
||||
connection.createLob(oracledb.CLOB, function(err, lob) {
|
||||
should.not.exist(err);
|
||||
|
||||
clob = lob;
|
||||
defaultChunkSize = clob.chunkSize;
|
||||
cb();
|
||||
});
|
||||
},
|
||||
function(cb) {
|
||||
connection.createLob(oracledb.BLOB, function(err, lob) {
|
||||
should.not.exist(err);
|
||||
|
||||
blob = lob;
|
||||
cb();
|
||||
});
|
||||
}
|
||||
], done);
|
||||
}); // before
|
||||
|
||||
after("close the lobs", function(done) {
|
||||
async.parallel([
|
||||
function(cb) {
|
||||
clob.close(cb);
|
||||
},
|
||||
function(cb) {
|
||||
blob.close(cb);
|
||||
}
|
||||
], done);
|
||||
}); // after
|
||||
|
||||
it("83.7.1 default value is chunkSize", function(done) {
|
||||
var t1 = clob.pieceSize,
|
||||
t2 = blob.pieceSize;
|
||||
|
||||
t1.should.eql(defaultChunkSize);
|
||||
t2.should.eql(defaultChunkSize);
|
||||
done();
|
||||
});
|
||||
|
||||
it("83.7.2 can be increased", function(done) {
|
||||
var newValue = clob.pieceSize * 5;
|
||||
|
||||
clob.pieceSize = clob.pieceSize * 5;
|
||||
blob.pieceSize = blob.pieceSize * 5;
|
||||
|
||||
(clob.pieceSize).should.eql(newValue);
|
||||
(blob.pieceSize).should.eql(newValue);
|
||||
|
||||
clob.pieceSize = defaultChunkSize;
|
||||
blob.pieceSize = defaultChunkSize;
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
it("83.7.3 can be decreased", function(done) {
|
||||
if (defaultChunkSize <= 500) {
|
||||
console.log('As default chunkSize is too small, this case is not applicable');
|
||||
} else {
|
||||
var newValue = clob.pieceSize - 500;
|
||||
|
||||
clob.pieceSize -= 500;
|
||||
blob.pieceSize -= 500;
|
||||
(clob.pieceSize).should.eql(newValue);
|
||||
(blob.pieceSize).should.eql(newValue);
|
||||
|
||||
// Restore
|
||||
clob.pieceSize = defaultChunkSize;
|
||||
blob.pieceSize = defaultChunkSize;
|
||||
}
|
||||
return done();
|
||||
});
|
||||
|
||||
it("83.7.4 can be zero", function(done) {
|
||||
clob.pieceSize = 0;
|
||||
blob.pieceSize = 0;
|
||||
|
||||
(clob.pieceSize).should.eql(0);
|
||||
(blob.pieceSize).should.eql(0);
|
||||
|
||||
// Remember to restore the value
|
||||
clob.pieceSize = defaultChunkSize;
|
||||
blob.pieceSize = defaultChunkSize;
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
it("83.7.5 cannot be less than zero", function(done) {
|
||||
try {
|
||||
clob.pieceSize = -100;
|
||||
} catch(err) {
|
||||
should.exist(err);
|
||||
(err.message).should.startWith('NJS-004:');
|
||||
// NJS-004: invalid value for property pieceSize
|
||||
}
|
||||
|
||||
// Remember to restore the value
|
||||
clob.pieceSize = defaultChunkSize;
|
||||
blob.pieceSize = defaultChunkSize;
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
it("83.7.6 cannot be null", function(done) {
|
||||
try {
|
||||
clob.pieceSize = null;
|
||||
} catch(err) {
|
||||
should.exist(err);
|
||||
(err.message).should.startWith('NJS-004:');
|
||||
// NJS-004: invalid value for property pieceSize
|
||||
}
|
||||
|
||||
// Remember to restore the value
|
||||
clob.pieceSize = defaultChunkSize;
|
||||
blob.pieceSize = defaultChunkSize;
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
it("83.7.7 must be a number", function(done) {
|
||||
try {
|
||||
clob.pieceSize = NaN;
|
||||
} catch(err) {
|
||||
should.exist(err);
|
||||
(err.message).should.startWith('NJS-004:');
|
||||
// NJS-004: invalid value for property pieceSize
|
||||
}
|
||||
|
||||
// Remember to restore the value
|
||||
clob.pieceSize = defaultChunkSize;
|
||||
blob.pieceSize = defaultChunkSize;
|
||||
|
||||
done();
|
||||
});
|
||||
}); // 83.7
|
||||
|
||||
});
|
|
@ -0,0 +1,249 @@
|
|||
/* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. */
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* You may not use the identified files except in compliance with the Apache
|
||||
* License, Version 2.0 (the "License.")
|
||||
*
|
||||
* You may obtain a copy of the License at
|
||||
* http://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.
|
||||
*
|
||||
* The node-oracledb test suite uses 'mocha', 'should' and 'async'.
|
||||
* See LICENSE.md for relevant licenses.
|
||||
*
|
||||
* NAME
|
||||
* 68. multipleLobInsertion.js
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Testing external authentication functionality.
|
||||
*
|
||||
* Note that enabling the externalAuth feature requires configuration on the
|
||||
* database besides setting "externalAuth" attribute to be true. Please refer
|
||||
* to api doc about the configuration.
|
||||
* https://github.com/oracle/node-oracledb/blob/master/doc/api.md#extauth
|
||||
*
|
||||
* NUMBERING RULE
|
||||
* Test numbers follow this numbering rule:
|
||||
* 1 - 20 are reserved for basic functional tests
|
||||
* 21 - 50 are reserved for data type supporting tests
|
||||
* 51 onwards are for other tests
|
||||
*
|
||||
*****************************************************************************/
|
||||
'use strict';
|
||||
|
||||
var oracledb = require('oracledb');
|
||||
var should = require('should');
|
||||
var async = require('async');
|
||||
var fs = require('fs');
|
||||
var dbConfig = require('./dbconfig.js');
|
||||
|
||||
describe('68. multipleLobInsertion.js', function() {
|
||||
|
||||
var connection = null;
|
||||
before(function(done) {
|
||||
|
||||
async.series([
|
||||
function getConn(cb) {
|
||||
oracledb.getConnection(
|
||||
dbConfig,
|
||||
function(err, conn) {
|
||||
should.not.exist(err);
|
||||
connection = conn;
|
||||
cb();
|
||||
}
|
||||
);
|
||||
},
|
||||
function createTabBLOB(cb) {
|
||||
var 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_multi_blob PURGE'); \n" +
|
||||
" EXCEPTION \n" +
|
||||
" WHEN e_table_missing \n" +
|
||||
" THEN NULL; \n" +
|
||||
" END; \n" +
|
||||
" EXECUTE IMMEDIATE (' \n" +
|
||||
" CREATE TABLE nodb_multi_blob ( \n" +
|
||||
" id NUMBER, \n" +
|
||||
" b1 BLOB, \n" +
|
||||
" b2 BLOB, \n" +
|
||||
" b3 BLOB, \n" +
|
||||
" b4 BLOB, \n" +
|
||||
" b5 BLOB \n" +
|
||||
" ) \n" +
|
||||
" '); \n" +
|
||||
"END; ";
|
||||
|
||||
connection.execute(
|
||||
proc,
|
||||
function(err) {
|
||||
should.not.exist(err);
|
||||
cb();
|
||||
}
|
||||
);
|
||||
},
|
||||
function createTabCLOB(cb) {
|
||||
var 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_multi_clob PURGE'); \n" +
|
||||
" EXCEPTION \n" +
|
||||
" WHEN e_table_missing \n" +
|
||||
" THEN NULL; \n" +
|
||||
" END; \n" +
|
||||
" EXECUTE IMMEDIATE (' \n" +
|
||||
" CREATE TABLE nodb_multi_clob ( \n" +
|
||||
" id NUMBER, \n" +
|
||||
" c1 CLOB, \n" +
|
||||
" c2 CLOB, \n" +
|
||||
" c3 CLOB, \n" +
|
||||
" c4 CLOB, \n" +
|
||||
" c5 CLOB \n" +
|
||||
" ) \n" +
|
||||
" '); \n" +
|
||||
"END; ";
|
||||
|
||||
connection.execute(
|
||||
proc,
|
||||
function(err) {
|
||||
should.not.exist(err);
|
||||
cb();
|
||||
}
|
||||
);
|
||||
}
|
||||
], done);
|
||||
|
||||
}); // before
|
||||
|
||||
after(function(done) {
|
||||
async.series([
|
||||
function(cb) {
|
||||
connection.execute(
|
||||
"DROP TABLE nodb_multi_clob PURGE",
|
||||
function(err) {
|
||||
should.not.exist(err);
|
||||
cb();
|
||||
}
|
||||
);
|
||||
},
|
||||
function(cb) {
|
||||
connection.execute(
|
||||
"DROP TABLE nodb_multi_blob PURGE",
|
||||
function(err) {
|
||||
should.not.exist(err);
|
||||
cb();
|
||||
}
|
||||
);
|
||||
},
|
||||
function(cb) {
|
||||
connection.release(function(err) {
|
||||
should.not.exist(err);
|
||||
cb();
|
||||
});
|
||||
}
|
||||
], done);
|
||||
}); // after
|
||||
|
||||
var lobInsert = function(sql, bindv, inFileName, cb) {
|
||||
|
||||
connection.execute(
|
||||
sql,
|
||||
bindv,
|
||||
{ autoCommit: false },
|
||||
function(err, result) {
|
||||
should.not.exist(err);
|
||||
|
||||
var lobArr = new Array();
|
||||
|
||||
// put lobbv1..5 to lobArr
|
||||
for(var item in result.outBinds) {
|
||||
lobArr.push(result.outBinds[item][0]);
|
||||
}
|
||||
|
||||
async.eachSeries(
|
||||
lobArr,
|
||||
function(lob, callback) {
|
||||
var inStream = fs.createReadStream(inFileName);
|
||||
|
||||
inStream.pipe(lob);
|
||||
|
||||
// one task completes
|
||||
lob.on('finish', function() {
|
||||
return callback();
|
||||
});
|
||||
|
||||
lob.on('error', function(err) {
|
||||
return callback(err);
|
||||
});
|
||||
|
||||
inStream.on('error', function(err) {
|
||||
return callback(err);
|
||||
});
|
||||
},
|
||||
function(err) {
|
||||
should.not.exist(err);
|
||||
|
||||
connection.commit(function(err) {
|
||||
should.not.exist(err);
|
||||
return cb();
|
||||
});
|
||||
}
|
||||
); // async.eachSeries
|
||||
|
||||
}
|
||||
);
|
||||
|
||||
};
|
||||
|
||||
it('68.1 inserts multiple BLOBs', function(done) {
|
||||
|
||||
var sql = "insert into nodb_multi_blob values(1, " +
|
||||
" EMPTY_BLOB(), EMPTY_BLOB(), EMPTY_BLOB(), EMPTY_BLOB(), EMPTY_BLOB() ) " +
|
||||
" returning b1, b2, b3, b4, b5 into :lobbv1, :lobbv2, :lobbv3, :lobbv4, :lobbv5";
|
||||
|
||||
var bindvars = {
|
||||
lobbv1: { type: oracledb.BLOB, dir: oracledb.BIND_OUT },
|
||||
lobbv2: { type: oracledb.BLOB, dir: oracledb.BIND_OUT },
|
||||
lobbv3: { type: oracledb.BLOB, dir: oracledb.BIND_OUT },
|
||||
lobbv4: { type: oracledb.BLOB, dir: oracledb.BIND_OUT },
|
||||
lobbv5: { type: oracledb.BLOB, dir: oracledb.BIND_OUT }
|
||||
};
|
||||
|
||||
var inFileName = './test/fuzzydinosaur.jpg';
|
||||
|
||||
lobInsert(sql, bindvars, inFileName, done);
|
||||
|
||||
}); // 68.1
|
||||
|
||||
it('68.2 inserts multiple CLOBs', function(done) {
|
||||
|
||||
var sql = "insert into nodb_multi_clob values(1, " +
|
||||
" EMPTY_CLOB(), EMPTY_CLOB(), EMPTY_CLOB(), EMPTY_CLOB(), EMPTY_CLOB() ) " +
|
||||
" returning c1, c2, c3, c4, c5 into :lobbv1, :lobbv2, :lobbv3, :lobbv4, :lobbv5";
|
||||
|
||||
var bindvars = {
|
||||
lobbv1: { type: oracledb.CLOB, dir: oracledb.BIND_OUT },
|
||||
lobbv2: { type: oracledb.CLOB, dir: oracledb.BIND_OUT },
|
||||
lobbv3: { type: oracledb.CLOB, dir: oracledb.BIND_OUT },
|
||||
lobbv4: { type: oracledb.CLOB, dir: oracledb.BIND_OUT },
|
||||
lobbv5: { type: oracledb.CLOB, dir: oracledb.BIND_OUT }
|
||||
};
|
||||
|
||||
var inFileName = './test/clobexample.txt';
|
||||
|
||||
lobInsert(sql, bindvars, inFileName, done);
|
||||
|
||||
});
|
||||
|
||||
});
|
|
@ -0,0 +1,128 @@
|
|||
--require should
|
||||
--require async
|
||||
--reporter spec
|
||||
--ui bdd
|
||||
--timeout 100000
|
||||
|
||||
test/connection.js
|
||||
test/pool.js
|
||||
test/examples.js
|
||||
test/binding.js
|
||||
test/externalAuth.js
|
||||
test/dmlReturning.js
|
||||
test/autoCommit.js
|
||||
test/autoCommitForSelect.js
|
||||
test/columnMetadata.js
|
||||
test/nullColumnValues.js
|
||||
|
||||
test/resultSet1.js
|
||||
test/stream1.js
|
||||
test/stream2.js
|
||||
test/resultsetToStream.js
|
||||
test/promises.js
|
||||
test/extendedMetaData.js
|
||||
test/constants.js
|
||||
test/fetchTimestampAsString.js
|
||||
test/dataTypeAssist.js
|
||||
test/dataTypeChar.js
|
||||
|
||||
test/dataTypeNchar.js
|
||||
test/dataTypeVarchar2.js
|
||||
test/dataTypeNvarchar2.js
|
||||
test/dataTypeNumber.js
|
||||
test/dataTypeNumber2.js
|
||||
test/dataTypeFloat.js
|
||||
test/dataTypeFloat2.js
|
||||
test/dataTypeBinaryFloat.js
|
||||
test/dataTypeBinaryDouble.js
|
||||
test/dataTypeDate.js
|
||||
|
||||
test/dataTypeTimestamp1.js
|
||||
test/dataTypeTimestamp2.js
|
||||
test/dataTypeTimestamp3.js
|
||||
test/dataTypeTimestamp4.js
|
||||
test/dataTypeTimestamp5.js
|
||||
test/dataTypeTimestamp6.js
|
||||
test/dataTypeRowid.js
|
||||
test/dataTypeClob.js
|
||||
test/dataTypeBlob.js
|
||||
test/dataTypeRaw.js
|
||||
|
||||
test/plsqlBindIndexedTable1.js
|
||||
test/plsqlBindIndexedTable2.js
|
||||
test/instanceof.js
|
||||
test/poolClose.js
|
||||
test/connClose.js
|
||||
test/resultSetClose.js
|
||||
test/resultSet2.js
|
||||
test/fetchAs.js
|
||||
test/nestedCursor.js
|
||||
|
||||
test/properties.js
|
||||
test/lobResultSet.js
|
||||
test/clobPlsqlString.js
|
||||
test/checkClassesTypes.js
|
||||
test/lobProperties1.js
|
||||
test/autoCommit4nestedExecutes.js
|
||||
test/sqlWithWarnings.js
|
||||
test/uninitializedLob.js
|
||||
test/writableProperties.js
|
||||
test/poolCache.js
|
||||
test/multipleLobInsertion.js
|
||||
test/driverName.js
|
||||
test/plsqlBindScalar.js
|
||||
test/lobBind1.js
|
||||
test/lobBind2.js
|
||||
test/poolPing.js
|
||||
test/clobPlsqlBindAsString_bindin.js
|
||||
test/clobPlsqlBindAsString_bindout.js
|
||||
test/clobPlsqlBindAsString_bindinout.js
|
||||
test/blobPlsqlBindAsBuffer_bindin.js
|
||||
test/blobPlsqlBindAsBuffer_bindout.js
|
||||
test/blobPlsqlBindAsBuffer_bindinout.js
|
||||
test/lobBindAsStringBuffer.js
|
||||
test/clobDMLBindAsString.js
|
||||
test/blobDMLBindAsBuffer.js
|
||||
test/lobProperties2.js
|
||||
test/fetchClobAsString1.js
|
||||
test/fetchClobAsString2.js
|
||||
test/fetchClobAsString3.js
|
||||
test/fetchBlobAsBuffer1.js
|
||||
test/fetchBlobAsBuffer2.js
|
||||
test/fetchBlobAsBuffer3.js
|
||||
test/fetchClobAsString4.js
|
||||
test/fetchBlobAsBuffer4.js
|
||||
test/binding_DMLInsert.js
|
||||
test/binding_procedureBindIn.js
|
||||
test/binding_procedureBindInout.js
|
||||
test/binding_functionBindInout.js
|
||||
test/binding_procedureBindOut.js
|
||||
test/binding_functionBindOut.js
|
||||
test/binding_DMLReturningInto.js
|
||||
test/binding_functionBindIn.js
|
||||
test/binding_defaultBindIn.js
|
||||
test/binding_defaultBindInout.js
|
||||
test/bindTimestamp.js
|
||||
test/dataTypeLong.js
|
||||
test/dataTypeLongRaw.js
|
||||
test/fetchRowidAsString.js
|
||||
test/rowidDMLBindAsString.js
|
||||
test/rowidProcedureBindAsString_bindin.js
|
||||
test/rowidFunctionBindAsString_bind.js
|
||||
test/rowidProcedureBindAsString_bindout.js
|
||||
test/rowidProcedureBindAsString_bindinout.js
|
||||
test/rowidFunctionBindAsString_bindinout.js
|
||||
test/dataTypeUrowid.js
|
||||
test/urowidDMLBindAsString.js
|
||||
test/urowidDMLBindAsString_indexed.js
|
||||
test/fetchUrowidAsString.js
|
||||
test/fetchUrowidAsString_indexed.js
|
||||
test/urowidProcedureBindAsString_bindin.js
|
||||
test/urowidProcedureBindAsString_bindout.js
|
||||
test/urowidProcedureBindAsString_bindinout.js
|
||||
test/urowidFunctionBindAsString_bind.js
|
||||
test/urowidFunctionBindAsString_bindinout.js
|
||||
test/dataTypeNclob.js
|
||||
test/nclobDMLBindAsString.js
|
||||
test/longDMLBind.js
|
||||
test/longrawDMLBind.js
|
|
@ -0,0 +1,68 @@
|
|||
/* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. */
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* You may not use the identified files except in compliance with the Apache
|
||||
* License, Version 2.0 (the "License.")
|
||||
*
|
||||
* You may obtain a copy of the License at
|
||||
* http://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
|
||||
* versions.js
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Shows the oracledb version attributes
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
var oracledb = require('oracledb');
|
||||
var dbConfig = require('../dbconfig.js');
|
||||
|
||||
var addonVer, clientVer, serverVer;
|
||||
var major, minor, update, port, portUpdate;
|
||||
|
||||
console.log("Node.js: " + process.version);
|
||||
|
||||
addonVer = oracledb.version;
|
||||
major = Math.floor(addonVer / 10000);
|
||||
minor = Math.floor(addonVer / 100) % 100;
|
||||
update = addonVer % 100;
|
||||
console.log("Node-oracledb: " + major + "." + minor + "." + update);
|
||||
|
||||
clientVer = oracledb.oracleClientVersion;
|
||||
major = Math.floor (clientVer / 100000000);
|
||||
minor = Math.floor (clientVer / 1000000) % 100 ;
|
||||
update = Math.floor (clientVer / 10000) % 100 ;
|
||||
port = Math.floor (clientVer / 100) % 100 ;
|
||||
portUpdate = clientVer % 100 ;
|
||||
console.log("Oracle Client library: " + major + "." + minor + "." + update + "." + port + "." + portUpdate);
|
||||
|
||||
oracledb.getConnection(
|
||||
{
|
||||
user : dbConfig.user,
|
||||
password : dbConfig.password,
|
||||
connectString : dbConfig.connectString
|
||||
},
|
||||
function(err, connection)
|
||||
{
|
||||
if (err) {
|
||||
console.error(err.message);
|
||||
return;
|
||||
}
|
||||
|
||||
serverVer = connection.oracleServerVersion;
|
||||
major = Math.floor (serverVer / 100000000);
|
||||
minor = Math.floor (serverVer / 1000000) % 100 ;
|
||||
update = Math.floor (serverVer / 10000) % 100 ;
|
||||
port = Math.floor (serverVer / 100) % 100 ;
|
||||
portUpdate = serverVer % 100 ;
|
||||
console.log("Oracle Database: " + major + "." + minor + "." + update + "." + port + "." + portUpdate + "\n");
|
||||
});
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,721 @@
|
|||
/* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. */
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* You may not use the identified files except in compliance with the Apache
|
||||
* License, Version 2.0 (the "License.")
|
||||
*
|
||||
* You may obtain a copy of the License at
|
||||
* http://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.
|
||||
*
|
||||
* The node-oracledb test suite uses 'mocha', 'should' and 'async'.
|
||||
* See LICENSE.md for relevant licenses.
|
||||
*
|
||||
* NAME
|
||||
* 44. plsqlBindIndexedTable2.js
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Testing PL/SQL indexed tables (associative arrays).
|
||||
*
|
||||
* NUMBERING RULE
|
||||
* Test numbers follow this numbering rule:
|
||||
* 1 - 20 are reserved for basic functional tests
|
||||
* 21 - 50 are reserved for data type supporting tests
|
||||
* 51 onwards are for other tests
|
||||
*
|
||||
*****************************************************************************/
|
||||
'use strict';
|
||||
|
||||
var oracledb = require('oracledb');
|
||||
var should = require('should');
|
||||
var async = require('async');
|
||||
var dbConfig = require('./dbconfig.js');
|
||||
|
||||
describe('44. plsqlBindIndexedTable2.js', function() {
|
||||
|
||||
var credentials = {
|
||||
user: dbConfig.user,
|
||||
password: dbConfig.password,
|
||||
connectString: dbConfig.connectString
|
||||
};
|
||||
|
||||
var connection = null;
|
||||
|
||||
beforeEach(function(done) {
|
||||
async.series([
|
||||
function(callback) {
|
||||
oracledb.getConnection(credentials, function(err, conn) {
|
||||
should.not.exist(err);
|
||||
connection = conn;
|
||||
callback();
|
||||
});
|
||||
},
|
||||
function createTab(callback) {
|
||||
var 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_waveheight PURGE'); \n" +
|
||||
" EXCEPTION \n" +
|
||||
" WHEN e_table_missing \n" +
|
||||
" THEN NULL; \n" +
|
||||
" END; \n" +
|
||||
" EXECUTE IMMEDIATE (' \n" +
|
||||
" CREATE TABLE nodb_waveheight (beach VARCHAR2(50), depth NUMBER) \n" +
|
||||
" '); \n" +
|
||||
"END; ";
|
||||
|
||||
connection.execute(
|
||||
proc,
|
||||
function(err) {
|
||||
should.not.exist(err);
|
||||
callback();
|
||||
}
|
||||
);
|
||||
|
||||
},
|
||||
function createPkg(callback) {
|
||||
var proc = "CREATE OR REPLACE PACKAGE nodb_beachpkg IS\n" +
|
||||
" TYPE beachType IS TABLE OF VARCHAR2(30) INDEX BY BINARY_INTEGER;\n" +
|
||||
" TYPE depthType IS TABLE OF NUMBER INDEX BY BINARY_INTEGER;\n" +
|
||||
" PROCEDURE array_in(beaches IN beachType, depths IN depthType);\n" +
|
||||
" PROCEDURE array_out(beaches OUT beachType, depths OUT depthType); \n" +
|
||||
" PROCEDURE array_inout(beaches IN OUT beachType, depths IN OUT depthType); \n" +
|
||||
"END;";
|
||||
|
||||
connection.execute(
|
||||
proc,
|
||||
function(err) {
|
||||
should.not.exist(err);
|
||||
callback();
|
||||
}
|
||||
);
|
||||
},
|
||||
function(callback) {
|
||||
var proc = "CREATE OR REPLACE PACKAGE BODY nodb_beachpkg IS \n" +
|
||||
" PROCEDURE array_in(beaches IN beachType, depths IN depthType) IS \n" +
|
||||
" BEGIN \n" +
|
||||
" IF beaches.COUNT <> depths.COUNT THEN \n" +
|
||||
" RAISE_APPLICATION_ERROR(-20000, 'Array lengths must match for this example.'); \n" +
|
||||
" END IF; \n" +
|
||||
" FORALL i IN INDICES OF beaches \n" +
|
||||
" INSERT INTO nodb_waveheight (beach, depth) VALUES (beaches(i), depths(i)); \n" +
|
||||
" END; \n" +
|
||||
" PROCEDURE array_out(beaches OUT beachType, depths OUT depthType) IS \n" +
|
||||
" BEGIN \n" +
|
||||
" SELECT beach, depth BULK COLLECT INTO beaches, depths FROM nodb_waveheight; \n" +
|
||||
" END; \n" +
|
||||
" PROCEDURE array_inout(beaches IN OUT beachType, depths IN OUT depthType) IS \n" +
|
||||
" BEGIN \n" +
|
||||
" IF beaches.COUNT <> depths.COUNT THEN \n" +
|
||||
" RAISE_APPLICATION_ERROR(-20001, 'Array lenghts must match for this example.'); \n" +
|
||||
" END IF; \n" +
|
||||
" FORALL i IN INDICES OF beaches \n" +
|
||||
" INSERT INTO nodb_waveheight (beach, depth) VALUES (beaches(i), depths(i)); \n" +
|
||||
" SELECT beach, depth BULK COLLECT INTO beaches, depths FROM nodb_waveheight ORDER BY 1; \n" +
|
||||
" END; \n " +
|
||||
"END;";
|
||||
|
||||
connection.execute(
|
||||
proc,
|
||||
function(err) {
|
||||
should.not.exist(err);
|
||||
callback();
|
||||
}
|
||||
);
|
||||
},
|
||||
function(callback) {
|
||||
connection.commit(function(err) {
|
||||
should.not.exist(err);
|
||||
callback();
|
||||
});
|
||||
}
|
||||
], done);
|
||||
}); // before
|
||||
|
||||
afterEach(function(done) {
|
||||
async.series([
|
||||
function(callback) {
|
||||
connection.execute(
|
||||
"DROP TABLE nodb_waveheight PURGE",
|
||||
function(err) {
|
||||
should.not.exist(err);
|
||||
callback();
|
||||
}
|
||||
);
|
||||
},
|
||||
function(callback) {
|
||||
connection.execute(
|
||||
"DROP PACKAGE nodb_beachpkg",
|
||||
function(err) {
|
||||
should.not.exist(err);
|
||||
callback();
|
||||
}
|
||||
);
|
||||
},
|
||||
function(callback) {
|
||||
connection.release(function(err) {
|
||||
should.not.exist(err);
|
||||
callback();
|
||||
});
|
||||
},
|
||||
], done);
|
||||
}); // after
|
||||
|
||||
it('44.1 example case', function(done) {
|
||||
async.series([
|
||||
// Pass arrays of values to a PL/SQL procedure
|
||||
function(callback) {
|
||||
connection.execute(
|
||||
"BEGIN nodb_beachpkg.array_in(:beach_in, :depth_in); END;",
|
||||
{
|
||||
beach_in: { type: oracledb.STRING,
|
||||
dir: oracledb.BIND_IN,
|
||||
val: ["Malibu Beach", "Bondi Beach", "Waikiki Beach"] },
|
||||
depth_in: { type: oracledb.NUMBER,
|
||||
dir: oracledb.BIND_IN,
|
||||
val: [45, 30, 67]
|
||||
}
|
||||
},
|
||||
function(err) {
|
||||
should.not.exist(err);
|
||||
callback();
|
||||
}
|
||||
);
|
||||
},
|
||||
// Fetch arrays of values from a PL/SQL procedure
|
||||
function(callback) {
|
||||
connection.execute(
|
||||
"BEGIN nodb_beachpkg.array_out(:beach_out, :depth_out); END;",
|
||||
{
|
||||
beach_out: { type: oracledb.STRING,
|
||||
dir: oracledb.BIND_OUT,
|
||||
maxArraySize: 3 },
|
||||
depth_out: { type: oracledb.NUMBER,
|
||||
dir: oracledb.BIND_OUT,
|
||||
maxArraySize: 3 }
|
||||
},
|
||||
function(err, result) {
|
||||
should.not.exist(err);
|
||||
// console.log(result.outBinds);
|
||||
(result.outBinds.beach_out).should.eql([ 'Malibu Beach', 'Bondi Beach', 'Waikiki Beach' ]);
|
||||
(result.outBinds.depth_out).should.eql([45, 30, 67]);
|
||||
callback();
|
||||
}
|
||||
);
|
||||
},
|
||||
function(callback) {
|
||||
connection.rollback(function(err) {
|
||||
should.not.exist(err);
|
||||
callback();
|
||||
});
|
||||
},
|
||||
// Return input arrays sorted by beach name
|
||||
function(callback) {
|
||||
connection.execute(
|
||||
"BEGIN nodb_beachpkg.array_inout(:beach_inout, :depth_inout); END;",
|
||||
{
|
||||
beach_inout: { type: oracledb.STRING,
|
||||
dir: oracledb.BIND_INOUT,
|
||||
val: ["Port Melbourne Beach", "Eighty Mile Beach", "Chesil Beach"],
|
||||
maxArraySize: 3},
|
||||
depth_inout: { type: oracledb.NUMBER,
|
||||
dir: oracledb.BIND_INOUT,
|
||||
val: [8, 3, 70],
|
||||
maxArraySize: 3}
|
||||
},
|
||||
function(err, result) {
|
||||
should.not.exist(err);
|
||||
//console.log(result.outBinds);
|
||||
(result.outBinds.beach_inout).should.eql([ 'Chesil Beach', 'Eighty Mile Beach', 'Port Melbourne Beach' ]);
|
||||
(result.outBinds.depth_inout).should.eql([ 70, 3, 8 ]);
|
||||
callback();
|
||||
}
|
||||
);
|
||||
}
|
||||
], done);
|
||||
}); // 44.1
|
||||
|
||||
it('44.2 example case binding by position', function(done) {
|
||||
async.series([
|
||||
// Pass arrays of values to a PL/SQL procedure
|
||||
function(callback) {
|
||||
connection.execute(
|
||||
"BEGIN nodb_beachpkg.array_in(:1, :2); END;",
|
||||
[
|
||||
{ type: oracledb.STRING,
|
||||
dir: oracledb.BIND_IN,
|
||||
val: ["Malibu Beach", "Bondi Beach", "Waikiki Beach"] },
|
||||
{ type: oracledb.NUMBER,
|
||||
dir: oracledb.BIND_IN,
|
||||
val: [45, 30, 67]
|
||||
}
|
||||
],
|
||||
function(err) {
|
||||
should.not.exist(err);
|
||||
callback();
|
||||
}
|
||||
);
|
||||
},
|
||||
// Fetch arrays of values from a PL/SQL procedure
|
||||
function(callback) {
|
||||
connection.execute(
|
||||
"BEGIN nodb_beachpkg.array_out(:1, :2); END;",
|
||||
[
|
||||
{ type: oracledb.STRING,
|
||||
dir: oracledb.BIND_OUT,
|
||||
maxArraySize: 3 },
|
||||
{ type: oracledb.NUMBER,
|
||||
dir: oracledb.BIND_OUT,
|
||||
maxArraySize: 3 }
|
||||
],
|
||||
function(err, result) {
|
||||
should.not.exist(err);
|
||||
// console.log(result.outBinds);
|
||||
(result.outBinds[0]).should.eql([ 'Malibu Beach', 'Bondi Beach', 'Waikiki Beach' ]);
|
||||
(result.outBinds[1]).should.eql([45, 30, 67]);
|
||||
callback();
|
||||
}
|
||||
);
|
||||
},
|
||||
function(callback) {
|
||||
connection.rollback(function(err) {
|
||||
should.not.exist(err);
|
||||
callback();
|
||||
});
|
||||
},
|
||||
// Return input arrays sorted by beach name
|
||||
function(callback) {
|
||||
connection.execute(
|
||||
"BEGIN nodb_beachpkg.array_inout(:1, :2); END;",
|
||||
[
|
||||
{ type: oracledb.STRING,
|
||||
dir: oracledb.BIND_INOUT,
|
||||
val: ["Port Melbourne Beach", "Eighty Mile Beach", "Chesil Beach"],
|
||||
maxArraySize: 3},
|
||||
{ type: oracledb.NUMBER,
|
||||
dir: oracledb.BIND_INOUT,
|
||||
val: [8, 3, 70],
|
||||
maxArraySize: 3}
|
||||
],
|
||||
function(err, result) {
|
||||
should.not.exist(err);
|
||||
// console.log(result.outBinds);
|
||||
(result.outBinds[0]).should.eql([ 'Chesil Beach', 'Eighty Mile Beach', 'Port Melbourne Beach' ]);
|
||||
(result.outBinds[1]).should.eql([ 70, 3, 8 ]);
|
||||
callback();
|
||||
}
|
||||
);
|
||||
}
|
||||
], done);
|
||||
});
|
||||
|
||||
it('44.3 default binding type and direction with binding by name', function(done) {
|
||||
async.series([
|
||||
// Pass arrays of values to a PL/SQL procedure
|
||||
function(callback) {
|
||||
connection.execute(
|
||||
"BEGIN nodb_beachpkg.array_in(:beach_in, :depth_in); END;",
|
||||
{
|
||||
beach_in: { //type: oracledb.STRING,
|
||||
//dir: oracledb.BIND_IN,
|
||||
val: ["Malibu Beach", "Bondi Beach", "Waikiki Beach"] },
|
||||
depth_in: { type: oracledb.NUMBER,
|
||||
dir: oracledb.BIND_IN,
|
||||
val: [45, 30, 67]
|
||||
}
|
||||
},
|
||||
function(err) {
|
||||
should.not.exist(err);
|
||||
callback();
|
||||
}
|
||||
);
|
||||
},
|
||||
// Fetch arrays of values from a PL/SQL procedure
|
||||
function(callback) {
|
||||
connection.execute(
|
||||
"BEGIN nodb_beachpkg.array_out(:beach_out, :depth_out); END;",
|
||||
{
|
||||
beach_out: { type: oracledb.STRING,
|
||||
dir: oracledb.BIND_OUT,
|
||||
maxArraySize: 3 },
|
||||
depth_out: { type: oracledb.NUMBER,
|
||||
dir: oracledb.BIND_OUT,
|
||||
maxArraySize: 3 }
|
||||
},
|
||||
function(err, result) {
|
||||
should.not.exist(err);
|
||||
// console.log(result.outBinds);
|
||||
(result.outBinds.beach_out).should.eql([ 'Malibu Beach', 'Bondi Beach', 'Waikiki Beach' ]);
|
||||
(result.outBinds.depth_out).should.eql([45, 30, 67]);
|
||||
callback();
|
||||
}
|
||||
);
|
||||
},
|
||||
function(callback) {
|
||||
connection.rollback(function(err) {
|
||||
should.not.exist(err);
|
||||
callback();
|
||||
});
|
||||
},
|
||||
// Return input arrays sorted by beach name
|
||||
function(callback) {
|
||||
connection.execute(
|
||||
"BEGIN nodb_beachpkg.array_inout(:beach_inout, :depth_inout); END;",
|
||||
{
|
||||
beach_inout: { type: oracledb.STRING,
|
||||
dir: oracledb.BIND_INOUT,
|
||||
val: ["Port Melbourne Beach", "Eighty Mile Beach", "Chesil Beach"],
|
||||
maxArraySize: 3},
|
||||
depth_inout: { type: oracledb.NUMBER,
|
||||
dir: oracledb.BIND_INOUT,
|
||||
val: [8, 3, 70],
|
||||
maxArraySize: 3}
|
||||
},
|
||||
function(err, result) {
|
||||
should.not.exist(err);
|
||||
//console.log(result.outBinds);
|
||||
(result.outBinds.beach_inout).should.eql([ 'Chesil Beach', 'Eighty Mile Beach', 'Port Melbourne Beach' ]);
|
||||
(result.outBinds.depth_inout).should.eql([ 70, 3, 8 ]);
|
||||
callback();
|
||||
}
|
||||
);
|
||||
}
|
||||
], done);
|
||||
}); // 44.3
|
||||
|
||||
it('44.4 default binding type and direction with binding by position', function(done) {
|
||||
async.series([
|
||||
// Pass arrays of values to a PL/SQL procedure
|
||||
function(callback) {
|
||||
connection.execute(
|
||||
"BEGIN nodb_beachpkg.array_in(:1, :2); END;",
|
||||
[
|
||||
{ type: oracledb.STRING,
|
||||
// dir: oracledb.BIND_IN,
|
||||
val: ["Malibu Beach", "Bondi Beach", "Waikiki Beach"] },
|
||||
{ type: oracledb.NUMBER,
|
||||
dir: oracledb.BIND_IN,
|
||||
val: [45, 30, 67]
|
||||
}
|
||||
],
|
||||
function(err) {
|
||||
should.not.exist(err);
|
||||
callback();
|
||||
}
|
||||
);
|
||||
},
|
||||
// Fetch arrays of values from a PL/SQL procedure
|
||||
function(callback) {
|
||||
connection.execute(
|
||||
"BEGIN nodb_beachpkg.array_out(:1, :2); END;",
|
||||
[
|
||||
{ type: oracledb.STRING,
|
||||
dir: oracledb.BIND_OUT,
|
||||
maxArraySize: 3 },
|
||||
{ type: oracledb.NUMBER,
|
||||
dir: oracledb.BIND_OUT,
|
||||
maxArraySize: 3 }
|
||||
],
|
||||
function(err, result) {
|
||||
should.not.exist(err);
|
||||
// console.log(result.outBinds);
|
||||
(result.outBinds[0]).should.eql([ 'Malibu Beach', 'Bondi Beach', 'Waikiki Beach' ]);
|
||||
(result.outBinds[1]).should.eql([45, 30, 67]);
|
||||
callback();
|
||||
}
|
||||
);
|
||||
},
|
||||
function(callback) {
|
||||
connection.rollback(function(err) {
|
||||
should.not.exist(err);
|
||||
callback();
|
||||
});
|
||||
},
|
||||
// Return input arrays sorted by beach name
|
||||
function(callback) {
|
||||
connection.execute(
|
||||
"BEGIN nodb_beachpkg.array_inout(:1, :2); END;",
|
||||
[
|
||||
{ type: oracledb.STRING,
|
||||
dir: oracledb.BIND_INOUT,
|
||||
val: ["Port Melbourne Beach", "Eighty Mile Beach", "Chesil Beach"],
|
||||
maxArraySize: 3},
|
||||
{ type: oracledb.NUMBER,
|
||||
dir: oracledb.BIND_INOUT,
|
||||
val: [8, 3, 70],
|
||||
maxArraySize: 3}
|
||||
],
|
||||
function(err, result) {
|
||||
should.not.exist(err);
|
||||
// console.log(result.outBinds);
|
||||
(result.outBinds[0]).should.eql([ 'Chesil Beach', 'Eighty Mile Beach', 'Port Melbourne Beach' ]);
|
||||
(result.outBinds[1]).should.eql([ 70, 3, 8 ]);
|
||||
callback();
|
||||
}
|
||||
);
|
||||
}
|
||||
], done);
|
||||
});
|
||||
|
||||
it('44.5 null elements in String and Number arrays', function(done) {
|
||||
async.series([
|
||||
// Pass arrays of values to a PL/SQL procedure
|
||||
function(callback) {
|
||||
connection.execute(
|
||||
"BEGIN nodb_beachpkg.array_in(:beach_in, :depth_in); END;",
|
||||
{
|
||||
beach_in: { type: oracledb.STRING,
|
||||
dir: oracledb.BIND_IN,
|
||||
val: ["Malibu Beach", "Bondi Beach", null, "Waikiki Beach", '', null] },
|
||||
depth_in: { type: oracledb.NUMBER,
|
||||
dir: oracledb.BIND_IN,
|
||||
val: [null, null, 45, 30, 67, null, ]
|
||||
}
|
||||
},
|
||||
function(err) {
|
||||
should.not.exist(err);
|
||||
callback();
|
||||
}
|
||||
);
|
||||
},
|
||||
// Fetch arrays of values from a PL/SQL procedure
|
||||
function(callback) {
|
||||
connection.execute(
|
||||
"BEGIN nodb_beachpkg.array_out(:beach_out, :depth_out); END;",
|
||||
{
|
||||
beach_out: { type: oracledb.STRING,
|
||||
dir: oracledb.BIND_OUT,
|
||||
maxArraySize: 10 },
|
||||
depth_out: { type: oracledb.NUMBER,
|
||||
dir: oracledb.BIND_OUT,
|
||||
maxArraySize: 10 }
|
||||
},
|
||||
function(err, result) {
|
||||
should.not.exist(err);
|
||||
// console.log(result.outBinds);
|
||||
(result.outBinds.beach_out).should.eql([ 'Malibu Beach', 'Bondi Beach', null, 'Waikiki Beach', null, null ]);
|
||||
(result.outBinds.depth_out).should.eql([ null, null, 45, 30, 67, null ]);
|
||||
callback();
|
||||
}
|
||||
);
|
||||
},
|
||||
function(callback) {
|
||||
connection.rollback(function(err) {
|
||||
should.not.exist(err);
|
||||
callback();
|
||||
});
|
||||
},
|
||||
// Return input arrays sorted by beach name
|
||||
function(callback) {
|
||||
connection.execute(
|
||||
"BEGIN nodb_beachpkg.array_inout(:beach_inout, :depth_inout); END;",
|
||||
{
|
||||
beach_inout: { type: oracledb.STRING,
|
||||
dir: oracledb.BIND_INOUT,
|
||||
val: ["Port Melbourne Beach", "Eighty Mile Beach", '', "Chesil Beach", null, ''],
|
||||
maxArraySize: 10},
|
||||
depth_inout: { type: oracledb.NUMBER,
|
||||
dir: oracledb.BIND_INOUT,
|
||||
val: [null, 8, null, 3, null, 70],
|
||||
maxArraySize: 10}
|
||||
},
|
||||
function(err, result) {
|
||||
should.not.exist(err);
|
||||
// console.log(result.outBinds);
|
||||
(result.outBinds.beach_inout).should.eql([ 'Chesil Beach', 'Eighty Mile Beach', 'Port Melbourne Beach', null, null, null ]);
|
||||
(result.outBinds.depth_inout).should.eql([ 3, 8, null, null, 70, null ]);
|
||||
callback();
|
||||
}
|
||||
);
|
||||
}
|
||||
], done);
|
||||
}); // 44.5
|
||||
|
||||
it('44.6 empty array for BIND_IN and BIND_INOUT', function(done) {
|
||||
async.series([
|
||||
// Pass arrays of values to a PL/SQL procedure
|
||||
function(callback) {
|
||||
connection.execute(
|
||||
"BEGIN nodb_beachpkg.array_in(:beach_in, :depth_in); END;",
|
||||
{
|
||||
beach_in: { type: oracledb.STRING,
|
||||
dir: oracledb.BIND_IN,
|
||||
val: [] },
|
||||
depth_in: { type: oracledb.NUMBER,
|
||||
dir: oracledb.BIND_IN,
|
||||
val: []
|
||||
}
|
||||
},
|
||||
function(err) {
|
||||
should.not.exist(err);
|
||||
callback();
|
||||
}
|
||||
);
|
||||
},
|
||||
// Return input arrays sorted by beach name
|
||||
function(callback) {
|
||||
connection.execute(
|
||||
"BEGIN nodb_beachpkg.array_inout(:beach_inout, :depth_inout); END;",
|
||||
{
|
||||
beach_inout: { type: oracledb.STRING,
|
||||
dir: oracledb.BIND_INOUT,
|
||||
val: [],
|
||||
maxArraySize: 0
|
||||
},
|
||||
depth_inout: { type: oracledb.NUMBER,
|
||||
dir: oracledb.BIND_INOUT,
|
||||
val: [],
|
||||
maxArraySize: 3}
|
||||
},
|
||||
function(err) {
|
||||
should.exist(err);
|
||||
(err.message).should.startWith('NJS-035:');
|
||||
callback();
|
||||
}
|
||||
);
|
||||
}
|
||||
], done);
|
||||
}); // 44.6
|
||||
|
||||
it('44.7 empty array for BIND_OUT', function(done) {
|
||||
async.series([
|
||||
function(callback) {
|
||||
var proc = "CREATE OR REPLACE PACKAGE\n" +
|
||||
"oracledb_testpack\n" +
|
||||
"IS\n" +
|
||||
" TYPE stringsType IS TABLE OF VARCHAR2(2000) INDEX BY BINARY_INTEGER;\n" +
|
||||
" PROCEDURE test(p OUT stringsType);\n" +
|
||||
"END;";
|
||||
connection.execute(
|
||||
proc,
|
||||
function(err) {
|
||||
should.not.exist(err);
|
||||
callback();
|
||||
}
|
||||
);
|
||||
},
|
||||
function(callback) {
|
||||
var proc = "CREATE OR REPLACE PACKAGE BODY\n" +
|
||||
"oracledb_testpack\n" +
|
||||
"IS\n" +
|
||||
" PROCEDURE test(p OUT stringsType) IS BEGIN NULL; END;\n" +
|
||||
"END;";
|
||||
connection.execute(
|
||||
proc,
|
||||
function(err) {
|
||||
should.not.exist(err);
|
||||
callback();
|
||||
}
|
||||
);
|
||||
},
|
||||
function(callback) {
|
||||
connection.execute(
|
||||
"BEGIN oracledb_testpack.test(:0); END;",
|
||||
[
|
||||
{type: oracledb.STRING, dir: oracledb.BIND_OUT, maxArraySize: 1}
|
||||
],
|
||||
function(err, result) {
|
||||
should.not.exist(err);
|
||||
result.outBinds[0].should.eql([]);
|
||||
callback();
|
||||
}
|
||||
);
|
||||
},
|
||||
function(callback) {
|
||||
connection.execute(
|
||||
"DROP PACKAGE oracledb_testpack",
|
||||
function(err) {
|
||||
should.not.exist(err);
|
||||
callback();
|
||||
}
|
||||
);
|
||||
}
|
||||
], done);
|
||||
}); // 44.7
|
||||
|
||||
it('44.8 maxSize option applies to each elements of an array', function(done) {
|
||||
async.series([
|
||||
// Pass arrays of values to a PL/SQL procedure
|
||||
function(callback) {
|
||||
connection.execute(
|
||||
"BEGIN nodb_beachpkg.array_in(:beach_in, :depth_in); END;",
|
||||
{
|
||||
beach_in: { type: oracledb.STRING,
|
||||
dir: oracledb.BIND_IN,
|
||||
val: ["Malibu", "Bondi", "Waikiki"] },
|
||||
depth_in: { type: oracledb.NUMBER,
|
||||
dir: oracledb.BIND_IN,
|
||||
val: [45, 30, 67]
|
||||
}
|
||||
},
|
||||
function(err) {
|
||||
should.not.exist(err);
|
||||
callback();
|
||||
}
|
||||
);
|
||||
},
|
||||
// Fetch arrays of values from a PL/SQL procedure
|
||||
function(callback) {
|
||||
connection.execute(
|
||||
"BEGIN nodb_beachpkg.array_out(:beach_out, :depth_out); END;",
|
||||
{
|
||||
beach_out: { type: oracledb.STRING,
|
||||
dir: oracledb.BIND_OUT,
|
||||
maxArraySize: 3,
|
||||
maxSize: 6 },
|
||||
depth_out: { type: oracledb.NUMBER,
|
||||
dir: oracledb.BIND_OUT,
|
||||
maxArraySize: 3 }
|
||||
},
|
||||
function(err) {
|
||||
should.exist(err);
|
||||
(err.message).should.startWith('ORA-06502:');
|
||||
// ORA-06502: PL/SQL: numeric or value error: host bind array too small
|
||||
callback();
|
||||
}
|
||||
);
|
||||
},
|
||||
function(callback) {
|
||||
connection.rollback(function(err) {
|
||||
should.not.exist(err);
|
||||
callback();
|
||||
});
|
||||
},
|
||||
// Return input arrays sorted by beach name
|
||||
function(callback) {
|
||||
connection.execute(
|
||||
"BEGIN nodb_beachpkg.array_inout(:beach_inout, :depth_inout); END;",
|
||||
{
|
||||
beach_inout: { type: oracledb.STRING,
|
||||
dir: oracledb.BIND_INOUT,
|
||||
val: ["Port Melbourne Beach", "Eighty Mile Beach", "Chesil Beach"],
|
||||
maxArraySize: 3,
|
||||
maxSize : 5},
|
||||
depth_inout: { type: oracledb.NUMBER,
|
||||
dir: oracledb.BIND_INOUT,
|
||||
val: [8, 3, 70],
|
||||
maxArraySize: 3}
|
||||
},
|
||||
function(err) {
|
||||
should.exist(err);
|
||||
should.strictEqual(
|
||||
err.message,
|
||||
"DPI-1019: buffer size of 5 is too small"
|
||||
);
|
||||
callback();
|
||||
}
|
||||
);
|
||||
}
|
||||
], done);
|
||||
}); // 44.8
|
||||
|
||||
});
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,728 @@
|
|||
/* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. */
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* You may not use the identified files except in compliance with the Apache
|
||||
* License, Version 2.0 (the "License.")
|
||||
*
|
||||
* You may obtain a copy of the License at
|
||||
* http://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.
|
||||
*
|
||||
* The node-oracledb test suite uses 'mocha', 'should' and 'async'.
|
||||
* See LICENSE.md for relevant licenses.
|
||||
*
|
||||
* NAME
|
||||
* 67. poolCache.js
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Testing properties of connection pool.
|
||||
*
|
||||
* NUMBERING RULE
|
||||
* Test numbers follow this numbering rule:
|
||||
* 1 - 20 are reserved for basic functional tests
|
||||
* 21 - 50 are reserved for data type supporting tests
|
||||
* 51 onwards are for other tests
|
||||
*
|
||||
*****************************************************************************/
|
||||
'use strict';
|
||||
|
||||
var oracledb = require('oracledb');
|
||||
var async = require('async');
|
||||
var should = require('should');
|
||||
var dbConfig = require('./dbconfig.js');
|
||||
|
||||
describe('67. poolCache.js', function() {
|
||||
beforeEach(function() {
|
||||
// ensure that no poolAlias has been specified
|
||||
delete dbConfig.poolAlias;
|
||||
});
|
||||
|
||||
after(function() {
|
||||
// ensure that no poolAlias has been specified
|
||||
delete dbConfig.poolAlias;
|
||||
});
|
||||
|
||||
describe('67.1 basic functional tests', function() {
|
||||
it('67.1.1 caches pool as default if pool is created when cache is empty', function(done) {
|
||||
oracledb.createPool(dbConfig, function(err, pool) {
|
||||
var defaultPool;
|
||||
|
||||
should.not.exist(err);
|
||||
|
||||
pool.should.be.ok();
|
||||
|
||||
// Not specifying a name, default will be used
|
||||
defaultPool = oracledb.getPool();
|
||||
|
||||
should.strictEqual(pool, defaultPool);
|
||||
|
||||
(defaultPool.poolAlias).should.equal('default');
|
||||
|
||||
pool.close(function(err){
|
||||
should.not.exist(err);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('67.1.2 removes the pool from the cache on terminate', function(done) {
|
||||
oracledb.createPool(dbConfig, function(err, pool) {
|
||||
should.not.exist(err);
|
||||
|
||||
pool.should.be.ok();
|
||||
|
||||
pool.close(function(err){
|
||||
var defaultPool;
|
||||
|
||||
should.not.exist(err);
|
||||
|
||||
(function() {
|
||||
defaultPool = oracledb.getPool();
|
||||
}).should.throw(/^NJS-047:/);
|
||||
|
||||
should.not.exist(defaultPool);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('67.1.3 can cache and retrieve an aliased pool', function(done) {
|
||||
var poolAlias = 'random-pool-alias';
|
||||
|
||||
dbConfig.poolAlias = poolAlias;
|
||||
|
||||
oracledb.createPool(dbConfig, function(err, pool) {
|
||||
var aliasedPool;
|
||||
|
||||
should.not.exist(err);
|
||||
|
||||
pool.should.be.ok();
|
||||
|
||||
pool.poolAlias.should.equal(poolAlias);
|
||||
|
||||
aliasedPool = oracledb.getPool(poolAlias);
|
||||
|
||||
should.strictEqual(pool, aliasedPool);
|
||||
|
||||
pool.close(function(err){
|
||||
should.not.exist(err);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('67.1.4 throws an error if the poolAlias already exists in the cache', function(done) {
|
||||
dbConfig.poolAlias = 'pool1';
|
||||
|
||||
oracledb.createPool(dbConfig, function(err, pool1) {
|
||||
should.not.exist(err);
|
||||
|
||||
pool1.should.be.ok();
|
||||
|
||||
// Creating another pool with the same poolAlias as before
|
||||
oracledb.createPool(dbConfig, function(err, pool2) {
|
||||
should.exist(err);
|
||||
|
||||
(err.message).should.startWith('NJS-046:');
|
||||
should.not.exist(pool2);
|
||||
|
||||
pool1.close(function(err){
|
||||
should.not.exist(err);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('67.1.5 does not throw an error if multiple pools are created without a poolAlias', function(done) {
|
||||
oracledb.createPool(dbConfig, function(err, pool1) {
|
||||
should.not.exist(err);
|
||||
|
||||
pool1.should.be.ok();
|
||||
|
||||
// Creating another pool with no poolAlias
|
||||
oracledb.createPool(dbConfig, function(err, pool2) {
|
||||
should.not.exist(err);
|
||||
|
||||
pool2.should.be.ok();
|
||||
|
||||
pool1.close(function(err){
|
||||
should.not.exist(err);
|
||||
|
||||
pool2.close(function(err){
|
||||
should.not.exist(err);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('67.1.6 throws an error if poolAttrs.poolAlias is not a string', function(done) {
|
||||
// Setting poolAlias to something other than a string. Could be
|
||||
// boolean, object, array, etc.
|
||||
dbConfig.poolAlias = {};
|
||||
|
||||
oracledb.createPool(dbConfig, function(err, pool) {
|
||||
should.exist(err);
|
||||
(err.message).should.startWith('NJS-004:');
|
||||
|
||||
should.not.exist(pool);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('67.1.7 makes poolAttrs.poolAlias a read-only attribute on the pool named poolAlias', function(done) {
|
||||
dbConfig.poolAlias = 'my-pool';
|
||||
|
||||
oracledb.createPool(dbConfig, function(err, pool) {
|
||||
should.not.exist(err);
|
||||
|
||||
pool.should.be.ok();
|
||||
|
||||
(pool.poolAlias).should.equal(dbConfig.poolAlias);
|
||||
|
||||
(function() {
|
||||
pool.poolAlias = 'some-new-value';
|
||||
}).should.throw(/^NJS-014:/);
|
||||
|
||||
(pool.poolAlias).should.equal(dbConfig.poolAlias);
|
||||
|
||||
pool.close(function(err) {
|
||||
should.not.exist(err);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('67.1.8 retrieves the default pool, even after an aliased pool is created', function(done) {
|
||||
oracledb.createPool(dbConfig, function(err, pool1) {
|
||||
should.not.exist(err);
|
||||
|
||||
pool1.should.be.ok();
|
||||
|
||||
dbConfig.poolAlias = 'random-pool-alias';
|
||||
|
||||
oracledb.createPool(dbConfig, function(err, pool2) {
|
||||
var defaultPool;
|
||||
|
||||
should.not.exist(err);
|
||||
|
||||
pool2.should.be.ok();
|
||||
|
||||
// Not specifying a name, default will be used
|
||||
defaultPool = oracledb.getPool();
|
||||
|
||||
should.strictEqual(pool1, defaultPool);
|
||||
|
||||
(defaultPool.poolAlias).should.equal('default');
|
||||
|
||||
pool1.close(function(err){
|
||||
should.not.exist(err);
|
||||
|
||||
pool2.close(function(err){
|
||||
should.not.exist(err);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('67.1.9 retrieves the right pool, even after multiple pools are created', function(done) {
|
||||
var aliasToGet = 'random-pool-alias-2';
|
||||
|
||||
dbConfig.poolAlias = 'random-pool-alias';
|
||||
|
||||
oracledb.createPool(dbConfig, function(err, pool1) {
|
||||
should.not.exist(err);
|
||||
|
||||
pool1.should.be.ok();
|
||||
|
||||
dbConfig.poolAlias = aliasToGet;
|
||||
|
||||
oracledb.createPool(dbConfig, function(err, pool2) {
|
||||
should.not.exist(err);
|
||||
|
||||
pool2.should.be.ok();
|
||||
|
||||
dbConfig.poolAlias = 'random-pool-alias-3';
|
||||
|
||||
oracledb.createPool(dbConfig, function(err, pool3) {
|
||||
var secondPool;
|
||||
|
||||
should.not.exist(err);
|
||||
|
||||
secondPool = oracledb.getPool(aliasToGet);
|
||||
|
||||
should.strictEqual(pool2, secondPool);
|
||||
|
||||
(secondPool.poolAlias).should.equal(aliasToGet);
|
||||
|
||||
pool1.close(function(err){
|
||||
should.not.exist(err);
|
||||
|
||||
pool2.close(function(err){
|
||||
should.not.exist(err);
|
||||
|
||||
pool3.close(function(err){
|
||||
should.not.exist(err);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('67.1.10 throws an error if the pool specified in getPool doesn\'t exist', function(done) {
|
||||
(function() {
|
||||
oracledb.getPool();
|
||||
}).should.throw(/^NJS-047:/);
|
||||
|
||||
(function() {
|
||||
oracledb.getPool('some-random-alias');
|
||||
}).should.throw(/^NJS-047:/);
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
it('67.1.11 does not throw an error if multiple pools are created without a poolAlias in the same call stack', function(done) {
|
||||
var pool1;
|
||||
var pool2;
|
||||
|
||||
async.parallel(
|
||||
[
|
||||
function(callback) {
|
||||
oracledb.createPool(dbConfig, function(err, pool) {
|
||||
should.not.exist(err);
|
||||
|
||||
pool1 = pool;
|
||||
|
||||
callback();
|
||||
});
|
||||
},
|
||||
function(callback) {
|
||||
oracledb.createPool(dbConfig, function(err, pool) {
|
||||
should.not.exist(err);
|
||||
|
||||
pool2 = pool;
|
||||
|
||||
callback();
|
||||
});
|
||||
}
|
||||
],
|
||||
function(createPoolErr) {
|
||||
should.not.exist(createPoolErr);
|
||||
|
||||
pool1.close(function(err) {
|
||||
should.not.exist(err);
|
||||
|
||||
pool2.close(function(err) {
|
||||
should.not.exist(err);
|
||||
|
||||
done(createPoolErr);
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('67.1.12 uses callback syntax function(err) instead of function(err, pool)', function(done) {
|
||||
oracledb.createPool({ // this becomes the default pool
|
||||
user : dbConfig.user,
|
||||
password : dbConfig.password,
|
||||
connectString : dbConfig.connectString,
|
||||
poolMax : 4,
|
||||
poolMin : 1,
|
||||
poolIncrement: 1,
|
||||
poolTimeout: 0 // never terminate unused connections
|
||||
}, function(err) {
|
||||
should.not.exist(err);
|
||||
|
||||
var defaultPool = oracledb.getPool();
|
||||
should.exist(defaultPool);
|
||||
(defaultPool.poolAlias).should.equal('default');
|
||||
|
||||
defaultPool.close(function(err) {
|
||||
should.not.exist(err);
|
||||
});
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('67.1.13 Negative: callback is called with function(err)', function(done) {
|
||||
this.timeout(10000);
|
||||
oracledb.createPool({ // this becomes the default pool
|
||||
user : dbConfig.user,
|
||||
password : 'wrongpassword',
|
||||
connectString : dbConfig.connectString,
|
||||
poolMax : 4,
|
||||
poolMin : 1,
|
||||
poolIncrement: 1,
|
||||
poolTimeout: 0 // never terminate unused connections
|
||||
}, function(err) {
|
||||
should.exist(err);
|
||||
// ORA-01017: invalid username/password; logon denied
|
||||
(err.message).should.startWith('ORA-01017:');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('67.1.14 a named pool does not also create a default pool', function(done) {
|
||||
var poolAlias = "named-pool";
|
||||
dbConfig.poolAlias = poolAlias;
|
||||
oracledb.createPool(dbConfig, function(err, pool) {
|
||||
should.not.exist(err);
|
||||
pool.should.be.ok();
|
||||
(pool.poolAlias).should.eql('named-pool');
|
||||
|
||||
(function() {
|
||||
oracledb.getPool();
|
||||
}).should.throw(/^NJS-047:/);
|
||||
|
||||
(function() {
|
||||
oracledb.getPool('named-pool');
|
||||
}).should.be.ok();
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('67.2 oracledb.getConnection functional tests', function() {
|
||||
it('67.2.1 gets a connection from the default pool when no alias is specified', function(done) {
|
||||
oracledb.createPool(dbConfig, function(err, pool) {
|
||||
should.not.exist(err);
|
||||
|
||||
// Not specifying a poolAlias, default will be used
|
||||
oracledb.getConnection(function(err, conn) {
|
||||
should.not.exist(err);
|
||||
|
||||
conn.release(function(err) {
|
||||
should.not.exist(err);
|
||||
|
||||
pool.close(function(err){
|
||||
should.not.exist(err);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('67.2.2 gets a connection from the pool with the specified poolAlias', function(done) {
|
||||
var poolAlias = 'random-pool-alias';
|
||||
|
||||
dbConfig.poolAlias = poolAlias;
|
||||
|
||||
oracledb.createPool(dbConfig, function(err, pool) {
|
||||
should.not.exist(err);
|
||||
|
||||
oracledb.getConnection(poolAlias, function(err, conn) {
|
||||
should.not.exist(err);
|
||||
|
||||
conn.release(function(err) {
|
||||
should.not.exist(err);
|
||||
|
||||
pool.close(function(err){
|
||||
should.not.exist(err);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('67.2.3 throws an error if an attempt is made to use the default pool when it does not exist', function(done) {
|
||||
dbConfig.poolAlias = 'random-pool-alias';
|
||||
|
||||
oracledb.createPool(dbConfig, function(err, pool) {
|
||||
should.not.exist(err);
|
||||
|
||||
// Not specifying a poolAlias, default will be used
|
||||
oracledb.getConnection(function(err) {
|
||||
should.exist(err);
|
||||
|
||||
(err.message).should.startWith('NJS-047:');
|
||||
|
||||
pool.close(function(err){
|
||||
should.not.exist(err);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('67.2.4 throws an error if an attempt is made to use a poolAlias for a pool that is not in the cache', function(done) {
|
||||
dbConfig.poolAlias = 'random-pool-alias';
|
||||
|
||||
oracledb.createPool(dbConfig, function(err, pool) {
|
||||
should.not.exist(err);
|
||||
|
||||
oracledb.getConnection('pool-alias-that-does-not-exist', function(err) {
|
||||
should.exist(err);
|
||||
|
||||
(err.message).should.startWith('NJS-047:');
|
||||
|
||||
pool.close(function(err){
|
||||
should.not.exist(err);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('67.2.5 gets a connection from the default pool, even after an aliased pool is created', function(done) {
|
||||
oracledb.createPool(dbConfig, function(err, pool1) {
|
||||
should.not.exist(err);
|
||||
|
||||
pool1.should.be.ok();
|
||||
|
||||
dbConfig.poolAlias = 'random-pool-alias';
|
||||
|
||||
oracledb.createPool(dbConfig, function(err, pool2) {
|
||||
should.not.exist(err);
|
||||
|
||||
pool2.should.be.ok();
|
||||
|
||||
oracledb.getConnection(function(err, conn) {
|
||||
should.not.exist(err);
|
||||
|
||||
// Using the hidden pool property to check where the connection came from
|
||||
should.strictEqual(pool1, conn._pool);
|
||||
|
||||
(conn._pool.poolAlias).should.equal('default');
|
||||
|
||||
conn.close(function(err) {
|
||||
should.not.exist(err);
|
||||
|
||||
pool1.close(function(err){
|
||||
should.not.exist(err);
|
||||
|
||||
pool2.close(function(err){
|
||||
should.not.exist(err);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('67.2.6 uses the right pool, even after multiple pools are created', function(done) {
|
||||
var aliasToUse = 'random-pool-alias-2';
|
||||
|
||||
dbConfig.poolAlias = 'random-pool-alias';
|
||||
|
||||
oracledb.createPool(dbConfig, function(err, pool1) {
|
||||
should.not.exist(err);
|
||||
|
||||
pool1.should.be.ok();
|
||||
|
||||
dbConfig.poolAlias = aliasToUse;
|
||||
|
||||
oracledb.createPool(dbConfig, function(err, pool2) {
|
||||
should.not.exist(err);
|
||||
|
||||
pool2.should.be.ok();
|
||||
|
||||
dbConfig.poolAlias = 'random-pool-alias-3';
|
||||
|
||||
oracledb.createPool(dbConfig, function(err, pool3) {
|
||||
should.not.exist(err);
|
||||
|
||||
oracledb.getConnection(aliasToUse, function(err, conn) {
|
||||
// Using the hidden pool property to check where the connection came from
|
||||
should.strictEqual(pool2, conn._pool);
|
||||
|
||||
(conn._pool.poolAlias).should.equal(aliasToUse);
|
||||
|
||||
conn.close(function(err) {
|
||||
should.not.exist(err);
|
||||
|
||||
pool1.close(function(err){
|
||||
should.not.exist(err);
|
||||
|
||||
pool2.close(function(err){
|
||||
should.not.exist(err);
|
||||
|
||||
pool3.close(function(err){
|
||||
should.not.exist(err);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('67.2.7 gets a connection from the default pool with callback function(err)', function(done) {
|
||||
oracledb.createPool({ // this becomes the default pool
|
||||
user : dbConfig.user,
|
||||
password : dbConfig.password,
|
||||
connectString : dbConfig.connectString,
|
||||
poolMax : 4,
|
||||
poolMin : 1,
|
||||
poolIncrement: 1,
|
||||
poolTimeout: 0 // never terminate unused connections
|
||||
}, function(err) {
|
||||
should.not.exist(err);
|
||||
|
||||
var defaultPool = oracledb.getPool();
|
||||
should.exist(defaultPool);
|
||||
|
||||
oracledb.getConnection(function(err, conn) {
|
||||
should.not.exist(err);
|
||||
|
||||
conn.close(function(err) {
|
||||
should.not.exist(err);
|
||||
|
||||
defaultPool.close(function(err){
|
||||
should.not.exist(err);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}); // 67.2
|
||||
|
||||
// This suite extends 67.1.6 case with various types
|
||||
describe('67.3 poolAlias attribute', function() {
|
||||
|
||||
it('67.3.1 throws an error if poolAttrs.poolAlias is an object', function(done) {
|
||||
|
||||
dbConfig.poolAlias = {'foo': 'bar'};
|
||||
|
||||
oracledb.createPool(dbConfig, function(err) {
|
||||
should.exist(err);
|
||||
|
||||
(err.message).should.startWith('NJS-004:');
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('67.3.2 throws an error if poolAttrs.poolAlias is an array', function(done) {
|
||||
|
||||
dbConfig.poolAlias = [];
|
||||
|
||||
oracledb.createPool(dbConfig, function(err) {
|
||||
should.exist(err);
|
||||
|
||||
(err.message).should.startWith('NJS-004:');
|
||||
// NJS-004: invalid value for property poolAttrs.poolAlias
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('67.3.3 throws an error if poolAttrs.poolAlias is a number', function(done) {
|
||||
|
||||
dbConfig.poolAlias = 123;
|
||||
|
||||
oracledb.createPool(dbConfig, function(err) {
|
||||
should.exist(err);
|
||||
|
||||
(err.message).should.startWith('NJS-004:');
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('67.3.4 throws an error if poolAttrs.poolAlias is a boolean', function(done) {
|
||||
|
||||
dbConfig.poolAlias = false;
|
||||
|
||||
oracledb.createPool(dbConfig, function(err) {
|
||||
should.exist(err);
|
||||
|
||||
(err.message).should.startWith('NJS-004:');
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('67.3.5 throws an error if poolAttrs.poolAlias is null', function(done) {
|
||||
|
||||
dbConfig.poolAlias = null;
|
||||
|
||||
oracledb.createPool(dbConfig, function(err) {
|
||||
should.exist(err);
|
||||
|
||||
(err.message).should.startWith('NJS-004:');
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('67.3.6 throws an error if poolAttrs.poolAlias is an empty string', function(done) {
|
||||
|
||||
dbConfig.poolAlias = '';
|
||||
|
||||
oracledb.createPool(dbConfig, function(err) {
|
||||
should.exist(err);
|
||||
|
||||
(err.message).should.startWith('NJS-004:');
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('67.3.7 throws an error if poolAttrs.poolAlias is NaN', function(done) {
|
||||
|
||||
dbConfig.poolAlias = NaN;
|
||||
|
||||
oracledb.createPool(dbConfig, function(err) {
|
||||
should.exist(err);
|
||||
|
||||
(err.message).should.startWith('NJS-004:');
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('67.3.8 works if poolAttrs.poolAlias is undefined', function(done) {
|
||||
|
||||
dbConfig.poolAlias = undefined;
|
||||
|
||||
oracledb.createPool(dbConfig, function(err, pool) {
|
||||
|
||||
pool.should.be.ok();
|
||||
(pool.poolAlias).should.equal('default');
|
||||
|
||||
pool.close(function(err) {
|
||||
should.not.exist(err);
|
||||
done();
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
}); // 67.3
|
||||
});
|
|
@ -0,0 +1,548 @@
|
|||
/* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. */
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* You may not use the identified files except in compliance with the Apache
|
||||
* License, Version 2.0 (the "License.")
|
||||
*
|
||||
* You may obtain a copy of the License at
|
||||
* http://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.
|
||||
*
|
||||
* The node-oracledb test suite uses 'mocha', 'should' and 'async'.
|
||||
* See LICENSE.md for relevant licenses.
|
||||
*
|
||||
* NAME
|
||||
* 73. poolPing.js
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Testing connection ping feature of Pool object.
|
||||
*
|
||||
* NUMBERING RULE
|
||||
* Test numbers follow this numbering rule:
|
||||
* 1 - 20 are reserved for basic functional tests
|
||||
* 21 - 50 are reserved for data type supporting tests
|
||||
* 51 onwards are for other tests
|
||||
*
|
||||
*****************************************************************************/
|
||||
'use strict';
|
||||
|
||||
var oracledb = require('oracledb');
|
||||
var async = require('async');
|
||||
var should = require('should');
|
||||
var dbConfig = require('./dbconfig.js');
|
||||
|
||||
describe("73. poolPing.js", function() {
|
||||
|
||||
var defaultInterval = oracledb.poolPingInterval;
|
||||
|
||||
afterEach("reset poolPingInterval to default", function() {
|
||||
|
||||
oracledb.poolPingInterval = defaultInterval;
|
||||
should.strictEqual(oracledb.poolPingInterval, 60);
|
||||
|
||||
});
|
||||
|
||||
it("73.1 the default value of poolPingInterval is 60", function(done) {
|
||||
|
||||
var defaultValue = 60;
|
||||
should.strictEqual(oracledb.poolPingInterval, defaultValue);
|
||||
|
||||
var pool;
|
||||
async.series([
|
||||
function(cb) {
|
||||
oracledb.createPool(
|
||||
dbConfig,
|
||||
function(err, pooling) {
|
||||
should.not.exist(err);
|
||||
pool = pooling;
|
||||
|
||||
should.strictEqual(pool.poolPingInterval, defaultValue);
|
||||
cb();
|
||||
}
|
||||
);
|
||||
},
|
||||
function(cb) {
|
||||
pool.close(function(err) {
|
||||
should.not.exist(err);
|
||||
cb();
|
||||
});
|
||||
}
|
||||
], done);
|
||||
|
||||
}); // 73.1
|
||||
|
||||
it("73.2 does not change after the pool has been created", function(done) {
|
||||
|
||||
var userSetInterval = 20;
|
||||
oracledb.poolPingInterval = userSetInterval;
|
||||
|
||||
var pool;
|
||||
async.series([
|
||||
function(cb) {
|
||||
oracledb.createPool(
|
||||
dbConfig,
|
||||
function(err, pooling) {
|
||||
should.not.exist(err);
|
||||
pool = pooling;
|
||||
|
||||
should.strictEqual(pool.poolPingInterval, userSetInterval);
|
||||
cb();
|
||||
}
|
||||
);
|
||||
},
|
||||
function(cb) {
|
||||
var newInterval = userSetInterval * 2;
|
||||
oracledb.poolPingInterval = newInterval;
|
||||
|
||||
// sleep a while
|
||||
setTimeout(function() {
|
||||
cb();
|
||||
}, 100);
|
||||
},
|
||||
function dotest(cb) {
|
||||
should.strictEqual(pool.poolPingInterval, userSetInterval);
|
||||
cb();
|
||||
},
|
||||
function(cb) {
|
||||
pool.close(function(err) {
|
||||
should.not.exist(err);
|
||||
cb();
|
||||
});
|
||||
}
|
||||
], done);
|
||||
|
||||
}); // 73.2
|
||||
|
||||
it("73.3 can not be changed on pool object", function(done) {
|
||||
|
||||
var userSetInterval = 30;
|
||||
oracledb.poolPingInterval = userSetInterval;
|
||||
|
||||
var pool;
|
||||
async.series([
|
||||
function(cb) {
|
||||
oracledb.createPool(
|
||||
dbConfig,
|
||||
function(err, pooling) {
|
||||
should.not.exist(err);
|
||||
pool = pooling;
|
||||
|
||||
should.strictEqual(pool.poolPingInterval, userSetInterval);
|
||||
cb();
|
||||
}
|
||||
);
|
||||
},
|
||||
function dotest(cb) {
|
||||
var newInterval = userSetInterval * 2;
|
||||
|
||||
try {
|
||||
pool.poolPingInterval = newInterval;
|
||||
} catch(err) {
|
||||
should.exist(err);
|
||||
(err.message).should.startWith('NJS-014:');
|
||||
// NJS-014: poolPingInterval is a read-only property
|
||||
}
|
||||
cb();
|
||||
|
||||
},
|
||||
function(cb) {
|
||||
pool.close(function(err) {
|
||||
should.not.exist(err);
|
||||
cb();
|
||||
});
|
||||
}
|
||||
], done);
|
||||
|
||||
}); // 73.3
|
||||
|
||||
it("73.4 can not be accessed on connection object", function(done) {
|
||||
|
||||
var pool, connection;
|
||||
|
||||
async.series([
|
||||
function(cb) {
|
||||
oracledb.createPool(
|
||||
dbConfig,
|
||||
function(err, pooling) {
|
||||
should.not.exist(err);
|
||||
pool = pooling;
|
||||
cb();
|
||||
}
|
||||
);
|
||||
},
|
||||
function dotest(cb) {
|
||||
pool.getConnection(function(err, conn) {
|
||||
should.not.exist(err);
|
||||
connection = conn;
|
||||
|
||||
should.not.exist(connection.poolPingInterval);
|
||||
|
||||
cb();
|
||||
});
|
||||
},
|
||||
function(cb) {
|
||||
connection.close(function(err) {
|
||||
should.not.exist(err);
|
||||
cb();
|
||||
});
|
||||
},
|
||||
function(cb) {
|
||||
pool.close(function(err) {
|
||||
should.not.exist(err);
|
||||
cb();
|
||||
});
|
||||
}
|
||||
], done);
|
||||
|
||||
}); // 73.4
|
||||
|
||||
// helper function for below test cases
|
||||
var testDefine = function(userSetInterval, callback) {
|
||||
|
||||
oracledb.poolPingInterval = userSetInterval;
|
||||
|
||||
var pool;
|
||||
async.series([
|
||||
function(cb) {
|
||||
oracledb.createPool(
|
||||
dbConfig,
|
||||
function(err, pooling) {
|
||||
should.not.exist(err);
|
||||
pool = pooling;
|
||||
|
||||
should.strictEqual(pool.poolPingInterval, userSetInterval);
|
||||
cb();
|
||||
}
|
||||
);
|
||||
},
|
||||
function(cb) {
|
||||
pool.close(function(err) {
|
||||
should.not.exist(err);
|
||||
cb();
|
||||
});
|
||||
}
|
||||
], callback);
|
||||
|
||||
}; // testDefine()
|
||||
|
||||
it("73.5 can be set to 0, means always ping", function(done) {
|
||||
|
||||
var userSetValue = 0;
|
||||
testDefine(userSetValue, done);
|
||||
|
||||
}); // 73.5
|
||||
|
||||
|
||||
it("73.6 can be set to negative values, means never ping", function(done) {
|
||||
|
||||
var userSetValue = -80;
|
||||
testDefine(userSetValue, done);
|
||||
|
||||
}); // 73.6
|
||||
|
||||
it("73.7 Negative: Number.MAX_SAFE_INTEGER", function(done) {
|
||||
|
||||
/*
|
||||
Number.MAX_SAFE_INTEGER // 9007199254740991
|
||||
Math.pow(2, 53) - 1 // 9007199254740991
|
||||
*/
|
||||
|
||||
try {
|
||||
oracledb.poolPingInterval = Number.MAX_SAFE_INTEGER;
|
||||
} catch(err) {
|
||||
should.exist(err);
|
||||
(err.message).should.startWith("NJS-004:");
|
||||
// NJS-004: invalid value for property pingPoolInterval
|
||||
|
||||
done();
|
||||
}
|
||||
|
||||
}); // 73.7
|
||||
|
||||
it("73.8 cannot surpass the upper limit", function(done) {
|
||||
|
||||
var upperLimit = 2147483647; // 2GB
|
||||
|
||||
async.series([
|
||||
function testMax(cb) {
|
||||
testDefine(upperLimit, cb);
|
||||
},
|
||||
function(cb) {
|
||||
var upperLimitPlus = upperLimit +1;
|
||||
|
||||
try{
|
||||
oracledb.poolPingInterval = upperLimitPlus;
|
||||
} catch(err) {
|
||||
should.exist(err);
|
||||
(err.message).should.startWith("NJS-004:");
|
||||
cb();
|
||||
}
|
||||
}
|
||||
], done);
|
||||
|
||||
}); // 73.8
|
||||
|
||||
it("73.9 cannot surpass the lower Limit", function(done) {
|
||||
|
||||
var lowerLimit = -2147483648;
|
||||
|
||||
async.series([
|
||||
function texstMin(cb) {
|
||||
testDefine(lowerLimit, cb);
|
||||
},
|
||||
function(cb) {
|
||||
var lowerLimitPlus = lowerLimit -1;
|
||||
|
||||
try {
|
||||
oracledb.poolPingInterval = lowerLimitPlus;
|
||||
} catch(err) {
|
||||
should.exist(err);
|
||||
(err.message).should.startWith("NJS-004:");
|
||||
cb();
|
||||
}
|
||||
}
|
||||
], done);
|
||||
|
||||
}); // 73.9
|
||||
|
||||
it("73.10 Negative: null", function(done) {
|
||||
|
||||
try {
|
||||
oracledb.poolPingInterval = null;
|
||||
} catch(err) {
|
||||
should.exist(err);
|
||||
(err.message).should.startWith("NJS-004:");
|
||||
|
||||
done();
|
||||
}
|
||||
|
||||
|
||||
}); // 73.10
|
||||
|
||||
it("73.11 Negative: NaN", function(done) {
|
||||
|
||||
try {
|
||||
oracledb.poolPingInterval = NaN;
|
||||
} catch(err) {
|
||||
should.exist(err);
|
||||
(err.message).should.startWith("NJS-004:");
|
||||
|
||||
done();
|
||||
}
|
||||
|
||||
}); // 73.11
|
||||
|
||||
it("73.12 Negative: undefined", function(done) {
|
||||
|
||||
try {
|
||||
oracledb.poolPingInterval = undefined;
|
||||
} catch(err) {
|
||||
should.exist(err);
|
||||
(err.message).should.startWith("NJS-004:");
|
||||
|
||||
done();
|
||||
}
|
||||
|
||||
}); // 73.12
|
||||
|
||||
it("73.13 Negative: 'random-string'", function(done) {
|
||||
|
||||
try {
|
||||
oracledb.poolPingInterval = 'random-string';
|
||||
} catch(err) {
|
||||
should.exist(err);
|
||||
(err.message).should.startWith("NJS-004:");
|
||||
|
||||
done();
|
||||
}
|
||||
|
||||
}); // 73.13
|
||||
|
||||
var testPoolDefine = function(userSetInterval, expectedValue, callback) {
|
||||
|
||||
var pool;
|
||||
async.series([
|
||||
function(cb) {
|
||||
oracledb.createPool(
|
||||
{
|
||||
user: dbConfig.user,
|
||||
password: dbConfig.password,
|
||||
connectString: dbConfig.connectString,
|
||||
poolPingInterval: userSetInterval
|
||||
},
|
||||
function(err, pooling) {
|
||||
should.not.exist(err);
|
||||
pool = pooling;
|
||||
|
||||
should.strictEqual(pool.poolPingInterval, expectedValue);
|
||||
cb();
|
||||
}
|
||||
);
|
||||
},
|
||||
function(cb) {
|
||||
pool.close(function(err) {
|
||||
should.not.exist(err);
|
||||
cb();
|
||||
});
|
||||
}
|
||||
], callback);
|
||||
|
||||
}; // testPoolDefine
|
||||
|
||||
it("73.14 can be set at pool creation, e.g. positive value 1234", function(done) {
|
||||
|
||||
var userSetValue = 1234;
|
||||
testPoolDefine(userSetValue, userSetValue, done);
|
||||
|
||||
});
|
||||
|
||||
it("73.15 can be set at pool creation, e.g. negative value -4321", function(done) {
|
||||
|
||||
var userSetValue = -4321;
|
||||
testPoolDefine(userSetValue, userSetValue, done);
|
||||
|
||||
});
|
||||
|
||||
it("73.16 can be set at pool creation, e.g. 0 means always ping", function(done) {
|
||||
|
||||
var userSetValue = 0;
|
||||
testPoolDefine(userSetValue, userSetValue, done);
|
||||
|
||||
});
|
||||
|
||||
it("73.17 Setting to 'null' will use current value from oracledb", function(done) {
|
||||
|
||||
oracledb.poolPingInterval = 789;
|
||||
var userSetValue = null;
|
||||
|
||||
testPoolDefine(userSetValue, 789, done);
|
||||
|
||||
});
|
||||
|
||||
it("73.18 Setting to 'undefined' will use current value from oracledb", function(done) {
|
||||
|
||||
oracledb.poolPingInterval = 9876;
|
||||
var userSetValue = undefined;
|
||||
|
||||
testPoolDefine(userSetValue, 9876, done);
|
||||
|
||||
});
|
||||
|
||||
it("73.19 can be set at pool creation. Negative: NaN", function(done) {
|
||||
|
||||
/*var userSetValue = 'random-string';*/
|
||||
|
||||
var userSetValue = NaN;
|
||||
|
||||
oracledb.createPool(
|
||||
{
|
||||
user: dbConfig.user,
|
||||
password: dbConfig.password,
|
||||
connectString: dbConfig.connectString,
|
||||
poolPingInterval: userSetValue
|
||||
},
|
||||
function(err, pool) {
|
||||
should.exist(err);
|
||||
(err.message).should.startWith("NJS-007:");
|
||||
// NJS-007: invalid value for "poolPingInterval" in parameter 1
|
||||
|
||||
should.not.exist(pool);
|
||||
done();
|
||||
}
|
||||
);
|
||||
|
||||
}); // 73.19
|
||||
|
||||
it("73.20 can be set at pool creation. Negative: 'random-string'", function(done) {
|
||||
|
||||
var userSetValue = 'random-string';
|
||||
|
||||
oracledb.createPool(
|
||||
{
|
||||
user: dbConfig.user,
|
||||
password: dbConfig.password,
|
||||
connectString: dbConfig.connectString,
|
||||
poolPingInterval: userSetValue
|
||||
},
|
||||
function(err, pool) {
|
||||
should.exist(err);
|
||||
(err.message).should.startWith("NJS-008:");
|
||||
// NJS-008: invalid type for "poolPingInterval" in parameter 1
|
||||
|
||||
should.not.exist(pool);
|
||||
done();
|
||||
}
|
||||
);
|
||||
|
||||
}); // 73.20
|
||||
|
||||
it("73.21 cannot surpass the upper limit at pool creation", function(done) {
|
||||
|
||||
var upperLimit = 2147483647; // 2GB
|
||||
|
||||
async.series([
|
||||
function testMax(cb) {
|
||||
testPoolDefine(upperLimit, upperLimit, cb);
|
||||
},
|
||||
function(cb) {
|
||||
|
||||
var userSetValue = upperLimit + 1;
|
||||
oracledb.createPool(
|
||||
{
|
||||
user: dbConfig.user,
|
||||
password: dbConfig.password,
|
||||
connectString: dbConfig.connectString,
|
||||
poolPingInterval: userSetValue
|
||||
},
|
||||
function(err, pool) {
|
||||
should.exist(err);
|
||||
(err.message).should.startWith("NJS-007:");
|
||||
|
||||
should.not.exist(pool);
|
||||
cb();
|
||||
}
|
||||
);
|
||||
}
|
||||
], done);
|
||||
|
||||
}); // 73.21
|
||||
|
||||
it("73.22 cannot surpass the lower limit at pool creation", function(done) {
|
||||
|
||||
var lowerLimit = -2147483648;
|
||||
|
||||
async.series([
|
||||
function testMax(cb) {
|
||||
testPoolDefine(lowerLimit, lowerLimit, cb);
|
||||
},
|
||||
function(cb) {
|
||||
|
||||
var userSetValue = lowerLimit - 1;
|
||||
oracledb.createPool(
|
||||
{
|
||||
user: dbConfig.user,
|
||||
password: dbConfig.password,
|
||||
connectString: dbConfig.connectString,
|
||||
poolPingInterval: userSetValue
|
||||
},
|
||||
function(err, pool) {
|
||||
should.exist(err);
|
||||
(err.message).should.startWith("NJS-007:");
|
||||
|
||||
should.not.exist(pool);
|
||||
cb();
|
||||
}
|
||||
);
|
||||
}
|
||||
], done);
|
||||
|
||||
}); // 73.22
|
||||
|
||||
});
|
|
@ -0,0 +1,82 @@
|
|||
/* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. */
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* You may not use the identified files except in compliance with the Apache
|
||||
* License, Version 2.0 (the "License.")
|
||||
*
|
||||
* You may obtain a copy of the License at
|
||||
* http://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.
|
||||
*
|
||||
* The node-oracledb test suite uses 'mocha', 'should' and 'async'.
|
||||
* See LICENSE.md for relevant licenses.
|
||||
*
|
||||
* NAME
|
||||
* random.js
|
||||
*
|
||||
* DESCRIPTION
|
||||
* generate a random string which length is 'length', with specialStr
|
||||
* in it's head and tail
|
||||
*****************************************************************************/
|
||||
'use strict';
|
||||
|
||||
var random = exports;
|
||||
module.exports = random;
|
||||
|
||||
// generate a random string which length is 'length', with specialStr in it's head and tail
|
||||
random.getRandomString = function(length, specialStr) {
|
||||
var str='';
|
||||
var strLength = length - specialStr.length * 2;
|
||||
for( ; str.length < strLength; str += Math.random().toString(36).slice(2));
|
||||
str = str.substr(0, strLength);
|
||||
str = specialStr + str + specialStr;
|
||||
return str;
|
||||
};
|
||||
|
||||
random.getRandomLengthString = function (length) {
|
||||
var str='';
|
||||
for( ; str.length < length; str += Math.random().toString(36).slice(2));
|
||||
str = str.substr(0, length);
|
||||
return str;
|
||||
};
|
||||
|
||||
random.getRandomNumArray = function(size) {
|
||||
var numbers = new Array(size);
|
||||
for (var i = 0; i < numbers.length; i++) {
|
||||
numbers[i] = getRandomInt(1,9999999);
|
||||
}
|
||||
return numbers;
|
||||
};
|
||||
|
||||
function getRandomInt(min, max) {
|
||||
min = Math.ceil(min);
|
||||
max = Math.floor(max);
|
||||
return Math.floor(Math.random() * (max - min)) + min;
|
||||
}
|
||||
|
||||
random.getIntArray = function(N) {
|
||||
var arr = Array.apply(null, Array(N));
|
||||
// The map() method creates a new array with the results of calling a provided function on every element in this array.
|
||||
// var new_array = arr.map(callback[, thisArg])
|
||||
// Parameters
|
||||
// callback
|
||||
// Function that produces an element of the new Array, taking three arguments:
|
||||
// currentValue
|
||||
// The current element being processed in the array.
|
||||
// index
|
||||
// The index of the current element being processed in the array.
|
||||
// array
|
||||
// The array map was called upon.
|
||||
// thisArg
|
||||
// Optional. Value to use as this when executing callback.
|
||||
// Return value
|
||||
// A new array with each element being the result of the callback function.
|
||||
return arr.map(function (x, i) { return i; });
|
||||
};
|
Binary file not shown.
After Width: | Height: | Size: 2.3 KiB |
Loading…
Reference in New Issue