From 83f7efd6490938e315a660a00f8c132beed40817 Mon Sep 17 00:00:00 2001 From: wangjiaming0909 Date: Mon, 20 Jan 2025 16:18:17 +0800 Subject: [PATCH] support decimal max func, cast func --- include/common/tdatablock.h | 3 + include/common/ttypes.h | 94 ++++++++++++----------- source/common/src/ttypes.c | 12 +++ source/libs/executor/src/tfill.c | 4 + source/libs/function/CMakeLists.txt | 1 + source/libs/function/inc/functionMgtInt.h | 1 + source/libs/function/src/builtins.c | 15 +++- source/libs/function/src/builtinsimpl.c | 6 ++ source/libs/function/src/detail/tminmax.c | 47 +++++++++++- source/libs/nodes/src/nodesCloneFuncs.c | 7 ++ source/libs/nodes/src/nodesMsgFuncs.c | 16 ++++ source/libs/nodes/src/nodesUtilFuncs.c | 18 ++++- source/libs/parser/src/parTranslater.c | 15 ++-- source/libs/scalar/src/sclfunc.c | 20 +++++ source/libs/scalar/src/sclvector.c | 2 - 15 files changed, 200 insertions(+), 61 deletions(-) diff --git a/include/common/tdatablock.h b/include/common/tdatablock.h index aa07183592..c4bb0be863 100644 --- a/include/common/tdatablock.h +++ b/include/common/tdatablock.h @@ -80,6 +80,9 @@ typedef struct SBlockOrderInfo { #define IS_JSON_NULL(type, data) \ ((type) == TSDB_DATA_TYPE_JSON && (*(data) == TSDB_DATA_TYPE_NULL || tTagIsJsonNull(data))) +#define GET_COL_DATA_TYPE(col) \ + { .type = (col).type, .precision = (col).precision, .bytes = (col).bytes, .scale = (col).scale } + static FORCE_INLINE bool colDataIsNull_s(const SColumnInfoData* pColumnInfoData, uint32_t row) { if (!pColumnInfoData->hasNull) { return false; diff --git a/include/common/ttypes.h b/include/common/ttypes.h index 4757cce810..ec8c743d78 100644 --- a/include/common/ttypes.h +++ b/include/common/ttypes.h @@ -72,51 +72,51 @@ typedef struct { DEFINE_TYPE_FROM_DECIMAL_FUNCS(extern, Decimal64); DEFINE_TYPE_FROM_DECIMAL_FUNCS(extern, Decimal128); -#define GET_TYPED_DATA(_v, _finalType, _type, _data) \ - do { \ - switch (_type) { \ - case TSDB_DATA_TYPE_BOOL: \ - case TSDB_DATA_TYPE_TINYINT: \ - (_v) = (_finalType)GET_INT8_VAL(_data); \ - break; \ - case TSDB_DATA_TYPE_UTINYINT: \ - (_v) = (_finalType)GET_UINT8_VAL(_data); \ - break; \ - case TSDB_DATA_TYPE_SMALLINT: \ - (_v) = (_finalType)GET_INT16_VAL(_data); \ - break; \ - case TSDB_DATA_TYPE_USMALLINT: \ - (_v) = (_finalType)GET_UINT16_VAL(_data); \ - break; \ - case TSDB_DATA_TYPE_TIMESTAMP: \ - case TSDB_DATA_TYPE_BIGINT: \ - (_v) = (_finalType)(GET_INT64_VAL(_data)); \ - break; \ - case TSDB_DATA_TYPE_UBIGINT: \ - (_v) = (_finalType)(GET_UINT64_VAL(_data)); \ - break; \ - case TSDB_DATA_TYPE_FLOAT: \ - (_v) = (_finalType)GET_FLOAT_VAL(_data); \ - break; \ - case TSDB_DATA_TYPE_DOUBLE: \ - (_v) = (_finalType)GET_DOUBLE_VAL(_data); \ - break; \ - case TSDB_DATA_TYPE_UINT: \ - (_v) = (_finalType)GET_UINT32_VAL(_data); \ - break; \ - case TSDB_DATA_TYPE_INT: \ - (_v) = (_finalType)GET_INT32_VAL(_data); \ - break; \ - case TSDB_DATA_TYPE_DECIMAL: \ - (_v) = _finalType##FromDecimal128(_data, 10, 0); \ - break; \ - case TSDB_DATA_TYPE_DECIMAL64: \ - (_v) = _finalType##FromDecimal64(_data, 10, 0); \ - break; \ - default: \ - (_v) = (_finalType)varDataLen(_data); \ - break; \ - } \ +#define GET_TYPED_DATA(_v, _finalType, _type, _data) \ + do { \ + switch (_type) { \ + case TSDB_DATA_TYPE_BOOL: \ + case TSDB_DATA_TYPE_TINYINT: \ + (_v) = (_finalType)GET_INT8_VAL(_data); \ + break; \ + case TSDB_DATA_TYPE_UTINYINT: \ + (_v) = (_finalType)GET_UINT8_VAL(_data); \ + break; \ + case TSDB_DATA_TYPE_SMALLINT: \ + (_v) = (_finalType)GET_INT16_VAL(_data); \ + break; \ + case TSDB_DATA_TYPE_USMALLINT: \ + (_v) = (_finalType)GET_UINT16_VAL(_data); \ + break; \ + case TSDB_DATA_TYPE_TIMESTAMP: \ + case TSDB_DATA_TYPE_BIGINT: \ + (_v) = (_finalType)(GET_INT64_VAL(_data)); \ + break; \ + case TSDB_DATA_TYPE_UBIGINT: \ + (_v) = (_finalType)(GET_UINT64_VAL(_data)); \ + break; \ + case TSDB_DATA_TYPE_FLOAT: \ + (_v) = (_finalType)GET_FLOAT_VAL(_data); \ + break; \ + case TSDB_DATA_TYPE_DOUBLE: \ + (_v) = (_finalType)GET_DOUBLE_VAL(_data); \ + break; \ + case TSDB_DATA_TYPE_UINT: \ + (_v) = (_finalType)GET_UINT32_VAL(_data); \ + break; \ + case TSDB_DATA_TYPE_INT: \ + (_v) = (_finalType)GET_INT32_VAL(_data); \ + break; \ + case TSDB_DATA_TYPE_DECIMAL: \ + (_v) = _finalType##FromDecimal128(_data, 10, 0); \ + break; \ + case TSDB_DATA_TYPE_DECIMAL64: \ + (_v) = _finalType##FromDecimal64(_data, 10, 0); \ + break; \ + default: \ + (_v) = (_finalType)varDataLen(_data); \ + break; \ + } \ } while (0) #define SET_TYPED_DATA(_v, _type, _data) \ @@ -405,9 +405,13 @@ void *getDataMin(int32_t type, void *value); void *getDataMax(int32_t type, void *value); #define STypeMod int32_t +STypeMod typeGetTypeMod(uint8_t type, uint8_t prec, uint8_t scale, int32_t bytes); +void extractTypeFromTypeMod(uint8_t type, STypeMod typeMod, uint8_t *prec, uint8_t scale, int32_t *bytes); uint8_t decimalTypeFromPrecision(uint8_t precision); STypeMod decimalCalcTypeMod(uint8_t prec, uint8_t scale); void decimalFromTypeMod(STypeMod typeMod, uint8_t *precision, uint8_t *scale); +// pType->type should has been set +void fillTypeFromTypeMod(SDataType *pType, STypeMod mod); #ifdef __cplusplus } diff --git a/source/common/src/ttypes.c b/source/common/src/ttypes.c index a5cf366921..181df0dd40 100644 --- a/source/common/src/ttypes.c +++ b/source/common/src/ttypes.c @@ -247,3 +247,15 @@ void decimalFromTypeMod(STypeMod typeMod, uint8_t* precision, uint8_t* scale) { *scale = (uint8_t)(typeMod & 0xFF); } +STypeMod typeGetTypeMod(uint8_t type, uint8_t prec, uint8_t scale, int32_t bytes) { + if (IS_DECIMAL_TYPE(type)) { + return decimalCalcTypeMod(prec, scale); + } + return 0; +} + +void fillTypeFromTypeMod(SDataType* pType, STypeMod mod) { + if (IS_DECIMAL_TYPE(pType->type)) { + decimalFromTypeMod(mod, &pType->precision, &pType->scale); + } +} diff --git a/source/libs/executor/src/tfill.c b/source/libs/executor/src/tfill.c index ecbb389f8a..5e355ff7e0 100644 --- a/source/libs/executor/src/tfill.c +++ b/source/libs/executor/src/tfill.c @@ -112,6 +112,10 @@ static int32_t doSetUserSpecifiedValue(SColumnInfoData* pDst, SVariant* pVar, in pDst->info.type == TSDB_DATA_TYPE_VARBINARY) { code = colDataSetVal(pDst, rowIndex, pVar->pz, isNull); QUERY_CHECK_CODE(code, lino, _end); + } else if (pDst->info.type == TSDB_DATA_TYPE_DECIMAL64) { + code = colDataSetVal(pDst, rowIndex, (char*)&pVar->i, isNull); + } else if (pDst->info.type == TSDB_DATA_TYPE_DECIMAL) { + code = colDataSetVal(pDst, rowIndex, (char*)pVar->pz, isNull); } else { // others data colDataSetNULL(pDst, rowIndex); } diff --git a/source/libs/function/CMakeLists.txt b/source/libs/function/CMakeLists.txt index 62989bb293..21dfeee68d 100644 --- a/source/libs/function/CMakeLists.txt +++ b/source/libs/function/CMakeLists.txt @@ -29,6 +29,7 @@ target_link_libraries( PRIVATE qcom PRIVATE scalar PRIVATE geometry + PRIVATE decimal PRIVATE transport PUBLIC uv_a ) diff --git a/source/libs/function/inc/functionMgtInt.h b/source/libs/function/inc/functionMgtInt.h index d676d4b728..029151da09 100644 --- a/source/libs/function/inc/functionMgtInt.h +++ b/source/libs/function/inc/functionMgtInt.h @@ -90,6 +90,7 @@ extern "C" { #define FUNC_PARAM_SUPPORT_INTEGER_TYPE FUNC_MGT_FUNC_PARAM_SUPPORT_TYPE(21) #define FUNC_PARAM_SUPPORT_NULL_TYPE FUNC_MGT_FUNC_PARAM_SUPPORT_TYPE(22) #define FUNC_PARAM_SUPPORT_UNIX_TS_TYPE FUNC_MGT_FUNC_PARAM_SUPPORT_TYPE(23) +#define FUNC_PARAM_SUPPORT_DECIMAL_TYPE FUNC_MGT_FUNC_PARAM_SUPPORT_TYPE(24) diff --git a/source/libs/function/src/builtins.c b/source/libs/function/src/builtins.c index 8233b2d450..97b83dbbc7 100644 --- a/source/libs/function/src/builtins.c +++ b/source/libs/function/src/builtins.c @@ -410,6 +410,11 @@ static bool paramSupportGeometry(uint64_t typeFlag) { FUNC_MGT_TEST_MASK(typeFlag, FUNC_PARAM_SUPPORT_VAR_TYPE); } +static bool paramSupportDecimal(uint64_t typeFlag) { + return FUNC_MGT_TEST_MASK(typeFlag, FUNC_PARAM_SUPPORT_DECIMAL_TYPE) || + FUNC_MGT_TEST_MASK(typeFlag, FUNC_PARAM_SUPPORT_ALL_TYPE); +} + static bool paramSupportValueNode(uint64_t typeFlag) { return FUNC_MGT_TEST_MASK(typeFlag, FUNC_PARAM_SUPPORT_VALUE_NODE) || FUNC_MGT_TEST_MASK(typeFlag, FUNC_PARAM_SUPPORT_EXPR_NODE); @@ -502,6 +507,9 @@ static bool paramSupportDataType(SDataType* pDataType, uint64_t typeFlag) { return paramSupportVarBinary(typeFlag); case TSDB_DATA_TYPE_GEOMETRY: return paramSupportGeometry(typeFlag); + case TSDB_DATA_TYPE_DECIMAL64: + case TSDB_DATA_TYPE_DECIMAL: + return paramSupportDecimal(typeFlag); default: return false; } @@ -965,7 +973,8 @@ static int32_t translateMinMax(SFunctionNode* pFunc, char* pErrBuf, int32_t len) SDataType* dataType = getSDataTypeFromNode(nodesListGetNode(pFunc->pParameterList, 0)); uint8_t paraType = IS_NULL_TYPE(dataType->type) ? TSDB_DATA_TYPE_BIGINT : dataType->type; int32_t bytes = IS_STR_DATA_TYPE(paraType) ? dataType->bytes : tDataTypes[paraType].bytes; - pFunc->node.resType = (SDataType){.bytes = bytes, .type = paraType}; + uint8_t prec = IS_DECIMAL_TYPE(paraType) ? dataType->precision : pFunc->node.resType.precision; + pFunc->node.resType = (SDataType){.bytes = bytes, .type = paraType, .precision = prec, .scale = dataType->scale}; return TSDB_CODE_SUCCESS; } @@ -1876,7 +1885,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = { .inputParaInfo[0][0] = {.isLastParam = true, .startParam = 1, .endParam = 1, - .validDataType = FUNC_PARAM_SUPPORT_NUMERIC_TYPE | FUNC_PARAM_SUPPORT_STRING_TYPE | FUNC_PARAM_SUPPORT_NULL_TYPE, + .validDataType = FUNC_PARAM_SUPPORT_NUMERIC_TYPE | FUNC_PARAM_SUPPORT_STRING_TYPE | FUNC_PARAM_SUPPORT_NULL_TYPE | FUNC_PARAM_SUPPORT_DECIMAL_TYPE, .validNodeType = FUNC_PARAM_SUPPORT_EXPR_NODE, .paramAttribute = FUNC_PARAM_NO_SPECIFIC_ATTRIBUTE, .valueRangeFlag = FUNC_PARAM_NO_SPECIFIC_VALUE,}, @@ -1903,7 +1912,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = { .inputParaInfo[0][0] = {.isLastParam = true, .startParam = 1, .endParam = 1, - .validDataType = FUNC_PARAM_SUPPORT_NUMERIC_TYPE | FUNC_PARAM_SUPPORT_STRING_TYPE | FUNC_PARAM_SUPPORT_NULL_TYPE, + .validDataType = FUNC_PARAM_SUPPORT_NUMERIC_TYPE | FUNC_PARAM_SUPPORT_STRING_TYPE | FUNC_PARAM_SUPPORT_NULL_TYPE |FUNC_PARAM_SUPPORT_DECIMAL_TYPE, .validNodeType = FUNC_PARAM_SUPPORT_EXPR_NODE, .paramAttribute = FUNC_PARAM_NO_SPECIFIC_ATTRIBUTE, .valueRangeFlag = FUNC_PARAM_NO_SPECIFIC_VALUE,}, diff --git a/source/libs/function/src/builtinsimpl.c b/source/libs/function/src/builtinsimpl.c index 863e2cdb6a..e522918b9b 100644 --- a/source/libs/function/src/builtinsimpl.c +++ b/source/libs/function/src/builtinsimpl.c @@ -902,6 +902,12 @@ int32_t minmaxFunctionFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) { } break; } + case TSDB_DATA_TYPE_DECIMAL64: + code = colDataSetVal(pCol, currentRow, (const char*)&pRes->v, false); + break; + case TSDB_DATA_TYPE_DECIMAL: + code = colDataSetVal(pCol, currentRow, pRes->str, false); + break; } } else { colDataSetNULL(pCol, currentRow); diff --git a/source/libs/function/src/detail/tminmax.c b/source/libs/function/src/detail/tminmax.c index 8712096033..9d2aff48ce 100644 --- a/source/libs/function/src/detail/tminmax.c +++ b/source/libs/function/src/detail/tminmax.c @@ -19,6 +19,7 @@ #include "tdatablock.h" #include "tfunctionInt.h" #include "tglobal.h" +#include "decimal.h" #define __COMPARE_ACQUIRED_MAX(i, end, bm, _data, ctx, val, pos) \ int32_t code = TSDB_CODE_SUCCESS; \ @@ -458,6 +459,40 @@ static int32_t doExtractVal(SColumnInfoData* pCol, int32_t i, int32_t end, SqlFu __COMPARE_ACQUIRED_MAX(i, end, pCol->nullbitmap, pData, pCtx, *(double*)&(pBuf->v), &pBuf->tuplePos) break; } + case TSDB_DATA_TYPE_DECIMAL64: { + const Decimal64* pData = (const Decimal64*)pCol->pData; + const SDecimalOps* pOps = getDecimalOps(TSDB_DATA_TYPE_DECIMAL64); + int32_t code = 0; + for (; i < end; ++i) { + if (colDataIsNull_f(pCol->nullbitmap, i)) { + continue; + } + if (pOps->lt(&pBuf->v, &pData[i], WORD_NUM(Decimal64))) { + pBuf->v = DECIMAL64_GET_VALUE(&pData[i]); + if (pCtx->subsidiaries.num > 0) { + code = updateTupleData(pCtx, i, pCtx->pSrcBlock, &pBuf->tuplePos); + if (TSDB_CODE_SUCCESS != code) return code; + } + } + } + } break; + case TSDB_DATA_TYPE_DECIMAL: { + int32_t code = 0; + const SDecimalOps* pOps = getDecimalOps(TSDB_DATA_TYPE_DECIMAL); + const Decimal128* pData = (const Decimal128*)pCol->pData; + for (; i < end; ++i) { + if (colDataIsNull_f(pCol->nullbitmap, i)) { + continue; + } + if (pOps->lt(pBuf->str, &pData[i], WORD_NUM(Decimal128))) { + memcpy(pBuf->str, pData + i, pCol->info.bytes); + if (pCtx->subsidiaries.num > 0) { + code = updateTupleData(pCtx, i, pCtx->pSrcBlock, &pBuf->tuplePos); + if (TSDB_CODE_SUCCESS != code) return code; + } + } + } + } break; case TSDB_DATA_TYPE_VARCHAR: case TSDB_DATA_TYPE_VARBINARY: { @@ -612,8 +647,8 @@ int32_t doMinMaxHelper(SqlFunctionCtx* pCtx, int32_t isMinFunc, int32_t* nElems) int32_t threshold[] = { //NULL, BOOL, TINYINT, SMALLINT, INT, BIGINT, FLOAT, DOUBLE, VARCHAR, TIMESTAMP, NCHAR, INT32_MAX, INT32_MAX, 32, 16, 8, 4, 8, 4, INT32_MAX, INT32_MAX, INT32_MAX, - // UTINYINT,USMALLINT, UINT, UBIGINT, JSON, VARBINARY, DECIMAL, BLOB, MEDIUMBLOB, BINARY - 32, 16, 8, 4, INT32_MAX, INT32_MAX, INT32_MAX, INT32_MAX, INT32_MAX, INT32_MAX, + // UTINYINT,USMALLINT, UINT, UBIGINT, JSON, VARBINARY, DECIMAL, BLOB, MEDIUMBLOB, BINARY, Decimal64 + 32, 16, 8, 4, INT32_MAX, INT32_MAX, INT32_MAX, INT32_MAX, INT32_MAX, INT32_MAX, INT32_MAX, }; // clang-format on @@ -656,6 +691,14 @@ int32_t doMinMaxHelper(SqlFunctionCtx* pCtx, int32_t isMinFunc, int32_t* nElems) (void)memcpy(pBuf->str, colDataGetData(pCol, i), varDataTLen(colDataGetData(pCol, i))); break; } + case TSDB_DATA_TYPE_DECIMAL64: + *(int64_t*)&pBuf->v = *(int64_t*)p; + break; + case TSDB_DATA_TYPE_DECIMAL: + pBuf->str = taosMemoryMalloc(pCol->info.bytes); + if (!pBuf->str) return terrno; + (void)memcpy(pBuf->str, p, pCol->info.bytes); + break; default: (void)memcpy(&pBuf->v, p, pCol->info.bytes); break; diff --git a/source/libs/nodes/src/nodesCloneFuncs.c b/source/libs/nodes/src/nodesCloneFuncs.c index fcb39c4284..64dc073e42 100644 --- a/source/libs/nodes/src/nodesCloneFuncs.c +++ b/source/libs/nodes/src/nodesCloneFuncs.c @@ -197,7 +197,14 @@ static int32_t valueNodeCopy(const SValueNode* pSrc, SValueNode* pDst) { memcpy(pDst->datum.p, pSrc->datum.p, len); break; } + case TSDB_DATA_TYPE_DECIMAL64: + COPY_SCALAR_FIELD(datum.d); + break; case TSDB_DATA_TYPE_DECIMAL: + pDst->datum.p = taosMemCalloc(1, pSrc->node.resType.bytes); + if (!pDst->datum.p) return terrno; + memcpy(pDst->datum.p, pSrc->datum.p, pSrc->node.resType.bytes); + break; case TSDB_DATA_TYPE_BLOB: case TSDB_DATA_TYPE_MEDIUMBLOB: default: diff --git a/source/libs/nodes/src/nodesMsgFuncs.c b/source/libs/nodes/src/nodesMsgFuncs.c index 3d4aed3bc8..b9aaa916ee 100644 --- a/source/libs/nodes/src/nodesMsgFuncs.c +++ b/source/libs/nodes/src/nodesMsgFuncs.c @@ -877,6 +877,11 @@ static int32_t datumToMsg(const void* pObj, STlvEncoder* pEncoder) { code = tlvEncodeBinary(pEncoder, VALUE_CODE_DATUM, pNode->datum.p, getJsonValueLen(pNode->datum.p)); break; case TSDB_DATA_TYPE_DECIMAL: + code = tlvEncodeBinary(pEncoder, VALUE_CODE_DATUM, pNode->datum.p, pNode->node.resType.bytes); + break; + case TSDB_DATA_TYPE_DECIMAL64: + code = tlvEncodeI64(pEncoder, VALUE_CODE_DATUM, pNode->datum.i); + break; case TSDB_DATA_TYPE_BLOB: // todo default: @@ -995,6 +1000,17 @@ static int32_t msgToDatum(STlv* pTlv, void* pObj) { break; } case TSDB_DATA_TYPE_DECIMAL: + pNode->datum.p = taosMemoryCalloc(1, pNode->node.resType.bytes); + if (!pNode->datum.p) { + code = terrno; + break; + } + code = tlvDecodeBinary(pTlv, pNode->datum.p); + break; + case TSDB_DATA_TYPE_DECIMAL64: + code = tlvDecodeI64(pTlv, &pNode->datum.i); + *(int64_t*)&pNode->typeData = pNode->datum.i; + break; case TSDB_DATA_TYPE_BLOB: // todo default: diff --git a/source/libs/nodes/src/nodesUtilFuncs.c b/source/libs/nodes/src/nodesUtilFuncs.c index 59f7813d63..5ba3a7e36b 100644 --- a/source/libs/nodes/src/nodesUtilFuncs.c +++ b/source/libs/nodes/src/nodesUtilFuncs.c @@ -2377,13 +2377,19 @@ int32_t nodesSetValueNodeValue(SValueNode* pNode, void* value) { case TSDB_DATA_TYPE_NCHAR: case TSDB_DATA_TYPE_VARCHAR: case TSDB_DATA_TYPE_VARBINARY: - case TSDB_DATA_TYPE_DECIMAL: case TSDB_DATA_TYPE_JSON: case TSDB_DATA_TYPE_BLOB: case TSDB_DATA_TYPE_MEDIUMBLOB: case TSDB_DATA_TYPE_GEOMETRY: pNode->datum.p = (char*)value; break; + case TSDB_DATA_TYPE_DECIMAL64: + pNode->datum.i = *(int64_t*)value; + pNode->typeData = *(int64_t*)value; + break; + case TSDB_DATA_TYPE_DECIMAL: + pNode->datum.p = (char*)value; + break; default: return TSDB_CODE_APP_ERROR; } @@ -3026,7 +3032,17 @@ int32_t nodesValueNodeToVariant(const SValueNode* pNode, SVariant* pVal) { code = terrno; } break; + case TSDB_DATA_TYPE_DECIMAL64: + pVal->d = pNode->datum.d; + break; case TSDB_DATA_TYPE_DECIMAL: + pVal->pz = taosMemoryCalloc(1, pVal->nLen); + if (!pVal->pz) { + code = terrno; + break; + } + memcpy(pVal->pz, pNode->datum.p, pVal->nLen); + break; case TSDB_DATA_TYPE_BLOB: // todo default: diff --git a/source/libs/parser/src/parTranslater.c b/source/libs/parser/src/parTranslater.c index 429fb36320..88f899ae34 100755 --- a/source/libs/parser/src/parTranslater.c +++ b/source/libs/parser/src/parTranslater.c @@ -1383,11 +1383,7 @@ static void setColumnInfoBySchema(const SRealTableNode* pTable, const SSchema* p pCol->isPk = (pCol->tableHasPk) && (pColSchema->flags & COL_IS_KEY); pCol->numOfPKs = pTable->pMeta->tableInfo.numOfPKs; - if (pExtSchema) { - if (IS_DECIMAL_TYPE(pCol->node.resType.type)) { - decimalFromTypeMod(pExtSchema->typeMod, &pCol->node.resType.precision, &pCol->node.resType.scale); - } - } + if (pExtSchema) fillTypeFromTypeMod(&pCol->node.resType, pExtSchema->typeMod); } static int32_t setColumnInfoByExpr(STempTableNode* pTable, SExprNode* pExpr, SColumnNode** pColRef) { @@ -1484,8 +1480,10 @@ static int32_t createColumnsByTable(STranslateContext* pCxt, const STableNode* p if (TSDB_CODE_SUCCESS != code) { return generateSyntaxErrMsg(&pCxt->msgBuf, code); } - SSchemaExt* pSchemaExt = i > pMeta->tableInfo.numOfColumns ? NULL : pMeta->schemaExt + i; - setColumnInfoBySchema((SRealTableNode*)pTable, pMeta->schema + i, (i - pMeta->tableInfo.numOfColumns), pCol, pSchemaExt); + SSchemaExt* pSchemaExt = + pMeta->schemaExt ? (i > pMeta->tableInfo.numOfColumns ? NULL : (pMeta->schemaExt + i)) : NULL; + setColumnInfoBySchema((SRealTableNode*)pTable, pMeta->schema + i, (i - pMeta->tableInfo.numOfColumns), pCol, + pSchemaExt); setColumnPrimTs(pCxt, pCol, pTable); code = nodesListStrictAppend(pList, (SNode*)pCol); } @@ -1563,7 +1561,7 @@ static int32_t findAndSetColumn(STranslateContext* pCxt, SColumnNode** pColRef, if (0 == strcmp(pCol->colName, pMeta->schema[i].name) && !invisibleColumn(pCxt->pParseCxt->enableSysInfo, pMeta->tableType, pMeta->schema[i].flags)) { - SSchemaExt* pSchemaExt = i > pMeta->tableInfo.numOfColumns ? NULL : pMeta->schemaExt + i; + SSchemaExt* pSchemaExt = pMeta->schemaExt ? (i > pMeta->tableInfo.numOfColumns ? NULL : (pMeta->schemaExt + i)) : NULL; setColumnInfoBySchema((SRealTableNode*)pTable, pMeta->schema + i, (i - pMeta->tableInfo.numOfColumns), pCol, pSchemaExt); setColumnPrimTs(pCxt, pCol, pTable); *pFound = true; @@ -3381,6 +3379,7 @@ static int32_t createCastFunc(STranslateContext* pCxt, SNode* pExpr, SDataType d return TSDB_CODE_OUT_OF_MEMORY; } code = getFuncInfo(pCxt, pFunc); + pFunc->node.resType = dt; if (TSDB_CODE_SUCCESS != code) { nodesClearList(pFunc->pParameterList); pFunc->pParameterList = NULL; diff --git a/source/libs/scalar/src/sclfunc.c b/source/libs/scalar/src/sclfunc.c index 280a469153..abd19466a7 100644 --- a/source/libs/scalar/src/sclfunc.c +++ b/source/libs/scalar/src/sclfunc.c @@ -9,6 +9,7 @@ #include "tjson.h" #include "ttime.h" #include "filter.h" +#include "decimal.h" typedef float (*_float_fn)(float); typedef float (*_float_fn_2)(float, float); @@ -2155,6 +2156,25 @@ int32_t castFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutp break; } + case TSDB_DATA_TYPE_DECIMAL64: + case TSDB_DATA_TYPE_DECIMAL: { + SDataType iT = GET_COL_DATA_TYPE(pInput[0].columnData->info), oT = GET_COL_DATA_TYPE(pOutput->columnData->info); + if (inputType == TSDB_DATA_TYPE_NCHAR) { + int32_t len = taosUcs4ToMbs((TdUcs4 *)(varDataVal(input)), varDataLen(input), convBuf, pInput->charsetCxt); + if (len < 0) { + code = TSDB_CODE_SCALAR_CONVERT_ERROR; + goto _end; + } + convBuf[len] = 0; + code = convertToDecimal(convBuf, &iT, output, &oT); + } else { + code = convertToDecimal(input, &iT, output, &oT); + } + if (code != TSDB_CODE_SUCCESS) { + terrno = code; + goto _end; + } + } break; default: { code = TSDB_CODE_FAILED; goto _end; diff --git a/source/libs/scalar/src/sclvector.c b/source/libs/scalar/src/sclvector.c index b751ffbb30..0fd42ced70 100644 --- a/source/libs/scalar/src/sclvector.c +++ b/source/libs/scalar/src/sclvector.c @@ -39,8 +39,6 @@ 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)) -#define GET_COL_DATA_TYPE(col) \ - { .type = (col).type, .precision = (col).precision, .bytes = (col).bytes, .scale = (col).scale } bool noConvertBeforeCompare(int32_t leftType, int32_t rightType, int32_t optr) { return !IS_DECIMAL_TYPE(leftType) && !IS_DECIMAL_TYPE(rightType) && IS_NUMERIC_TYPE(leftType) &&