Comparing version 0.10.0 to 0.11.0
@@ -139,2 +139,7 @@ // Copyright 2013 SAP AG. | ||
} | ||
}, | ||
useCesu8: { | ||
get: function shouldUseCesu8() { | ||
return (this._settings.useCesu8 === true); | ||
} | ||
} | ||
@@ -450,3 +455,4 @@ }); | ||
holdCursorsOverCommit: this.holdCursorsOverCommit, | ||
scrollableCursor: this.scrollableCursor | ||
scrollableCursor: this.scrollableCursor, | ||
useCesu8: this.useCesu8 | ||
}, options); | ||
@@ -453,0 +459,0 @@ this.enqueue(request.executeDirect(options), cb); |
@@ -18,3 +18,3 @@ // Copyright 2013 SAP AG. | ||
var ENCRYPTION_OPTIONS = ['pfx', 'key', 'cert', 'ca', 'passphrase', 'rejectUnauthorized', 'secureProtocol']; | ||
var ENCRYPTION_OPTIONS = ['pfx', 'key', 'cert', 'ca', 'passphrase', 'rejectUnauthorized', 'secureProtocol', 'checkServerIdentity']; | ||
var CONNECT_OPTIONS = ['user', 'password', 'assertion', 'sessionCookie']; | ||
@@ -21,0 +21,0 @@ var MULTIDB_OPTIONS = ['databaseName', 'instanceNumber']; |
@@ -16,2 +16,4 @@ // Copyright 2013 SAP AG. | ||
var util = require('../../util'); | ||
exports.read = read; | ||
@@ -23,3 +25,3 @@ exports.write = write; | ||
function read(part) { | ||
return part.buffer.toString('utf-8'); | ||
return util.convert.decode(part.buffer, part.useCesu8); | ||
} | ||
@@ -33,3 +35,3 @@ | ||
part.argumentCount = getArgumentCount(value); | ||
part.buffer = new Buffer(value, 'utf-8'); | ||
part.buffer = util.convert.encode(value, part.useCesu8); | ||
return part; | ||
@@ -36,0 +38,0 @@ } |
@@ -16,2 +16,4 @@ // Copyright 2013 SAP AG. | ||
var util = require('../../util'); | ||
exports.read = read; | ||
@@ -23,3 +25,3 @@ exports.write = write; | ||
function read(part) { | ||
return part.buffer.slice(1).toString('utf-8'); | ||
return util.convert.decode(part.buffer.slice(1), part.useCesu8); | ||
} | ||
@@ -33,3 +35,3 @@ | ||
part.argumentCount = getArgumentCount(value); | ||
part.buffer = new Buffer(' ' + value, 'utf-8'); | ||
part.buffer = util.convert.encode(' ' + value, part.useCesu8); | ||
return part; | ||
@@ -36,0 +38,0 @@ } |
@@ -28,3 +28,3 @@ // Copyright 2013 SAP AG. | ||
var byteLength = getByteLength(fields); | ||
var byteLength = getByteLength(fields, part.useCesu8); | ||
var buffer = new Buffer(byteLength); | ||
@@ -35,3 +35,3 @@ | ||
field = fields[i]; | ||
data = new Buffer(field, 'utf8'); | ||
data = util.convert.encode(field, part.useCesu8); | ||
@@ -57,7 +57,7 @@ fieldLength = data.length; | ||
function getByteLength(fields) { | ||
function getByteLength(fields, useCesu8) { | ||
var byteLength = 0; | ||
var fieldLength; | ||
for (var i = 0; i < fields.length; i++) { | ||
fieldLength = getByteLengthOfField(fields[i]); | ||
fieldLength = getByteLengthOfField(fields[i], useCesu8); | ||
if (fieldLength <= 245) { | ||
@@ -77,4 +77,9 @@ byteLength += fieldLength + 1; | ||
function getByteLengthOfField(field) { | ||
return Buffer.byteLength(field, 'utf8'); | ||
function getByteLengthOfField(field, useCesu8) { | ||
if (useCesu8) { | ||
return util.convert.encode(field, useCesu8).length; | ||
} | ||
return Buffer.byteLength(field); | ||
} | ||
@@ -33,3 +33,3 @@ // Copyright 2013 SAP AG. | ||
this.functionCode = options.functionCode; | ||
this.writer = new Writer(options.parameters.types); | ||
this.writer = new Writer(options.parameters.types, connection.useCesu8); | ||
var values = options.parameters.values; | ||
@@ -75,6 +75,6 @@ if (values.length && Array.isArray(values[0])) { | ||
self.sendExecute(function receive(err, reply) { | ||
self.pushReply(reply); | ||
if (err) { | ||
return finalize(err); | ||
} | ||
self.pushReply(reply); | ||
if (!self.writer.finished && reply.writeLobReply) { | ||
@@ -81,0 +81,0 @@ self.writer.update(reply.writeLobReply); |
@@ -39,3 +39,3 @@ // Copyright 2013 SAP AG. | ||
this.increaseOffset = function increaseOffsetNCLOB(chunk) { | ||
this._offset += chunk.toString('utf-8').length; | ||
this._offset += textChunkLength(chunk, options && options.useCesu8) | ||
}; | ||
@@ -69,2 +69,8 @@ break; | ||
function textChunkLength(chunk, useCesu8) { | ||
return (useCesu8) ? | ||
util.convert.lengthInCesu8(chunk) : | ||
chunk.toString('utf-8').length; | ||
} | ||
Lob.prototype.pause = function pause() { | ||
@@ -71,0 +77,0 @@ this._running = false; |
@@ -25,10 +25,11 @@ // Copyright 2013 SAP AG. | ||
function Parser(metadata, lobFactory) { | ||
function Parser(metadata, lobFactory, useCesu8) { | ||
this.metadata = metadata; | ||
this.lobFactory = lobFactory; | ||
this.honest = !!process.browser; | ||
this.useCesu8 = (useCesu8 === true); | ||
} | ||
Parser.create = function createParser(metadata, lobFactory) { | ||
return new Parser(metadata, lobFactory); | ||
Parser.create = function createParser(metadata, lobFactory, useCesu8) { | ||
return new Parser(metadata, lobFactory, useCesu8); | ||
}; | ||
@@ -57,3 +58,3 @@ | ||
Parser.prototype.parseParams = function parseParams(buffer, options) { | ||
var reader = new Reader(buffer, this.lobFactory); | ||
var reader = new Reader(buffer, this.lobFactory, this.useCesu8); | ||
return this.createParseParamsFunction(options).call(reader); | ||
@@ -63,3 +64,3 @@ }; | ||
Parser.prototype.parse = function parse(buffer, options) { | ||
var reader = new Reader(buffer, this.lobFactory); | ||
var reader = new Reader(buffer, this.lobFactory, this.useCesu8); | ||
var parseRow = this.createParseRowFunction(options).bind(reader); | ||
@@ -66,0 +67,0 @@ var rows = []; |
@@ -23,6 +23,7 @@ // Copyright 2013 SAP AG. | ||
function Reader(buffer, lobFactory) { | ||
function Reader(buffer, lobFactory, scrictEncoding) { | ||
this.buffer = buffer; | ||
this.offset = 0; | ||
this.lobFactory = lobFactory; | ||
this.scrictEncoding = scrictEncoding; | ||
} | ||
@@ -71,3 +72,3 @@ | ||
Reader.prototype.readString = function readString() { | ||
return this.readBytes('utf-8'); | ||
return this.readBytes(true); | ||
}; | ||
@@ -79,3 +80,3 @@ | ||
Reader.prototype.readBytes = function readBytes(encoding) { | ||
Reader.prototype.readBytes = function readBytes(isString) { | ||
var length = this.buffer[this.offset++]; | ||
@@ -95,5 +96,6 @@ switch (length) { | ||
var value; | ||
if (encoding) { | ||
value = this.buffer.toString(encoding, this.offset, this.offset + | ||
length); | ||
if (isString) { | ||
value = util.convert.decode( | ||
this.buffer.slice(this.offset, this.offset + length), | ||
this.scrictEncoding); | ||
} else { | ||
@@ -100,0 +102,0 @@ value = new Buffer(length); |
@@ -62,3 +62,3 @@ // Copyright 2013 SAP AG. | ||
} | ||
var segment = new Segment(type, commitImmediateley, commandOptions); | ||
var segment = new Segment(type, commitImmediateley, commandOptions, options.useCesu8); | ||
return segment; | ||
@@ -65,0 +65,0 @@ } |
@@ -27,2 +27,3 @@ // Copyright 2013 SAP AG. | ||
this.argumentCount = options.argumentCount || 0; | ||
this.useCesu8 = options.useCesu8; | ||
this.buffer = undefined; | ||
@@ -29,0 +30,0 @@ } |
@@ -28,3 +28,3 @@ // Copyright 2013 SAP AG. | ||
function Segment(type, commitImmediateley, commandOptions) { | ||
function Segment(type, commitImmediateley, commandOptions, useCesu8) { | ||
this.type = type || MessageType.NIL; | ||
@@ -34,2 +34,3 @@ this.commitImmediateley = !!commitImmediateley ? 1 : 0; | ||
this.parts = []; | ||
this.useCesu8 = (useCesu8 === true); | ||
} | ||
@@ -82,3 +83,3 @@ | ||
for (var i = 0; i < this.parts.length; i++) { | ||
var buffer = partToBuffer(this.parts[i], remainingSize); | ||
var buffer = partToBuffer(this.parts[i], remainingSize, this.useCesu8); | ||
remainingSize -= buffer.length; | ||
@@ -113,6 +114,7 @@ length += buffer.length; | ||
function partToBuffer(pd, remainingSize) { | ||
function partToBuffer(pd, remainingSize, useCesu8) { | ||
var m = pd.module || data[pd.kind]; | ||
var part = new Part({ | ||
kind: pd.kind | ||
kind: pd.kind, | ||
useCesu8: useCesu8 | ||
}); | ||
@@ -119,0 +121,0 @@ part.argumentCount = m.getArgumentCount(pd.args); |
@@ -39,3 +39,4 @@ // Copyright 2013 SAP AG. | ||
'nestTables', | ||
'columnNameProperty' | ||
'columnNameProperty', | ||
'useCesu8' | ||
]); | ||
@@ -80,2 +81,13 @@ this._settings = util.extend(settings, options); | ||
Result.prototype.handle = function handle(err, reply, cb) { | ||
var reply = reply || {}; | ||
switch (reply.functionCode) { | ||
case FunctionCode.INSERT: | ||
case FunctionCode.UPDATE: | ||
case FunctionCode.DELETE: | ||
cb(err, reply.rowsAffected); | ||
return; | ||
default: | ||
} | ||
if (err) { | ||
@@ -90,7 +102,2 @@ return cb(err); | ||
return; | ||
case FunctionCode.INSERT: | ||
case FunctionCode.UPDATE: | ||
case FunctionCode.DELETE: | ||
this.handleModify(cb, reply.rowsAffected); | ||
return; | ||
case FunctionCode.NIL: | ||
@@ -113,6 +120,2 @@ case FunctionCode.DDL: | ||
Result.prototype.handleModify = function handleModify(cb, rowsAffected) { | ||
cb(null, rowsAffected); | ||
}; | ||
Result.prototype.handleQuery = function handleQuery(cb, resultSets) { | ||
@@ -162,3 +165,4 @@ function done(err, results) { | ||
options = util.extend({ | ||
readSize: this.readSize | ||
readSize: this.readSize, | ||
useCesu8: this._settings.useCesu8 | ||
}, options); | ||
@@ -190,3 +194,3 @@ var readLob = this._connection.readLob.bind(this._connection); | ||
if (this._parameterMetadata && util.isObject(outputParameters)) { | ||
var parser = Parser.create(this._parameterMetadata, this); | ||
var parser = Parser.create(this._parameterMetadata, this, this._settings.useCesu8); | ||
return parser.parseParams(outputParameters.buffer); | ||
@@ -284,2 +288,2 @@ } | ||
return column.name; | ||
} | ||
} |
@@ -92,2 +92,7 @@ // Copyright 2013 SAP AG. | ||
}, | ||
useCesu8: { | ||
get: function shouldUseCesu8() { | ||
return (this._settings.useCesu8 === true); | ||
} | ||
} | ||
}); | ||
@@ -209,3 +214,3 @@ | ||
ResultSet.prototype.createParser = function createParser(options) { | ||
return Parser.create(this.metadata).createTransform(this, util.extend({ | ||
return Parser.create(this.metadata, undefined, this.useCesu8).createTransform(this, util.extend({ | ||
nestTables: this.nestTables, | ||
@@ -253,3 +258,4 @@ nameProperty: this.columnNameProperty | ||
options = util.extend({ | ||
readSize: this.readSize | ||
readSize: this.readSize, | ||
useCesu8: this.useCesu8 | ||
}, options); | ||
@@ -256,0 +262,0 @@ return new Lob(sendReadLob.bind(this), ld, options); |
@@ -46,3 +46,3 @@ // Copyright 2013 SAP AG. | ||
ResultSetTransform.prototype._createReader = function _createReader(chunk) { | ||
return new Reader(chunk, this._rs); | ||
return new Reader(chunk, this._rs, this._rs.useCesu8); | ||
}; | ||
@@ -49,0 +49,0 @@ |
@@ -34,5 +34,6 @@ // Copyright 2013 SAP AG. | ||
function Writer(types) { | ||
function Writer(types, useCesu8) { | ||
this._types = types.map(normalizeType); | ||
this.reset(); | ||
this._useCesu8 = (useCesu8 === true); | ||
} | ||
@@ -64,4 +65,4 @@ | ||
exports.create = function createWriter(params) { | ||
var writer = new Writer(params.types); | ||
exports.create = function createWriter(params, useCesu8) { | ||
var writer = new Writer(params.types, useCesu8); | ||
writer.setValues(params.values); | ||
@@ -431,3 +432,8 @@ return writer; | ||
Writer.prototype[TypeCode.NSTRING] = function writeNString(value) { | ||
this.writeCharacters(value, 'utf8'); | ||
if (this._useCesu8) { | ||
var encoded = util.convert.encode(value, true); | ||
this.push(createBinaryOutBuffer(TypeCode.NSTRING, encoded)) | ||
} else { | ||
this.writeCharacters(value, 'utf8'); | ||
} | ||
}; | ||
@@ -465,23 +471,3 @@ | ||
Writer.prototype[TypeCode.BINARY] = function writeBinary(value) { | ||
var length = value.length; | ||
var buffer; | ||
if (length <= 245) { | ||
buffer = new Buffer(2 + length); | ||
buffer[0] = TypeCode.BINARY; | ||
buffer[1] = length; | ||
value.copy(buffer, 2); | ||
} else if (length <= 32767) { | ||
buffer = new Buffer(4 + length); | ||
buffer[0] = TypeCode.BINARY; | ||
buffer[1] = 246; | ||
buffer.writeInt16LE(length, 2); | ||
value.copy(buffer, 4); | ||
} else { | ||
buffer = new Buffer(6 + length); | ||
buffer[0] = TypeCode.BINARY; | ||
buffer[1] = 247; | ||
buffer.writeInt32LE(length, 2); | ||
value.copy(buffer, 6); | ||
} | ||
this.push(buffer); | ||
this.push(createBinaryOutBuffer(TypeCode.BINARY, value)); | ||
}; | ||
@@ -511,3 +497,3 @@ | ||
if (util.isString(value)) { | ||
value = new Buffer(value, 'utf8'); | ||
value = util.convert.encode(value, this._useCesu8); | ||
} | ||
@@ -638,2 +624,26 @@ this.pushLob(buffer, value); | ||
return new Error('Chunk length larger than remaining bytes'); | ||
} | ||
} | ||
function createBinaryOutBuffer(type, value) { | ||
var length = value.length; | ||
var buffer; | ||
if (length <= 245) { | ||
buffer = new Buffer(2 + length); | ||
buffer[0] = type; | ||
buffer[1] = length; | ||
value.copy(buffer, 2); | ||
} else if (length <= 32767) { | ||
buffer = new Buffer(4 + length); | ||
buffer[0] = type; | ||
buffer[1] = 246; | ||
buffer.writeInt16LE(length, 2); | ||
value.copy(buffer, 4); | ||
} else { | ||
buffer = new Buffer(6 + length); | ||
buffer[0] = type; | ||
buffer[1] = 247; | ||
buffer.writeInt32LE(length, 2); | ||
value.copy(buffer, 6); | ||
} | ||
return buffer; | ||
} |
@@ -103,2 +103,3 @@ // Copyright 2013 SAP AG. | ||
exports.calendar = require('./calendar'); | ||
exports.convert = require('./convert'); | ||
exports.Queue = require('./Queue'); | ||
@@ -105,0 +106,0 @@ extend(exports, require('./zeropad')); |
@@ -9,3 +9,3 @@ { | ||
"description": "SAP HANA Database Client for Node", | ||
"version": "0.10.0", | ||
"version": "0.11.0", | ||
"repository": { | ||
@@ -32,3 +32,5 @@ "type": "git", | ||
}, | ||
"dependencies": {}, | ||
"dependencies": { | ||
"iconv-lite": "^0.4.15" | ||
}, | ||
"devDependencies": { | ||
@@ -35,0 +37,0 @@ "async": "^2.0.1", |
@@ -27,2 +27,3 @@ SAP HANA Database Client for Node | ||
* [Streaming Large Objects](#streaming-large-objects) | ||
* [CESU-8 encoding support](#cesu-8-encoding-support) | ||
* [Running tests](#running-tests) | ||
@@ -204,2 +205,5 @@ * [Running examples](#running-examples) | ||
In case you need custom logic to validate the server's hostname against the certificate, you can assign a callback function to the `checkServerIdentity` property, alongside the other connection options. The callback is | ||
supplied to the `tls.connect` funciton of the [TLS](https://nodejs.org/api/tls.html#connect) API and should conform to the signature described there. | ||
Direct Statement Execution | ||
@@ -523,2 +527,27 @@ -------------------------- | ||
CESU-8 encoding support | ||
------------- | ||
SAP HANA server connectivity protocol uses [CESU-8](https://en.wikipedia.org/wiki/CESU-8) encoding. Node.js does not suport CESU-8 natively which means that the driver needs to convert all text to CESU-8 format in the javascript layer including SQL statements. | ||
Node.js has built-in support for UTF-8, so using UTF-8 in the HDB drivers leads to performance gains. | ||
In cases when non-[BMP](https://en.wikipedia.org/wiki/Plane_(Unicode)#Basic_Multilingual_Plane) characters are present you should use the following option to convert all text to CESU-8. | ||
`createClient` accepts the parameter `useCesu8` to enable CESU-8 support. Here is how to provide the configuration: | ||
```js | ||
var hdb = require('hdb'); | ||
var client = hdb.createClient({ | ||
host : 'hostname', | ||
port : 30015, | ||
user : 'user', | ||
password : 'secret', | ||
useCesu8 : true | ||
}); | ||
``` | ||
This setting is per client and cannot be changed later. | ||
__Note:__ Using CESU-8 brings performance penalties proportionate to the text size that has to be converted. | ||
Running tests | ||
@@ -525,0 +554,0 @@ ------------- |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
287678
99
8030
602
1
+ Addediconv-lite@^0.4.15
+ Addediconv-lite@0.4.24(transitive)
+ Addedsafer-buffer@2.1.2(transitive)