UNPKG

@tdengine/websocket

Version:

The websocket Node.js connector for TDengine. TDengine versions 3.3.2.0 and above are recommended to use this connector.

450 lines (449 loc) 16.8 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.TaosResult = void 0; exports.parseBlock = parseBlock; exports._isVarType = _isVarType; exports.readSolidDataToArray = readSolidDataToArray; exports.readSolidData = readSolidData; exports.readBinary = readBinary; exports.readVarchar = readVarchar; exports.readNchar = readNchar; exports.getString = getString; exports.getCharOffset = getCharOffset; exports.setBitmapNull = setBitmapNull; exports.bitmapLen = bitmapLen; const constant_1 = require("./constant"); const wsError_1 = require("./wsError"); const ut8Helper_1 = require("./ut8Helper"); const log_1 = __importDefault(require("./log")); class TaosResult { constructor(queryResponse) { this._totalTime = 0; if (queryResponse == null) { this._meta = []; this._data = []; this._timing = BigInt(0); return; } if (queryResponse.is_update == true) { this._meta = null; this._data = null; } else { if (queryResponse.fields_count && queryResponse.fields_names && queryResponse.fields_types && queryResponse.fields_lengths) { let _meta = []; for (let i = 0; i < queryResponse.fields_count; i++) { _meta.push({ name: queryResponse.fields_names[i], type: queryResponse.fields_types[i], length: queryResponse.fields_lengths[i] }); } this._meta = _meta; } else { throw new wsError_1.TaosResultError(wsError_1.ErrorCode.ERR_INVALID_FETCH_MESSAGE_DATA, `fields_count,fields_names,fields_types,fields_lengths of the update query response should be null`); } this._data = []; } this._affectRows = queryResponse.affected_rows; this._timing = queryResponse.timing; this._precision = queryResponse.precision; this._totalTime = queryResponse.totalTime; } setPrecision(precision) { this._precision = precision; } setRowsAndTime(rows, timing) { if (this._affectRows) { this._affectRows += rows; } else { this._affectRows = rows; } if (timing) { this.setTiming(timing); } } getTopic() { if (this._topic) { return this._topic; } return ""; } setTopic(topic = "") { this._topic = topic; } getMeta() { return this.getTDengineMeta(); } setMeta(metaData) { if (this._meta) { this._meta.push(metaData); } } getData() { return this._data; } setData(value) { this._data = value; } getAffectRows() { return this._affectRows; } getTaosMeta() { return this._meta; } getPrecision() { return this._precision; } getTotalTime() { return this._totalTime; } addTotalTime(totalTime) { this._totalTime += totalTime; } setTiming(timing) { if (!this._timing) { this._timing = BigInt(0); } if (timing) { this._timing = this._timing + timing; } } /** * Mapping the WebSocket response type code to TDengine's type name. */ getTDengineMeta() { if (this._meta) { let tdMeta = new Array(); this._meta.forEach(m => { tdMeta.push({ name: m.name, type: constant_1.TDengineTypeName[m.type], length: m.length }); }); return tdMeta; } return null; } } exports.TaosResult = TaosResult; function parseBlock(blocks, taosResult) { let metaList = taosResult.getTaosMeta(); let dataList = taosResult.getData(); let textDecoder = new TextDecoder(); if (metaList && dataList && blocks && blocks.data) { let rows = blocks.data.getUint32(8, true); if (rows == 0) { return taosResult; } taosResult.setTiming(blocks.timing); const INT_32_SIZE = 4; // Offset num of bytes from rawBlockBuffer. let bufferOffset = (4 * 5) + 8 + (4 + 1) * metaList.length; let colLengthBlockSize = INT_32_SIZE * metaList.length; log_1.default.debug("===colLengthBlockSize:" + colLengthBlockSize); let bitMapSize = (rows + (1 << 3) - 1) >> 3; // whole raw block ArrayBuffer // let dataBuffer = blocks.data.slice(bufferOffset); let headOffset = blocks.data.byteOffset + bufferOffset; let dataView = new DataView(blocks.data.buffer, headOffset); // record the head of column in block let colBlockHead = 0; for (let i = 0; i < rows; i++) { let row = []; // point to the head of the column in the block colBlockHead = 0 + colLengthBlockSize; // point to the head of columns's data in the block (include bitMap and offsetArray) let colDataHead = colBlockHead; // traverse row after row. for (let j = 0; j < metaList.length; j++) { let isVarType = _isVarType(metaList[j].type); if (isVarType == constant_1.ColumnsBlockType.SOLID) { colDataHead = colBlockHead + bitMapSize + metaList[j].length * i; let byteArrayIndex = i >> 3; let bitwiseOffset = 7 - (i & 7); // let bitMapArr = dataBuffer.slice(colBlockHead, colBlockHead + bitMapSize) let bitMapArr = new DataView(dataView.buffer, dataView.byteOffset + colBlockHead, bitMapSize); let bitFlag = (bitMapArr.getUint8(byteArrayIndex) & (1 << bitwiseOffset)) >> bitwiseOffset; if (bitFlag == 1) { row.push("NULL"); } else { row.push(readSolidData(dataView, colDataHead, metaList[j])); } colBlockHead = colBlockHead + bitMapSize + dataView.getInt32(INT_32_SIZE * j, true); } else { // if null check let varOffset = dataView.getInt32(colBlockHead + (INT_32_SIZE * i), true); if (varOffset == -1) { row.push("NULL"); colBlockHead = colBlockHead + INT_32_SIZE * rows + dataView.getInt32(j * INT_32_SIZE, true); } else { colDataHead = colBlockHead + INT_32_SIZE * rows + varOffset; let dataLength = dataView.getInt16(colDataHead, true); if (isVarType == constant_1.ColumnsBlockType.VARCHAR) { row.push(readVarchar(dataView.buffer, dataView.byteOffset + colDataHead + 2, dataLength, textDecoder)); } else if (isVarType == constant_1.ColumnsBlockType.GEOMETRY || isVarType == constant_1.ColumnsBlockType.VARBINARY) { row.push(readBinary(dataView.buffer, dataView.byteOffset + colDataHead + 2, dataLength)); } else { row.push(readNchar(dataView.buffer, dataView.byteOffset + colDataHead + 2, dataLength)); } colBlockHead = colBlockHead + INT_32_SIZE * rows + dataView.getInt32(j * INT_32_SIZE, true); } } } dataList.push(row); } return taosResult; } else { throw new wsError_1.TaosResultError(wsError_1.ErrorCode.ERR_INVALID_FETCH_MESSAGE_DATA, "cannot fetch block for an update query."); } } function _isVarType(metaType) { switch (metaType) { case constant_1.TDengineTypeCode.NCHAR: { return constant_1.ColumnsBlockType['NCHAR']; } case constant_1.TDengineTypeCode.VARCHAR: { return constant_1.ColumnsBlockType['VARCHAR']; } case constant_1.TDengineTypeCode.BINARY: { return constant_1.ColumnsBlockType['VARCHAR']; } case constant_1.TDengineTypeCode.JSON: { return constant_1.ColumnsBlockType['VARCHAR']; } case constant_1.TDengineTypeCode.GEOMETRY: { return constant_1.ColumnsBlockType['GEOMETRY']; } case constant_1.TDengineTypeCode.VARBINARY: { return constant_1.ColumnsBlockType.VARBINARY; } default: { return constant_1.ColumnsBlockType['SOLID']; } } } function readSolidDataToArray(dataBuffer, colBlockHead, rows, metaType, bitMapArr) { let result = []; switch (metaType) { case constant_1.TDengineTypeCode.BOOL: case constant_1.TDengineTypeCode.TINYINT: case constant_1.TDengineTypeCode.TINYINT_UNSIGNED: { for (let i = 0; i < rows; i++, colBlockHead++) { if (isNull(bitMapArr, i)) { result.push(null); } else { result.push(dataBuffer.getInt8(colBlockHead)); } } break; } case constant_1.TDengineTypeCode.SMALLINT: { for (let i = 0; i < rows; i++, colBlockHead += 2) { if (isNull(bitMapArr, i)) { result.push(null); } else { result.push(dataBuffer.getInt16(colBlockHead, true)); } } break; } case constant_1.TDengineTypeCode.INT: { for (let i = 0; i < rows; i++, colBlockHead += 4) { if (isNull(bitMapArr, i)) { result.push(null); } else { result.push(dataBuffer.getInt32(colBlockHead, true)); } } break; } case constant_1.TDengineTypeCode.BIGINT: { for (let i = 0; i < rows; i++, colBlockHead += 8) { if (isNull(bitMapArr, i)) { result.push(null); } else { result.push(dataBuffer.getBigInt64(colBlockHead, true)); } } break; } case constant_1.TDengineTypeCode.SMALLINT_UNSIGNED: { for (let i = 0; i < rows; i++, colBlockHead += 2) { if (isNull(bitMapArr, i)) { result.push(null); } else { result.push(dataBuffer.getUint16(colBlockHead, true)); } } break; } case constant_1.TDengineTypeCode.INT_UNSIGNED: { for (let i = 0; i < rows; i++, colBlockHead += 4) { if (isNull(bitMapArr, i)) { result.push(null); } else { result.push(dataBuffer.getUint32(colBlockHead, true)); } } break; } case constant_1.TDengineTypeCode.BIGINT_UNSIGNED: { for (let i = 0; i < rows; i++, colBlockHead += 8) { if (isNull(bitMapArr, i)) { result.push(null); } else { result.push(dataBuffer.getBigUint64(colBlockHead, true)); } } break; } case constant_1.TDengineTypeCode.FLOAT: { for (let i = 0; i < rows; i++, colBlockHead += 4) { if (isNull(bitMapArr, i)) { result.push(null); } else { result.push(parseFloat(dataBuffer.getFloat32(colBlockHead, true).toFixed(5))); } } break; } case constant_1.TDengineTypeCode.DOUBLE: { for (let i = 0; i < rows; i++, colBlockHead += 8) { if (isNull(bitMapArr, i)) { result.push(null); } else { result.push(parseFloat(dataBuffer.getFloat64(colBlockHead, true).toFixed(15))); } } break; } case constant_1.TDengineTypeCode.TIMESTAMP: { for (let i = 0; i < rows; i++, colBlockHead += 8) { if (isNull(bitMapArr, i)) { result.push(null); } else { result.push(dataBuffer.getBigInt64(colBlockHead, true)); } } break; } default: { throw new wsError_1.WebSocketQueryInterFaceError(wsError_1.ErrorCode.ERR_UNSUPPORTED_TDENGINE_TYPE, `unspported type ${metaType}`); } } return result; } function readSolidData(dataBuffer, colDataHead, meta) { switch (meta.type) { case constant_1.TDengineTypeCode.BOOL: { return (Boolean)(dataBuffer.getInt8(colDataHead)); } case constant_1.TDengineTypeCode.TINYINT: { return dataBuffer.getInt8(colDataHead); } case constant_1.TDengineTypeCode.SMALLINT: { return dataBuffer.getInt16(colDataHead, true); } case constant_1.TDengineTypeCode.INT: { return dataBuffer.getInt32(colDataHead, true); } case constant_1.TDengineTypeCode.BIGINT: { return dataBuffer.getBigInt64(colDataHead, true); } case constant_1.TDengineTypeCode.TINYINT_UNSIGNED: { return dataBuffer.getUint8(colDataHead); } case constant_1.TDengineTypeCode.SMALLINT_UNSIGNED: { return dataBuffer.getUint16(colDataHead, true); } case constant_1.TDengineTypeCode.INT_UNSIGNED: { return dataBuffer.getUint32(colDataHead, true); } case constant_1.TDengineTypeCode.BIGINT_UNSIGNED: { return dataBuffer.getBigUint64(colDataHead, true); } case constant_1.TDengineTypeCode.FLOAT: { return parseFloat(dataBuffer.getFloat32(colDataHead, true).toFixed(5)); } case constant_1.TDengineTypeCode.DOUBLE: { return parseFloat(dataBuffer.getFloat64(colDataHead, true).toFixed(15)); } case constant_1.TDengineTypeCode.TIMESTAMP: { return dataBuffer.getBigInt64(colDataHead, true); // could change } default: { throw new wsError_1.WebSocketQueryInterFaceError(wsError_1.ErrorCode.ERR_UNSUPPORTED_TDENGINE_TYPE, `unspported type ${meta.type} for column ${meta.name}`); } } } function readBinary(dataBuffer, colDataHead, length) { let buff = dataBuffer.slice(colDataHead, colDataHead + length); return buff; } function readVarchar(dataBuffer, colDataHead, length, textDecoder) { // let buff = dataBuffer.slice(colDataHead, colDataHead + length) let dataView = new DataView(dataBuffer, colDataHead, length); return textDecoder.decode(dataView); } function readNchar(dataBuffer, colDataHead, length) { let data = []; // let buff: ArrayBuffer = dataBuffer.slice(colDataHead, colDataHead + length); let dataView = new DataView(dataBuffer, colDataHead, length); for (let i = 0; i < length / 4; i++) { data.push((0, ut8Helper_1.appendRune)(dataView.getUint32(i * 4, true))); } return data.join(''); } function getString(dataBuffer, colDataHead, length, textDecoder) { // let buff = dataBuffer.slice(colDataHead, colDataHead + length - 1) let dataView = new Uint8Array(dataBuffer.buffer, dataBuffer.byteOffset + colDataHead, length - 1); return textDecoder.decode(dataView); } function iteratorBuff(arr) { let buf = Buffer.from(arr); for (const value of buf) { log_1.default.debug(value.toString()); } } function isNull(bitMapArr, n) { let c = new Uint8Array(bitMapArr); let position = n >>> 3; let index = n & 0x7; return (c[position] & (1 << (7 - index))) == (1 << (7 - index)); } function getCharOffset(n) { return n >> 3; } function setBitmapNull(c, n) { return c + (1 << (7 - bitPos(n))); } function bitPos(n) { return n & ((1 << 3) - 1); } function bitmapLen(n) { return ((n) + ((1 << 3) - 1)) >> 3; }