Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

impr(oracledb): 4 fix #3480

Merged
merged 2 commits into from Oct 15, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion .travis.yml
Expand Up @@ -16,7 +16,7 @@ matrix:
env: TESTSCRIPT=test:everything DB="oracledb mssql mysql mysql2 postgres sqlite3" KNEX_TEST_TIMEOUT=60000
install:
- npm i
- (echo $DB | grep oracledb) && npm install oracledb@3.1.2 || true
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wait, whole line shouldn't be removed :D. just the @3.1.2 part, so that latest driver version is picked up.

- (echo $DB | grep oracledb) && npm install oracledb || true

before_script:
- npm run db:start
Expand Down
85 changes: 61 additions & 24 deletions lib/dialects/oracledb/index.js
Expand Up @@ -131,7 +131,11 @@ Client_Oracledb.prototype.acquireRawConnection = function() {
};
const fetchAsync = promisify(function(sql, bindParams, options, cb) {
options = options || {};
options.outFormat = client.driver.OBJECT;
options.outFormat =
client.driver.OUT_FORMAT_OBJECT || client.driver.OBJECT;
if (!options.outFormat) {
throw new Error('not found oracledb.outFormat constants');
}
if (options.resultSet) {
connection.execute(sql, bindParams || [], options, function(
err,
Expand Down Expand Up @@ -202,7 +206,10 @@ Client_Oracledb.prototype.acquireRawConnection = function() {

try {
for (const lob of lobs) {
results.rows[lob.index][lob.key] = await readStream(lob.stream);
// todo should be fetchAsString/fetchAsBuffer polyfill only
results.rows[lob.index][lob.key] = await lobProcessing(
lob.stream
);
}
} catch (e) {
await closeResultSet().catch(() => {});
Expand Down Expand Up @@ -328,30 +335,29 @@ Client_Oracledb.prototype._query = function(connection, obj) {
});
};

// Handle clob
const readStream = promisify((stream, cb) => {
const oracledb = require('oracledb');
let data = '';
/**
* @param stream
* @param {'string' | 'buffer'} type
*/
function readStream(stream, type) {
return new Promise((resolve, reject) => {
let data = '';

if (stream.iLob.type === oracledb.CLOB) {
stream.setEncoding('utf-8');
} else {
data = Buffer.alloc(0);
}
stream.on('error', function(err) {
cb(err);
});
stream.on('data', function(chunk) {
if (stream.iLob.type === oracledb.CLOB) {
data += chunk;
} else {
data = Buffer.concat([data, chunk]);
}
});
stream.on('end', function() {
cb(null, data);
stream.on('error', function(err) {
reject(err);
});
stream.on('data', function(chunk) {
if (type === 'string') {
data += chunk;
} else {
data = Buffer.concat([data, chunk]);
}
});
stream.on('end', function() {
resolve(data);
});
});
});
}

// Process the response as returned from the query.
Client_Oracledb.prototype.processResponse = function(obj, runner) {
Expand Down Expand Up @@ -387,6 +393,37 @@ Client_Oracledb.prototype.processResponse = function(obj, runner) {
}
};

const lobProcessing = function(stream) {
const oracledb = require('oracledb');

/**
* @type 'string' | 'buffer'
*/
let type;

if (stream.type) {
// v1.2-v4
if (stream.type === oracledb.BLOB) {
type = 'buffer';
} else if (stream.type === oracledb.CLOB) {
type = 'string';
}
} else if (stream.iLob) {
// v1
if (stream.iLob.type === oracledb.CLOB) {
type = 'string';
} else if (stream.iLob.type === oracledb.BLOB) {
type = 'buffer';
}
} else {
throw new Error('Unrecognized oracledb lob stream type');
}
if (type === 'string') {
stream.setEncoding('utf-8');
}
return readStream(stream, type);
};

class Oracledb_Formatter extends Oracle_Formatter {
// Checks whether a value is a function... if it is, we compile it
// otherwise we check whether it's a raw
Expand Down
9 changes: 9 additions & 0 deletions test/unit/dialects/oracledb.js
Expand Up @@ -71,6 +71,15 @@ describe('OracleDb parameters', function() {
});
});

it('on clob', function() {
return knexClient
.raw('select TO_CLOB(\'LONG CONTENT\') as "field" from dual')
.then(function(result) {
expect(result[0]).to.be.ok;
expect(result[0].field).to.be.equal('LONG CONTENT');
});
});

after(function() {
return knexClient.destroy();
});
Expand Down