tedious
Version:
A TDS driver, for connecting to MS SQLServer databases.
146 lines (133 loc) • 3.62 kB
JavaScript
const types = {
1: {
name: 'DATABASE',
event: 'databaseChange'
},
2: {
name: 'LANGUAGE',
event: 'languageChange'
},
3: {
name: 'CHARSET',
event: 'charsetChange'
},
4: {
name: 'PACKET_SIZE',
event: 'packetSizeChange'
},
7: {
name: 'SQL_COLLATION',
event: 'sqlCollationChange'
},
8: {
name: 'BEGIN_TXN',
event: 'beginTransaction'
},
9: {
name: 'COMMIT_TXN',
event: 'commitTransaction'
},
10: {
name: 'ROLLBACK_TXN',
event: 'rollbackTransaction'
},
13: {
name: 'DATABASE_MIRRORING_PARTNER',
event: 'partnerNode'
},
17: {
name: 'TXN_ENDED'
},
18: {
name: 'RESET_CONNECTION',
event: 'resetConnection'
},
20: {
name: 'ROUTING_CHANGE',
event: 'routingChange'
}
};
function readNewAndOldValue(parser, length, type, callback) {
switch (type.name) {
case 'DATABASE':
case 'LANGUAGE':
case 'CHARSET':
case 'PACKET_SIZE':
case 'DATABASE_MIRRORING_PARTNER':
return parser.readBVarChar(newValue => {
parser.readBVarChar(oldValue => {
if (type.name === 'PACKET_SIZE') {
callback(parseInt(newValue), parseInt(oldValue));
} else {
callback(newValue, oldValue);
}
});
});
case 'SQL_COLLATION':
case 'BEGIN_TXN':
case 'COMMIT_TXN':
case 'ROLLBACK_TXN':
case 'RESET_CONNECTION':
return parser.readBVarByte(newValue => {
parser.readBVarByte(oldValue => {
callback(newValue, oldValue);
});
});
case 'ROUTING_CHANGE':
parser.readUInt16LE(valueLength => {
// Routing Change:
// Byte 1: Protocol (must be 0)
// Bytes 2-3 (USHORT): Port number
// Bytes 4-5 (USHORT): Length of server data in unicode (2byte chars)
// Bytes 6-*: Server name in unicode characters
parser.readBuffer(valueLength, routePacket => {
const protocol = routePacket.readUInt8(0);
if (protocol !== 0) {
return parser.emit('error', new Error('Unknown protocol byte in routing change event'));
}
const port = routePacket.readUInt16LE(1);
const serverLen = routePacket.readUInt16LE(3); // 2 bytes per char, starting at offset 5
const server = routePacket.toString('ucs2', 5, 5 + serverLen * 2);
const newValue = {
protocol: protocol,
port: port,
server: server
};
parser.readUInt16LE(oldValueLength => {
parser.readBuffer(oldValueLength, oldValue => {
callback(newValue, oldValue);
});
});
});
});
break;
default:
console.error('Tedious > Unsupported ENVCHANGE type ' + type.name); // skip unknown bytes
parser.readBuffer(length - 1, () => {
callback(undefined, undefined);
});
}
}
module.exports = function (parser, colMetadata, options, callback) {
parser.readUInt16LE(length => {
parser.readUInt8(typeNumber => {
const type = types[typeNumber];
if (!type) {
console.error('Tedious > Unsupported ENVCHANGE type ' + typeNumber); // skip unknown bytes
return parser.readBuffer(length - 1, () => {
callback();
});
}
readNewAndOldValue(parser, length, type, (newValue, oldValue) => {
callback({
name: 'ENVCHANGE',
type: type.name,
event: type.event,
oldValue: oldValue,
newValue: newValue
});
});
});
});
};
;