/* * Copyright (c) 2019 TAOS Data, Inc. * * This program is free software: you can use, redistribute, and/or modify * it under the terms of the GNU Affero General Public License, version 3 * or later ("AGPL"), as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ #include "os.h" #include "filter.h" #include "filterInt.h" #include "query.h" #include "querynodes.h" #include "sclInt.h" #include "sclvector.h" #include "tcompare.h" #include "tdatablock.h" #include "tdataformat.h" #include "ttime.h" #include "ttypes.h" #define LEFT_COL ((pLeftCol->info.type == TSDB_DATA_TYPE_JSON ? (void *)pLeftCol : pLeftCol->pData)) #define RIGHT_COL ((pRightCol->info.type == TSDB_DATA_TYPE_JSON ? (void *)pRightCol : pRightCol->pData)) #define IS_NULL \ colDataIsNull_s(pLeft->columnData, i) || colDataIsNull_s(pRight->columnData, i) || \ IS_JSON_NULL(pLeft->columnData->info.type, colDataGetVarData(pLeft->columnData, i)) || \ IS_JSON_NULL(pRight->columnData->info.type, colDataGetVarData(pRight->columnData, i)) #define IS_HELPER_NULL(col, i) colDataIsNull_s(col, i) || IS_JSON_NULL(col->info.type, colDataGetVarData(col, i)) bool noConvertBeforeCompare(int32_t leftType, int32_t rightType, int32_t optr) { return IS_NUMERIC_TYPE(leftType) && IS_NUMERIC_TYPE(rightType) && (optr >= OP_TYPE_GREATER_THAN && optr <= OP_TYPE_NOT_EQUAL); } void convertNumberToNumber(const void *inData, void *outData, int8_t inType, int8_t outType) { switch (outType) { case TSDB_DATA_TYPE_BOOL: { GET_TYPED_DATA(*((bool *)outData), bool, inType, inData); break; } case TSDB_DATA_TYPE_TINYINT: { GET_TYPED_DATA(*((int8_t *)outData), int8_t, inType, inData); break; } case TSDB_DATA_TYPE_SMALLINT: { GET_TYPED_DATA(*((int16_t *)outData), int16_t, inType, inData); break; } case TSDB_DATA_TYPE_INT: { GET_TYPED_DATA(*((int32_t *)outData), int32_t, inType, inData); break; } case TSDB_DATA_TYPE_BIGINT: case TSDB_DATA_TYPE_TIMESTAMP: { GET_TYPED_DATA(*((int64_t *)outData), int64_t, inType, inData); break; } case TSDB_DATA_TYPE_UTINYINT: { GET_TYPED_DATA(*((uint8_t *)outData), uint8_t, inType, inData); break; } case TSDB_DATA_TYPE_USMALLINT: { GET_TYPED_DATA(*((uint16_t *)outData), uint16_t, inType, inData); break; } case TSDB_DATA_TYPE_UINT: { GET_TYPED_DATA(*((uint32_t *)outData), uint32_t, inType, inData); break; } case TSDB_DATA_TYPE_UBIGINT: { GET_TYPED_DATA(*((uint64_t *)outData), uint64_t, inType, inData); break; } case TSDB_DATA_TYPE_FLOAT: { GET_TYPED_DATA(*((float *)outData), float, inType, inData); break; } case TSDB_DATA_TYPE_DOUBLE: { GET_TYPED_DATA(*((double *)outData), double, inType, inData); break; } default: { ASSERT(0); } } } void convertNcharToDouble(const void *inData, void *outData) { char *tmp = taosMemoryMalloc(varDataTLen(inData)); int len = taosUcs4ToMbs((TdUcs4 *)varDataVal(inData), varDataLen(inData), tmp); if (len < 0) { sclError("castConvert taosUcs4ToMbs error 1"); } tmp[len] = 0; double value = taosStr2Double(tmp, NULL); *((double *)outData) = value; taosMemoryFreeClear(tmp); } void convertBinaryToDouble(const void *inData, void *outData) { char *tmp = taosMemoryCalloc(1, varDataTLen(inData)); if (tmp == NULL) { *((double *)outData) = 0.; return; } memcpy(tmp, varDataVal(inData), varDataLen(inData)); double ret = taosStr2Double(tmp, NULL); taosMemoryFree(tmp); *((double *)outData) = ret; } typedef int64_t (*_getBigintValue_fn_t)(void *src, int32_t index); int64_t getVectorBigintValue_TINYINT(void *src, int32_t index) { return (int64_t) * ((int8_t *)src + index); } int64_t getVectorBigintValue_UTINYINT(void *src, int32_t index) { return (int64_t) * ((uint8_t *)src + index); } int64_t getVectorBigintValue_SMALLINT(void *src, int32_t index) { return (int64_t) * ((int16_t *)src + index); } int64_t getVectorBigintValue_USMALLINT(void *src, int32_t index) { return (int64_t) * ((uint16_t *)src + index); } int64_t getVectorBigintValue_INT(void *src, int32_t index) { return (int64_t) * ((int32_t *)src + index); } int64_t getVectorBigintValue_UINT(void *src, int32_t index) { return (int64_t) * ((uint32_t *)src + index); } int64_t getVectorBigintValue_BIGINT(void *src, int32_t index) { return (int64_t) * ((int64_t *)src + index); } int64_t getVectorBigintValue_UBIGINT(void *src, int32_t index) { return (int64_t) * ((uint64_t *)src + index); } int64_t getVectorBigintValue_FLOAT(void *src, int32_t index) { return (int64_t) * ((float *)src + index); } int64_t getVectorBigintValue_DOUBLE(void *src, int32_t index) { return (int64_t) * ((double *)src + index); } int64_t getVectorBigintValue_BOOL(void *src, int32_t index) { return (int64_t) * ((bool *)src + index); } int64_t getVectorBigintValue_JSON(void *src, int32_t index) { ASSERT(!colDataIsNull_var(((SColumnInfoData *)src), index)); char *data = colDataGetVarData((SColumnInfoData *)src, index); double out = 0; if (*data == TSDB_DATA_TYPE_NULL) { return 0; } else if (*data == TSDB_DATA_TYPE_NCHAR) { // json inner type can not be BINARY convertNcharToDouble(data + CHAR_BYTES, &out); } else if (tTagIsJson(data)) { terrno = TSDB_CODE_QRY_JSON_NOT_SUPPORT_ERROR; return 0; } else { convertNumberToNumber(data + CHAR_BYTES, &out, *data, TSDB_DATA_TYPE_DOUBLE); } return (int64_t)out; } _getBigintValue_fn_t getVectorBigintValueFn(int32_t srcType) { _getBigintValue_fn_t p = NULL; if (srcType == TSDB_DATA_TYPE_TINYINT) { p = getVectorBigintValue_TINYINT; } else if (srcType == TSDB_DATA_TYPE_UTINYINT) { p = getVectorBigintValue_UTINYINT; } else if (srcType == TSDB_DATA_TYPE_SMALLINT) { p = getVectorBigintValue_SMALLINT; } else if (srcType == TSDB_DATA_TYPE_USMALLINT) { p = getVectorBigintValue_USMALLINT; } else if (srcType == TSDB_DATA_TYPE_INT) { p = getVectorBigintValue_INT; } else if (srcType == TSDB_DATA_TYPE_UINT) { p = getVectorBigintValue_UINT; } else if (srcType == TSDB_DATA_TYPE_BIGINT) { p = getVectorBigintValue_BIGINT; } else if (srcType == TSDB_DATA_TYPE_UBIGINT) { p = getVectorBigintValue_UBIGINT; } else if (srcType == TSDB_DATA_TYPE_FLOAT) { p = getVectorBigintValue_FLOAT; } else if (srcType == TSDB_DATA_TYPE_DOUBLE) { p = getVectorBigintValue_DOUBLE; } else if (srcType == TSDB_DATA_TYPE_TIMESTAMP) { p = getVectorBigintValue_BIGINT; } else if (srcType == TSDB_DATA_TYPE_BOOL) { p = getVectorBigintValue_BOOL; } else if (srcType == TSDB_DATA_TYPE_JSON) { p = getVectorBigintValue_JSON; } else if (srcType == TSDB_DATA_TYPE_NULL) { p = NULL; } else { ASSERT(0); } return p; } typedef void *(*_getValueAddr_fn_t)(void *src, int32_t index); void *getVectorValueAddr_TINYINT(void *src, int32_t index) { return (void *)((int8_t *)src + index); } void *getVectorValueAddr_UTINYINT(void *src, int32_t index) { return (void *)((uint8_t *)src + index); } void *getVectorValueAddr_SMALLINT(void *src, int32_t index) { return (void *)((int16_t *)src + index); } void *getVectorValueAddr_USMALLINT(void *src, int32_t index) { return (void *)((uint16_t *)src + index); } void *getVectorValueAddr_INT(void *src, int32_t index) { return (void *)((int32_t *)src + index); } void *getVectorValueAddr_UINT(void *src, int32_t index) { return (void *)((uint32_t *)src + index); } void *getVectorValueAddr_BIGINT(void *src, int32_t index) { return (void *)((int64_t *)src + index); } void *getVectorValueAddr_UBIGINT(void *src, int32_t index) { return (void *)((uint64_t *)src + index); } void *getVectorValueAddr_FLOAT(void *src, int32_t index) { return (void *)((float *)src + index); } void *getVectorValueAddr_DOUBLE(void *src, int32_t index) { return (void *)((double *)src + index); } void *getVectorValueAddr_default(void *src, int32_t index) { return src; } void *getVectorValueAddr_VAR(void *src, int32_t index) { return colDataGetData((SColumnInfoData *)src, index); } _getValueAddr_fn_t getVectorValueAddrFn(int32_t srcType) { _getValueAddr_fn_t p = NULL; if (srcType == TSDB_DATA_TYPE_TINYINT) { p = getVectorValueAddr_TINYINT; } else if (srcType == TSDB_DATA_TYPE_UTINYINT) { p = getVectorValueAddr_UTINYINT; } else if (srcType == TSDB_DATA_TYPE_SMALLINT) { p = getVectorValueAddr_SMALLINT; } else if (srcType == TSDB_DATA_TYPE_USMALLINT) { p = getVectorValueAddr_USMALLINT; } else if (srcType == TSDB_DATA_TYPE_INT) { p = getVectorValueAddr_INT; } else if (srcType == TSDB_DATA_TYPE_UINT) { p = getVectorValueAddr_UINT; } else if (srcType == TSDB_DATA_TYPE_BIGINT) { p = getVectorValueAddr_BIGINT; } else if (srcType == TSDB_DATA_TYPE_UBIGINT) { p = getVectorValueAddr_UBIGINT; } else if (srcType == TSDB_DATA_TYPE_FLOAT) { p = getVectorValueAddr_FLOAT; } else if (srcType == TSDB_DATA_TYPE_DOUBLE) { p = getVectorValueAddr_DOUBLE; } else if (srcType == TSDB_DATA_TYPE_BINARY) { p = getVectorValueAddr_VAR; } else if (srcType == TSDB_DATA_TYPE_NCHAR) { p = getVectorValueAddr_VAR; } else { p = getVectorValueAddr_default; } return p; } static FORCE_INLINE void varToTimestamp(char *buf, SScalarParam *pOut, int32_t rowIndex, int32_t *overflow) { int64_t value = 0; if (taosParseTime(buf, &value, strlen(buf), pOut->columnData->info.precision, tsDaylight) != TSDB_CODE_SUCCESS) { value = 0; } colDataSetInt64(pOut->columnData, rowIndex, &value); } static FORCE_INLINE void varToSigned(char *buf, SScalarParam *pOut, int32_t rowIndex, int32_t *overflow) { if (overflow) { int64_t minValue = tDataTypes[pOut->columnData->info.type].minValue; int64_t maxValue = tDataTypes[pOut->columnData->info.type].maxValue; int64_t value = (int64_t)taosStr2Int64(buf, NULL, 10); if (value > maxValue) { *overflow = 1; return; } else if (value < minValue) { *overflow = -1; return; } else { *overflow = 0; } } switch (pOut->columnData->info.type) { case TSDB_DATA_TYPE_TINYINT: { int8_t value = (int8_t)taosStr2Int8(buf, NULL, 10); colDataSetInt8(pOut->columnData, rowIndex, (int8_t *)&value); break; } case TSDB_DATA_TYPE_SMALLINT: { int16_t value = (int16_t)taosStr2Int16(buf, NULL, 10); colDataSetInt16(pOut->columnData, rowIndex, (int16_t *)&value); break; } case TSDB_DATA_TYPE_INT: { int32_t value = (int32_t)taosStr2Int32(buf, NULL, 10); colDataSetInt32(pOut->columnData, rowIndex, (int32_t *)&value); break; } case TSDB_DATA_TYPE_BIGINT: { int64_t value = (int64_t)taosStr2Int64(buf, NULL, 10); colDataSetInt64(pOut->columnData, rowIndex, (int64_t *)&value); break; } } } static FORCE_INLINE void varToUnsigned(char *buf, SScalarParam *pOut, int32_t rowIndex, int32_t *overflow) { if (overflow) { uint64_t minValue = (uint64_t)tDataTypes[pOut->columnData->info.type].minValue; uint64_t maxValue = (uint64_t)tDataTypes[pOut->columnData->info.type].maxValue; uint64_t value = (uint64_t)taosStr2UInt64(buf, NULL, 10); if (value > maxValue) { *overflow = 1; return; } else if (value < minValue) { *overflow = -1; return; } else { *overflow = 0; } } switch (pOut->columnData->info.type) { case TSDB_DATA_TYPE_UTINYINT: { uint8_t value = (uint8_t)taosStr2UInt8(buf, NULL, 10); colDataSetInt8(pOut->columnData, rowIndex, (int8_t *)&value); break; } case TSDB_DATA_TYPE_USMALLINT: { uint16_t value = (uint16_t)taosStr2UInt16(buf, NULL, 10); colDataSetInt16(pOut->columnData, rowIndex, (int16_t *)&value); break; } case TSDB_DATA_TYPE_UINT: { uint32_t value = (uint32_t)taosStr2UInt32(buf, NULL, 10); colDataSetInt32(pOut->columnData, rowIndex, (int32_t *)&value); break; } case TSDB_DATA_TYPE_UBIGINT: { uint64_t value = (uint64_t)taosStr2UInt64(buf, NULL, 10); colDataSetInt64(pOut->columnData, rowIndex, (int64_t *)&value); break; } } } static FORCE_INLINE void varToFloat(char *buf, SScalarParam *pOut, int32_t rowIndex, int32_t *overflow) { if (TSDB_DATA_TYPE_FLOAT == pOut->columnData->info.type) { float value = taosStr2Float(buf, NULL); colDataSetFloat(pOut->columnData, rowIndex, &value); return; } double value = taosStr2Double(buf, NULL); colDataSetDouble(pOut->columnData, rowIndex, &value); } static FORCE_INLINE void varToBool(char *buf, SScalarParam *pOut, int32_t rowIndex, int32_t *overflow) { int64_t value = taosStr2Int64(buf, NULL, 10); bool v = (value != 0) ? true : false; colDataSetInt8(pOut->columnData, rowIndex, (int8_t *)&v); } // todo remove this malloc static FORCE_INLINE void varToNchar(char *buf, SScalarParam *pOut, int32_t rowIndex, int32_t *overflow) { int32_t len = 0; int32_t inputLen = varDataLen(buf); int32_t outputMaxLen = (inputLen + 1) * TSDB_NCHAR_SIZE + VARSTR_HEADER_SIZE; char *t = taosMemoryCalloc(1, outputMaxLen); int32_t ret = taosMbsToUcs4(varDataVal(buf), inputLen, (TdUcs4 *)varDataVal(t), outputMaxLen - VARSTR_HEADER_SIZE, &len); if (!ret) { sclError("failed to convert to NCHAR"); } varDataSetLen(t, len); colDataSetVal(pOut->columnData, rowIndex, t, false); taosMemoryFree(t); } static FORCE_INLINE void ncharToVar(char *buf, SScalarParam *pOut, int32_t rowIndex, int32_t *overflow) { int32_t inputLen = varDataLen(buf); char *t = taosMemoryCalloc(1, inputLen + VARSTR_HEADER_SIZE); int32_t len = taosUcs4ToMbs((TdUcs4 *)varDataVal(buf), varDataLen(buf), varDataVal(t)); if (len < 0) { taosMemoryFree(t); return; } varDataSetLen(t, len); colDataSetVal(pOut->columnData, rowIndex, t, false); taosMemoryFree(t); } // TODO opt performance, tmp is not needed. int32_t vectorConvertFromVarData(SSclVectorConvCtx *pCtx, int32_t *overflow) { bool vton = false; _bufConverteFunc func = NULL; if (TSDB_DATA_TYPE_BOOL == pCtx->outType) { func = varToBool; } else if (IS_SIGNED_NUMERIC_TYPE(pCtx->outType)) { func = varToSigned; } else if (IS_UNSIGNED_NUMERIC_TYPE(pCtx->outType)) { func = varToUnsigned; } else if (IS_FLOAT_TYPE(pCtx->outType)) { func = varToFloat; } else if (pCtx->outType == TSDB_DATA_TYPE_VARCHAR && pCtx->inType == TSDB_DATA_TYPE_NCHAR) { // nchar -> binary func = ncharToVar; vton = true; } else if (pCtx->outType == TSDB_DATA_TYPE_NCHAR && pCtx->inType == TSDB_DATA_TYPE_VARCHAR) { // binary -> nchar func = varToNchar; vton = true; } else if (TSDB_DATA_TYPE_TIMESTAMP == pCtx->outType) { func = varToTimestamp; } else { sclError("invalid convert outType:%d, inType:%d", pCtx->outType, pCtx->inType); return TSDB_CODE_APP_ERROR; } pCtx->pOut->numOfRows = pCtx->pIn->numOfRows; char* tmp = NULL; for (int32_t i = pCtx->startIndex; i <= pCtx->endIndex; ++i) { if (IS_HELPER_NULL(pCtx->pIn->columnData, i)) { colDataSetNULL(pCtx->pOut->columnData, i); continue; } char *data = colDataGetVarData(pCtx->pIn->columnData, i); int32_t convertType = pCtx->inType; if (pCtx->inType == TSDB_DATA_TYPE_JSON) { if (*data == TSDB_DATA_TYPE_NCHAR) { data += CHAR_BYTES; convertType = TSDB_DATA_TYPE_NCHAR; } else if (tTagIsJson(data) || *data == TSDB_DATA_TYPE_NULL) { terrno = TSDB_CODE_QRY_JSON_NOT_SUPPORT_ERROR; return terrno; } else { convertNumberToNumber(data + CHAR_BYTES, colDataGetNumData(pCtx->pOut->columnData, i), *data, pCtx->outType); continue; } } int32_t bufSize = pCtx->pIn->columnData->info.bytes; if (tmp == NULL) { tmp = taosMemoryMalloc(bufSize); if (tmp == NULL) { sclError("out of memory in vectorConvertFromVarData"); return TSDB_CODE_OUT_OF_MEMORY; } } if (vton) { memcpy(tmp, data, varDataTLen(data)); } else { if (TSDB_DATA_TYPE_VARCHAR == convertType) { memcpy(tmp, varDataVal(data), varDataLen(data)); tmp[varDataLen(data)] = 0; } else if (TSDB_DATA_TYPE_NCHAR == convertType) { // we need to convert it to native char string, and then perform the string to numeric data if (varDataLen(data) > bufSize) { sclError("castConvert convert buffer size too small"); taosMemoryFreeClear(tmp); return TSDB_CODE_APP_ERROR; } int len = taosUcs4ToMbs((TdUcs4 *)varDataVal(data), varDataLen(data), tmp); if (len < 0) { sclError("castConvert taosUcs4ToMbs error 1"); taosMemoryFreeClear(tmp); return TSDB_CODE_APP_ERROR; } tmp[len] = 0; } } (*func)(tmp, pCtx->pOut, i, overflow); } if (tmp != NULL) { taosMemoryFreeClear(tmp); } return TSDB_CODE_SUCCESS; } double getVectorDoubleValue_JSON(void *src, int32_t index) { char *data = colDataGetVarData((SColumnInfoData *)src, index); double out = 0; if (*data == TSDB_DATA_TYPE_NULL) { return out; } else if (*data == TSDB_DATA_TYPE_NCHAR) { // json inner type can not be BINARY convertNcharToDouble(data + CHAR_BYTES, &out); } else if (tTagIsJson(data)) { terrno = TSDB_CODE_QRY_JSON_NOT_SUPPORT_ERROR; return 0; } else { convertNumberToNumber(data + CHAR_BYTES, &out, *data, TSDB_DATA_TYPE_DOUBLE); } return out; } void *ncharTobinary(void *buf) { // todo need to remove , if tobinary is nchar int32_t inputLen = varDataTLen(buf); void *t = taosMemoryCalloc(1, inputLen); int32_t len = taosUcs4ToMbs((TdUcs4 *)varDataVal(buf), varDataLen(buf), varDataVal(t)); if (len < 0) { sclError("charset:%s to %s. val:%s convert ncharTobinary failed.", DEFAULT_UNICODE_ENCODEC, tsCharset, (char *)varDataVal(buf)); taosMemoryFree(t); return NULL; } varDataSetLen(t, len); return t; } bool convertJsonValue(__compar_fn_t *fp, int32_t optr, int8_t typeLeft, int8_t typeRight, char **pLeftData, char **pRightData, void *pLeftOut, void *pRightOut, bool *isNull, bool *freeLeft, bool *freeRight) { if (optr == OP_TYPE_JSON_CONTAINS) { return true; } if (typeLeft != TSDB_DATA_TYPE_JSON && typeRight != TSDB_DATA_TYPE_JSON) { return true; } if (typeLeft == TSDB_DATA_TYPE_JSON) { if (tTagIsJson(*pLeftData)) { terrno = TSDB_CODE_QRY_JSON_NOT_SUPPORT_ERROR; return false; } typeLeft = **pLeftData; (*pLeftData)++; } if (typeRight == TSDB_DATA_TYPE_JSON) { if (tTagIsJson(*pRightData)) { terrno = TSDB_CODE_QRY_JSON_NOT_SUPPORT_ERROR; return false; } typeRight = **pRightData; (*pRightData)++; } if (optr == OP_TYPE_LIKE || optr == OP_TYPE_NOT_LIKE || optr == OP_TYPE_MATCH || optr == OP_TYPE_NMATCH) { if (typeLeft != TSDB_DATA_TYPE_NCHAR && typeLeft != TSDB_DATA_TYPE_BINARY) { return false; } } // if types can not comparable if ((IS_NUMERIC_TYPE(typeLeft) && !IS_NUMERIC_TYPE(typeRight)) || (IS_NUMERIC_TYPE(typeRight) && !IS_NUMERIC_TYPE(typeLeft)) || (IS_VAR_DATA_TYPE(typeLeft) && !IS_VAR_DATA_TYPE(typeRight)) || (IS_VAR_DATA_TYPE(typeRight) && !IS_VAR_DATA_TYPE(typeLeft)) || ((typeLeft == TSDB_DATA_TYPE_BOOL) && (typeRight != TSDB_DATA_TYPE_BOOL)) || ((typeRight == TSDB_DATA_TYPE_BOOL) && (typeLeft != TSDB_DATA_TYPE_BOOL))) return false; if (typeLeft == TSDB_DATA_TYPE_NULL || typeRight == TSDB_DATA_TYPE_NULL) { *isNull = true; return true; } int8_t type = vectorGetConvertType(typeLeft, typeRight); if (type == 0) { *fp = filterGetCompFunc(typeLeft, optr); return true; } *fp = filterGetCompFunc(type, optr); if (IS_NUMERIC_TYPE(type)) { if (typeLeft == TSDB_DATA_TYPE_NCHAR || typeLeft == TSDB_DATA_TYPE_VARCHAR) { return false; } else if (typeLeft != type) { convertNumberToNumber(*pLeftData, pLeftOut, typeLeft, type); *pLeftData = pLeftOut; } if (typeRight == TSDB_DATA_TYPE_NCHAR || typeRight == TSDB_DATA_TYPE_VARCHAR) { return false; } else if (typeRight != type) { convertNumberToNumber(*pRightData, pRightOut, typeRight, type); *pRightData = pRightOut; } } else if (type == TSDB_DATA_TYPE_BINARY) { if (typeLeft == TSDB_DATA_TYPE_NCHAR) { *pLeftData = ncharTobinary(*pLeftData); *freeLeft = true; } if (typeRight == TSDB_DATA_TYPE_NCHAR) { *pRightData = ncharTobinary(*pRightData); *freeRight = true; } } else { return false; } return true; } int32_t vectorConvertToVarData(SSclVectorConvCtx *pCtx) { SColumnInfoData *pInputCol = pCtx->pIn->columnData; SColumnInfoData *pOutputCol = pCtx->pOut->columnData; char tmp[128] = {0}; if (IS_SIGNED_NUMERIC_TYPE(pCtx->inType) || pCtx->inType == TSDB_DATA_TYPE_BOOL || pCtx->inType == TSDB_DATA_TYPE_TIMESTAMP) { for (int32_t i = pCtx->startIndex; i <= pCtx->endIndex; ++i) { if (colDataIsNull_f(pInputCol->nullbitmap, i)) { colDataSetNULL(pOutputCol, i); continue; } int64_t value = 0; GET_TYPED_DATA(value, int64_t, pCtx->inType, colDataGetData(pInputCol, i)); int32_t len = sprintf(varDataVal(tmp), "%" PRId64, value); varDataLen(tmp) = len; if (pCtx->outType == TSDB_DATA_TYPE_NCHAR) { varToNchar(tmp, pCtx->pOut, i, NULL); } else { colDataSetVal(pOutputCol, i, (char *)tmp, false); } } } else if (IS_UNSIGNED_NUMERIC_TYPE(pCtx->inType)) { for (int32_t i = pCtx->startIndex; i <= pCtx->endIndex; ++i) { if (colDataIsNull_f(pInputCol->nullbitmap, i)) { colDataSetNULL(pOutputCol, i); continue; } uint64_t value = 0; GET_TYPED_DATA(value, uint64_t, pCtx->inType, colDataGetData(pInputCol, i)); int32_t len = sprintf(varDataVal(tmp), "%" PRIu64, value); varDataLen(tmp) = len; if (pCtx->outType == TSDB_DATA_TYPE_NCHAR) { varToNchar(tmp, pCtx->pOut, i, NULL); } else { colDataSetVal(pOutputCol, i, (char *)tmp, false); } } } else if (IS_FLOAT_TYPE(pCtx->inType)) { for (int32_t i = pCtx->startIndex; i <= pCtx->endIndex; ++i) { if (colDataIsNull_f(pInputCol->nullbitmap, i)) { colDataSetNULL(pOutputCol, i); continue; } double value = 0; GET_TYPED_DATA(value, double, pCtx->inType, colDataGetData(pInputCol, i)); int32_t len = sprintf(varDataVal(tmp), "%lf", value); varDataLen(tmp) = len; if (pCtx->outType == TSDB_DATA_TYPE_NCHAR) { varToNchar(tmp, pCtx->pOut, i, NULL); } else { colDataSetVal(pOutputCol, i, (char *)tmp, false); } } } else { sclError("not supported input type:%d", pCtx->inType); return TSDB_CODE_APP_ERROR; } return TSDB_CODE_SUCCESS; } // TODO opt performance int32_t vectorConvertSingleColImpl(const SScalarParam *pIn, SScalarParam *pOut, int32_t *overflow, int32_t startIndex, int32_t numOfRows) { SColumnInfoData *pInputCol = pIn->columnData; SColumnInfoData *pOutputCol = pOut->columnData; if (NULL == pInputCol) { sclError("input column is NULL, hashFilter %p", pIn->pHashFilter); return TSDB_CODE_APP_ERROR; } int32_t rstart = (startIndex >= 0 && startIndex < pIn->numOfRows) ? startIndex : 0; int32_t rend = numOfRows > 0 ? rstart + numOfRows - 1 : rstart + pIn->numOfRows - 1; SSclVectorConvCtx cCtx = {pIn, pOut, rstart, rend, pInputCol->info.type, pOutputCol->info.type}; if (IS_VAR_DATA_TYPE(cCtx.inType)) { return vectorConvertFromVarData(&cCtx, overflow); } if (overflow) { if (1 != pIn->numOfRows) { sclError("invalid numOfRows %d", pIn->numOfRows); return TSDB_CODE_APP_ERROR; } pOut->numOfRows = 0; if (IS_SIGNED_NUMERIC_TYPE(cCtx.outType)) { int64_t minValue = tDataTypes[cCtx.outType].minValue; int64_t maxValue = tDataTypes[cCtx.outType].maxValue; double value = 0; GET_TYPED_DATA(value, double, cCtx.inType, colDataGetData(pInputCol, 0)); if (value > maxValue) { *overflow = 1; return TSDB_CODE_SUCCESS; } else if (value < minValue) { *overflow = -1; return TSDB_CODE_SUCCESS; } else { *overflow = 0; } } else if (IS_UNSIGNED_NUMERIC_TYPE(cCtx.outType)) { uint64_t minValue = (uint64_t)tDataTypes[cCtx.outType].minValue; uint64_t maxValue = (uint64_t)tDataTypes[cCtx.outType].maxValue; double value = 0; GET_TYPED_DATA(value, double, cCtx.inType, colDataGetData(pInputCol, 0)); if (value > maxValue) { *overflow = 1; return TSDB_CODE_SUCCESS; } else if (value < minValue) { *overflow = -1; return TSDB_CODE_SUCCESS; } else { *overflow = 0; } } } pOut->numOfRows = pIn->numOfRows; switch (cCtx.outType) { case TSDB_DATA_TYPE_BOOL: { for (int32_t i = cCtx.startIndex; i <= cCtx.endIndex; ++i) { if (colDataIsNull_f(pInputCol->nullbitmap, i)) { colDataSetNULL(pOutputCol, i); continue; } bool value = 0; GET_TYPED_DATA(value, bool, cCtx.inType, colDataGetData(pInputCol, i)); colDataSetInt8(pOutputCol, i, (int8_t *)&value); } break; } case TSDB_DATA_TYPE_TINYINT: { for (int32_t i = cCtx.startIndex; i <= cCtx.endIndex; ++i) { if (colDataIsNull_f(pInputCol->nullbitmap, i)) { colDataSetNULL(pOutputCol, i); continue; } int8_t value = 0; GET_TYPED_DATA(value, int8_t, cCtx.inType, colDataGetData(pInputCol, i)); colDataSetInt8(pOutputCol, i, (int8_t *)&value); } break; } case TSDB_DATA_TYPE_SMALLINT: { for (int32_t i = cCtx.startIndex; i <= cCtx.endIndex; ++i) { if (colDataIsNull_f(pInputCol->nullbitmap, i)) { colDataSetNULL(pOutputCol, i); continue; } int16_t value = 0; GET_TYPED_DATA(value, int16_t, cCtx.inType, colDataGetData(pInputCol, i)); colDataSetInt16(pOutputCol, i, (int16_t *)&value); } break; } case TSDB_DATA_TYPE_INT: { for (int32_t i = cCtx.startIndex; i <= cCtx.endIndex; ++i) { if (colDataIsNull_f(pInputCol->nullbitmap, i)) { colDataSetNULL(pOutputCol, i); continue; } int32_t value = 0; GET_TYPED_DATA(value, int32_t, cCtx.inType, colDataGetData(pInputCol, i)); colDataSetInt32(pOutputCol, i, (int32_t *)&value); } break; } case TSDB_DATA_TYPE_BIGINT: case TSDB_DATA_TYPE_TIMESTAMP: { for (int32_t i = cCtx.startIndex; i <= cCtx.endIndex; ++i) { if (colDataIsNull_f(pInputCol->nullbitmap, i)) { colDataSetNULL(pOutputCol, i); continue; } int64_t value = 0; GET_TYPED_DATA(value, int64_t, cCtx.inType, colDataGetData(pInputCol, i)); colDataSetInt64(pOutputCol, i, (int64_t *)&value); } break; } case TSDB_DATA_TYPE_UTINYINT: { for (int32_t i = cCtx.startIndex; i <= cCtx.endIndex; ++i) { if (colDataIsNull_f(pInputCol->nullbitmap, i)) { colDataSetNULL(pOutputCol, i); continue; } uint8_t value = 0; GET_TYPED_DATA(value, uint8_t, cCtx.inType, colDataGetData(pInputCol, i)); colDataSetInt8(pOutputCol, i, (int8_t *)&value); } break; } case TSDB_DATA_TYPE_USMALLINT: { for (int32_t i = cCtx.startIndex; i <= cCtx.endIndex; ++i) { if (colDataIsNull_f(pInputCol->nullbitmap, i)) { colDataSetNULL(pOutputCol, i); continue; } uint16_t value = 0; GET_TYPED_DATA(value, uint16_t, cCtx.inType, colDataGetData(pInputCol, i)); colDataSetInt16(pOutputCol, i, (int16_t *)&value); } break; } case TSDB_DATA_TYPE_UINT: { for (int32_t i = cCtx.startIndex; i <= cCtx.endIndex; ++i) { if (colDataIsNull_f(pInputCol->nullbitmap, i)) { colDataSetNULL(pOutputCol, i); continue; } uint32_t value = 0; GET_TYPED_DATA(value, uint32_t, cCtx.inType, colDataGetData(pInputCol, i)); colDataSetInt32(pOutputCol, i, (int32_t *)&value); } break; } case TSDB_DATA_TYPE_UBIGINT: { for (int32_t i = cCtx.startIndex; i <= cCtx.endIndex; ++i) { if (colDataIsNull_f(pInputCol->nullbitmap, i)) { colDataSetNULL(pOutputCol, i); continue; } uint64_t value = 0; GET_TYPED_DATA(value, uint64_t, cCtx.inType, colDataGetData(pInputCol, i)); colDataSetInt64(pOutputCol, i, (int64_t *)&value); } break; } case TSDB_DATA_TYPE_FLOAT: { for (int32_t i = cCtx.startIndex; i <= cCtx.endIndex; ++i) { if (colDataIsNull_f(pInputCol->nullbitmap, i)) { colDataSetNULL(pOutputCol, i); continue; } float value = 0; GET_TYPED_DATA(value, float, cCtx.inType, colDataGetData(pInputCol, i)); colDataSetFloat(pOutputCol, i, (float *)&value); } break; } case TSDB_DATA_TYPE_DOUBLE: { for (int32_t i = cCtx.startIndex; i <= cCtx.endIndex; ++i) { if (colDataIsNull_f(pInputCol->nullbitmap, i)) { colDataSetNULL(pOutputCol, i); continue; } double value = 0; GET_TYPED_DATA(value, double, cCtx.inType, colDataGetData(pInputCol, i)); colDataSetDouble(pOutputCol, i, (double *)&value); } break; } case TSDB_DATA_TYPE_BINARY: case TSDB_DATA_TYPE_NCHAR: { return vectorConvertToVarData(&cCtx); } default: sclError("invalid convert output type:%d", cCtx.outType); return TSDB_CODE_APP_ERROR; } return TSDB_CODE_SUCCESS; } int8_t gConvertTypes[TSDB_DATA_TYPE_BLOB + 1][TSDB_DATA_TYPE_BLOB + 1] = { /* NULL BOOL TINY SMAL INT BIG FLOA DOUB VARC TIME NCHA UTIN USMA UINT UBIG JSON VARB DECI BLOB */ /*NULL*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*BOOL*/ 0, 0, 2, 3, 4, 5, 6, 7, 5, 9, 7, 11, 12, 13, 14, 0, 7, 0, 0, /*TINY*/ 0, 0, 0, 3, 4, 5, 6, 7, 5, 9, 7, 3, 4, 5, 7, 0, 7, 0, 0, /*SMAL*/ 0, 0, 0, 0, 4, 5, 6, 7, 5, 9, 7, 3, 4, 5, 7, 0, 7, 0, 0, /*INT */ 0, 0, 0, 0, 0, 5, 6, 7, 5, 9, 7, 4, 4, 5, 7, 0, 7, 0, 0, /*BIGI*/ 0, 0, 0, 0, 0, 0, 6, 7, 5, 9, 7, 5, 5, 5, 7, 0, 7, 0, 0, /*FLOA*/ 0, 0, 0, 0, 0, 0, 0, 7, 7, 6, 7, 6, 6, 6, 6, 0, 7, 0, 0, /*DOUB*/ 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 7, 7, 0, 7, 0, 0, /*VARC*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 8, 7, 7, 7, 7, 0, 0, 0, 0, /*TIME*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 7, 0, 7, 0, 0, /*NCHA*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 7, 0, 0, 0, 0, /*UTIN*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 13, 14, 0, 7, 0, 0, /*USMA*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 14, 0, 7, 0, 0, /*UINT*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 7, 0, 0, /*UBIG*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, /*JSON*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*VARB*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*DECI*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*BLOB*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; int32_t vectorGetConvertType(int32_t type1, int32_t type2) { if (type1 == type2) { return 0; } if (type1 < type2) { return gConvertTypes[type1][type2]; } return gConvertTypes[type2][type1]; } int32_t vectorConvertSingleCol(SScalarParam *input, SScalarParam *output, int32_t type, int32_t startIndex, int32_t numOfRows) { output->numOfRows = input->numOfRows; SDataType t = {.type = type}; t.bytes = IS_VAR_DATA_TYPE(t.type)? input->columnData->info.bytes:tDataTypes[type].bytes; t.precision = input->columnData->info.precision; int32_t code = sclCreateColumnInfoData(&t, input->numOfRows, output); if (code != TSDB_CODE_SUCCESS) { return TSDB_CODE_OUT_OF_MEMORY; } code = vectorConvertSingleColImpl(input, output, NULL, startIndex, numOfRows); if (code) { return code; } return TSDB_CODE_SUCCESS; } int32_t vectorConvertCols(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pLeftOut, SScalarParam *pRightOut, int32_t startIndex, int32_t numOfRows) { int32_t leftType = GET_PARAM_TYPE(pLeft); int32_t rightType = GET_PARAM_TYPE(pRight); if (leftType == rightType) { return TSDB_CODE_SUCCESS; } int8_t type = 0; int32_t code = 0; SScalarParam *param1 = NULL, *paramOut1 = NULL; SScalarParam *param2 = NULL, *paramOut2 = NULL; // always convert least data if (IS_VAR_DATA_TYPE(leftType) && IS_VAR_DATA_TYPE(rightType) && (pLeft->numOfRows != pRight->numOfRows) && leftType != TSDB_DATA_TYPE_JSON && rightType != TSDB_DATA_TYPE_JSON) { param1 = pLeft; param2 = pRight; paramOut1 = pLeftOut; paramOut2 = pRightOut; if (pLeft->numOfRows > pRight->numOfRows) { type = leftType; } else { type = rightType; } } else { // we only define half value in the convert-matrix, so make sure param1 always less equal than param2 if (leftType < rightType) { param1 = pLeft; param2 = pRight; paramOut1 = pLeftOut; paramOut2 = pRightOut; } else { param1 = pRight; param2 = pLeft; paramOut1 = pRightOut; paramOut2 = pLeftOut; } type = vectorGetConvertType(GET_PARAM_TYPE(param1), GET_PARAM_TYPE(param2)); if (0 == type) { return TSDB_CODE_SUCCESS; } } if (type != GET_PARAM_TYPE(param1)) { code = vectorConvertSingleCol(param1, paramOut1, type, startIndex, numOfRows); if (code) { return code; } } if (type != GET_PARAM_TYPE(param2)) { code = vectorConvertSingleCol(param2, paramOut2, type, startIndex, numOfRows); if (code) { return code; } } return TSDB_CODE_SUCCESS; } enum { VECTOR_DO_CONVERT = 0x1, VECTOR_UN_CONVERT = 0x2, }; // TODO not correct for descending order scan static void vectorMathAddHelper(SColumnInfoData *pLeftCol, SColumnInfoData *pRightCol, SColumnInfoData *pOutputCol, int32_t numOfRows, int32_t step, int32_t i) { _getDoubleValue_fn_t getVectorDoubleValueFnLeft = getVectorDoubleValueFn(pLeftCol->info.type); _getDoubleValue_fn_t getVectorDoubleValueFnRight = getVectorDoubleValueFn(pRightCol->info.type); double *output = (double *)pOutputCol->pData; if (IS_HELPER_NULL(pRightCol, 0)) { // Set pLeft->numOfRows NULL value colDataSetNNULL(pOutputCol, 0, numOfRows); } else { for (; i >= 0 && i < numOfRows; i += step, output += 1) { if (IS_HELPER_NULL(pLeftCol, i)) { colDataSetNULL(pOutputCol, i); continue; // TODO set null or ignore } *output = getVectorDoubleValueFnLeft(LEFT_COL, i) + getVectorDoubleValueFnRight(RIGHT_COL, 0); } } } static void vectorMathTsAddHelper(SColumnInfoData *pLeftCol, SColumnInfoData *pRightCol, SColumnInfoData *pOutputCol, int32_t numOfRows, int32_t step, int32_t i) { _getBigintValue_fn_t getVectorBigintValueFnLeft = getVectorBigintValueFn(pLeftCol->info.type); _getBigintValue_fn_t getVectorBigintValueFnRight = getVectorBigintValueFn(pRightCol->info.type); int64_t *output = (int64_t *)pOutputCol->pData; if (IS_HELPER_NULL(pRightCol, 0)) { // Set pLeft->numOfRows NULL value colDataSetNNULL(pOutputCol, 0, numOfRows); } else { for (; i >= 0 && i < numOfRows; i += step, output += 1) { if (IS_HELPER_NULL(pLeftCol, i)) { colDataSetNULL(pOutputCol, i); continue; // TODO set null or ignore } *output = taosTimeAdd(getVectorBigintValueFnLeft(pLeftCol->pData, i), getVectorBigintValueFnRight(pRightCol->pData, 0), pRightCol->info.scale, pRightCol->info.precision); } } } static SColumnInfoData *vectorConvertVarToDouble(SScalarParam *pInput, int32_t *converted) { SScalarParam output = {0}; SColumnInfoData *pCol = pInput->columnData; if (IS_VAR_DATA_TYPE(pCol->info.type) && pCol->info.type != TSDB_DATA_TYPE_JSON) { int32_t code = vectorConvertSingleCol(pInput, &output, TSDB_DATA_TYPE_DOUBLE, -1, -1); if (code != TSDB_CODE_SUCCESS) { terrno = code; return NULL; } *converted = VECTOR_DO_CONVERT; return output.columnData; } *converted = VECTOR_UN_CONVERT; return pInput->columnData; } static void doReleaseVec(SColumnInfoData *pCol, int32_t type) { if (type == VECTOR_DO_CONVERT) { colDataDestroy(pCol); taosMemoryFree(pCol); } } void vectorMathAdd(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pOut, int32_t _ord) { SColumnInfoData *pOutputCol = pOut->columnData; int32_t i = ((_ord) == TSDB_ORDER_ASC) ? 0 : TMAX(pLeft->numOfRows, pRight->numOfRows) - 1; int32_t step = ((_ord) == TSDB_ORDER_ASC) ? 1 : -1; pOut->numOfRows = TMAX(pLeft->numOfRows, pRight->numOfRows); int32_t leftConvert = 0, rightConvert = 0; SColumnInfoData *pLeftCol = vectorConvertVarToDouble(pLeft, &leftConvert); SColumnInfoData *pRightCol = vectorConvertVarToDouble(pRight, &rightConvert); if ((GET_PARAM_TYPE(pLeft) == TSDB_DATA_TYPE_TIMESTAMP && IS_INTEGER_TYPE(GET_PARAM_TYPE(pRight))) || (GET_PARAM_TYPE(pRight) == TSDB_DATA_TYPE_TIMESTAMP && IS_INTEGER_TYPE(GET_PARAM_TYPE(pLeft))) || (GET_PARAM_TYPE(pLeft) == TSDB_DATA_TYPE_TIMESTAMP && GET_PARAM_TYPE(pRight) == TSDB_DATA_TYPE_BOOL) || (GET_PARAM_TYPE(pRight) == TSDB_DATA_TYPE_TIMESTAMP && GET_PARAM_TYPE(pLeft) == TSDB_DATA_TYPE_BOOL)) { // timestamp plus duration int64_t *output = (int64_t *)pOutputCol->pData; _getBigintValue_fn_t getVectorBigintValueFnLeft = getVectorBigintValueFn(pLeftCol->info.type); _getBigintValue_fn_t getVectorBigintValueFnRight = getVectorBigintValueFn(pRightCol->info.type); if (pLeft->numOfRows == 1 && pRight->numOfRows == 1) { if (GET_PARAM_TYPE(pLeft) == TSDB_DATA_TYPE_TIMESTAMP) { vectorMathTsAddHelper(pLeftCol, pRightCol, pOutputCol, pRight->numOfRows, step, i); } else { vectorMathTsAddHelper(pRightCol, pLeftCol, pOutputCol, pRight->numOfRows, step, i); } } else if (pLeft->numOfRows == 1) { vectorMathTsAddHelper(pRightCol, pLeftCol, pOutputCol, pRight->numOfRows, step, i); } else if (pRight->numOfRows == 1) { vectorMathTsAddHelper(pLeftCol, pRightCol, pOutputCol, pLeft->numOfRows, step, i); } else if (pLeft->numOfRows == pRight->numOfRows) { for (; i < pRight->numOfRows && i >= 0; i += step, output += 1) { if (IS_NULL) { colDataSetNULL(pOutputCol, i); continue; // TODO set null or ignore } *output = getVectorBigintValueFnLeft(pLeftCol->pData, i) + getVectorBigintValueFnRight(pRightCol->pData, i); } } } else { double *output = (double *)pOutputCol->pData; _getDoubleValue_fn_t getVectorDoubleValueFnLeft = getVectorDoubleValueFn(pLeftCol->info.type); _getDoubleValue_fn_t getVectorDoubleValueFnRight = getVectorDoubleValueFn(pRightCol->info.type); if (pLeft->numOfRows == pRight->numOfRows) { for (; i < pRight->numOfRows && i >= 0; i += step, output += 1) { if (IS_NULL) { colDataSetNULL(pOutputCol, i); continue; // TODO set null or ignore } *output = getVectorDoubleValueFnLeft(LEFT_COL, i) + getVectorDoubleValueFnRight(RIGHT_COL, i); } } else if (pLeft->numOfRows == 1) { vectorMathAddHelper(pRightCol, pLeftCol, pOutputCol, pRight->numOfRows, step, i); } else if (pRight->numOfRows == 1) { vectorMathAddHelper(pLeftCol, pRightCol, pOutputCol, pLeft->numOfRows, step, i); } } doReleaseVec(pLeftCol, leftConvert); doReleaseVec(pRightCol, rightConvert); } // TODO not correct for descending order scan static void vectorMathSubHelper(SColumnInfoData *pLeftCol, SColumnInfoData *pRightCol, SColumnInfoData *pOutputCol, int32_t numOfRows, int32_t step, int32_t factor, int32_t i) { _getDoubleValue_fn_t getVectorDoubleValueFnLeft = getVectorDoubleValueFn(pLeftCol->info.type); _getDoubleValue_fn_t getVectorDoubleValueFnRight = getVectorDoubleValueFn(pRightCol->info.type); double *output = (double *)pOutputCol->pData; if (IS_HELPER_NULL(pRightCol, 0)) { // Set pLeft->numOfRows NULL value colDataSetNNULL(pOutputCol, 0, numOfRows); } else { for (; i >= 0 && i < numOfRows; i += step, output += 1) { if (IS_HELPER_NULL(pLeftCol, i)) { colDataSetNULL(pOutputCol, i); continue; // TODO set null or ignore } *output = (getVectorDoubleValueFnLeft(LEFT_COL, i) - getVectorDoubleValueFnRight(RIGHT_COL, 0)) * factor; } } } static void vectorMathTsSubHelper(SColumnInfoData *pLeftCol, SColumnInfoData *pRightCol, SColumnInfoData *pOutputCol, int32_t numOfRows, int32_t step, int32_t factor, int32_t i) { _getBigintValue_fn_t getVectorBigintValueFnLeft = getVectorBigintValueFn(pLeftCol->info.type); _getBigintValue_fn_t getVectorBigintValueFnRight = getVectorBigintValueFn(pRightCol->info.type); int64_t *output = (int64_t *)pOutputCol->pData; if (IS_HELPER_NULL(pRightCol, 0)) { // Set pLeft->numOfRows NULL value colDataSetNNULL(pOutputCol, 0, numOfRows); } else { for (; i >= 0 && i < numOfRows; i += step, output += 1) { if (IS_HELPER_NULL(pLeftCol, i)) { colDataSetNULL(pOutputCol, i); continue; // TODO set null or ignore } *output = taosTimeAdd(getVectorBigintValueFnLeft(pLeftCol->pData, i), -getVectorBigintValueFnRight(pRightCol->pData, 0), pRightCol->info.scale, pRightCol->info.precision); } } } void vectorMathSub(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pOut, int32_t _ord) { SColumnInfoData *pOutputCol = pOut->columnData; pOut->numOfRows = TMAX(pLeft->numOfRows, pRight->numOfRows); int32_t i = ((_ord) == TSDB_ORDER_ASC) ? 0 : TMAX(pLeft->numOfRows, pRight->numOfRows) - 1; int32_t step = ((_ord) == TSDB_ORDER_ASC) ? 1 : -1; int32_t leftConvert = 0, rightConvert = 0; SColumnInfoData *pLeftCol = vectorConvertVarToDouble(pLeft, &leftConvert); SColumnInfoData *pRightCol = vectorConvertVarToDouble(pRight, &rightConvert); if ((GET_PARAM_TYPE(pLeft) == TSDB_DATA_TYPE_TIMESTAMP && GET_PARAM_TYPE(pRight) == TSDB_DATA_TYPE_BIGINT) || (GET_PARAM_TYPE(pRight) == TSDB_DATA_TYPE_TIMESTAMP && GET_PARAM_TYPE(pLeft) == TSDB_DATA_TYPE_BIGINT)) { // timestamp minus duration int64_t *output = (int64_t *)pOutputCol->pData; _getBigintValue_fn_t getVectorBigintValueFnLeft = getVectorBigintValueFn(pLeftCol->info.type); _getBigintValue_fn_t getVectorBigintValueFnRight = getVectorBigintValueFn(pRightCol->info.type); if (pLeft->numOfRows == 1 && pRight->numOfRows == 1) { vectorMathTsSubHelper(pLeftCol, pRightCol, pOutputCol, pLeft->numOfRows, step, 1, i); } else if (pLeft->numOfRows == 1) { vectorMathTsSubHelper(pRightCol, pLeftCol, pOutputCol, pRight->numOfRows, step, -1, i); } else if (pRight->numOfRows == 1) { vectorMathTsSubHelper(pLeftCol, pRightCol, pOutputCol, pLeft->numOfRows, step, 1, i); } else if (pLeft->numOfRows == pRight->numOfRows) { for (; i < pRight->numOfRows && i >= 0; i += step, output += 1) { if (IS_NULL) { colDataSetNULL(pOutputCol, i); continue; // TODO set null or ignore } *output = getVectorBigintValueFnLeft(pLeftCol->pData, i) - getVectorBigintValueFnRight(pRightCol->pData, i); } } } else { double *output = (double *)pOutputCol->pData; _getDoubleValue_fn_t getVectorDoubleValueFnLeft = getVectorDoubleValueFn(pLeftCol->info.type); _getDoubleValue_fn_t getVectorDoubleValueFnRight = getVectorDoubleValueFn(pRightCol->info.type); if (pLeft->numOfRows == pRight->numOfRows) { for (; i < pRight->numOfRows && i >= 0; i += step, output += 1) { if (IS_NULL) { colDataSetNULL(pOutputCol, i); continue; // TODO set null or ignore } *output = getVectorDoubleValueFnLeft(LEFT_COL, i) - getVectorDoubleValueFnRight(RIGHT_COL, i); } } else if (pLeft->numOfRows == 1) { vectorMathSubHelper(pRightCol, pLeftCol, pOutputCol, pRight->numOfRows, step, -1, i); } else if (pRight->numOfRows == 1) { vectorMathSubHelper(pLeftCol, pRightCol, pOutputCol, pLeft->numOfRows, step, 1, i); } } doReleaseVec(pLeftCol, leftConvert); doReleaseVec(pRightCol, rightConvert); } // TODO not correct for descending order scan static void vectorMathMultiplyHelper(SColumnInfoData *pLeftCol, SColumnInfoData *pRightCol, SColumnInfoData *pOutputCol, int32_t numOfRows, int32_t step, int32_t i) { _getDoubleValue_fn_t getVectorDoubleValueFnLeft = getVectorDoubleValueFn(pLeftCol->info.type); _getDoubleValue_fn_t getVectorDoubleValueFnRight = getVectorDoubleValueFn(pRightCol->info.type); double *output = (double *)pOutputCol->pData; if (IS_HELPER_NULL(pRightCol, 0)) { // Set pLeft->numOfRows NULL value colDataSetNNULL(pOutputCol, 0, numOfRows); } else { for (; i >= 0 && i < numOfRows; i += step, output += 1) { if (IS_HELPER_NULL(pLeftCol, i)) { colDataSetNULL(pOutputCol, i); continue; // TODO set null or ignore } *output = getVectorDoubleValueFnLeft(LEFT_COL, i) * getVectorDoubleValueFnRight(RIGHT_COL, 0); } } } void vectorMathMultiply(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pOut, int32_t _ord) { SColumnInfoData *pOutputCol = pOut->columnData; pOut->numOfRows = TMAX(pLeft->numOfRows, pRight->numOfRows); int32_t i = ((_ord) == TSDB_ORDER_ASC) ? 0 : TMAX(pLeft->numOfRows, pRight->numOfRows) - 1; int32_t step = ((_ord) == TSDB_ORDER_ASC) ? 1 : -1; int32_t leftConvert = 0, rightConvert = 0; SColumnInfoData *pLeftCol = vectorConvertVarToDouble(pLeft, &leftConvert); SColumnInfoData *pRightCol = vectorConvertVarToDouble(pRight, &rightConvert); _getDoubleValue_fn_t getVectorDoubleValueFnLeft = getVectorDoubleValueFn(pLeftCol->info.type); _getDoubleValue_fn_t getVectorDoubleValueFnRight = getVectorDoubleValueFn(pRightCol->info.type); double *output = (double *)pOutputCol->pData; if (pLeft->numOfRows == pRight->numOfRows) { for (; i < pRight->numOfRows && i >= 0; i += step, output += 1) { if (IS_NULL) { colDataSetNULL(pOutputCol, i); continue; // TODO set null or ignore } *output = getVectorDoubleValueFnLeft(LEFT_COL, i) * getVectorDoubleValueFnRight(RIGHT_COL, i); } } else if (pLeft->numOfRows == 1) { vectorMathMultiplyHelper(pRightCol, pLeftCol, pOutputCol, pRight->numOfRows, step, i); } else if (pRight->numOfRows == 1) { vectorMathMultiplyHelper(pLeftCol, pRightCol, pOutputCol, pLeft->numOfRows, step, i); } doReleaseVec(pLeftCol, leftConvert); doReleaseVec(pRightCol, rightConvert); } void vectorMathDivide(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pOut, int32_t _ord) { SColumnInfoData *pOutputCol = pOut->columnData; pOut->numOfRows = TMAX(pLeft->numOfRows, pRight->numOfRows); int32_t i = ((_ord) == TSDB_ORDER_ASC) ? 0 : TMAX(pLeft->numOfRows, pRight->numOfRows) - 1; int32_t step = ((_ord) == TSDB_ORDER_ASC) ? 1 : -1; int32_t leftConvert = 0, rightConvert = 0; SColumnInfoData *pLeftCol = vectorConvertVarToDouble(pLeft, &leftConvert); SColumnInfoData *pRightCol = vectorConvertVarToDouble(pRight, &rightConvert); _getDoubleValue_fn_t getVectorDoubleValueFnLeft = getVectorDoubleValueFn(pLeftCol->info.type); _getDoubleValue_fn_t getVectorDoubleValueFnRight = getVectorDoubleValueFn(pRightCol->info.type); double *output = (double *)pOutputCol->pData; if (pLeft->numOfRows == pRight->numOfRows) { for (; i < pRight->numOfRows && i >= 0; i += step, output += 1) { if (IS_NULL || (getVectorDoubleValueFnRight(RIGHT_COL, i) == 0)) { // divide by 0 check colDataSetNULL(pOutputCol, i); continue; } *output = getVectorDoubleValueFnLeft(LEFT_COL, i) / getVectorDoubleValueFnRight(RIGHT_COL, i); } } else if (pLeft->numOfRows == 1) { if (IS_HELPER_NULL(pLeftCol, 0)) { // Set pLeft->numOfRows NULL value colDataSetNNULL(pOutputCol, 0, pRight->numOfRows); } else { for (; i >= 0 && i < pRight->numOfRows; i += step, output += 1) { if (IS_HELPER_NULL(pRightCol, i) || (getVectorDoubleValueFnRight(RIGHT_COL, i) == 0)) { // divide by 0 check colDataSetNULL(pOutputCol, i); continue; } *output = getVectorDoubleValueFnLeft(LEFT_COL, 0) / getVectorDoubleValueFnRight(RIGHT_COL, i); } } } else if (pRight->numOfRows == 1) { if (IS_HELPER_NULL(pRightCol, 0) || (getVectorDoubleValueFnRight(RIGHT_COL, 0) == 0)) { // Set pLeft->numOfRows NULL value (divde by 0 check) colDataSetNNULL(pOutputCol, 0, pLeft->numOfRows); } else { for (; i >= 0 && i < pLeft->numOfRows; i += step, output += 1) { if (IS_HELPER_NULL(pLeftCol, i)) { colDataSetNULL(pOutputCol, i); continue; } *output = getVectorDoubleValueFnLeft(LEFT_COL, i) / getVectorDoubleValueFnRight(RIGHT_COL, 0); } } } doReleaseVec(pLeftCol, leftConvert); doReleaseVec(pRightCol, rightConvert); } void vectorMathRemainder(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pOut, int32_t _ord) { SColumnInfoData *pOutputCol = pOut->columnData; pOut->numOfRows = TMAX(pLeft->numOfRows, pRight->numOfRows); int32_t i = ((_ord) == TSDB_ORDER_ASC) ? 0 : TMAX(pLeft->numOfRows, pRight->numOfRows) - 1; int32_t step = ((_ord) == TSDB_ORDER_ASC) ? 1 : -1; int32_t leftConvert = 0, rightConvert = 0; SColumnInfoData *pLeftCol = vectorConvertVarToDouble(pLeft, &leftConvert); SColumnInfoData *pRightCol = vectorConvertVarToDouble(pRight, &rightConvert); _getDoubleValue_fn_t getVectorDoubleValueFnLeft = getVectorDoubleValueFn(pLeftCol->info.type); _getDoubleValue_fn_t getVectorDoubleValueFnRight = getVectorDoubleValueFn(pRightCol->info.type); double *output = (double *)pOutputCol->pData; if (pLeft->numOfRows == pRight->numOfRows) { for (; i < pRight->numOfRows && i >= 0; i += step, output += 1) { if (IS_NULL) { colDataSetNULL(pOutputCol, i); continue; } double lx = getVectorDoubleValueFnLeft(LEFT_COL, i); double rx = getVectorDoubleValueFnRight(RIGHT_COL, i); if (isnan(lx) || isinf(lx) || isnan(rx) || isinf(rx) || FLT_EQUAL(rx, 0)) { colDataSetNULL(pOutputCol, i); continue; } *output = lx - ((int64_t)(lx / rx)) * rx; } } else if (pLeft->numOfRows == 1) { double lx = getVectorDoubleValueFnLeft(LEFT_COL, 0); if (IS_HELPER_NULL(pLeftCol, 0)) { // Set pLeft->numOfRows NULL value colDataSetNNULL(pOutputCol, 0, pRight->numOfRows); } else { for (; i >= 0 && i < pRight->numOfRows; i += step, output += 1) { if (IS_HELPER_NULL(pRightCol, i)) { colDataSetNULL(pOutputCol, i); continue; } double rx = getVectorDoubleValueFnRight(RIGHT_COL, i); if (isnan(rx) || isinf(rx) || FLT_EQUAL(rx, 0)) { colDataSetNULL(pOutputCol, i); continue; } *output = lx - ((int64_t)(lx / rx)) * rx; } } } else if (pRight->numOfRows == 1) { double rx = getVectorDoubleValueFnRight(RIGHT_COL, 0); if (IS_HELPER_NULL(pRightCol, 0) || FLT_EQUAL(rx, 0)) { // Set pLeft->numOfRows NULL value colDataSetNNULL(pOutputCol, 0, pLeft->numOfRows); } else { for (; i >= 0 && i < pLeft->numOfRows; i += step, output += 1) { if (IS_HELPER_NULL(pLeftCol, i)) { colDataSetNULL(pOutputCol, i); continue; } double lx = getVectorDoubleValueFnLeft(LEFT_COL, i); if (isnan(lx) || isinf(lx)) { colDataSetNULL(pOutputCol, i); continue; } *output = lx - ((int64_t)(lx / rx)) * rx; } } } doReleaseVec(pLeftCol, leftConvert); doReleaseVec(pRightCol, rightConvert); } void vectorMathMinus(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pOut, int32_t _ord) { SColumnInfoData *pOutputCol = pOut->columnData; pOut->numOfRows = pLeft->numOfRows; int32_t i = ((_ord) == TSDB_ORDER_ASC) ? 0 : (pLeft->numOfRows - 1); int32_t step = ((_ord) == TSDB_ORDER_ASC) ? 1 : -1; int32_t leftConvert = 0; SColumnInfoData *pLeftCol = vectorConvertVarToDouble(pLeft, &leftConvert); _getDoubleValue_fn_t getVectorDoubleValueFnLeft = getVectorDoubleValueFn(pLeftCol->info.type); double *output = (double *)pOutputCol->pData; for (; i < pLeft->numOfRows && i >= 0; i += step, output += 1) { if (IS_HELPER_NULL(pLeftCol, i)) { colDataSetNULL(pOutputCol, i); continue; } double result = getVectorDoubleValueFnLeft(LEFT_COL, i); *output = (result == 0) ? 0 : -result; } doReleaseVec(pLeftCol, leftConvert); } void vectorAssign(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pOut, int32_t _ord) { SColumnInfoData *pOutputCol = pOut->columnData; pOut->numOfRows = pLeft->numOfRows; if (colDataIsNull_s(pRight->columnData, 0)) { colDataSetNNULL(pOutputCol, 0, pOut->numOfRows); } else { char *d = colDataGetData(pRight->columnData, 0); for (int32_t i = 0; i < pOut->numOfRows; ++i) { colDataSetVal(pOutputCol, i, d, false); } } ASSERT(pRight->numOfQualified == 1 || pRight->numOfQualified == 0); pOut->numOfQualified = pRight->numOfQualified * pOut->numOfRows; } static void vectorBitAndHelper(SColumnInfoData *pLeftCol, SColumnInfoData *pRightCol, SColumnInfoData *pOutputCol, int32_t numOfRows, int32_t step, int32_t i) { _getBigintValue_fn_t getVectorBigintValueFnLeft = getVectorBigintValueFn(pLeftCol->info.type); _getBigintValue_fn_t getVectorBigintValueFnRight = getVectorBigintValueFn(pRightCol->info.type); int64_t *output = (int64_t *)pOutputCol->pData; if (IS_HELPER_NULL(pRightCol, 0)) { // Set pLeft->numOfRows NULL value colDataSetNNULL(pOutputCol, 0, numOfRows); } else { for (; i >= 0 && i < numOfRows; i += step, output += 1) { if (IS_HELPER_NULL(pLeftCol, i)) { colDataSetNULL(pOutputCol, i); continue; // TODO set null or ignore } *output = getVectorBigintValueFnLeft(LEFT_COL, i) & getVectorBigintValueFnRight(RIGHT_COL, 0); } } } void vectorBitAnd(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pOut, int32_t _ord) { SColumnInfoData *pOutputCol = pOut->columnData; pOut->numOfRows = TMAX(pLeft->numOfRows, pRight->numOfRows); int32_t i = ((_ord) == TSDB_ORDER_ASC) ? 0 : TMAX(pLeft->numOfRows, pRight->numOfRows) - 1; int32_t step = ((_ord) == TSDB_ORDER_ASC) ? 1 : -1; int32_t leftConvert = 0, rightConvert = 0; SColumnInfoData *pLeftCol = vectorConvertVarToDouble(pLeft, &leftConvert); SColumnInfoData *pRightCol = vectorConvertVarToDouble(pRight, &rightConvert); _getBigintValue_fn_t getVectorBigintValueFnLeft = getVectorBigintValueFn(pLeftCol->info.type); _getBigintValue_fn_t getVectorBigintValueFnRight = getVectorBigintValueFn(pRightCol->info.type); int64_t *output = (int64_t *)pOutputCol->pData; if (pLeft->numOfRows == pRight->numOfRows) { for (; i < pRight->numOfRows && i >= 0; i += step, output += 1) { if (IS_NULL) { colDataSetNULL(pOutputCol, i); continue; // TODO set null or ignore } *output = getVectorBigintValueFnLeft(LEFT_COL, i) & getVectorBigintValueFnRight(RIGHT_COL, i); } } else if (pLeft->numOfRows == 1) { vectorBitAndHelper(pRightCol, pLeftCol, pOutputCol, pRight->numOfRows, step, i); } else if (pRight->numOfRows == 1) { vectorBitAndHelper(pLeftCol, pRightCol, pOutputCol, pLeft->numOfRows, step, i); } doReleaseVec(pLeftCol, leftConvert); doReleaseVec(pRightCol, rightConvert); } static void vectorBitOrHelper(SColumnInfoData *pLeftCol, SColumnInfoData *pRightCol, SColumnInfoData *pOutputCol, int32_t numOfRows, int32_t step, int32_t i) { _getBigintValue_fn_t getVectorBigintValueFnLeft = getVectorBigintValueFn(pLeftCol->info.type); _getBigintValue_fn_t getVectorBigintValueFnRight = getVectorBigintValueFn(pRightCol->info.type); int64_t *output = (int64_t *)pOutputCol->pData; if (IS_HELPER_NULL(pRightCol, 0)) { // Set pLeft->numOfRows NULL value colDataSetNNULL(pOutputCol, 0, numOfRows); } else { int64_t rx = getVectorBigintValueFnRight(RIGHT_COL, 0); for (; i >= 0 && i < numOfRows; i += step, output += 1) { if (IS_HELPER_NULL(pLeftCol, i)) { colDataSetNULL(pOutputCol, i); continue; // TODO set null or ignore } *output = getVectorBigintValueFnLeft(LEFT_COL, i) | rx; } } } void vectorBitOr(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pOut, int32_t _ord) { SColumnInfoData *pOutputCol = pOut->columnData; pOut->numOfRows = TMAX(pLeft->numOfRows, pRight->numOfRows); int32_t i = ((_ord) == TSDB_ORDER_ASC) ? 0 : TMAX(pLeft->numOfRows, pRight->numOfRows) - 1; int32_t step = ((_ord) == TSDB_ORDER_ASC) ? 1 : -1; int32_t leftConvert = 0, rightConvert = 0; SColumnInfoData *pLeftCol = vectorConvertVarToDouble(pLeft, &leftConvert); SColumnInfoData *pRightCol = vectorConvertVarToDouble(pRight, &rightConvert); _getBigintValue_fn_t getVectorBigintValueFnLeft = getVectorBigintValueFn(pLeftCol->info.type); _getBigintValue_fn_t getVectorBigintValueFnRight = getVectorBigintValueFn(pRightCol->info.type); int64_t *output = (int64_t *)pOutputCol->pData; if (pLeft->numOfRows == pRight->numOfRows) { for (; i < pRight->numOfRows && i >= 0; i += step, output += 1) { if (IS_NULL) { colDataSetNULL(pOutputCol, i); continue; // TODO set null or ignore } *output = getVectorBigintValueFnLeft(LEFT_COL, i) | getVectorBigintValueFnRight(RIGHT_COL, i); } } else if (pLeft->numOfRows == 1) { vectorBitOrHelper(pRightCol, pLeftCol, pOutputCol, pRight->numOfRows, step, i); } else if (pRight->numOfRows == 1) { vectorBitOrHelper(pLeftCol, pRightCol, pOutputCol, pLeft->numOfRows, step, i); } doReleaseVec(pLeftCol, leftConvert); doReleaseVec(pRightCol, rightConvert); } int32_t doVectorCompareImpl(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pOut, int32_t startIndex, int32_t numOfRows, int32_t step, __compar_fn_t fp, int32_t optr) { int32_t num = 0; bool *pRes = (bool *)pOut->columnData->pData; if (IS_MATHABLE_TYPE(GET_PARAM_TYPE(pLeft)) && IS_MATHABLE_TYPE(GET_PARAM_TYPE(pRight))) { if (!(pLeft->columnData->hasNull || pRight->columnData->hasNull)) { for (int32_t i = startIndex; i < numOfRows && i >= 0; i += step) { int32_t leftIndex = (i >= pLeft->numOfRows) ? 0 : i; int32_t rightIndex = (i >= pRight->numOfRows) ? 0 : i; char *pLeftData = colDataGetData(pLeft->columnData, leftIndex); char *pRightData = colDataGetData(pRight->columnData, rightIndex); pRes[i] = filterDoCompare(fp, optr, pLeftData, pRightData); if (pRes[i]) { ++num; } } } else { for (int32_t i = startIndex; i < numOfRows && i >= 0; i += step) { int32_t leftIndex = (i >= pLeft->numOfRows) ? 0 : i; int32_t rightIndex = (i >= pRight->numOfRows) ? 0 : i; if (colDataIsNull_f(pLeft->columnData->nullbitmap, leftIndex) || colDataIsNull_f(pRight->columnData->nullbitmap, rightIndex)) { pRes[i] = false; continue; } char *pLeftData = colDataGetData(pLeft->columnData, leftIndex); char *pRightData = colDataGetData(pRight->columnData, rightIndex); pRes[i] = filterDoCompare(fp, optr, pLeftData, pRightData); if (pRes[i]) { ++num; } } } } else { // if (GET_PARAM_TYPE(pLeft) == TSDB_DATA_TYPE_JSON || GET_PARAM_TYPE(pRight) == TSDB_DATA_TYPE_JSON) { for (int32_t i = startIndex; i < numOfRows && i >= startIndex; i += step) { int32_t leftIndex = (i >= pLeft->numOfRows) ? 0 : i; int32_t rightIndex = (i >= pRight->numOfRows) ? 0 : i; if (IS_HELPER_NULL(pLeft->columnData, leftIndex) || IS_HELPER_NULL(pRight->columnData, rightIndex)) { bool res = false; colDataSetInt8(pOut->columnData, i, (int8_t *)&res); continue; } char *pLeftData = colDataGetData(pLeft->columnData, leftIndex); char *pRightData = colDataGetData(pRight->columnData, rightIndex); int64_t leftOut = 0; int64_t rightOut = 0; bool freeLeft = false; bool freeRight = false; bool isJsonnull = false; bool result = convertJsonValue(&fp, optr, GET_PARAM_TYPE(pLeft), GET_PARAM_TYPE(pRight), &pLeftData, &pRightData, &leftOut, &rightOut, &isJsonnull, &freeLeft, &freeRight); if (isJsonnull) { ASSERT(0); } if (!pLeftData || !pRightData) { result = false; } if (!result) { colDataSetInt8(pOut->columnData, i, (int8_t *)&result); } else { bool res = filterDoCompare(fp, optr, pLeftData, pRightData); colDataSetInt8(pOut->columnData, i, (int8_t *)&res); if (res) { ++num; } } if (freeLeft) { taosMemoryFreeClear(pLeftData); } if (freeRight) { taosMemoryFreeClear(pRightData); } } } return num; } void doVectorCompare(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pOut, int32_t startIndex, int32_t numOfRows, int32_t _ord, int32_t optr) { int32_t i = 0; int32_t step = ((_ord) == TSDB_ORDER_ASC) ? 1 : -1; int32_t lType = GET_PARAM_TYPE(pLeft); int32_t rType = GET_PARAM_TYPE(pRight); __compar_fn_t fp = NULL; int32_t compRows = 0; if (lType == rType) { fp = filterGetCompFunc(lType, optr); } else { fp = filterGetCompFuncEx(lType, rType, optr); } if (startIndex < 0) { i = ((_ord) == TSDB_ORDER_ASC) ? 0 : TMAX(pLeft->numOfRows, pRight->numOfRows) - 1; pOut->numOfRows = TMAX(pLeft->numOfRows, pRight->numOfRows); compRows = pOut->numOfRows; } else { compRows = startIndex + numOfRows; i = startIndex; } if (pRight->pHashFilter != NULL) { for (; i >= 0 && i < pLeft->numOfRows; i += step) { if (IS_HELPER_NULL(pLeft->columnData, i)) { bool res = false; colDataSetInt8(pOut->columnData, i, (int8_t *)&res); continue; } char *pLeftData = colDataGetData(pLeft->columnData, i); bool res = filterDoCompare(fp, optr, pLeftData, pRight->pHashFilter); colDataSetInt8(pOut->columnData, i, (int8_t *)&res); if (res) { pOut->numOfQualified++; } } } else { // normal compare pOut->numOfQualified = doVectorCompareImpl(pLeft, pRight, pOut, i, compRows, step, fp, optr); } } void vectorCompareImpl(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pOut, int32_t startIndex, int32_t numOfRows, int32_t _ord, int32_t optr) { SScalarParam pLeftOut = {0}; SScalarParam pRightOut = {0}; SScalarParam *param1 = NULL; SScalarParam *param2 = NULL; if (noConvertBeforeCompare(GET_PARAM_TYPE(pLeft), GET_PARAM_TYPE(pRight), optr)) { param1 = pLeft; param2 = pRight; } else { vectorConvertCols(pLeft, pRight, &pLeftOut, &pRightOut, startIndex, numOfRows); param1 = (pLeftOut.columnData != NULL) ? &pLeftOut : pLeft; param2 = (pRightOut.columnData != NULL) ? &pRightOut : pRight; } doVectorCompare(param1, param2, pOut, startIndex, numOfRows, _ord, optr); sclFreeParam(&pLeftOut); sclFreeParam(&pRightOut); } void vectorCompare(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pOut, int32_t _ord, int32_t optr) { vectorCompareImpl(pLeft, pRight, pOut, -1, -1, _ord, optr); } void vectorGreater(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pOut, int32_t _ord) { vectorCompare(pLeft, pRight, pOut, _ord, OP_TYPE_GREATER_THAN); } void vectorGreaterEqual(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pOut, int32_t _ord) { vectorCompare(pLeft, pRight, pOut, _ord, OP_TYPE_GREATER_EQUAL); } void vectorLower(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pOut, int32_t _ord) { vectorCompare(pLeft, pRight, pOut, _ord, OP_TYPE_LOWER_THAN); } void vectorLowerEqual(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pOut, int32_t _ord) { vectorCompare(pLeft, pRight, pOut, _ord, OP_TYPE_LOWER_EQUAL); } void vectorEqual(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pOut, int32_t _ord) { vectorCompare(pLeft, pRight, pOut, _ord, OP_TYPE_EQUAL); } void vectorNotEqual(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pOut, int32_t _ord) { vectorCompare(pLeft, pRight, pOut, _ord, OP_TYPE_NOT_EQUAL); } void vectorIn(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pOut, int32_t _ord) { vectorCompare(pLeft, pRight, pOut, _ord, OP_TYPE_IN); } void vectorNotIn(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pOut, int32_t _ord) { vectorCompare(pLeft, pRight, pOut, _ord, OP_TYPE_NOT_IN); } void vectorLike(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pOut, int32_t _ord) { vectorCompare(pLeft, pRight, pOut, _ord, OP_TYPE_LIKE); } void vectorNotLike(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pOut, int32_t _ord) { vectorCompare(pLeft, pRight, pOut, _ord, OP_TYPE_NOT_LIKE); } void vectorMatch(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pOut, int32_t _ord) { vectorCompare(pLeft, pRight, pOut, _ord, OP_TYPE_MATCH); } void vectorNotMatch(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pOut, int32_t _ord) { vectorCompare(pLeft, pRight, pOut, _ord, OP_TYPE_NMATCH); } void vectorIsNull(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pOut, int32_t _ord) { for (int32_t i = 0; i < pLeft->numOfRows; ++i) { int8_t v = IS_HELPER_NULL(pLeft->columnData, i) ? 1 : 0; colDataSetInt8(pOut->columnData, i, &v); } pOut->numOfRows = pLeft->numOfRows; } void vectorNotNull(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pOut, int32_t _ord) { for (int32_t i = 0; i < pLeft->numOfRows; ++i) { int8_t v = IS_HELPER_NULL(pLeft->columnData, i) ? 0 : 1; colDataSetInt8(pOut->columnData, i, &v); } pOut->numOfRows = pLeft->numOfRows; } void vectorIsTrue(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pOut, int32_t _ord) { vectorConvertSingleColImpl(pLeft, pOut, NULL, -1, -1); for (int32_t i = 0; i < pOut->numOfRows; ++i) { if (colDataIsNull_s(pOut->columnData, i)) { int8_t v = 0; colDataSetInt8(pOut->columnData, i, &v); colDataClearNull_f(pOut->columnData->nullbitmap, i); } } pOut->columnData->hasNull = false; } STagVal getJsonValue(char *json, char *key, bool *isExist) { STagVal val = {.pKey = key}; if (json == NULL || tTagIsJson((const STag *)json) == false) { terrno = TSDB_CODE_QRY_JSON_NOT_SUPPORT_ERROR; if (isExist) { *isExist = false; } return val; } bool find = tTagGet(((const STag *)json), &val); // json value is null and not exist is different if (isExist) { *isExist = find; } return val; } void vectorJsonContains(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pOut, int32_t _ord) { SColumnInfoData *pOutputCol = pOut->columnData; int32_t i = ((_ord) == TSDB_ORDER_ASC) ? 0 : TMAX(pLeft->numOfRows, pRight->numOfRows) - 1; int32_t step = ((_ord) == TSDB_ORDER_ASC) ? 1 : -1; pOut->numOfRows = TMAX(pLeft->numOfRows, pRight->numOfRows); char *pRightData = colDataGetVarData(pRight->columnData, 0); char *jsonKey = taosMemoryCalloc(1, varDataLen(pRightData) + 1); memcpy(jsonKey, varDataVal(pRightData), varDataLen(pRightData)); for (; i >= 0 && i < pLeft->numOfRows; i += step) { bool isExist = false; if (!colDataIsNull_var(pLeft->columnData, i)) { char *pLeftData = colDataGetVarData(pLeft->columnData, i); getJsonValue(pLeftData, jsonKey, &isExist); } colDataSetVal(pOutputCol, i, (const char *)(&isExist), false); } taosMemoryFree(jsonKey); } void vectorJsonArrow(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pOut, int32_t _ord) { SColumnInfoData *pOutputCol = pOut->columnData; int32_t i = ((_ord) == TSDB_ORDER_ASC) ? 0 : TMAX(pLeft->numOfRows, pRight->numOfRows) - 1; int32_t step = ((_ord) == TSDB_ORDER_ASC) ? 1 : -1; pOut->numOfRows = TMAX(pLeft->numOfRows, pRight->numOfRows); char *pRightData = colDataGetVarData(pRight->columnData, 0); char *jsonKey = taosMemoryCalloc(1, varDataLen(pRightData) + 1); memcpy(jsonKey, varDataVal(pRightData), varDataLen(pRightData)); for (; i >= 0 && i < pLeft->numOfRows; i += step) { if (colDataIsNull_var(pLeft->columnData, i)) { colDataSetNull_var(pOutputCol, i); pOutputCol->hasNull = true; continue; } char *pLeftData = colDataGetVarData(pLeft->columnData, i); bool isExist = false; STagVal value = getJsonValue(pLeftData, jsonKey, &isExist); char *data = isExist ? tTagValToData(&value, true) : NULL; colDataSetVal(pOutputCol, i, data, data == NULL); if (isExist && IS_VAR_DATA_TYPE(value.type) && data) { taosMemoryFree(data); } } taosMemoryFree(jsonKey); } _bin_scalar_fn_t getBinScalarOperatorFn(int32_t binFunctionId) { switch (binFunctionId) { case OP_TYPE_ADD: return vectorMathAdd; case OP_TYPE_SUB: return vectorMathSub; case OP_TYPE_MULTI: return vectorMathMultiply; case OP_TYPE_DIV: return vectorMathDivide; case OP_TYPE_REM: return vectorMathRemainder; case OP_TYPE_MINUS: return vectorMathMinus; case OP_TYPE_ASSIGN: return vectorAssign; case OP_TYPE_GREATER_THAN: return vectorGreater; case OP_TYPE_GREATER_EQUAL: return vectorGreaterEqual; case OP_TYPE_LOWER_THAN: return vectorLower; case OP_TYPE_LOWER_EQUAL: return vectorLowerEqual; case OP_TYPE_EQUAL: return vectorEqual; case OP_TYPE_NOT_EQUAL: return vectorNotEqual; case OP_TYPE_IN: return vectorIn; case OP_TYPE_NOT_IN: return vectorNotIn; case OP_TYPE_LIKE: return vectorLike; case OP_TYPE_NOT_LIKE: return vectorNotLike; case OP_TYPE_MATCH: return vectorMatch; case OP_TYPE_NMATCH: return vectorNotMatch; case OP_TYPE_IS_NULL: return vectorIsNull; case OP_TYPE_IS_NOT_NULL: return vectorNotNull; case OP_TYPE_BIT_AND: return vectorBitAnd; case OP_TYPE_BIT_OR: return vectorBitOr; case OP_TYPE_IS_TRUE: return vectorIsTrue; case OP_TYPE_JSON_GET_VALUE: return vectorJsonArrow; case OP_TYPE_JSON_CONTAINS: return vectorJsonContains; default: return NULL; } }