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.

429 lines (428 loc) 21.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.StmtBindParams = exports.ColumnInfo = void 0; const constant_1 = require("../common/constant"); const wsError_1 = require("../common/wsError"); const taosResult_1 = require("../common/taosResult"); const utils_1 = require("../common/utils"); class ColumnInfo { constructor([length, data], type, typeLen) { this.data = data; this.type = type; this.length = length; this.typeLen = typeLen; } } exports.ColumnInfo = ColumnInfo; class StmtBindParams { constructor(precision) { this.precisionLength = constant_1.PrecisionLength['ms']; this._dataTotalLen = 0; this._rows = 0; if (precision) { this.precisionLength = precision; } this._params = []; } getDataRows() { return this._rows; } getDataTotalLen() { return this._dataTotalLen; } getParams() { return this._params; } setBoolean(params) { if (!params || params.length == 0) { throw new wsError_1.TaosError(wsError_1.ErrorCode.ERR_INVALID_PARAMS, "SetBooleanColumn params is invalid!"); } let arrayBuffer = this.encodeDigitColumns(params, "boolean", constant_1.TDengineTypeLength['BOOL'], constant_1.TDengineTypeCode.BOOL); this._params.push(new ColumnInfo(arrayBuffer, constant_1.TDengineTypeCode.BOOL, constant_1.TDengineTypeLength['BOOL'])); } setTinyInt(params) { if (!params || params.length == 0) { throw new wsError_1.TaosError(wsError_1.ErrorCode.ERR_INVALID_PARAMS, "SetTinyIntColumn params is invalid!"); } let arrayBuffer = this.encodeDigitColumns(params, "number", constant_1.TDengineTypeLength['TINYINT'], constant_1.TDengineTypeCode.TINYINT); this._params.push(new ColumnInfo(arrayBuffer, constant_1.TDengineTypeCode.TINYINT, constant_1.TDengineTypeLength['TINYINT'])); } setUTinyInt(params) { if (!params || params.length == 0) { throw new wsError_1.TaosError(wsError_1.ErrorCode.ERR_INVALID_PARAMS, "SetUTinyIntColumn params is invalid!"); } let arrayBuffer = this.encodeDigitColumns(params, "number", constant_1.TDengineTypeLength['TINYINT UNSIGNED'], constant_1.TDengineTypeCode.TINYINT_UNSIGNED); this._params.push(new ColumnInfo(arrayBuffer, constant_1.TDengineTypeCode.TINYINT_UNSIGNED, constant_1.TDengineTypeLength['TINYINT UNSIGNED'])); } setSmallInt(params) { if (!params || params.length == 0) { throw new wsError_1.TaosError(wsError_1.ErrorCode.ERR_INVALID_PARAMS, "SetSmallIntColumn params is invalid!"); } let arrayBuffer = this.encodeDigitColumns(params, "number", constant_1.TDengineTypeLength['SMALLINT'], constant_1.TDengineTypeCode.SMALLINT); this._params.push(new ColumnInfo(arrayBuffer, constant_1.TDengineTypeCode.SMALLINT, constant_1.TDengineTypeLength['SMALLINT'])); } setUSmallInt(params) { if (!params || params.length == 0) { throw new wsError_1.TaosError(wsError_1.ErrorCode.ERR_INVALID_PARAMS, "SetSmallIntColumn params is invalid!"); } let arrayBuffer = this.encodeDigitColumns(params, "number", constant_1.TDengineTypeLength['SMALLINT UNSIGNED'], constant_1.TDengineTypeCode.SMALLINT_UNSIGNED); this._params.push(new ColumnInfo(arrayBuffer, constant_1.TDengineTypeCode.SMALLINT_UNSIGNED, constant_1.TDengineTypeLength['SMALLINT UNSIGNED'])); } setInt(params) { if (!params || params.length == 0) { throw new wsError_1.TaosError(wsError_1.ErrorCode.ERR_INVALID_PARAMS, "SetIntColumn params is invalid!"); } let arrayBuffer = this.encodeDigitColumns(params, "number", constant_1.TDengineTypeLength['INT'], constant_1.TDengineTypeCode.INT); this._params.push(new ColumnInfo(arrayBuffer, constant_1.TDengineTypeCode.INT, constant_1.TDengineTypeLength['INT'])); } setUInt(params) { if (!params || params.length == 0) { throw new wsError_1.TaosError(wsError_1.ErrorCode.ERR_INVALID_PARAMS, "SetUIntColumn params is invalid!"); } let arrayBuffer = this.encodeDigitColumns(params, "number", constant_1.TDengineTypeLength['INT UNSIGNED'], constant_1.TDengineTypeCode.INT_UNSIGNED); this._params.push(new ColumnInfo(arrayBuffer, constant_1.TDengineTypeCode.INT_UNSIGNED, constant_1.TDengineTypeLength['INT UNSIGNED'])); } setBigint(params) { if (!params || params.length == 0) { throw new wsError_1.TaosError(wsError_1.ErrorCode.ERR_INVALID_PARAMS, "SetBigIntColumn params is invalid!"); } let arrayBuffer = this.encodeDigitColumns(params, "bigint", constant_1.TDengineTypeLength['BIGINT'], constant_1.TDengineTypeCode.BIGINT); this._params.push(new ColumnInfo(arrayBuffer, constant_1.TDengineTypeCode.INT, constant_1.TDengineTypeLength['BIGINT'])); } setUBigint(params) { if (!params || params.length == 0) { throw new wsError_1.TaosError(wsError_1.ErrorCode.ERR_INVALID_PARAMS, "SetUBigIntColumn params is invalid!"); } let arrayBuffer = this.encodeDigitColumns(params, "bigint", constant_1.TDengineTypeLength['BIGINT UNSIGNED'], constant_1.TDengineTypeCode.BIGINT_UNSIGNED); this._params.push(new ColumnInfo(arrayBuffer, constant_1.TDengineTypeCode.BIGINT_UNSIGNED, constant_1.TDengineTypeLength['BIGINT UNSIGNED'])); } setFloat(params) { if (!params || params.length == 0) { throw new wsError_1.TaosError(wsError_1.ErrorCode.ERR_INVALID_PARAMS, "SetFloatColumn params is invalid!"); } let arrayBuffer = this.encodeDigitColumns(params, "number", constant_1.TDengineTypeLength['FLOAT'], constant_1.TDengineTypeCode.FLOAT); this._params.push(new ColumnInfo(arrayBuffer, constant_1.TDengineTypeCode.FLOAT, constant_1.TDengineTypeLength['FLOAT'])); } setDouble(params) { if (!params || params.length == 0) { throw new wsError_1.TaosError(wsError_1.ErrorCode.ERR_INVALID_PARAMS, "SetDoubleColumn params is invalid!"); } let arrayBuffer = this.encodeDigitColumns(params, "number", constant_1.TDengineTypeLength['DOUBLE'], constant_1.TDengineTypeCode.DOUBLE); this._params.push(new ColumnInfo(arrayBuffer, constant_1.TDengineTypeCode.DOUBLE, constant_1.TDengineTypeLength['DOUBLE'])); } setVarchar(params) { let data = this.encodeVarLengthColumn(params); this._params.push(new ColumnInfo(data, constant_1.TDengineTypeCode.VARCHAR, 0)); } setBinary(params) { this._params.push(new ColumnInfo(this.encodeVarLengthColumn(params), constant_1.TDengineTypeCode.BINARY, 0)); } setNchar(params) { this._params.push(new ColumnInfo(this.encodeNcharColumn(params), constant_1.TDengineTypeCode.NCHAR, 0)); } setJson(params) { this._params.push(new ColumnInfo(this.encodeVarLengthColumn(params), constant_1.TDengineTypeCode.JSON, 0)); } setVarBinary(params) { this._params.push(new ColumnInfo(this.encodeVarLengthColumn(params), constant_1.TDengineTypeCode.VARBINARY, 0)); } setGeometry(params) { this._params.push(new ColumnInfo(this.encodeVarLengthColumn(params), constant_1.TDengineTypeCode.GEOMETRY, 0)); } setTimestamp(params) { if (!params || params.length == 0) { throw new wsError_1.TaosError(wsError_1.ErrorCode.ERR_INVALID_PARAMS, "SeTimestampColumn params is invalid!"); } //computing bitmap length let bitMapLen = (0, taosResult_1.bitmapLen)(params.length); //Computing the length of data let arrayBuffer = new ArrayBuffer(bitMapLen + constant_1.TDengineTypeLength['TIMESTAMP'] * params.length); //bitmap get data range let bitmapBuffer = new DataView(arrayBuffer); //skip bitmap get data range let dataBuffer = new DataView(arrayBuffer, bitMapLen); if (this._rows > 0) { if (this._rows !== params.length) { throw new wsError_1.TaosError(wsError_1.ErrorCode.ERR_INVALID_PARAMS, "wrong row length!"); } } else { this._rows = params.length; } for (let i = 0; i < params.length; i++) { if (!(0, utils_1.isEmpty)(params[i])) { if (params[i] instanceof Date) { let date = params[i]; //node only support milliseconds, need fill 0 if (this.precisionLength == constant_1.PrecisionLength['us']) { let ms = date.getMilliseconds() * 1000; dataBuffer.setBigInt64(i * 8, BigInt(ms), true); } else if (this.precisionLength == constant_1.PrecisionLength['ns']) { let ns = date.getMilliseconds() * 1000 * 1000; dataBuffer.setBigInt64(i * 8, BigInt(ns), true); } else { dataBuffer.setBigInt64(i * 8, BigInt(date.getMilliseconds()), true); } } else if (typeof params[i] == 'bigint' || typeof params[i] == 'number') { let data; if (typeof params[i] == 'number') { data = BigInt(params[i]); } else { data = params[i]; } //statistical bits of digit let digit = this.countBigintDigits(data); //check digit same table Precision if (this.precisionLength == constant_1.PrecisionLength['ns']) { if (this.precisionLength <= digit) { dataBuffer.setBigInt64(i * 8, data, true); } else { throw new wsError_1.TaosError(wsError_1.ErrorCode.ERR_INVALID_PARAMS, "SeTimestampColumn params precisionLength is invalid! param:=" + params[i]); } } else if (this.precisionLength == digit) { dataBuffer.setBigInt64(i * 8, data, true); } else { throw new wsError_1.TaosError(wsError_1.ErrorCode.ERR_INVALID_PARAMS, "SeTimestampColumn params is invalid! param:=" + params[i]); } } } else { //set bitmap bit is null let charOffset = (0, taosResult_1.getCharOffset)(i); let nullVal = (0, taosResult_1.setBitmapNull)(dataBuffer.getInt8(charOffset), i); bitmapBuffer.setInt8(charOffset, nullVal); } } this._dataTotalLen += arrayBuffer.byteLength; this._params.push(new ColumnInfo([constant_1.TDengineTypeLength['TIMESTAMP'] * params.length, arrayBuffer], constant_1.TDengineTypeCode.TIMESTAMP, constant_1.TDengineTypeLength['TIMESTAMP'])); } encodeDigitColumns(params, dataType = 'number', typeLen, columnType) { let bitMapLen = (0, taosResult_1.bitmapLen)(params.length); let arrayBuffer = new ArrayBuffer(typeLen * params.length + bitMapLen); let bitmapBuffer = new DataView(arrayBuffer); let dataBuffer = new DataView(arrayBuffer, bitMapLen); if (this._rows > 0) { if (this._rows !== params.length) { throw new wsError_1.TaosError(wsError_1.ErrorCode.ERR_INVALID_PARAMS, "wrong row length!"); } } else { this._rows = params.length; } for (let i = 0; i < params.length; i++) { if (!(0, utils_1.isEmpty)(params[i])) { if (typeof params[i] == dataType) { switch (columnType) { case constant_1.TDengineTypeCode.BOOL: { if (params[i]) { dataBuffer.setInt8(i, 1); } else { dataBuffer.setInt8(i, 0); } break; } case constant_1.TDengineTypeCode.TINYINT: { dataBuffer.setInt8(i, params[i]); break; } case constant_1.TDengineTypeCode.TINYINT_UNSIGNED: { dataBuffer.setUint8(i, params[i]); break; } case constant_1.TDengineTypeCode.SMALLINT: { dataBuffer.setInt16(i * 2, params[i], true); break; } case constant_1.TDengineTypeCode.SMALLINT_UNSIGNED: { dataBuffer.setUint16(i * 2, params[i], true); break; } case constant_1.TDengineTypeCode.INT: { dataBuffer.setInt32(i * 4, params[i], true); break; } case constant_1.TDengineTypeCode.INT_UNSIGNED: { dataBuffer.setUint32(i * 4, params[i], true); break; } case constant_1.TDengineTypeCode.BIGINT: { dataBuffer.setBigInt64(i * 8, params[i], true); break; } case constant_1.TDengineTypeCode.BIGINT_UNSIGNED: { dataBuffer.setBigUint64(i * 8, params[i], true); break; } case constant_1.TDengineTypeCode.FLOAT: { dataBuffer.setFloat32(i * 4, params[i], true); break; } case constant_1.TDengineTypeCode.DOUBLE: { dataBuffer.setFloat64(i * 8, params[i], true); break; } default: { throw new wsError_1.TaosError(wsError_1.ErrorCode.ERR_UNSUPPORTED_TDENGINE_TYPE, "unsupported type for column" + columnType); } } } else { throw new wsError_1.TaosError(wsError_1.ErrorCode.ERR_INVALID_PARAMS, "SetTinyIntColumn params is invalid! param:=" + params[i]); } } else { //set bitmap bit is null let charOffset = (0, taosResult_1.getCharOffset)(i); let nullVal = (0, taosResult_1.setBitmapNull)(bitmapBuffer.getUint8(charOffset), i); bitmapBuffer.setInt8(charOffset, nullVal); } } this._dataTotalLen += dataBuffer.buffer.byteLength; return [typeLen * params.length, dataBuffer.buffer]; } encodeVarLengthColumn(params) { let data = []; let dataLength = 0; //create params length buffer let paramsLenBuffer = new ArrayBuffer(constant_1.TDengineTypeLength['INT'] * params.length); let paramsLenView = new DataView(paramsLenBuffer); if (this._rows > 0) { if (this._rows !== params.length) { throw new wsError_1.TaosError(wsError_1.ErrorCode.ERR_INVALID_PARAMS, "wrong row length!"); } } else { this._rows = params.length; } for (let i = 0; i < params.length; i++) { //get param length offset 4byte let offset = constant_1.TDengineTypeLength['INT'] * i; if (!(0, utils_1.isEmpty)(params[i])) { //save param length offset 4byte paramsLenView.setInt32(offset, dataLength, true); if (typeof params[i] == 'string') { //string TextEncoder let encode = new TextEncoder(); let value = encode.encode(params[i]).buffer; data.push(value); //add offset length dataLength += value.byteLength + constant_1.TDengineTypeLength['SMALLINT']; } else if (params[i] instanceof ArrayBuffer) { //input arraybuffer, save not need encode let value = params[i]; dataLength += value.byteLength + constant_1.TDengineTypeLength['SMALLINT']; data.push(value); } else { throw new wsError_1.TaosError(wsError_1.ErrorCode.ERR_INVALID_PARAMS, "getColumString params is invalid! param_type:=" + typeof params[i]); } } else { //set length -1, param is null for (let j = 0; j < constant_1.TDengineTypeLength['INT']; j++) { paramsLenView.setInt8(offset + j, 255); } } } this._dataTotalLen += paramsLenBuffer.byteLength + dataLength; return [dataLength, this.getBinaryColumnArrayBuffer(data, paramsLenView.buffer, dataLength)]; } //splicing encode params to arraybuffer getBinaryColumnArrayBuffer(data, paramsLenBuffer, dataLength) { //create arraybuffer let paramsBuffer = new ArrayBuffer(paramsLenBuffer.byteLength + dataLength); //get length data range const paramsUint8 = new Uint8Array(paramsBuffer); const paramsLenView = new Uint8Array(paramsLenBuffer); paramsUint8.set(paramsLenView, 0); //get data range const paramsView = new DataView(paramsBuffer, paramsLenBuffer.byteLength); let offset = 0; for (let i = 0; i < data.length; i++) { //save param field length paramsView.setInt16(offset, data[i].byteLength, true); const dataView = new DataView(data[i]); //save data for (let j = 0; j < data[i].byteLength; j++) { paramsView.setUint8(offset + 2 + j, dataView.getUint8(j)); } offset += data[i].byteLength + 2; } return paramsBuffer; } //encode nchar type params encodeNcharColumn(params) { let data = []; let dataLength = 0; let indexBuffer = new ArrayBuffer(constant_1.TDengineTypeLength['INT'] * params.length); let indexView = new DataView(indexBuffer); if (this._rows > 0) { if (this._rows !== params.length) { throw new wsError_1.TaosError(wsError_1.ErrorCode.ERR_INVALID_PARAMS, "wrong row length!"); } } else { this._rows = params.length; } for (let i = 0; i < params.length; i++) { let offset = constant_1.TDengineTypeLength['INT'] * i; if (!(0, utils_1.isEmpty)(params[i])) { indexView.setInt32(offset, dataLength, true); if (typeof params[i] == 'string') { let codes = []; let strNcharParams = params[i]; for (let j = 0; j < params[i].length; j++) { //get char, cn char need 3~4 byte codes.push(strNcharParams.charCodeAt(j)); } let ncharBuffer = new ArrayBuffer(codes.length * 4); let ncharView = new DataView(ncharBuffer); for (let j = 0; j < codes.length; j++) { //1char, save into uint32 ncharView.setUint32(j * 4, codes[j], true); } data.push(ncharBuffer); dataLength += codes.length * 4 + constant_1.TDengineTypeLength['SMALLINT']; } else if (params[i] instanceof ArrayBuffer) { let value = params[i]; dataLength += value.byteLength + constant_1.TDengineTypeLength['SMALLINT']; data.push(value); } else { throw new wsError_1.TaosError(wsError_1.ErrorCode.ERR_INVALID_PARAMS, "getColumString params is invalid! param_type:=" + typeof params[i]); } } else { //set length -1, param is null for (let j = 0; j < constant_1.TDengineTypeLength['INT']; j++) { indexView.setInt8(offset + j, 255); } } } this._dataTotalLen += indexBuffer.byteLength + dataLength; return [dataLength, this.getBinaryColumnArrayBuffer(data, indexView.buffer, dataLength)]; } countBigintDigits(numeral) { if (numeral === 0n) { return 1; } let count = 0; let temp = numeral; while (temp !== 0n) { temp /= 10n; count++; } return count; } } exports.StmtBindParams = StmtBindParams;