Socket
Socket
Sign inDemoInstall

hdb

Package Overview
Dependencies
Maintainers
1
Versions
62
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

hdb - npm Package Compare versions

Comparing version 0.0.5 to 0.1.0

lib/protocol/common/ReadFunction.js

22

lib/Client.js

@@ -22,4 +22,2 @@ // Copyright 2013 SAP AG.

var Statement = protocol.Statement;
var ResultSet = protocol.ResultSet;
var Lob = protocol.Lob;

@@ -165,2 +163,15 @@ module.exports = Client;

};
executeDirect(this._connection, defaults, command, options, cb);
return this;
};
Client.prototype.execute = function execute(command, options, cb) {
var defaults = {
autoFetch: false
};
executeDirect(this._connection, defaults, command, options, cb);
return this;
};
function executeDirect(connection, defaults, command, options, cb) {
if (util.isFunction(options)) {

@@ -176,4 +187,4 @@ cb = options;

}
var result = new Result(this._connection, options);
this._connection.executeDirect({
var result = new Result(connection, options);
connection.executeDirect({
command: command

@@ -183,3 +194,2 @@ }, function onreply(err, reply) {

});
return this;
};
}

@@ -27,2 +27,3 @@ // Copyright 2013 SAP AG.

exports.LobOptions = require('./LobOptions');
exports.LobSourceType = require('./LobSourceType');
exports.MessageType = require('./MessageType');

@@ -37,2 +38,3 @@ exports.ParameterMode = require('./ParameterMode');

exports.TypeCode = require('./TypeCode');
exports.ReadFunction = require('./ReadFunction');

@@ -39,0 +41,0 @@ invert('ConnectOption');

@@ -28,2 +28,3 @@ // Copyright 2013 SAP AG.

var bignum = util.bignum;
var debug = util.debuglog('hdb');

@@ -97,2 +98,3 @@ var MAX_PACKET_SIZE = Math.pow(2, 17);

function cleanup() {
debug('cleanup');
self._socket.removeListener('error', onerror);

@@ -279,10 +281,12 @@ self._socket = undefined;

if (this._queue.empty && !this._queue.busy) {
return endSocket(this._socket);
return closeConnection.call(this);
}
this._queue.once('drain', endSocket.bind(null, this._socket));
this._queue.once('drain', closeConnection.bind(this));
};
function endSocket(socket) {
socket.readable = false;
socket.end();
function closeConnection() {
/* jshint validthis:true */
debug('close');
this._socket.readable = false;
this._socket.end();
}

@@ -293,2 +297,4 @@

debug('send', message);
var state = this._state;

@@ -322,3 +328,3 @@ var buffer = messageToBuffer(message);

var buffer;
if (util.isBuffer(message)) {
if (Buffer.isBuffer(message)) {
buffer = message;

@@ -392,2 +398,3 @@ } else {

}
debug('receive', reply);
cb(error, reply);

@@ -394,0 +401,0 @@ }

@@ -19,2 +19,3 @@ // Copyright 2013 SAP AG.

var TypeCode = common.TypeCode;
var LobOptions = common.LobOptions;
var bignum = util.bignum;

@@ -31,125 +32,33 @@

var buffers = [];
var byteLength;
var buffer, type, value;
for (var i = 0; i < params.length; i++) {
type = params[i].type;
var offset = 0;
var lobs = [];
var data = [];
var dataType, value, buffer, i;
for (i = 0; i < params.length; i++) {
dataType = DataType[params[i].type];
value = params[i].value;
if (typeof value === 'undefined' || value === null) {
buffer = new Buffer(1);
buffer[0] = type | 0x80;
buffers.push(buffer);
buffer = writeNull(dataType);
} else {
switch (type) {
case TypeCode.TINYINT:
buffer = new Buffer(2);
buffer[0] = type;
buffer.writeInt8(value, 1);
buffers.push(buffer);
break;
case TypeCode.SMALLINT:
buffer = new Buffer(3);
buffer[0] = type;
buffer.writeInt16LE(value, 1);
buffers.push(buffer);
break;
case TypeCode.INT:
buffer = new Buffer(5);
buffer[0] = type;
buffer.writeInt32LE(value, 1);
buffers.push(buffer);
break;
case TypeCode.BIGINT:
buffer = new Buffer(9);
buffer[0] = type;
bignum.writeInt64LE(buffer, value, 1);
buffers.push(buffer);
break;
case TypeCode.REAL:
buffer = new Buffer(5);
buffer[0] = type;
buffer.writeFloatLE(value, 1);
buffers.push(buffer);
break;
case TypeCode.DOUBLE:
buffer = new Buffer(9);
buffer[0] = type;
buffer.writeDoubleLE(value, 1);
buffers.push(buffer);
break;
case TypeCode.STRING:
case TypeCode.NSTRING:
case TypeCode.VARCHAR1:
case TypeCode.VARCHAR2:
case TypeCode.CHAR:
case TypeCode.NCHAR:
case TypeCode.NVARCHAR:
case TypeCode.SHORTTEXT:
case TypeCode.ALPHANUM:
byteLength = Buffer.byteLength(value, 'utf-8');
if (byteLength <= 245) {
buffer = new Buffer(2 + byteLength);
buffer[0] = type;
buffer[1] = byteLength;
buffer.write(value, 2, byteLength, 'utf-8');
} else if (byteLength <= 32767) {
buffer = new Buffer(4 + byteLength);
buffer[0] = type;
buffer[1] = 246;
buffer.writeInt16LE(byteLength, 2);
buffer.write(value, 4, byteLength, 'utf-8');
} else {
buffer = new Buffer(6 + byteLength);
buffer[0] = type;
buffer[1] = 247;
buffer.writeInt32LE(byteLength, 2);
buffer.write(value, 6, byteLength, 'utf-8');
}
buffers.push(buffer);
break;
case TypeCode.BSTRING:
case TypeCode.BINARY:
case TypeCode.VARBINARY:
byteLength = value.length;
if (byteLength <= 245) {
buffer = new Buffer(2 + byteLength);
buffer[0] = type;
buffer[1] = byteLength;
value.copy(buffer, 2);
} else if (byteLength <= 32767) {
buffer = new Buffer(4 + byteLength);
buffer[0] = type;
buffer[1] = 246;
buffer.writeInt16LE(byteLength, 2);
value.copy(buffer, 4);
} else {
buffer = new Buffer(6 + byteLength);
buffer[0] = type;
buffer[1] = 247;
buffer.writeInt32LE(byteLength, 2);
value.copy(buffer, 6);
}
buffers.push(buffer);
break;
case TypeCode.DATE:
buffer = new Buffer(6);
buffer[0] = type;
buffer.writeInt16LE(~~value.substring(0, 4), 1);
buffer.writeInt8(~~value.substring(5, 7), 3);
buffer.writeInt16LE(~~value.substring(8, 10), 4);
buffers.push(buffer);
break;
case TypeCode.TIME:
buffer = new Buffer(5);
buffer[0] = type;
buffer.writeInt8(~~value.substring(0, 2), 1);
buffer.writeInt8(~~value.substring(3, 5), 2);
buffer.writeUInt16LE(Math.round(parseFloat(value.substring(6))), 3);
buffers.push(buffer);
break;
buffer = dataType.write(value);
if (dataType === BLOB || dataType === NCLOB) {
lobs.push({
index: i,
buffer: value
});
}
}
offset += buffer.length;
data.push(buffer);
}
for (i = 0; i < lobs.length; i++) {
// update position of lob in part
data[lobs[i].index].writeInt32LE(offset + 1, 6);
// append lob to part data
buffer = lobs[i].buffer;
offset += buffer.length;
data.push(buffer);
}
part.argumentCount = getArgumentCount(params);
part.buffer = Buffer.concat(buffers);
part.buffer = Buffer.concat(data, offset);
return part;

@@ -161,2 +70,403 @@ }

return 1;
}
var REGEX = {
DATE: /(\d{4})-(\d{2})-(\d{2})/,
TIME: /(\d{2}):(\d{2}):(\d{2}(?:\.\d+)?)/,
TIMESTAMP: /(\d{4})-(\d{2})-(\d{2})[T ](\d{2}):(\d{2}):(\d{2}(?:\.\d+)?)/,
DECIMAL: /^([+-])?(\d+)(?:\.(\d+))?(?:e([+-]?\d+))?$/
};
function writeNull(dataType) {
return new Buffer([dataType.type | 0x80]);
}
function writeTinyInt(value) {
/* jshint validthis:true */
var buffer = new Buffer(2);
buffer[0] = this.type;
buffer.writeInt8(value, 1);
return buffer;
}
function writeSmallInt(value) {
/* jshint validthis:true */
var buffer = new Buffer(3);
buffer[0] = this.type;
buffer.writeInt16LE(value, 1);
return buffer;
}
function writeInt(value) {
/* jshint validthis:true */
var buffer = new Buffer(5);
buffer[0] = this.type;
buffer.writeInt32LE(value, 1);
return buffer;
}
function writeBigInt(value) {
/* jshint validthis:true */
var buffer = new Buffer(9);
buffer[0] = this.type;
bignum.writeInt64LE(buffer, value, 1);
return buffer;
}
function writeReal(value) {
/* jshint validthis:true */
var buffer = new Buffer(5);
buffer[0] = this.type;
buffer.writeFloatLE(value, 1);
return buffer;
}
function writeDouble(value) {
/* jshint validthis:true */
var buffer = new Buffer(9);
buffer[0] = this.type;
buffer.writeDoubleLE(value, 1);
return buffer;
}
function writeDecimal(value) {
/* jshint validthis:true */
var decimal;
if (util.isString(value)) {
decimal = stringToDecimal(value);
} else if (util.isNumber(value)) {
decimal = stringToDecimal(value.toExponential());
} else {
throw createInputError('DECIMAL');
}
var buffer = new Buffer(17);
buffer[0] = this.type;
bignum.writeDec128(buffer, decimal, 1);
return buffer;
}
function writeString(value) {
/* jshint validthis:true */
var length = Buffer.byteLength(value, 'utf8');
var buffer;
if (length <= 245) {
buffer = new Buffer(2 + length);
buffer[0] = this.type;
buffer[1] = length;
buffer.write(value, 2, length, 'utf8');
} else if (length <= 32767) {
buffer = new Buffer(4 + length);
buffer[0] = this.type;
buffer[1] = 246;
buffer.writeInt16LE(length, 2);
buffer.write(value, 4, length, 'utf8');
} else {
buffer = new Buffer(6 + length);
buffer[0] = this.type;
buffer[1] = 247;
buffer.writeInt32LE(length, 2);
buffer.write(value, 6, length, 'utf8');
}
return buffer;
}
function writeBinary(value) {
/* jshint validthis:true */
var length = value.length;
var buffer;
if (length <= 245) {
buffer = new Buffer(2 + length);
buffer[0] = this.type;
buffer[1] = length;
value.copy(buffer, 2);
} else if (length <= 32767) {
buffer = new Buffer(4 + length);
buffer[0] = this.type;
buffer[1] = 246;
buffer.writeInt16LE(length, 2);
value.copy(buffer, 4);
} else {
buffer = new Buffer(6 + length);
buffer[0] = this.type;
buffer[1] = 247;
buffer.writeInt32LE(length, 2);
value.copy(buffer, 6);
}
return buffer;
}
function writeLob(value) {
/* jshint validthis:true, bitwise:false */
var buffer = new Buffer(10);
buffer[0] = this.type;
buffer[1] = LobOptions.DATA_INCLUDED | LobOptions.LAST_DATA;
buffer.writeInt32LE(value.length, 2);
return buffer;
}
function writeTime(value) {
/* jshint validthis:true, bitwise:false */
var hours, minutes, milliseconds;
if (util.isString(value)) {
var time = value.match(REGEX.TIME);
if (!time) {
throw createInputError('TIME');
}
hours = ~~time[1];
minutes = ~~time[2];
milliseconds = Math.floor(time[3] * 1000);
} else {
throw createInputError('TIME');
}
var buffer = new Buffer(5);
buffer[0] = this.type;
buffer[1] = hours | 0x80;
buffer[2] = minutes;
buffer.writeUInt16LE(milliseconds, 3);
return buffer;
}
function writeDate(value) {
/* jshint validthis:true, bitwise:false */
var year, month, day;
if (util.isString(value)) {
var date = value.match(REGEX.DATE);
if (!date) {
throw createInputError('DATE');
}
year = ~~date[1];
month = ~~date[2] - 1;
day = ~~date[3];
} else {
throw createInputError('DATE');
}
var buffer = new Buffer(5);
buffer[0] = this.type;
buffer.writeUInt16LE(year, 1);
buffer[2] |= 0x80;
buffer[3] = month;
buffer[4] = day;
return buffer;
}
function writeTimestamp(value) {
/* jshint validthis:true, bitwise:false */
var year, month, day, hours, minutes, milliseconds;
if (util.isString(value)) {
var ts = value.match(REGEX.TIMESTAMP);
if (!ts) {
throw createInputError('TIMESTAMP');
}
year = ~~ts[1];
month = ~~ts[2] - 1;
day = ~~ts[3];
hours = ~~ts[4];
minutes = ~~ts[5];
milliseconds = Math.floor(ts[6] * 1000);
} else {
throw createInputError('TIMESTAMP');
}
var buffer = new Buffer(9);
buffer[0] = this.type;
buffer.writeUInt16LE(year, 1);
buffer[2] |= 0x80;
buffer[3] = month;
buffer[4] = day;
buffer[5] = hours | 0x80;
buffer[6] = minutes;
buffer.writeUInt16LE(milliseconds, 7);
return buffer;
}
function writeDayDate(value) {
/* jshint validthis:true, unused:false */
throw createNotImplementedError();
}
function writeSecondTime(value) {
/* jshint validthis:true, unused:false */
throw createNotImplementedError();
}
function writeLongDate(value) {
/* jshint validthis:true, unused:false */
throw createNotImplementedError();
}
function writeSecondDate(value) {
/* jshint validthis:true, unused:false */
throw createNotImplementedError();
}
var TINYINT = {
type: TypeCode.TINYINT,
write: writeTinyInt
};
var SMALLINT = {
type: TypeCode.SMALLINT,
write: writeSmallInt
};
var INT = {
type: TypeCode.INT,
write: writeInt
};
var BIGINT = {
type: TypeCode.BIGINT,
write: writeBigInt
};
var STRING = {
type: TypeCode.STRING,
write: writeString
};
var NSTRING = {
type: TypeCode.NSTRING,
write: writeString
};
var BINARY = {
type: TypeCode.BINARY,
write: writeBinary
};
var TIME = {
type: TypeCode.TIME,
write: writeTime
};
var DATE = {
type: TypeCode.DATE,
write: writeDate
};
var TIMESTAMP = {
type: TypeCode.TIMESTAMP,
write: writeTimestamp
};
var BLOB = {
type: TypeCode.BLOB,
write: writeLob
};
var NCLOB = {
type: TypeCode.NCLOB,
write: writeLob
};
var DOUBLE = {
type: TypeCode.DOUBLE,
write: writeDouble
};
var REAL = {
type: TypeCode.REAL,
write: writeReal
};
var DECIMAL = {
type: TypeCode.DECIMAL,
write: writeDecimal
};
var DAYDATE = {
type: TypeCode.DAYDATE,
write: writeDayDate
};
var SECONDTIME = {
type: TypeCode.SECONDTIME,
write: writeSecondTime
};
var LONGDATE = {
type: TypeCode.LONGDATE,
write: writeLongDate
};
var SECONDDATE = {
type: TypeCode.SECONDDATE,
write: writeSecondDate
};
var DataType = {};
// TinyInt
DataType[TypeCode.TINYINT] = TINYINT;
// SmallInt
DataType[TypeCode.SMALLINT] = SMALLINT;
// Int
DataType[TypeCode.INT] = INT;
// BigInt
DataType[TypeCode.BIGINT] = BIGINT;
// Double
DataType[TypeCode.DOUBLE] = DOUBLE;
// Real
DataType[TypeCode.REAL] = REAL;
// Decimal
DataType[TypeCode.DECIMAL] = DECIMAL;
// String
DataType[TypeCode.STRING] = STRING;
DataType[TypeCode.VARCHAR1] = STRING;
DataType[TypeCode.VARCHAR2] = STRING;
DataType[TypeCode.CHAR] = STRING;
DataType[TypeCode.SHORTTEXT] = STRING;
DataType[TypeCode.ALPHANUM] = STRING;
// NString
DataType[TypeCode.NCHAR] = NSTRING;
DataType[TypeCode.NVARCHAR] = NSTRING;
DataType[TypeCode.NSTRING] = NSTRING;
// Binary
DataType[TypeCode.BINARY] = BINARY;
DataType[TypeCode.VARBINARY] = BINARY;
DataType[TypeCode.BSTRING] = BINARY;
// BLob
DataType[TypeCode.BLOB] = BLOB;
DataType[TypeCode.LOCATOR] = BLOB;
// NCLob
DataType[TypeCode.CLOB] = NCLOB;
DataType[TypeCode.NCLOB] = NCLOB;
DataType[TypeCode.NLOCATOR] = NCLOB;
DataType[TypeCode.TEXT] = NCLOB;
// Date
DataType[TypeCode.DATE] = DATE;
// Time
DataType[TypeCode.TIME] = TIME;
// Timestamp
DataType[TypeCode.TIMESTAMP] = TIMESTAMP;
// DayDate
DataType[TypeCode.DAYDATE] = DAYDATE;
// SecondTime
DataType[TypeCode.SECONDTIME] = SECONDTIME;
// LongDate
DataType[TypeCode.LONGDATE] = LONGDATE;
// SecondDate
DataType[TypeCode.SECONDDATE] = SECONDDATE;
function stringToDecimal(str) {
/* jshint bitwise:false */
var dec = str.match(REGEX.DECIMAL);
if (!dec) {
throw createInputError('DECIMAL');
}
var sign = dec[1] === '-' ? -1 : 1;
var mInt = dec[2] || '0';
var mFrac = dec[3] || '';
var exp = ~~dec[4];
return {
s: sign,
m: mInt + mFrac,
e: exp - mFrac.length
};
}
function createInputError(type) {
return new Error(util.format('Wrong input for %s type', type));
}
function createNotImplementedError() {
return new Error('Not implemented yet');
}

@@ -60,3 +60,9 @@ // Copyright 2013 SAP AG.

util.inherits(SqlError, Error);
function SqlError() {
Error.call(this);
if (Error.captureStackTrace) {
Error.captureStackTrace(this, SqlError);
}
this.message = undefined;

@@ -63,0 +69,0 @@ this.code = undefined;

@@ -18,3 +18,3 @@ // Copyright 2013 SAP AG.

var EventEmitter = require('events').EventEmitter;
var Readable = require('stream').Readable;
var debug = util.debuglog('hdb_lob');

@@ -25,158 +25,75 @@ module.exports = Lob;

Lob.DEFAULT_READ_SIZE = Math.pow(2, 14);
Lob.DEFAULT_READ_SIZE = Math.pow(2, 17);
Lob.MAX_READ_SIZE = Math.pow(2, 18);
Lob.TYPE_BLOB = 0;
Lob.TYPE_CLOB = 1;
function Lob(connection, ld) {
function Lob(readLob, ld, options) {
EventEmitter.call(this);
this._connection = connection;
// public
this.locatorId = ld.locatorId;
this.finished = false;
// private
this._readLob = readLob;
this._running = undefined;
this._readSize = Lob.DEFAULT_READ_SIZE;
this.type = ld.type;
this.id = ld.locatorId;
this.byteLength = ld.byteLength;
this.charLength = ld.charLength;
this.finished = false;
this.offset = 0;
this._data = null;
if (Buffer.isBuffer(ld.chunk) && ld.chunk.length) {
var size = ld.chunk.length;
if (this.type === Lob.TYPE_CLOB) {
size = ld.chunk.toString('utf-8').length;
}
this._data = {
isLast: ld.isLast,
chunk: ld.chunk,
size: size
};
this._offset = 0;
options = options || {};
this._readSize = options.readSize || Lob.DEFAULT_READ_SIZE;
this._data = undefined;
if (ld.chunk) {
this._data = ld;
}
}
Lob.create = function createLob(connection, ld) {
return new Lob(connection, ld);
Lob.prototype.pause = function pause() {
this._running = false;
};
Object.defineProperties(Lob.prototype, {
readSize: {
get: function getFetchSize() {
return this._readSize;
}
Lob.prototype.resume = function resume() {
if (this._running || this.finished) {
return;
}
});
Lob.prototype.setReadSize = function setReadSize(readSize) {
if (readSize > Lob.MAX_READ_SIZE) {
this._readSize = Lob.MAX_READ_SIZE;
this._running = true;
if (util.isObject(this._data)) {
handleData.call(this, this._data);
this._data = undefined;
} else {
sendReadLob.call(this);
}
this._readSize = readSize;
return this;
};
Lob.prototype.end = function end() {
this.finished = true;
this._running = false;
this._connection = undefined;
process.nextTick(emitEnd.bind(this));
};
function emitEnd() {
/* jshint validthis:true */
debug('emit "end"');
this.emit('end');
}
Lob.prototype.read = function read(cb) {
if (typeof this._running !== 'undefined') {
if (!util.isUndefined(this._running)) {
var err = new Error('Lob invalid state error');
return cb(err);
}
readLob(this, cb);
util.readData(this, cb);
};
Lob.prototype.createReadStream = function createReadStream(options) {
if (typeof this._running !== 'undefined') {
if (!util.isUndefined(this._running)) {
return null;
}
return createReadLobStream(this, options);
};
Lob.prototype.stopRead = function stopRead() {
this._running = false;
return this;
return util.createReadStream(this, ['error'], options);
};
Lob.prototype.startRead = function startRead() {
if (!this._running && !this.finished) {
this._running = true;
if (util.isObject(this._data)) {
handleData.call(this, this._data);
this._data = undefined;
} else {
sendReadLob.call(this);
}
}
return this;
};
function createReadLobStream(lob, options) {
options = options || {};
var readable = new Readable(options);
readable._read = function _read() {
lob.startRead();
};
function cleanup() {
lob.removeListener('error', onerror);
lob.removeListener('data', ondata);
lob.removeListener('end', onend);
}
function onerror(err) {
cleanup();
readable.emit('error', err);
}
lob.on('error', onerror);
function ondata(chunk) {
if (!readable.push(chunk)) {
lob.stopFetch();
}
}
lob.on('data', ondata);
function onend() {
cleanup();
readable.push(null);
}
lob.on('end', onend);
return readable;
}
function readLob(lob, cb) {
var offset = 0;
var buffer = new Buffer(lob.byteLength);
function done(err) {
lob.removeListener('error', onerror);
lob.removeListener('data', ondata);
lob.removeListener('end', onend);
if (util.isFunction(cb)) {
cb(err, buffer);
}
}
function onerror(err) {
done(err);
}
lob.on('error', onerror);
function ondata(chunk) {
chunk.copy(buffer, offset);
offset += chunk.length;
}
lob.on('data', ondata);
function onend() {
done(null);
}
lob.on('end', onend);
lob.startRead();
}
function sendReadLob() {
/* jshint validthis:true */
this._connection.readLob({
locatorId: this.id,
offset: this.offset + 1,
debug('sendReadLob', this.locatorId);
this._readLob({
locatorId: this.locatorId,
offset: this._offset + 1,
length: this._readSize

@@ -188,3 +105,3 @@ }, receiveData.bind(this));

/* jshint validthis:true */
debug('receiveData()');
if (err) {

@@ -206,5 +123,6 @@ this._running = false;

/* jshint validthis:true */
var size = data.size || this._readSize;
debug('handleData(%d)', size);
if (Buffer.isBuffer(data.chunk)) {
this.offset += data.size || this._readSize;
this._offset += size;
this.emit('data', data.chunk);

@@ -214,6 +132,3 @@ }

if (data.isLast) {
this.finished = true;
this._running = false;
process.nextTick(this.emit.bind(this, 'end'));
return;
return this.end();
}

@@ -220,0 +135,0 @@

@@ -16,426 +16,72 @@ // Copyright 2013 SAP AG.

var util = require('../util');
var util = require('util');
var common = require('./common');
var bignum = util.bignum;
var ResultSetTransform = require('./ResultSetTransform');
var Reader = require('./Reader');
var ReadFunction = common.ReadFunction;
var TypeCode = common.TypeCode;
var READ_TINYINT = 'readTinyInt()';
var READ_SMALLINT = 'readSmallInt()';
var READ_INT = 'readInt()';
var READ_BIGINT = 'readBigInt()';
var READ_STRING = 'readBytes(\'utf-8\')';
var READ_BINARY = 'readBytes()';
var READ_DATE = 'readDate()';
var READ_DAYDATE = 'readDayDate()';
var READ_TIME = 'readTime()';
var READ_SECONDTIME = 'readSecondTime()';
var READ_TIMESTAMP = 'readTimestamp()';
var READ_LONGDATE = 'readLongDate()';
var READ_SECONDDATE = 'readSecondDate()';
var READ_LOB = 'readLob(0)';
var READ_NCLOB = 'readLob(1)';
var READ_DOUBLE = 'readDouble()';
var READ_FLOAT = 'readFloat()';
var READ_DECIMAL = 'readDecimal(%d)';
var readFunctionMap = {};
readFunctionMap[TypeCode.TINYINT] = READ_TINYINT;
readFunctionMap[TypeCode.SMALLINT] = READ_SMALLINT;
readFunctionMap[TypeCode.INT] = READ_INT;
readFunctionMap[TypeCode.BIGINT] = READ_BIGINT;
readFunctionMap[TypeCode.STRING] = READ_STRING;
readFunctionMap[TypeCode.VARCHAR1] = READ_STRING;
readFunctionMap[TypeCode.VARCHAR2] = READ_STRING;
readFunctionMap[TypeCode.CHAR] = READ_STRING;
readFunctionMap[TypeCode.NCHAR] = READ_STRING;
readFunctionMap[TypeCode.NVARCHAR] = READ_STRING;
readFunctionMap[TypeCode.NSTRING] = READ_STRING;
readFunctionMap[TypeCode.SHORTTEXT] = READ_STRING;
readFunctionMap[TypeCode.ALPHANUM] = READ_STRING;
readFunctionMap[TypeCode.BINARY] = READ_BINARY;
readFunctionMap[TypeCode.VARBINARY] = READ_BINARY;
readFunctionMap[TypeCode.BSTRING] = READ_BINARY;
readFunctionMap[TypeCode.DATE] = READ_DATE;
readFunctionMap[TypeCode.TIME] = READ_TIME;
readFunctionMap[TypeCode.TIMESTAMP] = READ_TIMESTAMP;
readFunctionMap[TypeCode.DAYDATE] = READ_DAYDATE;
readFunctionMap[TypeCode.SECONDTIME] = READ_SECONDTIME;
readFunctionMap[TypeCode.LONGDATE] = READ_LONGDATE;
readFunctionMap[TypeCode.SECONDDATE] = READ_SECONDDATE;
readFunctionMap[TypeCode.BLOB] = READ_LOB;
readFunctionMap[TypeCode.LOCATOR] = READ_LOB;
readFunctionMap[TypeCode.CLOB] = READ_NCLOB;
readFunctionMap[TypeCode.NCLOB] = READ_NCLOB;
readFunctionMap[TypeCode.NLOCATOR] = READ_NCLOB;
readFunctionMap[TypeCode.TEXT] = READ_NCLOB;
readFunctionMap[TypeCode.DOUBLE] = READ_DOUBLE;
readFunctionMap[TypeCode.REAL] = READ_FLOAT;
readFunctionMap[TypeCode.DECIMAL] = READ_DECIMAL;
function createFunctionBody(metadata, nameProperty) {
var functionBody = ['var obj = {};'];
metadata.forEach(function (column, index) {
var fn = readFunctionMap[column.dataType];
if (column.dataType === TypeCode.DECIMAL) {
fn = util.format(fn, column.fraction);
}
var key = (typeof nameProperty === 'string') ? column[nameProperty] :
index;
functionBody.push('obj["' + key + '"] = this.' + fn + ';');
});
functionBody.push('return obj;');
return functionBody.join('\n');
}
module.exports = Parser;
Parser.DEFAULT_THRESHOLD = 128;
function Parser(metadata, options) {
/*jshint evil:true */
options = options || {};
if (typeof options.nameProperty === 'undefined') {
options.nameProperty = 'columnDisplayName';
}
this._parseRow = new Function(createFunctionBody(metadata, options.nameProperty));
this._threshold = options.threshold || Parser.DEFAULT_THRESHOLD;
this._queue = [];
this.taskId = 0;
if (typeof setImmediate !== 'undefined') {
this._setImmediate = setImmediate;
} else {
this._setImmediate = process.nextTick;
}
function Parser(metadata) {
this.metadata = metadata;
}
Parser.prototype.parse = function parse(buffer, target, done) {
var task = new ParserTask(buffer, target, done);
task.id = ++this.taskId;
if (this._queue.push(task) === 1) {
executeTask(this);
}
Parser.create = function createParser(metadata) {
return new Parser(metadata);
};
Parser.prototype.parseParameters = function parseParameters(buffer) {
return this._parseRow.call(new ParserState(buffer));
Parser.parseParameters = function parseParameters(metadata, buffer) {
return Parser.create(metadata).parseParams(buffer);
};
function executeTask(parser) {
var task = parser._queue[0];
if (task.active) return;
task.active = true;
var state = task.state;
var target = task.target;
var parseRow = parser._parseRow.bind(state);
var bufferLength = state.buffer.length;
function read() {
for (var i = 0; i < parser._threshold && state.offset < bufferLength; i++) {
target.push(parseRow());
}
return state.offset < bufferLength;
}
function done(err) {
task.done(err);
parser._queue.shift();
if (err) return;
if (parser._queue.length) {
executeTask(parser);
}
}
function next() {
parser._setImmediate(function () {
var bytesRemaining;
try {
bytesRemaining = read();
} catch (err) {
return done(err);
}
if (bytesRemaining > 0) {
next();
} else {
done(null);
}
});
}
next();
}
function ParserTask(buffer, target, callback) {
this.state = new ParserState(buffer);
this.active = false;
var self = this;
if (typeof target === 'function') {
this.target = [];
callback = target;
this.done = function (err) {
callback(err, self.target);
};
} else {
this.target = target;
this.done = function (err) {
callback(err);
};
}
}
function ParserState(buffer) {
this.buffer = buffer;
this.offset = 0;
}
ParserState.prototype.readTinyInt = function () {
if (this.buffer[this.offset++] === 0x00) {
return null;
}
/*
var uInt = this.buffer[this.offset++];
if (!(uInt & 0x80))
return uInt;
return ((0xff - uInt + 1) * -1);
*/
var value = this.buffer.readInt8(this.offset);
this.offset += 1;
return value;
Parser.prototype.createParseRowFunction = function createParseRowFunction() {
return this.createParseFunction('columnDisplayName');
};
ParserState.prototype.readSmallInt = function () {
if (this.buffer[this.offset++] === 0x00) {
return null;
}
var value = this.buffer.readInt16LE(this.offset);
this.offset += 2;
return value;
Parser.prototype.createParseParamsFunction = function createParseParamsFunction() {
return this.createParseFunction('name');
};
ParserState.prototype.readInt = function () {
if (this.buffer[this.offset++] === 0x00) {
return null;
}
var value = this.buffer.readInt32LE(this.offset);
this.offset += 4;
return value;
Parser.prototype.createParseFunction = function createParseFunction(name) {
/*jshint evil:true */
return new Function(createFunctionBody(this.metadata, name ||
'columnDisplayName'));
};
ParserState.prototype.readBigInt = function () {
if (this.buffer[this.offset++] === 0x00) {
return null;
}
var value = bignum.readInt64LE(this.buffer, this.offset);
this.offset += 8;
return value;
Parser.prototype.parseParams = function parseParams(buffer) {
var reader = new Reader(buffer);
var parseParamsFunction = this.createParseParamsFunction();
return parseParamsFunction.call(reader);
};
ParserState.prototype.readString = function () {
this.readBytes('utf-8');
};
ParserState.prototype.readBinary = function () {
this.readBytes();
};
ParserState.prototype.readBytes = function (encoding) {
var length = this.buffer[this.offset++];
switch (length) {
case 0xff:
return null;
case 0xf6:
length = this.buffer.readInt16LE(this.offset);
this.offset += 2;
break;
case 0xf7:
length = this.buffer.readInt32LE(this.offset);
this.offset += 4;
break;
Parser.prototype.parse = function parse(buffer) {
var reader = new Reader(buffer);
var parseRow = this.createParseRowFunction().bind(reader);
var rows = [];
while (reader.hasMore()) {
rows.push(parseRow());
}
var value;
if (encoding) {
value = this.buffer.toString(encoding, this.offset, this.offset + length);
} else {
value = new Buffer(length);
this.buffer.copy(value, 0, this.offset, this.offset + length);
}
this.offset += length;
return value;
return rows;
};
ParserState.prototype.readDate = function () {
if (!(this.buffer[this.offset + 1] & 0x80)) {
this.offset += 4;
return null;
}
var year = this.buffer.readInt16LE(this.offset);
if (year & 0x8000) year = year & 0x7fff;
if (year & 0x4000) year = year | 0x8000;
var month = this.buffer.readInt8(this.offset + 2) + 1;
var day = this.buffer.readInt8(this.offset + 3);
this.offset += 4;
return bignum.lpad4(year) + '-' + bignum.lpad2(month) + '-' + bignum.lpad2(
day);
Parser.prototype.createTransform = function createTransform(rs, options) {
return new ResultSetTransform(this.createParseRowFunction(), rs, options);
};
ParserState.prototype.readTime = function () {
if (!(this.buffer[this.offset] & 0x80)) {
this.offset += 4;
return null;
}
var hour = this.buffer.readInt8(this.offset);
if (hour & 0x80) hour = hour & 0x7f;
var min = this.buffer.readInt8(this.offset + 1);
var msec = this.buffer.readUInt16LE(this.offset + 2);
this.offset += 4;
return bignum.lpad2(hour) + ':' + bignum.lpad2(min) + ':' + bignum.lpad2(msec /
1000);
};
function createFunctionBody(metadata, nameProperty) {
var functionBody = ['var obj = {};'];
ParserState.prototype.readTimestamp = function () {
var date = this.readDate();
var time = this.readTime();
if (!date && !time) {
return null;
} else if (date && time) {
return date + 'T' + time;
} else if (date) {
return date;
} else {
return time;
function addParseColumnLine(column, index) {
var fn = ReadFunction[column.dataType];
if (column.dataType === TypeCode.DECIMAL) {
fn = util.format(fn, column.fraction);
}
var key = (typeof nameProperty === 'string') ? column[nameProperty] :
index;
functionBody.push('obj["' + key + '"] = this.' + fn + ';');
}
};
ParserState.prototype.readDayDate = function () {
var value = this.buffer.readInt32LE(this.offset);
this.offset += 4;
if (value === 3652062 || value === 0) {
return null;
}
return value - 1;
};
ParserState.prototype.readSecondTime = function () {
var value = this.buffer.readInt32LE(this.offset);
this.offset += 4;
if (value === 86402 || value === 0) {
return null;
}
return value - 1;
};
ParserState.prototype.readSecondDate = function () {
var value = bignum.readInt64LE(this.buffer, this.offset);
this.offset += 8;
if (value === 315538070401) {
return null;
}
return value - 1;
};
ParserState.prototype.readLongDate = function () {
var value = bignum.readInt64LE(this.buffer, this.offset);
this.offset += 8;
if (value === '3155380704000000001') {
return null;
}
if (typeof value === 'string') {
var index = value.length - 7;
return value.substring(0, index) + lpad7(value.substring(index) - 1);
} else {
return value - 1;
}
};
ParserState.prototype.readLob = function readLob(type) {
// skip source type
this.offset += 1;
// offset 1
var options = this.buffer[this.offset];
this.offset += 1;
// offset 2
if ( !! (options & 0x01)) {
return null;
}
// skip 2 byte filler
this.offset += 2;
// offset 4
var charLength = bignum.readInt64LE(this.buffer, this.offset);
this.offset += 8;
// offset 12
var byteLength = bignum.readInt64LE(this.buffer, this.offset);
this.offset += 8;
// offset 20
var locatorId = this.buffer.slice(this.offset, this.offset + 8);
this.offset += 8;
// offset 28
var chunkLength = this.buffer.readInt32LE(this.offset);
this.offset += 4;
// offset 32
var chunk = this.buffer.slice(this.offset, this.offset + chunkLength);
this.offset += chunkLength;
// is last
var isLast = !! (options & 0x04);
if (isLast) {
return chunk;
}
return {
type: type,
locatorId: locatorId,
charLength: charLength,
byteLength: byteLength,
isLast: isLast,
chunk: chunk
};
};
ParserState.prototype.readNCLob = function () {
if (this.buffer[this.offset + 1] === 0x01) {
this.offset += 2;
return null;
}
var length = this.buffer.readInt32LE(this.offset + 28);
this.offset += 32;
var value = this.buffer.toString('utf-8', this.offset, this.offset + length);
this.offset += length;
return value;
};
ParserState.prototype.readDouble = function () {
if (this.buffer[this.offset] === 0xff &&
this.buffer[this.offset + 1] === 0xff &&
this.buffer[this.offset + 2] === 0xff &&
this.buffer[this.offset + 3] === 0xff &&
this.buffer[this.offset + 4] === 0xff &&
this.buffer[this.offset + 5] === 0xff &&
this.buffer[this.offset + 6] === 0xff &&
this.buffer[this.offset + 7] === 0xff) {
this.offset += 8;
return null;
}
var value = this.buffer.readDoubleLE(this.offset);
this.offset += 8;
return value;
};
ParserState.prototype.readFloat = function () {
if (this.buffer[this.offset] === 0xff && this.buffer[this.offset + 1] ===
0xff && this.buffer[this.offset + 2] === 0xff && this.buffer[this.offset +
3] === 0xff) {
this.offset += 4;
return null;
}
var value = this.buffer.readFloatLE(this.offset);
this.offset += 4;
return value;
};
ParserState.prototype.readDecimal = function (fraction) {
var value;
if (fraction > 34) {
value = bignum.readDecFloat(this.buffer, this.offset);
} else {
value = bignum.readDecFixed(this.buffer, this.offset, fraction);
}
this.offset += 16;
return value;
};
metadata.forEach(addParseColumnLine);
functionBody.push('return obj;');
return functionBody.join('\n');
}

@@ -42,18 +42,20 @@ // Copyright 2013 SAP AG.

Segment.prototype.add = function add(kind, options) {
if (options) {
var dataModule;
if (util.isNumber(kind)) {
dataModule = data[kind];
} else {
dataModule = kind.module;
kind = kind.kind;
}
var part = new Part({
kind: kind
Segment.prototype.add = function add(kind, args) {
if (!args) {
return;
}
if (util.isNumber(kind)) {
this.parts.push({
kind: kind,
args: args
});
part.argumentCount = dataModule.getArgumentCount(options);
dataModule.write(part, options);
this.parts.push(part);
return;
}
if (util.isObject(kind)) {
this.parts.push({
kind: kind.kind,
module: kind.module,
args: args
});
}
};

@@ -65,8 +67,10 @@

var length = SEGMENT_HEADER_LENGTH;
var buffers = this.parts.map(function (part) {
var buffer = part.toBuffer(remainingSize);
var buffers = [];
for (var i = 0; i < this.parts.length; i++) {
this.parts[i]
var buffer = partToBuffer(this.parts[i], remainingSize);
remainingSize -= buffer.length;
length += buffer.length;
return buffer;
});
buffers.push(buffer);
};

@@ -95,2 +99,12 @@ var header = new Buffer(SEGMENT_HEADER_LENGTH);

return Buffer.concat(buffers, length);
};
};
function partToBuffer(pd, remainingSize) {
var m = pd.module || data[pd.kind];
var part = new Part({
kind: pd.kind
});
part.argumentCount = m.getArgumentCount(pd.args);
m.write(part, pd.args, remainingSize);
return part.toBuffer(remainingSize);
}

@@ -25,7 +25,5 @@ // Copyright 2013 SAP AG.

function Result(connection, options) {
options = util.extend({
autoFetch: true
}, options);
options = options || {};
this._connection = connection;
this._autoFetch = options.autoFetch;
this._resultSetMode = options.resultSetMode || options.autoFetch === false;
this._resultSetMetadata = undefined;

@@ -44,3 +42,2 @@ this._parameterMetadata = undefined;

Result.prototype.handle = function handle(err, reply, cb) {
if (err) {

@@ -50,35 +47,13 @@ return cb(err);

var args = [null];
var resultSets = reply.resultSets || [];
var outputParameters = {};
// handle missing resultSet metadata
if (this._resultSetMetadata && resultSets.length) {
if (!resultSets[0].metadata) {
resultSets[0].metadata = this._resultSetMetadata;
}
}
// output parameter
if (this._parameterMetadata && util.isObject(reply.outputParameters)) {
outputParameters = getOutputParameters(this._parameterMetadata,
reply.outputParameters.buffer);
}
function onresults(err, results) {
if (err) {
return cb(err);
}
Array.prototype.push.apply(args, results);
cb.apply(null, args);
}
switch (reply.functionCode) {
case FunctionCode.SELECT:
case FunctionCode.SELECT_FOR_UPDATE:
this.createResultSets(resultSets, onresults);
this.handleQuery(cb, this.createResultSets(reply.resultSets));
return;
case FunctionCode.INSERT:
case FunctionCode.UPDATE:
this.handleModify(cb, reply.rowsAffected, reply.writeLobReply);
return;
case FunctionCode.DELETE:
cb(null, reply.rowsAffected);
this.handleDelete(cb, reply.rowsAffected);
return;

@@ -90,4 +65,5 @@ case FunctionCode.DDL:

case FunctionCode.DB_PROCEDURE_CALL_WITH_RESULT:
args.push(outputParameters);
this.createResultSets(resultSets, onresults);
this.handleDBCall(cb,
this.createOutputParameters(reply.outputParameters),
this.createResultSets(reply.resultSets));
return;

@@ -97,39 +73,92 @@ default:

cb(err);
return;
}
};
Result.prototype.createResultSets = function createResultSets(resultSets, cb) {
if (!resultSets.length) {
return cb(null, []);
Result.prototype.handleModify = function handleModify(cb, rowsAffected,
writeLobReply) {
cb(null, rowsAffected, writeLobReply);
};
Result.prototype.handleDelete = function handleDelete(cb, rowsAffected) {
cb(null, rowsAffected);
};
Result.prototype.handleQuery = function handleQuery(cb, resultSets) {
function done(err, results) {
if (err) {
return cb(err);
}
var args = [null];
Array.prototype.push.apply(args, results);
return cb.apply(null, args);
}
var resultSetObjects = [];
for (var i = 0; i < resultSets.length; i++) {
resultSetObjects.push(new ResultSet(this._connection, resultSets[i]));
if (this._resultSetMode) {
return done(null, resultSets);
}
if (!this._autoFetch) {
return cb(null, resultSetObjects);
fetchAll(resultSets, done);
};
Result.prototype.handleDBCall = function handleDBCall(cb, params, resultSets) {
function done(err, results) {
if (err) {
return cb(err);
}
var args = [null, params || {}];
Array.prototype.push.apply(args, results);
return cb.apply(null, args);
}
fetchAll(resultSetObjects, cb);
if (this._resultSetMode) {
return done(null, resultSets);
}
fetchAll(resultSets, done);
};
function getOutputParameters(metadata, buffer) {
var parser = new Parser(metadata, {
nameProperty: 'name',
});
return parser.parseParameters(buffer);
function createResultSets(resultSets) {
/* jshint validthis:true */
resultSets = resultSets || [];
// handle missing resultSet metadata
if (this._resultSetMetadata && resultSets.length) {
if (!resultSets[0].metadata) {
resultSets[0].metadata = this._resultSetMetadata;
}
}
return resultSets.map(createResultSet, this._connection);
}
Result.prototype.createResultSets = createResultSets;
function createOutputParameters(outputParameters) {
/* jshint validthis:true */
if (this._parameterMetadata && util.isObject(outputParameters)) {
return Parser.parseParameters(this._parameterMetadata, outputParameters.buffer);
}
return null;
}
Result.prototype.createOutputParameters = createOutputParameters;
function createResultSet(rsd) {
/* jshint validthis:true */
return new ResultSet(this, rsd);
}
function fetchAll(resultSets, cb) {
var results = [];
function isOpen(rs) {
return !rs.closed;
}
function handleClose(err) {
if (err) {
// ignore errors
}
}
function close(rs) {
rs.close(handleClose);
}
function done(err) {
resultSets.filter(function isOpen(rs) {
return !rs.closed;
}).forEach(function close(rs) {
rs.close(function onclose(err) {
console.log('close', err)
});
});
resultSets.filter(isOpen).forEach(close);
if (err) {

@@ -145,3 +174,4 @@ return cb(err);

}
resultSets[i].fetch(function onfetch(err, rows) {
function handleFetch(err, rows) {
if (err) {

@@ -152,5 +182,6 @@ return done(err);

process.nextTick(next.bind(null, i + 1));
});
}
resultSets[i].fetch(handleFetch);
}
next(0);
}

@@ -18,7 +18,8 @@ // Copyright 2013 SAP AG.

var EventEmitter = require('events').EventEmitter;
var Readable = require('stream').Readable;
var common = require('./common');
var Parser = require('./Parser');
var Lob = require('./Lob');
var ResultSetAttributes = common.ResultSetAttributes;
var TypeCode = common.TypeCode;
var debug = util.debuglog('hdb_rs');

@@ -31,2 +32,4 @@ module.exports = ResultSet;

ResultSet.DEFAULT_FETCH_SIZE = Math.pow(2, 10);
ResultSet.DEFAULT_ROW_LENGTH = Math.pow(2, 6);
ResultSet.DEFAULT_ARRAY_LENGTH = Math.pow(2, 8);

@@ -46,2 +49,4 @@ function ResultSet(connection, rsd) {

this._fetchSize = ResultSet.DEFAULT_FETCH_SIZE;
this._rowLength = ResultSet.DEFAULT_ROW_LENGTH;
this._readSize = Lob.DEFAULT_READ_SIZE;
}

@@ -58,2 +63,12 @@

}
},
averageRowLength: {
get: function getAverageRowLength() {
return this._rowLength;
}
},
readSize: {
get: function getReadSize() {
return this._readSize;
}
}

@@ -70,44 +85,30 @@ });

ResultSet.prototype.fetch = function fetch(cb) {
var self = this;
function done(err, rows) {
/* jshint validthis:true */
if (util.isFunction(cb)) {
cb(err, rows, self.closed);
}
}
if (typeof this._running !== 'undefined') {
var err = new Error('ResultSet invalid state error');
return done(err);
}
fetchRows(this, done);
ResultSet.prototype.setAverageRowLength = function setAverageRowLength(length) {
this._rowLength = length;
return this;
};
ResultSet.prototype.createReadStream = function createReadStream(options) {
if (typeof this._running !== 'undefined') {
return null;
ResultSet.prototype.setReadSize = function setReadSize(readSize) {
if (readSize > Lob.MAX_READ_SIZE) {
this._readSize = Lob.MAX_READ_SIZE;
}
return createResultSetStream(this, options);
this._readSize = readSize;
return this;
};
ResultSet.prototype.stopFetch = function stopFetch() {
ResultSet.prototype.pause = function pause() {
this._running = false;
return this;
};
ResultSet.prototype.startFetch = function startFetch() {
if (!this._running && !this.finished) {
this._running = true;
if (util.isObject(this._data)) {
handleData.call(this, this._data);
this._data = undefined;
} else {
sendFetch.call(this);
}
ResultSet.prototype.resume = function resume() {
if (this._running || this.finished) {
return;
}
return this;
this._running = true;
if (util.isObject(this._data)) {
handleData.call(this, this._data);
this._data = undefined;
} else {
sendFetch.call(this);
}
};

@@ -121,193 +122,107 @@

}
return this;
};
ResultSet.prototype.createParser = function createParser(treshhold) {
return new Parser(this.metadata, {
treshhold: treshhold || 0
});
ResultSet.prototype.getLobColumnNames = function getLobColumnNames() {
return this.metadata.filter(isLob).map(getColumName);
};
ResultSet.prototype.readLob = function readLob(ld, cb) {
Lob.create(this._connection, ld).read(cb);
};
ResultSet.prototype.fetch = function fetch(cb) {
var stream = this.createArrayStream();
var collector = new util.stream.Writable({
objectMode: true,
highWaterMark: 16
});
collector.rows = [];
collector.columns = this.getLobColumnNames();
if (collector.columns.length) {
collector._write = collectLobRows;
} else {
collector._write = collectRows;
}
ResultSet.prototype.createLobStream = function createLobStream(ld, options) {
return new Lob(this._connection, ld).createReadStream(options);
};
function createResultSetStream(rs, options) {
var parser = rs.createParser();
options = options || {};
options.objectMode = true;
var readable = new Readable(options);
readable._read = function _read() {
rs.startFetch();
};
var finished = false;
var pending = 0;
function cleanup() {
if (finished) {
return;
}
finished = true;
rs.removeListener('error', onerror);
rs.removeListener('data', ondata);
rs.removeListener('end', onend);
function done(err, rows) {
stream.removeListener('error', onerror);
collector.removeListener('finish', onfinish);
cb(err, rows);
}
function onerror(err) {
cleanup();
readable.emit('error', err);
done(err);
}
rs.once('error', onerror);
function ondata(count, chunk) {
var rows = [];
pending += 1;
parser.parse(chunk, rows, function parsed(err) {
pending -= 1;
if (err) {
cleanup();
readable.emit('error', err);
return;
}
if (!readable.push(rows)) {
rs.stopFetch();
}
if (pending === 0 && finished) {
readable.push(null);
}
});
function onfinish() {
done(null, this.rows);
}
rs.on('data', ondata);
function onend(closed) {
cleanup();
if (!closed && rs._close) {
sendClose.call(rs);
}
if (pending === 0) {
readable.push(null);
}
}
rs.once('end', onend);
return readable;
stream.on('error', onerror).pipe(collector).on('finish', onfinish);
}
function rowReadLob(connection, row, name, cb) {
if (!row[name] || Buffer.isBuffer(row[name])) {
return cb();
ResultSet.prototype.createBinaryStream = function createBinaryStream(options) {
if (!util.isUndefined(this._running)) {
return null;
}
function done(err, buffer) {
if (err) {
return cb(err);
}
row[name] = buffer;
cb();
}
Lob.create(connection, row[name]).read(done);
}
options = util.extend({
highWaterMark: Math.floor(1.5 * this._fetchSize * this._rowLength)
}, options);
options.objectMode = false;
return util.createReadStream(this, ['error', 'close'], options);
};
function rowReadLobs(connection, row, names, cb) {
var i = 0;
ResultSet.prototype.createParser = function createParser(options) {
return Parser.create(this.metadata).createTransform(this, options);
};
function next() {
// ignore errors
if (i === names.length) {
return cb();
}
process.nextTick(rowReadLob.bind(null, connection, row, names[i], next));
i += 1;
}
next();
}
ResultSet.prototype.createObjectStream = function createObjectStream(options) {
options = util.extend({}, options);
options.arrayMode = false;
function readLobs(connection, rows, names, cb) {
var i = 0;
return util.pipe(this.createBinaryStream(), this.createParser(options));
};
function next() {
// ignore errors
if (i === rows.length) {
return cb(null, rows);
}
process.nextTick(rowReadLobs.bind(null, connection, rows[i], names, next));
i += 1;
ResultSet.prototype.createArrayStream = function createArrayStream(options) {
if (util.isNumber(options) || options === true) {
options = {
arrayMode: options
};
} else if (util.isObject(options)) {
options = util.extend({}, options);
} else {
options = {
arrayMode: ResultSet.DEFAULT_ARRAY_LENGTH
};
}
next();
}
function fetchRows(rs, cb) {
return util.pipe(this.createBinaryStream(), this.createParser(options));
};
var parser = rs.createParser();
var lobs = rs.metadata.filter(isLob).map(getColumName);
var rows = [];
var finished = false;
var pending = 0;
ResultSet.prototype.createReadStream = function createReadStream(options) {
options = options || {};
function done(err) {
if (err) {
return cb(err);
}
if (!lobs.length) {
return cb(null, rows);
}
readLobs(rs._connection, rows, lobs, cb);
if (options.objectMode === false) {
return this.createBinaryStream(options);
}
function cleanup() {
if (finished) {
return;
}
finished = true;
rs.removeListener('error', onerror);
rs.removeListener('data', ondata);
rs.removeListener('end', onend);
if (options.arrayMode) {
return this.createArrayStream(options);
}
return this.createObjectStream(options);
};
function onerror(err) {
cleanup();
done(err);
}
rs.on('error', onerror);
ResultSet.prototype.createLob = function createLob(ld, options) {
options = util.extend({
readSize: this._readSize
}, options);
return new Lob(sendReadLob.bind(this), ld, options);
};
function ondata(count, chunk) {
pending += 1;
parser.parse(chunk, rows, function parsed(err) {
pending -= 1;
if (err) {
cleanup();
done(err);
return;
}
if (pending === 0 && finished) {
done(null);
}
});
}
rs.on('data', ondata);
function onend() {
cleanup();
if (pending === 0) {
done(null);
}
}
rs.on('end', onend);
rs.startFetch();
}
function sendClose() {
/* jshint validthis:true */
debug('sendClose');
function done(err) {
this._connection = undefined;
if (!err) {
if (err) {
debug('close failed: %s', err);
} else {
this.closed = true;
emitClose.call(this);
this.emit('close');

@@ -326,3 +241,3 @@ }

/* jshint validthis:true */
debug('sendFetch(%d)', this.fetchSize);
this._connection.fetchNext({

@@ -334,7 +249,13 @@ resultSetId: this.id,

function sendReadLob(req, cb) {
/* jshint validthis:true */
this._connection.readLob(req, cb);
}
function receiveData(err, reply) {
/* jshint validthis:true */
debug('receiveData()');
if (err) {
this._running = false;
debug('emit "error": %s', err);
this.emit('error', err);

@@ -354,5 +275,6 @@ return;

/* jshint validthis:true */
debug('handleData(%d)', data.argumentCount);
if (data.argumentCount && Buffer.isBuffer(data.buffer)) {
this.emit('data', data.argumentCount, data.buffer);
debug('emit "data": length=%d', data.buffer.length);
this.emit('data', data.buffer);
}

@@ -364,8 +286,3 @@

this.closed = isClosed(data);
this.emit('end', this.closed);
if (this.closed) {
process.nextTick(this.emit.bind(this, 'close'));
} else if (util.isFunction(this._close)) {
sendClose.call(this);
}
process.nextTick(emitEnd.bind(this));
return;

@@ -379,5 +296,22 @@ }

function emitEnd() {
/* jshint validthis:true */
debug('emit "end"');
this.emit('end');
if (this.closed) {
process.nextTick(emitClose.bind(this));
} else if (util.isFunction(this._close)) {
sendClose.call(this);
}
}
function emitClose() {
/* jshint validthis:true */
debug('emit "close"');
this.emit('close');
}
function isLast(data) {
/* jshint bitwise:false */
return !!(data.attributes & common.ResultSetAttributes.LAST);
return !!(data.attributes & ResultSetAttributes.LAST);
}

@@ -387,3 +321,3 @@

/* jshint bitwise:false */
return !!(data.attributes & common.ResultSetAttributes.CLOSED);
return !!(data.attributes & ResultSetAttributes.CLOSED);
}

@@ -407,2 +341,63 @@

return column.columnDisplayName;
}
function collectRows(rows, encoding, done) {
/* jshint validthis:true */
for (var i = 0; i < rows.length; i++) {
this.rows.push(rows[i]);
}
done();
}
function collectLobRows(rows, encoding, done) {
/* jshint validthis:true */
var self = this;
var i = 0;
function handleRow(err) {
if (err) {
return done(err);
}
// next row
i += 1;
next();
}
function next() {
if (i === rows.length) {
return done(null, rows);
}
util.setImmediate(collectLobRow.bind(self, rows[i], handleRow));
}
next();
}
function collectLobRow(row, done) {
/* jshint validthis:true */
var self = this;
var i = 0;
function receiveLob(err, buffer) {
if (err) {
return done(err);
}
// update lob
row[self.columns[i]] = buffer;
// next lob
i += 1;
next();
}
function next() {
if (i === self.columns.length) {
self.rows.push(row);
return done(null);
}
var lob = row[self.columns[i]];
if (lob === null || Buffer.isBuffer(lob)) {
return receiveLob(null, lob);
}
lob.read(receiveLob);
}
next();
}

@@ -37,22 +37,11 @@ // Copyright 2013 SAP AG.

};
if (util.isFunction(options)) {
cb = options;
options = defaults;
} else if (util.isObject(options)) {
options = util.extend(defaults, options);
} else {
var autoFetch = !! options;
options = defaults;
options.autoFetch = autoFetch;
}
executeStatement.call(this, defaults, values, options, cb);
return this;
};
var result = new Result(this._connection, options);
result.setResultSetMetadata(this.resultSetMetadata);
result.setParameterMetadata(this.parameterMetadata.filter(isOutputParameter));
this._connection.execute({
statementId: this.id,
parameters: getInputParameters(this.parameterMetadata, values)
}, function onreply(err, reply) {
result.handle(err, reply, cb);
});
Statement.prototype.execute = function execute(values, options, cb) {
var defaults = {
autoFetch: false
};
executeStatement.call(this, defaults, values, options, cb);
return this;

@@ -120,2 +109,26 @@ };

function executeStatement(defaults, values, options, cb) {
/* jshint validthis:true */
if (util.isFunction(options)) {
cb = options;
options = defaults;
} else if (util.isObject(options)) {
options = util.extend(defaults, options);
} else {
var autoFetch = !! options;
options = defaults;
options.autoFetch = autoFetch;
}
var result = new Result(this._connection, options);
result.setResultSetMetadata(this.resultSetMetadata);
result.setParameterMetadata(this.parameterMetadata.filter(isOutputParameter));
this._connection.execute({
statementId: this.id,
parameters: getInputParameters(this.parameterMetadata, values)
}, function onreply(err, reply) {
result.handle(err, reply, cb);
});
}
function isInputParameter(metadata) {

@@ -122,0 +135,0 @@ return metadata.ioType === IoType.INPUT || metadata.ioType === IoType.IN_OUT;

@@ -16,4 +16,4 @@ // Copyright 2013 SAP AG.

var util = require('util');
var Transform = require('stream').Transform;
var util = require('../util');
var Transform = util.stream.Transform;

@@ -30,4 +30,2 @@ module.exports = Stringifier;

this._writableState.objectMode = true;
this._map = options.map;
this._header = options.header !== undefined ? options.header : '[';

@@ -37,23 +35,21 @@ this._footer = options.footer !== undefined ? options.footer : ']';

this._stringify = options.stringify || JSON.stringify;
this._map = undefined;
if (util.isFunction(options.map)) {
this._map = options.map;
}
this._first = true;
}
Stringifier.prototype._transform = function (chunk, encoding, done) {
var str = '';
if (chunk && chunk.length) {
if (typeof this._map === 'function') {
chunk = chunk.map(this.map);
}
str = this._first ? this._header : this._seperator;
this._first = false;
for (var i = 0; i < chunk.length; i++) {
if (i > 0)
str += this._seperator;
str += this._stringify(chunk[i]);
}
Stringifier.prototype._transform = function _transform(thing, encoding, done) {
if (util.isArray(thing) && thing.length) {
this.push(this.transformRows(thing));
} else if (util.isObject(thing)) {
this.push(this.transformRow(thing));
} else {
this.push('');
}
done(null, str);
done();
};
Stringifier.prototype._flush = function (done) {
Stringifier.prototype._flush = function _flush(done) {
if (this._first) {

@@ -65,2 +61,28 @@ this.push(this._header + this._footer);

done(null);
};
Stringifier.prototype.transformRows = function transformRows(rows) {
if (this._map) {
rows = rows.map(this._map);
}
var str = this._first ? this._header : this._seperator;
this._first = false;
for (var i = 0; i < rows.length; i++) {
if (i > 0) {
str += this._seperator;
}
str += this._stringify(rows[i]);
}
return str;
};
Stringifier.prototype.transformRow = function transformRow(row) {
if (this._map) {
row = this._map(row);
}
if (this._first) {
this._first = false;
return this._header + this._stringify(row);
}
return this._seperator + this._stringify(row);
};

@@ -31,3 +31,2 @@ // Copyright 2013 SAP AG.

var INT_10_13 = Math.pow(10, 13);
var INT_10_14 = Math.pow(10, 14);

@@ -71,12 +70,37 @@ var ZERO_1 = '0';

/* 10^7 for base 2^16 */
var BIN_10_7_0 = INT_10_7 % INT_2_16;
var BIN_10_7_1 = Math.floor(INT_10_7 / INT_2_16);
var BIN_10_7_0 = 38528;
var BIN_10_7_1 = 152;
/* 10^14 for base 2^16 */
var BIN_10_14_0 = INT_10_14 % INT_2_16;
var BIN_10_14_1 = Math.floor(INT_10_14 / INT_2_16) % INT_2_16;
var BIN_10_14_2 = Math.floor(Math.floor(INT_10_14 / INT_2_16) / INT_2_16);
var BIN_10_14_0 = 16384;
var BIN_10_14_1 = 4218;
var BIN_10_14_2 = 23283;
/* 10^21 for base 2^16 */
var BIN_10_21_0 = 0;
var BIN_10_21_1 = 56992;
var BIN_10_21_2 = 44485;
var BIN_10_21_3 = 13769;
var BIN_10_21_4 = 54;
/* 10^28 for base 2^16 */
var BIN_10_28_0 = 0;
var BIN_10_28_1 = 4096;
var BIN_10_28_2 = 609;
var BIN_10_28_3 = 15909;
var BIN_10_28_4 = 52830;
var BIN_10_28_5 = 8271;
/* 10^35 for base 2^16 */
var BIN_10_35_0 = 0;
var BIN_10_35_1 = 0;
var BIN_10_35_2 = 36840;
var BIN_10_35_3 = 11143;
var BIN_10_35_4 = 19842;
var BIN_10_35_5 = 29383;
var BIN_10_35_6 = 16993;
var BIN_10_35_7 = 19;
/* Decimal zero padding */
var MAX_DECIMAL_LENGTH = 34;
var MAX_DECIMAL_LENGTH = 35;
var ZEROS = [''];

@@ -200,2 +224,39 @@ for (var i = 1; i < MAX_DECIMAL_LENGTH; i++) {

function isUInt64(value) {
if (typeof value === 'number') {
return true;
}
if (value.length < 20) {
return true;
}
if (value.length === 20 && value <= '18446744073709551616') {
return true;
}
return false;
}
function writeDec128(buffer, value, offset) {
offset = offset || 0;
buffer.fill(0x00, offset, offset + 16);
if (isUInt64(value.m)) {
writeUInt64(buffer, value.m, offset);
} else {
writeUInt128(buffer, value.m, offset);
}
var e = EXP_BIAS + value.e;
var e0 = e << 1;
e0 &= 0xfe;
e0 |= buffer[offset + 14] & 0x01;
buffer[offset + 14] = e0;
var e1 = e >> 7;
if (value.s < 0) {
e1 |= 0x80;
}
buffer[offset + 15] = e1;
}
function readDec128(buffer, offset) {

@@ -237,3 +298,4 @@

m: undefined,
e: ((((buffer[offset + 1] << 8) | buffer[offset]) & 0x7ffe) >> 1) - EXP_BIAS
e: ((((buffer[offset + 1] << 8) | buffer[offset]) & 0x7ffe) >> 1) -
EXP_BIAS
};

@@ -348,2 +410,5 @@

var value = readDec128(buffer, offset);
if (value === null) {
return null;
}
if (value.s === -1) {

@@ -357,2 +422,5 @@ return '-' + value.m + 'e' + value.e;

var value = readDec128(buffer, offset);
if (value === null) {
return null;
}
var d = value.m;

@@ -401,3 +469,3 @@ if (typeof d === 'number') {

a = +value.substring(l - 7);
b = +value.substring(l - 7, l - 14);
b = +value.substring(l - 14, l - 7);
c = +value.substring(0, l - 14);

@@ -497,2 +565,303 @@

function readUInt128(buffer, offset) {
var i, j, k, l, z0, z1, y0, y1, y2, x0, x1, x2, x3, x4;
offset = offset || 0;
i = buffer[offset + 2] << 16;
i |= buffer[offset + 1] << 8;
i |= buffer[offset];
i += buffer[offset + 3] << 24 >>> 0;
offset += 4;
j = buffer[offset + 2] << 16;
j |= buffer[offset + 1] << 8;
j |= buffer[offset];
j += buffer[offset + 3] << 24 >>> 0;
offset += 4;
k = buffer[offset + 2] << 16;
k |= buffer[offset + 1] << 8;
k |= buffer[offset];
k += buffer[offset + 3] << 24 >>> 0;
offset += 4;
l = (buffer[offset + 2]) << 16;
l |= buffer[offset + 1] << 8;
l |= buffer[offset];
l += buffer[offset + 3] << 24 >>> 0;
if (k === 0 && l === 0) {
if (j === 0) {
return i;
}
if (j < INT_2_21 || (j === INT_2_21 && i === 0)) {
return j * INT_2_32 + i;
}
}
if (i < BASE) {
x0 = i;
x1 = 0;
} else {
x0 = i % BASE;
x1 = Math.floor(i / BASE);
}
if (j < BASE) {
x0 += j * INT_2_32_0;
x1 += j * INT_2_32_1;
x2 = 0;
} else {
z0 = j % BASE;
z1 = Math.floor(j / BASE);
x0 += z0 * INT_2_32_0;
x1 += z0 * INT_2_32_1 + z1 * INT_2_32_0;
x2 = z1 * INT_2_32_1;
}
if (k < BASE) {
y0 = k;
y1 = 0;
} else {
y0 = k % BASE;
y1 = Math.floor(k / BASE);
}
if (l < BASE) {
y0 += l * INT_2_32_0;
y1 += l * INT_2_32_1;
y2 = 0;
} else {
z0 = l % BASE;
z1 = Math.floor(l / BASE);
y0 += z0 * INT_2_32_0;
y1 += z0 * INT_2_32_1 + z1 * INT_2_32_0;
y2 = z1 * INT_2_32_1;
}
if (y0 >= BASE) {
y1 += Math.floor(y0 / BASE);
y0 %= BASE;
}
if (y1 >= BASE) {
y2 += Math.floor(y1 / BASE);
y1 %= BASE;
}
x0 += y0 * INT_2_64_0;
x1 += y0 * INT_2_64_1 + y1 * INT_2_64_0;
x2 += y0 * INT_2_64_2 + y1 * INT_2_64_1 + y2 * INT_2_64_0;
x3 = y1 * INT_2_64_2 + y2 * INT_2_64_1;
x4 = y2 * INT_2_64_2;
if (x0 >= BASE) {
x1 += Math.floor(x0 / BASE);
x0 %= BASE;
}
if (x1 >= BASE) {
x2 += Math.floor(x1 / BASE);
x1 %= BASE;
}
if (x2 >= BASE) {
x3 += Math.floor(x2 / BASE);
x2 %= BASE;
}
if (x3 >= BASE) {
x4 += Math.floor(x3 / BASE);
x3 %= BASE;
}
if (x4) {
return '' + x4 + lpad14(x3 * BASE + x2) + lpad14(x1 * BASE + x0);
}
if (x3) {
return '' + (x3 * BASE + x2) + lpad14(x1 * BASE + x0);
}
if (x2) {
if (x2 < INT_2_53_2 || (x2 === INT_2_53_2 &&
(x1 < INT_2_53_1 || (x1 === INT_2_53_1 && x0 <= INT_2_53_0)))) {
return (x2 * BASE + x1) * BASE + x0;
}
return '' + x2 + lpad14(x1 * BASE + x0);
}
return x1 * BASE + x0;
}
function writeUInt128(buffer, value, offset) {
var l, a, b, c, d, e, f,
x0, x1, x2, x3, y0, y1, z0, z1, z2, z3, z4, z5, z6, z7;
l = value.length;
a = ~~value.substring(l - 7);
if (l > 7) {
b = ~~value.substring(l - 14, l - 7);
} else {
b = 0;
}
if (l > 14) {
c = ~~value.substring(l - 21, l - 14);
} else {
c = 0;
}
if (l > 21) {
d = ~~value.substring(l - 28, l - 21);
} else {
d = 0;
}
if (l > 28) {
e = ~~value.substring(l - 35, l - 28);
} else {
e = 0;
}
if (l > 35) {
f = ~~value.substring(0, l - 35);
} else {
f = 0;
}
z0 = z1 = z2 = z3 = z4 = z5 = z6 = z7 = 0;
// set a * 10^0
if (a) {
z0 = a % INT_2_16;
z1 = Math.floor(a / INT_2_16);
}
// add b * 10^7
if (b) {
y0 = b % INT_2_16;
y1 = Math.floor(b / INT_2_16);
if (y0 >= INT_2_16) {
y1 += Math.floor(y0 / INT_2_16);
y0 %= INT_2_16;
}
z0 += y0 * BIN_10_7_0;
z1 += y0 * BIN_10_7_1 + y1 * BIN_10_7_0;
z2 += y1 * BIN_10_7_1;
}
// add c * 10^14
if (c) {
y0 = c % INT_2_16;
y1 = Math.floor(c / INT_2_16);
if (y0 >= INT_2_16) {
y1 += Math.floor(y0 / INT_2_16);
y0 %= INT_2_16;
}
z0 += y0 * BIN_10_14_0;
z1 += y0 * BIN_10_14_1 + y1 * BIN_10_14_0;
z2 += y0 * BIN_10_14_2 + y1 * BIN_10_14_1;
z3 += y1 * BIN_10_14_2;
}
// add d * 10^21
if (d) {
y0 = d % INT_2_16;
y1 = Math.floor(d / INT_2_16);
if (y0 >= INT_2_16) {
y1 += Math.floor(y0 / INT_2_16);
y0 %= INT_2_16;
}
z0 += y0 * BIN_10_21_0;
z1 += y0 * BIN_10_21_1 + y1 * BIN_10_21_0;
z2 += y0 * BIN_10_21_2 + y1 * BIN_10_21_1;
z3 += y0 * BIN_10_21_3 + y1 * BIN_10_21_2;
z4 += y0 * BIN_10_21_4 + y1 * BIN_10_21_3;
z5 += y1 * BIN_10_21_4;
}
// add e * 10^28
if (e) {
y0 = e % INT_2_16;
y1 = Math.floor(e / INT_2_16);
if (y0 >= INT_2_16) {
y1 += Math.floor(y0 / INT_2_16);
y0 %= INT_2_16;
}
z0 += y0 * BIN_10_28_0;
z1 += y0 * BIN_10_28_1 + y1 * BIN_10_28_0;
z2 += y0 * BIN_10_28_2 + y1 * BIN_10_28_1;
z3 += y0 * BIN_10_28_3 + y1 * BIN_10_28_2;
z4 += y0 * BIN_10_28_4 + y1 * BIN_10_28_3;
z5 += y0 * BIN_10_28_5 + y1 * BIN_10_28_4;
z6 += y1 * BIN_10_28_5;
}
// add f * 10^35
if (f) {
y0 = f % INT_2_16;
z0 += y0 * BIN_10_35_0;
z1 += y0 * BIN_10_35_1;
z2 += y0 * BIN_10_35_2;
z3 += y0 * BIN_10_35_3;
z4 += y0 * BIN_10_35_4;
z5 += y0 * BIN_10_35_5;
z6 += y0 * BIN_10_35_6;
z7 += y0 * BIN_10_35_7;
}
if (z0 >= INT_2_16) {
z1 += Math.floor(z0 / INT_2_16);
z0 %= INT_2_16;
}
if (z1 >= INT_2_16) {
z2 += Math.floor(z1 / INT_2_16);
z1 %= INT_2_16;
}
if (z2 >= INT_2_16) {
z3 += Math.floor(z2 / INT_2_16);
z2 %= INT_2_16;
}
if (z3 >= INT_2_16) {
z4 += Math.floor(z3 / INT_2_16);
z3 %= INT_2_16;
}
if (z4 >= INT_2_16) {
z5 += Math.floor(z4 / INT_2_16);
z4 %= INT_2_16;
}
if (z5 >= INT_2_16) {
z6 += Math.floor(z5 / INT_2_16);
z5 %= INT_2_16;
}
if (z6 >= INT_2_16) {
z7 += Math.floor(z6 / INT_2_16);
z6 %= INT_2_16;
}
x0 = z1 * INT_2_16 + z0;
x1 = z3 * INT_2_16 + z2;
x2 = z5 * INT_2_16 + z4;
x3 = z7 * INT_2_16 + z6;
buffer[offset + 3] = (x0 >>> 24) & 0xff;
buffer[offset + 2] = (x0 >>> 16) & 0xff;
buffer[offset + 1] = (x0 >>> 8) & 0xff;
buffer[offset] = x0 & 0xff;
offset += 4;
buffer[offset + 3] = (x1 >>> 24) & 0xff;
buffer[offset + 2] = (x1 >>> 16) & 0xff;
buffer[offset + 1] = (x1 >>> 8) & 0xff;
buffer[offset] = x1 & 0xff;
offset += 4;
buffer[offset + 3] = (x2 >>> 24) & 0xff;
buffer[offset + 2] = (x2 >>> 16) & 0xff;
buffer[offset + 1] = (x2 >>> 8) & 0xff;
buffer[offset] = x2 & 0xff;
offset += 4;
buffer[offset + 3] = (x3 >>> 24) & 0xff;
buffer[offset + 2] = (x3 >>> 16) & 0xff;
buffer[offset + 1] = (x3 >>> 8) & 0xff;
buffer[offset] = x3 & 0xff;
}
function readInt64(buffer, offset) {

@@ -514,18 +883,2 @@ return _readInt64(buffer, offset || 0, false);

Buffer.prototype.readInt64LE = function readInt64LE(offset) {
return _readInt64(this, offset || 0, false);
};
Buffer.prototype.readUInt64LE = function readUInt64LE(offset) {
return _readInt64(this, offset || 0, true);
};
Buffer.prototype.writeInt64LE = function writeInt64LE(value, offset) {
_writeInt64(this, value, offset || 0, false);
};
Buffer.prototype.writeUInt64LE = function writeUInt64LE(value, offset) {
_writeInt64(this, value, offset || 0, true);
};
exports.readInt64LE = readInt64;

@@ -535,3 +888,6 @@ exports.readUInt64LE = readUInt64;

exports.writeUInt64LE = writeUInt64;
exports.readUInt128LE = readUInt128;
exports.writeUInt128LE = writeUInt128;
exports.readDec128 = readDec128;
exports.writeDec128 = writeDec128;
exports.readDecFloat = readDecFloat;

@@ -538,0 +894,0 @@ exports.readDecFixed = readDecFixed;

@@ -16,4 +16,28 @@ // Copyright 2013 SAP AG.

/* jshint camelcase:false */
var util = require('util');
var stream = require('stream');
if (isFunction(setImmediate)) {
exports.setImmediate = setImmediate;
} else {
// inoffical 0.8.x support
exports.setImmediate = process.nextTick;
}
if (!stream.Readable) {
// inoffical 0.8.x support
stream = require('readable-stream');
}
exports.stream = {
Readable: stream.Readable,
Writable: stream.Writable,
Transform: stream.Transform
};
function exportNativeUtil(fn) {
exports[fn] = util[fn];
}
[

@@ -32,6 +56,19 @@ 'format',

'inherits'
].forEach(function exportNativeUtils(fn) {
exports[fn] = util[fn];
});
].forEach(exportNativeUtil);
var debuglog;
if (util.debuglog) {
debuglog = util.debuglog;
} else {
try {
debuglog = require('debuglog');
} catch (err) {
/* jshint unused:false */
debuglog = function dbglg(name) {
return function () {};
};
}
}
exports.debuglog = debuglog;
exports.bignum = require('./bignum');

@@ -42,3 +79,3 @@

function extend(obj) {
Array.prototype.slice.call(arguments, 1).forEach(function extendOnce(source) {
function extendOnce(source) {
/* jshint forin:false */

@@ -50,3 +87,4 @@ if (source) {

}
});
}
Array.prototype.slice.call(arguments, 1).forEach(extendOnce);
return obj;

@@ -61,7 +99,2 @@ }

function isNull(arg) {
return arg === null;
}
exports.isNull = isNull;
function isNumber(arg) {

@@ -92,7 +125,2 @@ return typeof arg === 'number';

function isBuffer(arg) {
return arg instanceof Buffer;
}
exports.isBuffer = isBuffer;
function alignLength(length, alignment) {

@@ -116,2 +144,85 @@ if (length % alignment === 0) {

}
exports._2cc = _2cc;
exports._2cc = _2cc;
function readData(ds, cb) {
var length = 0;
var chunks = [];
function done(err) {
ds.removeListener('error', onerror);
ds.removeListener('data', ondata);
ds.removeListener('end', onend);
if (isFunction(cb)) {
if (err) {
return cb(err);
}
cb(null, Buffer.concat(chunks, length));
}
}
function onerror(err) {
done(err);
}
ds.on('error', onerror);
function ondata(chunk) {
chunks.push(chunk);
length += chunk.length;
}
ds.on('data', ondata);
function onend() {
done(null);
}
ds.on('end', onend);
ds.resume();
}
exports.readData = readData;
function proxyEvents(source, target, events) {
function proxyEvent(ev) {
source.on(ev, target.emit.bind(target, ev));
}
events.forEach(proxyEvent);
return target;
}
exports.proxyEvents = proxyEvents;
function createReadStream(ds, events, options) {
if (!util.isArray(events)) {
options = events;
events = ['error', 'close'];
}
var readable = new stream.Readable(options);
readable._read = function _read() {
ds.resume();
};
function onend() {
readable.push(null);
}
ds.once('end', onend);
function ondata(chunk) {
if (!chunk || !chunk.length) {
return;
}
if (!readable.push(chunk)) {
ds.pause();
}
}
ds.on('data', ondata);
proxyEvents(ds, readable, events);
return readable;
}
exports.createReadStream = createReadStream;
function pipe(source, target, events) {
proxyEvents(source, target, events || ['error']);
return source.pipe(target);
}
exports.pipe = pipe;

@@ -8,3 +8,3 @@ {

"description": "SAP HANA Database Client for Node",
"version": "0.0.5",
"version": "0.1.0",
"repository": {

@@ -33,8 +33,13 @@ "type": "git",

"devDependencies": {
"should": "~1.2.2",
"mocha": "~1.9.0",
"should": "~2.1.0",
"mocha": "~1.14.0",
"async": "~0.2.9",
"generic-pool": "~2.0.3"
"generic-pool": "~2.0.4",
"fstream": "~0.1.24",
"concat-stream": "~1.2.0"
},
"optionalDependencies": {}
"optionalDependencies": {
"debuglog": "~0.0.2",
"readable-stream": "~1.1.9"
}
}

@@ -12,7 +12,5 @@ SAP HANA Database Client for Node

Install from [npm](https://npmjs.org/):
Install from npm:
```bash
npm install hdb
```
[![NPM](https://nodei.co/npm/hdb.png?compact=true)](https://npmjs.org/)

@@ -39,11 +37,15 @@ or clone from the [GitHub repository](https://github.com/SAP/node-hdb) to run tests and examples locally:

password : 'secret'
}).connect();
});
client.exec('select * from DUMMY', function(err, rows) {
client.connect(function (err) {
if (err) {
console.error('Error:', err);
} else {
return console.error('Connect error', err);
}
client.exec('select * from DUMMY', function (err, rows) {
client.end();
if (err) {
return console.error('Execute error:', err);
}
console.log('Results:', rows);
}
client.end();
});
});

@@ -74,18 +76,21 @@ ```

host : 'hostname',
port : 30015
port : 30015,
user : 'user',
password : 'secret'
});
client.connect({
user : 'user',
password : 'secret'
}, function(err) {
user : 'somebody',
password : 'abc123'
}, function (err) {
if (err) {
console.error('Client connection error:', err);
} else {
console.log('Client connected!');
}
return console.error('Client connection error:', err);
}
console.log('Client connected!');
});
```
If user and password are specified it will override the defaults of the client. It is possible to disconnect and reconnect with a different user on the same client instance and the same network connection.
Direct Statement Execution
Direct Statement Execution
--------------------------

@@ -106,3 +111,3 @@

```js
client.exec('create table TEST.NUMBERS (a int, b varchar(16))', function(err) {
client.exec('create table TEST.NUMBERS (a int, b varchar(16))', function (err) {
if (err) {

@@ -120,3 +125,3 @@ return console.error('Error:', err);

```js
client.exec('insert into TEST.NUMBERS values (1, \'one\')', function(err, affectedRows) {
client.exec('insert into TEST.NUMBERS values (1, \'one\')', function (err, affectedRows) {
if (err) {

@@ -131,4 +136,8 @@ return console.error('Error:', err);

In the case of a Query all selected `rows` are fetched and returned in the callback.
The client has two functions for query execution.
#### `exec`
The `exec` function is the short form. In this case all selected `rows` are fetched and returned in the callback. The `resultSet` is automatically closed and all `Lobs` are completely read and returned as Buffer objects.
```js

@@ -141,5 +150,25 @@ client.exec('select A, B from TEST.NUMBERS oder by A', function(err, rows) {

});
```
#### `execute`
The `execute` function is the long form. In this case the `resultSet` object is returned in the callback. The `resultSet` object allows you to create an object based `row` stream or an array based `rows` stream which can be piped to an writer object. Don't forget to close the resultset in this case. Take a look at the example `app4` for further details.
```js
client.execute('select A, B from TEST.NUMBERS oder by A', function(err, rs) {
if (err) {
return console.error('Error:', err);
}
rs.setFetchSize(2048);
rs.createObjectStream()
.pipe(new MyWriteStream())
.on('finish', function (){
if (!rs.closed) {
rs.close();
}
});
});
```
Prepared Statement Execution

@@ -164,2 +193,4 @@ ----------------------------

The execution of a prepared statement is similar to the direct statement execution on the client. The difference is that the first parameter of `exec` function is an array with positional `parameters`. In case of named parameters it can also be an `parameters` object.
```js

@@ -174,2 +205,4 @@ statement.exec([1], function (err, rows) {

If you use the `execute` instead of `exec` function the `resultSet` is returned in the callback like in direct query execution above.
### Calling Stored Procedures

@@ -222,6 +255,8 @@

}
console.log('Statement droped');
console.log('Statement dropped');
});
```
The callback is optional in this case.
Running tests

@@ -242,5 +277,3 @@ -------------

For the acceptance tests a database connection has to be established. Therefore you
need to copy the configuration template [config.tpl.json](./test/lib/config.tpl.json)
in the ```test/lib``` folder to ```config.json``` and change the connection data to yours.
For the acceptance tests a database connection has to be established. Therefore you need to copy the configuration template [config.tpl.json](https://github.com/SAP/node-hdb/blob/master/test/lib/config.tpl.json) in the ```test/lib``` folder to ```config.json``` and change the connection data to yours.

@@ -251,8 +284,20 @@

Also, for the [examples](./examples) you need a valid a ```config.json``` in the ```test/lib``` folder.
Also, for the examples you need a valid a ```config.json``` in the ```test/lib``` folder.
The example for call procedure:
- [app1](https://github.com/SAP/node-hdb/blob/master/examples/app1.js): Simple query.
- [app2](https://github.com/SAP/node-hdb/blob/master/examples/app2.js): Fetch rows from `ResultSet`.
- [app3](https://github.com/SAP/node-hdb/blob/master/examples/app3.js): Streaming rows `createObjectStream()`.
- [app4](https://github.com/SAP/node-hdb/blob/master/examples/app4.js): Pipe row into JSON-Transform and to `stdout`.
- [app5](https://github.com/SAP/node-hdb/blob/master/examples/app5.js): Stream XS repository into the filesystem.
- [app6](https://github.com/SAP/node-hdb/blob/master/examples/app6.js): Stream from the filesystem into a db table.
- [call1](https://github.com/SAP/node-hdb/blob/master/examples/call1.js): Call stored procedure.
- [csv](https://github.com/SAP/node-hdb/blob/master/examples/csv.js): Stream a db table into csv file.
- [server](https://github.com/SAP/node-hdb/blob/master/examples/server.js): Stream rows into http response `http://localhost:1337/{schema}/{tablename}?top={top}`
To call e.g. the first example:
```bash
node examples/call1
node examples/app1
```

@@ -262,10 +307,8 @@

----
* Finish support for Lob data types
* Support for read Lob in development
* Support for write Lob not yet started
* Transaction handling
* Support for (streamed) WriteLob requests
* Improve documentation of the client api
* Improve error handling
* SAML Authentication support
* Transaction handling
* Enhance tests
* ...
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc