Skip to content

Commit

Permalink
Support for data format version 4 datetime and alphanum types
Browse files Browse the repository at this point in the history
Add support for ALPHANUM, LONGDATE, SECONDDATE, DAYDATE, and
SECONDTIME data types.
  • Loading branch information
IanMcCurdy authored Jan 16, 2025
1 parent f35c471 commit ffbfdd5
Show file tree
Hide file tree
Showing 15 changed files with 644 additions and 106 deletions.
24 changes: 16 additions & 8 deletions lib/protocol/Connection.js
Original file line number Diff line number Diff line change
Expand Up @@ -457,15 +457,23 @@ Connection.prototype.connect = function connect(options, cb) {
}
delete options[key];
}
if(key.toUpperCase() === "DATAFORMATVERSION") {
this.connectOptions.setOptions([
{name : common.ConnectOption.DATA_FORMAT_VERSION,
value : options[key]},
{name : common.ConnectOption.DATA_FORMAT_VERSION2,
value : options[key]}
]);
}
}
this.connectOptions.setOptions([{
name : common.ConnectOption.OS_USER,
value : this._clientInfo.getUser()
}]);
this.clientContextOptions.setOptions([{
name : common.ClientContextOption.CLIENT_APPLICATION_PROGRAM,
value : this._clientInfo.getApplication()
}]);
this.connectOptions.setOptions([
{name : common.ConnectOption.OS_USER,
value : this._clientInfo.getUser()}
]);
this.clientContextOptions.setOptions([
{name : common.ClientContextOption.CLIENT_APPLICATION_PROGRAM,
value : this._clientInfo.getApplication()}
]);
if(options["disableCloudRedirect"] == true) {
this._redirectType = common.RedirectType.REDIRECTION_DISABLED;
}
Expand Down
2 changes: 1 addition & 1 deletion lib/protocol/Parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -245,4 +245,4 @@ function getNestedMetadata(metadata, options) {
}
metadata.forEach(pushTableColumn);
return tables;
}
}
114 changes: 91 additions & 23 deletions lib/protocol/Reader.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,20 @@

var util = require('../util');
var bignum = util.bignum;
var lpad2 = util.lpad2;
var lpad4 = util.lpad4;
var lrpad9 = util.lrpad9;
var common = require('./common');
var LobOptions = common.LobOptions;
var calendar = util.calendar;

module.exports = Reader;

function Reader(buffer, lobFactory, scrictEncoding) {
function Reader(buffer, lobFactory, strictEncoding) {
this.buffer = buffer;
this.offset = 0;
this.lobFactory = lobFactory;
this.scrictEncoding = scrictEncoding;
this.strictEncoding = strictEncoding;
}

Reader.prototype.hasMore = function hasMore() {
Expand Down Expand Up @@ -75,7 +79,9 @@ Reader.prototype.readBinary = function readBinary() {
return this.readBytes();
};

Reader.prototype.readBytes = function readBytes(isString) {
Reader.prototype.readBytes = function readBytes(isString, isAlphanum) {
const ALPHANUM_LENGTH_MASK = 0x7f;
const ALPHANUM_NUMERIC_VALUE = 0x80;
var length = this.buffer[this.offset++];
switch (length) {
case 0xff:
Expand All @@ -95,7 +101,21 @@ Reader.prototype.readBytes = function readBytes(isString) {
if (isString) {
value = util.convert.decode(
this.buffer.slice(this.offset, this.offset + length),
this.scrictEncoding);
this.strictEncoding);
} else if (isAlphanum) {
var ind = this.buffer[this.offset];
var newOffset = this.offset + 1;
var definitionLen = ind & ALPHANUM_LENGTH_MASK;
value = util.convert.decode(
this.buffer.slice(newOffset, newOffset + length - 1),
this.strictEncoding);
if (ind & ALPHANUM_NUMERIC_VALUE) {
// the value is purely numeric
if (definitionLen >= length) {
// zero-pad the value
value = "0".repeat(definitionLen - length + 1) + value;
}
}
} else {
value = new Buffer(length);
this.buffer.copy(value, 0, this.offset, this.offset + length);
Expand Down Expand Up @@ -123,8 +143,8 @@ Reader.prototype.readDate = function readDate() {
high &= 0x3f;
year |= high << 8;
return util.lpad4(year) + '-' +
util.lpad2(month) + '-' +
util.lpad2(day);
lpad2(month) + '-' +
lpad2(day);
};

Reader.prototype.readTime = function readTime() {
Expand All @@ -142,9 +162,9 @@ Reader.prototype.readTime = function readTime() {
// msb set ==> not null
// unset msb
hour &= 0x7f;
return util.lpad2(hour) + ':' +
util.lpad2(min) + ':' +
util.lpad2(msec / 1000);
return lpad2(hour) + ':' +
lpad2(min) + ':' +
lpad2(msec / 1000);
};

Reader.prototype.readTimestamp = function readTimestamp() {
Expand All @@ -163,12 +183,13 @@ Reader.prototype.readTimestamp = function readTimestamp() {
};

Reader.prototype.readDayDate = function readDayDate() {
var value = this.buffer.readInt32LE(this.offset);
var value = this.buffer.readUInt32LE(this.offset);
this.offset += 4;
if (value === 3652062 || value === 0) {
return null;
}
return value - 1;
var date = calendar.DATE(value);
return lpad4(date.y) + "-" + lpad2(date.m) + "-" + lpad2(date.d);
};

Reader.prototype.readSecondTime = function readSecondTime() {
Expand All @@ -177,7 +198,13 @@ Reader.prototype.readSecondTime = function readSecondTime() {
if (value === 86402 || value === 0) {
return null;
}
return value - 1;
value -= 1;
const seconds = value % 60;
value = ~~(value / 60);
const minutes = value % 60;
value = ~~(value / 60);
const hours = value;
return lpad2(hours) + ':' + lpad2(minutes) + ':' + lpad2(seconds);
};

Reader.prototype.readSecondDate = function readSecondDate() {
Expand All @@ -186,27 +213,64 @@ Reader.prototype.readSecondDate = function readSecondDate() {
if (value === 315538070401 || value === 0) {
return null;
}
return value - 1;
const dayFactor = 60 * 60 * 24;
var seconds, minutes, hours, day, month, year;
value -= 1;
var timeValue = value % dayFactor;
var dayDate = ~~(value / dayFactor) + 1;
var date = calendar.DATE(dayDate);
year = date.y;
month = date.m;
day = date.d;
seconds = timeValue % 60;
timeValue = ~~(timeValue / 60);
minutes = timeValue % 60;
hours = ~~(timeValue / 60);
var dateString = lpad4(year) + '-' + lpad2(month) + '-' + lpad2(day)
var timeString = lpad2(hours) + ':' + lpad2(minutes) + ':' + lpad2(seconds);
return dateString + ' ' + timeString;
};

Reader.prototype.readLongDate = function readLongDate() {
var value = bignum.readInt64LE(this.buffer, this.offset);
var seconds, minutes, hours, day, month, year;
const dayFactor = 60 * 60 * 24;
this.offset += 8;
if (value === '3155380704000000001' || value === 0) {
return null;
}
var fractionalSeconds, secondDate;

if (typeof value === 'string') {
/* FIXME */
var index = value.length - 7;
var secondDate = parseInt(value.substring(0, index), 10);
var fractionalSeconds = parseInt(value.substring(index), 10) - 1;
if (fractionalSeconds < 0) {
fractionalSeconds = 9999999;
secondDate -= 1;
}
return secondDate + util.lpad7(fractionalSeconds);
secondDate = parseInt(value.substring(0, index), 10);
fractionalSeconds = parseInt(value.substring(index), 10);
} else {
secondDate = ~~(value / 10000000);
fractionalSeconds = value % 10000000;
}
return value - 1;

if (fractionalSeconds == 0) {
fractionalSeconds = 9999999;
secondDate -= 1;
} else {
fractionalSeconds -= 1;
}
var timeValue = secondDate % dayFactor;
var dayDate = ~~(secondDate / dayFactor) + 1;
seconds = timeValue % 60;
timeValue = ~~(timeValue / 60);
minutes = timeValue % 60;
timeValue = ~~(timeValue / 60);
hours = timeValue;

var date = calendar.DATE(dayDate);
day = date.d;
month = date.m;
year = date.y;
var dateString = lpad4(year) + '-' + lpad2(month) + '-' + lpad2(day)
var timeString = lpad2(hours) + ':' + lpad2(minutes) + ':' + lpad2(seconds) + '.' + lrpad9(fractionalSeconds);
return dateString + ' ' + timeString;
};

Reader.prototype.readBLob = function readBLob() {
Expand Down Expand Up @@ -301,6 +365,10 @@ Reader.prototype.readDecimal = function readDecimal(fraction) {
return value;
};

Reader.prototype.readAlphanum = function readAlphanum() {
return this.readBytes(false, true);
}

Reader.LobDescriptor = LobDescriptor;

function LobDescriptor(type, options, charLength, byteLength, locatorId, chunk, defaultType) {
Expand All @@ -320,4 +388,4 @@ Object.defineProperties(LobDescriptor.prototype, {
return !!(this.options & LobOptions.LAST_DATA);
}
}
});
});
Loading

0 comments on commit ffbfdd5

Please sign in to comment.