diff --git a/include/libs/scalar/scalar.h b/include/libs/scalar/scalar.h index 6322c6a1e9..ef8e80b57f 100644 --- a/include/libs/scalar/scalar.h +++ b/include/libs/scalar/scalar.h @@ -43,7 +43,7 @@ int32_t scalarGetOperatorParamNum(EOperatorType type); int32_t scalarGenerateSetFromList(void **data, void *pNode, uint32_t type); int32_t vectorGetConvertType(int32_t type1, int32_t type2); -int32_t vectorConvertImpl(const SScalarParam *pIn, SScalarParam *pOut, int32_t *overflow); +int32_t vectorConvertSingleColImpl(const SScalarParam *pIn, SScalarParam *pOut, int32_t *overflow, int32_t startIndex, int32_t numOfRows); /* Math functions */ int32_t absFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput); diff --git a/source/libs/executor/src/executil.c b/source/libs/executor/src/executil.c index 2f6b737f79..0fadacb2c2 100644 --- a/source/libs/executor/src/executil.c +++ b/source/libs/executor/src/executil.c @@ -1250,6 +1250,17 @@ void createExprFromOneNode(SExprInfo* pExp, SNode* pNode, int16_t slotId) { pExp->base.resSchema = createResSchema(pType->type, pType->bytes, slotId, pType->scale, pType->precision, pOpNode->node.aliasName); pExp->pExpr->_optrRoot.pRootNode = pNode; + } else if (type == QUERY_NODE_CASE_WHEN) { + pExp->pExpr->nodeType = QUERY_NODE_OPERATOR; + SCaseWhenNode* pCaseNode = (SCaseWhenNode*)pNode; + + pExp->base.pParam = taosMemoryCalloc(1, sizeof(SFunctParam)); + pExp->base.numOfParams = 1; + + SDataType* pType = &pCaseNode->node.resType; + pExp->base.resSchema = createResSchema(pType->type, pType->bytes, slotId, pType->scale, + pType->precision, pCaseNode->node.aliasName); + pExp->pExpr->_optrRoot.pRootNode = pNode; } else { ASSERT(0); } diff --git a/source/libs/nodes/src/nodesCloneFuncs.c b/source/libs/nodes/src/nodesCloneFuncs.c index dac9b85740..b9b365fb42 100644 --- a/source/libs/nodes/src/nodesCloneFuncs.c +++ b/source/libs/nodes/src/nodesCloneFuncs.c @@ -131,7 +131,7 @@ static int32_t valueNodeCopy(const SValueNode* pSrc, SValueNode* pDst) { COPY_SCALAR_FIELD(placeholderNo); COPY_SCALAR_FIELD(typeData); COPY_SCALAR_FIELD(unit); - if (!pSrc->translate) { + if (!pSrc->translate || pSrc->isNull) { return TSDB_CODE_SUCCESS; } switch (pSrc->node.resType.type) { diff --git a/source/libs/nodes/src/nodesCodeFuncs.c b/source/libs/nodes/src/nodesCodeFuncs.c index e401a3da7f..f0f1fc9975 100644 --- a/source/libs/nodes/src/nodesCodeFuncs.c +++ b/source/libs/nodes/src/nodesCodeFuncs.c @@ -3011,7 +3011,7 @@ static int32_t valueNodeToJson(const void* pObj, SJson* pJson) { if (TSDB_CODE_SUCCESS == code) { code = tjsonAddBoolToObject(pJson, jkValueIsNull, pNode->isNull); } - if (TSDB_CODE_SUCCESS == code && pNode->translate) { + if (TSDB_CODE_SUCCESS == code && pNode->translate && !pNode->isNull) { code = datumToJson(pNode, pJson); } @@ -3161,7 +3161,7 @@ static int32_t jsonToValueNode(const SJson* pJson, void* pObj) { if (TSDB_CODE_SUCCESS == code) { code = tjsonGetBoolValue(pJson, jkValueIsNull, &pNode->isNull); } - if (TSDB_CODE_SUCCESS == code && pNode->translate) { + if (TSDB_CODE_SUCCESS == code && pNode->translate && !pNode->isNull) { code = jsonToDatum(pJson, pNode); } diff --git a/source/libs/nodes/src/nodesUtilFuncs.c b/source/libs/nodes/src/nodesUtilFuncs.c index 6e964fb53a..9196f77124 100644 --- a/source/libs/nodes/src/nodesUtilFuncs.c +++ b/source/libs/nodes/src/nodesUtilFuncs.c @@ -1604,7 +1604,7 @@ char* nodesGetStrValueFromNode(SValueNode* pNode) { bool nodesIsExprNode(const SNode* pNode) { ENodeType type = nodeType(pNode); return (QUERY_NODE_COLUMN == type || QUERY_NODE_VALUE == type || QUERY_NODE_OPERATOR == type || - QUERY_NODE_FUNCTION == type || QUERY_NODE_LOGIC_CONDITION == type); + QUERY_NODE_FUNCTION == type || QUERY_NODE_LOGIC_CONDITION == type || QUERY_NODE_CASE_WHEN == type); } bool nodesIsUnaryOp(const SOperatorNode* pOp) { diff --git a/source/libs/parser/src/parTranslater.c b/source/libs/parser/src/parTranslater.c index b398b645b3..2cef80c4cb 100644 --- a/source/libs/parser/src/parTranslater.c +++ b/source/libs/parser/src/parTranslater.c @@ -1888,6 +1888,7 @@ static EDealRes translateCaseWhen(STranslateContext* pCxt, SCaseWhenNode* pCaseW pWhenThen->pWhen = pIsTrue; } if (first) { + first = false; pCaseWhen->node.resType = ((SExprNode*)pNode)->resType; } else if (!dataTypeEqual(&pCaseWhen->node.resType, &((SExprNode*)pNode)->resType)) { SNode* pCastFunc = NULL; diff --git a/source/libs/planner/src/planLogicCreater.c b/source/libs/planner/src/planLogicCreater.c index e6868f0ceb..e149460550 100644 --- a/source/libs/planner/src/planLogicCreater.c +++ b/source/libs/planner/src/planLogicCreater.c @@ -66,7 +66,8 @@ static EDealRes doRewriteExpr(SNode** pNode, void* pContext) { switch (nodeType(*pNode)) { case QUERY_NODE_OPERATOR: case QUERY_NODE_LOGIC_CONDITION: - case QUERY_NODE_FUNCTION: { + case QUERY_NODE_FUNCTION: + case QUERY_NODE_CASE_WHEN: { SRewriteExprCxt* pCxt = (SRewriteExprCxt*)pContext; SNode* pExpr; int32_t index = 0; @@ -118,6 +119,17 @@ static EDealRes doNameExpr(SNode* pNode, void* pContext) { return DEAL_RES_CONTINUE; } +static int32_t rewriteExprForSelect(SNode* pExpr, SSelectStmt* pSelect, ESqlClause clause) { + nodesWalkExpr(pExpr, doNameExpr, NULL); + SRewriteExprCxt cxt = {.errCode = TSDB_CODE_SUCCESS, .pExprs = NULL}; + cxt.errCode = nodesListMakeAppend(&cxt.pExprs, pExpr); + if (TSDB_CODE_SUCCESS == cxt.errCode) { + nodesRewriteSelectStmt(pSelect, clause, doRewriteExpr, &cxt); + nodesClearList(cxt.pExprs); + } + return cxt.errCode; +} + static int32_t rewriteExprsForSelect(SNodeList* pExprs, SSelectStmt* pSelect, ESqlClause clause) { nodesWalkExprs(pExprs, doNameExpr, NULL); SRewriteExprCxt cxt = {.errCode = TSDB_CODE_SUCCESS, .pExprs = pExprs}; @@ -711,8 +723,13 @@ static int32_t createWindowLogicNodeByState(SLogicPlanContext* pCxt, SStateWindo nodesDestroyNode((SNode*)pWindow); return TSDB_CODE_OUT_OF_MEMORY; } - - return createWindowLogicNodeFinalize(pCxt, pSelect, pWindow, pLogicNode); + // rewrite the expression in subsequent clauses + int32_t code = rewriteExprForSelect(pWindow->pStateExpr, pSelect, SQL_CLAUSE_WINDOW); + if (TSDB_CODE_SUCCESS == code) { + code = createWindowLogicNodeFinalize(pCxt, pSelect, pWindow, pLogicNode); + } + + return code; } static int32_t createWindowLogicNodeBySession(SLogicPlanContext* pCxt, SSessionWindowNode* pSession, diff --git a/source/libs/planner/src/planPhysiCreater.c b/source/libs/planner/src/planPhysiCreater.c index 2935c647aa..81a3a2cb16 100644 --- a/source/libs/planner/src/planPhysiCreater.c +++ b/source/libs/planner/src/planPhysiCreater.c @@ -761,7 +761,8 @@ static EDealRes doRewritePrecalcExprs(SNode** pNode, void* pContext) { return collectAndRewrite(pCxt, pNode); } case QUERY_NODE_OPERATOR: - case QUERY_NODE_LOGIC_CONDITION: { + case QUERY_NODE_LOGIC_CONDITION: + case QUERY_NODE_CASE_WHEN: { return collectAndRewrite(pCxt, pNode); } case QUERY_NODE_FUNCTION: { diff --git a/source/libs/planner/src/planUtil.c b/source/libs/planner/src/planUtil.c index ac1589bec0..a13e959a36 100644 --- a/source/libs/planner/src/planUtil.c +++ b/source/libs/planner/src/planUtil.c @@ -53,7 +53,8 @@ static EDealRes doCreateColumn(SNode* pNode, void* pContext) { } case QUERY_NODE_OPERATOR: case QUERY_NODE_LOGIC_CONDITION: - case QUERY_NODE_FUNCTION: { + case QUERY_NODE_FUNCTION: + case QUERY_NODE_CASE_WHEN: { SExprNode* pExpr = (SExprNode*)pNode; SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN); if (NULL == pCol) { diff --git a/source/libs/scalar/inc/sclInt.h b/source/libs/scalar/inc/sclInt.h index 0a9913e004..d3f29c0e49 100644 --- a/source/libs/scalar/inc/sclInt.h +++ b/source/libs/scalar/inc/sclInt.h @@ -86,7 +86,7 @@ typedef struct SScalarCtx { } \ } while (0) -int32_t doConvertDataType(SValueNode* pValueNode, SScalarParam* out, int32_t* overflow); +int32_t sclConvertValueToSclParam(SValueNode* pValueNode, SScalarParam* out, int32_t* overflow); int32_t sclCreateColumnInfoData(SDataType* pType, int32_t numOfRows, SScalarParam* pParam); int32_t sclConvertToTsValueNode(int8_t precision, SValueNode* valueNode); @@ -95,6 +95,11 @@ int32_t sclConvertToTsValueNode(int8_t precision, SValueNode* valueNode); #define GET_PARAM_PRECISON(_c) ((_c)->columnData->info.precision) void sclFreeParam(SScalarParam* param); +void doVectorCompare(SScalarParam* pLeft, SScalarParam* pRight, SScalarParam *pOut, int32_t startIndex, int32_t numOfRows, + int32_t _ord, int32_t optr); +void vectorCompareImpl(SScalarParam* pLeft, SScalarParam* pRight, SScalarParam *pOut, int32_t startIndex, int32_t numOfRows, + int32_t _ord, int32_t optr); +void vectorCompare(SScalarParam* pLeft, SScalarParam* pRight, SScalarParam *pOut, int32_t _ord, int32_t optr); #ifdef __cplusplus } diff --git a/source/libs/scalar/inc/sclvector.h b/source/libs/scalar/inc/sclvector.h index 1a749c61b3..e633b39223 100644 --- a/source/libs/scalar/inc/sclvector.h +++ b/source/libs/scalar/inc/sclvector.h @@ -20,6 +20,15 @@ extern "C" { #endif +typedef struct SSclVectorConvCtx { + const SScalarParam* pIn; + SScalarParam* pOut; + int32_t startIndex; + int32_t endIndex; + int16_t inType; + int16_t outType; +} SSclVectorConvCtx; + typedef double (*_getDoubleValue_fn_t)(void *src, int32_t index); static FORCE_INLINE double getVectorDoubleValue_TINYINT(void *src, int32_t index) { diff --git a/source/libs/scalar/src/filter.c b/source/libs/scalar/src/filter.c index 132e0ed214..81ee173648 100644 --- a/source/libs/scalar/src/filter.c +++ b/source/libs/scalar/src/filter.c @@ -1165,7 +1165,7 @@ int32_t fltAddGroupUnitFromNode(SFilterInfo *info, SNode *tree, SArray *group) { SValueNode *valueNode = (SValueNode *)cell->pNode; if (valueNode->node.resType.type != type) { int32_t overflow = 0; - code = doConvertDataType(valueNode, &out, &overflow); + code = sclConvertValueToSclParam(valueNode, &out, &overflow); if (code) { // fltError("convert from %d to %d failed", in.type, out.type); FLT_ERR_RET(code); @@ -1973,7 +1973,7 @@ int32_t fltInitValFieldData(SFilterInfo *info) { } // todo refactor the convert - int32_t code = doConvertDataType(var, &out, NULL); + int32_t code = sclConvertValueToSclParam(var, &out, NULL); if (code != TSDB_CODE_SUCCESS) { qError("convert value to type[%d] failed", type); return TSDB_CODE_TSC_INVALID_OPERATION; @@ -3792,6 +3792,11 @@ EDealRes fltReviseRewriter(SNode **pNode, void *pContext) { return DEAL_RES_CONTINUE; } + if (QUERY_NODE_CASE_WHEN == nodeType(*pNode) || QUERY_NODE_WHEN_THEN == nodeType(*pNode)) { + stat->scalarMode = true; + return DEAL_RES_CONTINUE; + } + if (QUERY_NODE_OPERATOR == nodeType(*pNode)) { SOperatorNode *node = (SOperatorNode *)*pNode; if (!FLT_IS_COMPARISON_OPERATOR(node->opType)) { diff --git a/source/libs/scalar/src/scalar.c b/source/libs/scalar/src/scalar.c index da7e286036..1f09fd4799 100644 --- a/source/libs/scalar/src/scalar.c +++ b/source/libs/scalar/src/scalar.c @@ -61,7 +61,7 @@ int32_t sclCreateColumnInfoData(SDataType *pType, int32_t numOfRows, SScalarPara return TSDB_CODE_SUCCESS; } -int32_t doConvertDataType(SValueNode *pValueNode, SScalarParam *out, int32_t *overflow) { +int32_t sclConvertValueToSclParam(SValueNode* pValueNode, SScalarParam* out, int32_t* overflow) { SScalarParam in = {.numOfRows = 1}; int32_t code = sclCreateColumnInfoData(&pValueNode->node.resType, 1, &in); if (code != TSDB_CODE_SUCCESS) { @@ -71,12 +71,34 @@ int32_t doConvertDataType(SValueNode *pValueNode, SScalarParam *out, int32_t *ov colDataAppend(in.columnData, 0, nodesGetValueFromNode(pValueNode), false); colInfoDataEnsureCapacity(out->columnData, 1); - code = vectorConvertImpl(&in, out, overflow); + code = vectorConvertSingleColImpl(&in, out, overflow, -1, -1); sclFreeParam(&in); return code; } +int32_t sclExtendResRows(SScalarParam *pDst, SScalarParam *pSrc, SArray *pBlockList) { + SSDataBlock* pb = taosArrayGetP(pBlockList, 0); + SScalarParam *pLeft = taosMemoryCalloc(1, sizeof(SScalarParam)); + if (NULL == pLeft) { + sclError("calloc %d failed", (int32_t)sizeof(SScalarParam)); + SCL_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY); + } + + pLeft->numOfRows = pb->info.rows; + + if (pDst->numOfRows < pb->info.rows) { + colInfoDataEnsureCapacity(pDst->columnData, pb->info.rows); + } + + _bin_scalar_fn_t OperatorFn = getBinScalarOperatorFn(OP_TYPE_ASSIGN); + OperatorFn(pLeft, pSrc, pDst, TSDB_ORDER_ASC); + + taosMemoryFree(pLeft); + + return TSDB_CODE_SUCCESS; +} + int32_t scalarGenerateSetFromList(void **data, void *pNode, uint32_t type) { SHashObj *pObj = taosHashInit(256, taosGetDefaultHashFunction(type), true, false); if (NULL == pObj) { @@ -110,7 +132,7 @@ int32_t scalarGenerateSetFromList(void **data, void *pNode, uint32_t type) { } int32_t overflow = 0; - code = doConvertDataType(valueNode, &out, &overflow); + code = sclConvertValueToSclParam(valueNode, &out, &overflow); if (code != TSDB_CODE_SUCCESS) { // sclError("convert data from %d to %d failed", in.type, out.type); SCL_ERR_JRET(code); @@ -178,7 +200,7 @@ void sclFreeRes(SHashObj *res) { } void sclFreeParam(SScalarParam *param) { - if (!param->colAlloced) { + if (NULL == param || !param->colAlloced) { return; } @@ -386,7 +408,8 @@ int32_t sclInitParam(SNode *node, SScalarParam *param, SScalarCtx *ctx, int32_t } case QUERY_NODE_FUNCTION: case QUERY_NODE_OPERATOR: - case QUERY_NODE_LOGIC_CONDITION: { + case QUERY_NODE_LOGIC_CONDITION: + case QUERY_NODE_CASE_WHEN: { SScalarParam *res = (SScalarParam *)taosHashGet(ctx->pRes, &node, POINTER_BYTES); if (NULL == res) { sclError("no result for node, type:%d, node:%p", nodeType(node), node); @@ -540,6 +563,135 @@ _return: SCL_RET(code); } +int32_t sclGetNodeRes(SNode* node, SScalarCtx *ctx, SScalarParam **res) { + if (NULL == node) { + return TSDB_CODE_SUCCESS; + } + + int32_t rowNum = 0; + *res = taosMemoryCalloc(1, sizeof(**res)); + if (NULL == *res) { + SCL_ERR_RET(TSDB_CODE_OUT_OF_MEMORY); + } + + SCL_ERR_RET(sclInitParam(node, *res, ctx, &rowNum)); + + return TSDB_CODE_SUCCESS; +} + +int32_t sclWalkCaseWhenList(SScalarCtx *ctx, SNodeList* pList, struct SListCell* pCell, SScalarParam *pCase, SScalarParam *pElse, SScalarParam *pComp, SScalarParam *output, int32_t rowIdx, int32_t totalRows, bool *complete) { + SNode *node = NULL; + SWhenThenNode* pWhenThen = NULL; + SScalarParam *pWhen = NULL; + SScalarParam *pThen = NULL; + int32_t code = 0; + + for (SListCell* cell = pCell; (NULL != cell ? (node = cell->pNode, true) : (node = NULL, false)); cell = cell->pNext) { + pWhenThen = (SWhenThenNode*)node; + + SCL_ERR_RET(sclGetNodeRes(pWhenThen->pWhen, ctx, &pWhen)); + SCL_ERR_RET(sclGetNodeRes(pWhenThen->pThen, ctx, &pThen)); + + vectorCompareImpl(pCase, pWhen, pComp, rowIdx, 1, TSDB_ORDER_ASC, OP_TYPE_EQUAL); + + bool *equal = (bool*)colDataGetData(pComp->columnData, rowIdx); + if (*equal) { + colDataAppend(output->columnData, rowIdx, colDataGetData(pThen->columnData, (pThen->numOfRows > 1 ? rowIdx : 0)), colDataIsNull_s(pThen->columnData, (pThen->numOfRows > 1 ? rowIdx : 0))); + + if (0 == rowIdx && 1 == pCase->numOfRows && 1 == pWhen->numOfRows && 1 == pThen->numOfRows && totalRows > 1) { + SCL_ERR_JRET(sclExtendResRows(output, output, ctx->pBlockList)); + *complete = true; + } + + goto _return; + } + } + + if (pElse) { + colDataAppend(output->columnData, rowIdx, colDataGetData(pElse->columnData, (pElse->numOfRows > 1 ? rowIdx : 0)), colDataIsNull_s(pElse->columnData, (pElse->numOfRows > 1 ? rowIdx : 0))); + + if (0 == rowIdx && 1 == pCase->numOfRows && 1 == pElse->numOfRows && totalRows > 1) { + SCL_ERR_JRET(sclExtendResRows(output, output, ctx->pBlockList)); + *complete = true; + } + + goto _return; + } + + colDataAppend(output->columnData, rowIdx, NULL, true); + + if (0 == rowIdx && 1 == pCase->numOfRows && totalRows > 1) { + SCL_ERR_JRET(sclExtendResRows(output, output, ctx->pBlockList)); + *complete = true; + } + +_return: + + sclFreeParam(pWhen); + sclFreeParam(pThen); + + SCL_RET(code); +} + +int32_t sclWalkWhenList(SScalarCtx *ctx, SNodeList* pList, struct SListCell* pCell, SScalarParam *pElse, SScalarParam *output, + int32_t rowIdx, int32_t totalRows, bool *complete, bool preSingle) { + SNode *node = NULL; + SWhenThenNode* pWhenThen = NULL; + SScalarParam *pWhen = NULL; + SScalarParam *pThen = NULL; + int32_t code = 0; + + for (SListCell* cell = pCell; (NULL != cell ? (node = cell->pNode, true) : (node = NULL, false)); cell = cell->pNext) { + pWhenThen = (SWhenThenNode*)node; + pWhen = NULL; + pThen = NULL; + + SCL_ERR_JRET(sclGetNodeRes(pWhenThen->pWhen, ctx, &pWhen)); + SCL_ERR_JRET(sclGetNodeRes(pWhenThen->pThen, ctx, &pThen)); + + bool *whenValue = (bool*)colDataGetData(pWhen->columnData, (pWhen->numOfRows > 1 ? rowIdx : 0)); + + if (*whenValue) { + colDataAppend(output->columnData, rowIdx, colDataGetData(pThen->columnData, (pThen->numOfRows > 1 ? rowIdx : 0)), colDataIsNull_s(pThen->columnData, (pThen->numOfRows > 1 ? rowIdx : 0))); + + if (preSingle && 0 == rowIdx && 1 == pWhen->numOfRows && 1 == pThen->numOfRows && totalRows > 1) { + SCL_ERR_JRET(sclExtendResRows(output, output, ctx->pBlockList)); + *complete = true; + } + + goto _return; + } + + sclFreeParam(pWhen); + sclFreeParam(pThen); + } + + if (pElse) { + colDataAppend(output->columnData, rowIdx, colDataGetData(pElse->columnData, (pElse->numOfRows > 1 ? rowIdx : 0)), colDataIsNull_s(pElse->columnData, (pElse->numOfRows > 1 ? rowIdx : 0))); + + if (preSingle && 0 == rowIdx && 1 == pElse->numOfRows && totalRows > 1) { + SCL_ERR_JRET(sclExtendResRows(output, output, ctx->pBlockList)); + *complete = true; + } + + goto _return; + } + + colDataAppend(output->columnData, rowIdx, NULL, true); + + if (preSingle && 0 == rowIdx && totalRows > 1) { + SCL_ERR_JRET(sclExtendResRows(output, output, ctx->pBlockList)); + *complete = true; + } + +_return: + + sclFreeParam(pWhen); + sclFreeParam(pThen); + + SCL_RET(code); +} + int32_t sclExecFunction(SFunctionNode *node, SScalarCtx *ctx, SScalarParam *output) { SScalarParam *params = NULL; int32_t rowNum = 0; @@ -698,6 +850,101 @@ _return: SCL_RET(code); } +int32_t sclExecCaseWhen(SCaseWhenNode *node, SScalarCtx *ctx, SScalarParam *output) { + int32_t code = 0; + SScalarParam *pCase = NULL; + SScalarParam *pElse = NULL; + SScalarParam *pWhen = NULL; + SScalarParam *pThen = NULL; + SScalarParam comp = {0}; + int32_t rowNum = 1; + bool complete = false; + + if (NULL == node->pWhenThenList || node->pWhenThenList->length <= 0) { + sclError("invalid whenThen list"); + SCL_ERR_RET(TSDB_CODE_INVALID_PARA); + } + + if (ctx->pBlockList) { + SSDataBlock* pb = taosArrayGetP(ctx->pBlockList, 0); + rowNum = pb->info.rows; + output->numOfRows = pb->info.rows; + } + + SCL_ERR_JRET(sclCreateColumnInfoData(&node->node.resType, rowNum, output)); + + SCL_ERR_JRET(sclGetNodeRes(node->pCase, ctx, &pCase)); + SCL_ERR_JRET(sclGetNodeRes(node->pElse, ctx, &pElse)); + + SDataType compType = {0}; + compType.type = TSDB_DATA_TYPE_BOOL; + compType.bytes = tDataTypes[compType.type].bytes; + + SCL_ERR_JRET(sclCreateColumnInfoData(&compType, rowNum, &comp)); + + SNode* tnode = NULL; + SWhenThenNode* pWhenThen = (SWhenThenNode*)node->pWhenThenList->pHead->pNode; + + SCL_ERR_JRET(sclGetNodeRes(pWhenThen->pWhen, ctx, &pWhen)); + SCL_ERR_JRET(sclGetNodeRes(pWhenThen->pThen, ctx, &pThen)); + + if (pCase) { + vectorCompare(pCase, pWhen, &comp, TSDB_ORDER_ASC, OP_TYPE_EQUAL); + + for (int32_t i = 0; i < rowNum; ++i) { + bool *equal = (bool*)colDataGetData(comp.columnData, (comp.numOfRows > 1 ? i : 0)); + if (*equal) { + colDataAppend(output->columnData, i, colDataGetData(pThen->columnData, (pThen->numOfRows > 1 ? i : 0)), colDataIsNull_s(pThen->columnData, (pThen->numOfRows > 1 ? i : 0))); + if (0 == i && 1 == pCase->numOfRows && 1 == pWhen->numOfRows && 1 == pThen->numOfRows && rowNum > 1) { + SCL_ERR_JRET(sclExtendResRows(output, output, ctx->pBlockList)); + break; + } + } else { + SCL_ERR_JRET(sclWalkCaseWhenList(ctx, node->pWhenThenList, node->pWhenThenList->pHead->pNext, pCase, pElse, &comp, output, i, rowNum, &complete)); + if (complete) { + break; + } + } + } + } else { + for (int32_t i = 0; i < rowNum; ++i) { + bool *whenValue = (bool*)colDataGetData(pWhen->columnData, (pWhen->numOfRows > 1 ? i : 0)); + if (*whenValue) { + colDataAppend(output->columnData, i, colDataGetData(pThen->columnData, (pThen->numOfRows > 1 ? i : 0)), colDataIsNull_s(pThen->columnData, (pThen->numOfRows > 1 ? i : 0))); + if (0 == i && 1 == pWhen->numOfRows && 1 == pThen->numOfRows && rowNum > 1) { + SCL_ERR_JRET(sclExtendResRows(output, output, ctx->pBlockList)); + break; + } + } else { + SCL_ERR_JRET(sclWalkWhenList(ctx, node->pWhenThenList, node->pWhenThenList->pHead->pNext, pElse, output, i, rowNum, &complete, (pWhen->numOfRows == 1 && pThen->numOfRows == 1))); + if (complete) { + break; + } + } + } + } + + sclFreeParam(pCase); + sclFreeParam(pElse); + sclFreeParam(&comp); + sclFreeParam(pWhen); + sclFreeParam(pThen); + + return TSDB_CODE_SUCCESS; + +_return: + + sclFreeParam(pCase); + sclFreeParam(pElse); + sclFreeParam(&comp); + sclFreeParam(pWhen); + sclFreeParam(pThen); + sclFreeParam(output); + + SCL_RET(code); +} + + EDealRes sclRewriteNullInOptr(SNode **pNode, SScalarCtx *ctx, EOperatorType opType) { if (opType <= OP_TYPE_CALC_MAX) { SValueNode *res = (SValueNode *)nodesMakeNode(QUERY_NODE_VALUE); @@ -960,9 +1207,66 @@ EDealRes sclRewriteOperator(SNode **pNode, SScalarCtx *ctx) { return DEAL_RES_CONTINUE; } +EDealRes sclRewriteCaseWhen(SNode** pNode, SScalarCtx *ctx) { + SCaseWhenNode *node = (SCaseWhenNode *)*pNode; + + if ((!SCL_IS_CONST_NODE(node->pCase)) || (!SCL_IS_CONST_NODE(node->pElse))) { + return DEAL_RES_CONTINUE; + } + + SNode* tnode = NULL; + FOREACH(tnode, node->pWhenThenList) { + SWhenThenNode* pWhenThen = (SWhenThenNode*)tnode; + if (!SCL_IS_CONST_NODE(pWhenThen->pWhen) || !SCL_IS_CONST_NODE(pWhenThen->pThen)) { + return DEAL_RES_CONTINUE; + } + } + + SScalarParam output = {0}; + ctx->code = sclExecCaseWhen(node, ctx, &output); + if (ctx->code) { + return DEAL_RES_ERROR; + } + + SValueNode *res = (SValueNode *)nodesMakeNode(QUERY_NODE_VALUE); + if (NULL == res) { + sclError("make value node failed"); + sclFreeParam(&output); + ctx->code = TSDB_CODE_QRY_OUT_OF_MEMORY; + return DEAL_RES_ERROR; + } + + res->translate = true; + + res->node.resType = node->node.resType; + if (colDataIsNull_s(output.columnData, 0)) { + res->isNull = true; + res->node.resType = node->node.resType; + } else { + int32_t type = output.columnData->info.type; + if (IS_VAR_DATA_TYPE(type)) { // todo refactor + res->datum.p = output.columnData->pData; + output.columnData->pData = NULL; + } else { + nodesSetValueNodeValue(res, output.columnData->pData); + } + } + + nodesDestroyNode(*pNode); + *pNode = (SNode*)res; + + sclFreeParam(&output); + return DEAL_RES_CONTINUE; +} + + EDealRes sclConstantsRewriter(SNode **pNode, void *pContext) { SScalarCtx *ctx = (SScalarCtx *)pContext; + if (QUERY_NODE_OPERATOR == nodeType(*pNode)) { + return sclRewriteOperator(pNode, ctx); + } + if (QUERY_NODE_FUNCTION == nodeType(*pNode)) { return sclRewriteFunction(pNode, ctx); } @@ -971,8 +1275,8 @@ EDealRes sclConstantsRewriter(SNode **pNode, void *pContext) { return sclRewriteLogic(pNode, ctx); } - if (QUERY_NODE_OPERATOR == nodeType(*pNode)) { - return sclRewriteOperator(pNode, ctx); + if (QUERY_NODE_CASE_WHEN == nodeType(*pNode)) { + return sclRewriteCaseWhen(pNode, ctx); } return DEAL_RES_CONTINUE; @@ -1082,13 +1386,36 @@ EDealRes sclWalkTarget(SNode *pNode, SScalarCtx *ctx) { return DEAL_RES_CONTINUE; } +EDealRes sclWalkCaseWhen(SNode* pNode, SScalarCtx *ctx) { + SCaseWhenNode *node = (SCaseWhenNode *)pNode; + SScalarParam output = {0}; + + ctx->code = sclExecCaseWhen(node, ctx, &output); + if (ctx->code) { + return DEAL_RES_ERROR; + } + + if (taosHashPut(ctx->pRes, &pNode, POINTER_BYTES, &output, sizeof(output))) { + ctx->code = TSDB_CODE_QRY_OUT_OF_MEMORY; + return DEAL_RES_ERROR; + } + + return DEAL_RES_CONTINUE; +} + + EDealRes sclCalcWalker(SNode *pNode, void *pContext) { - if (QUERY_NODE_VALUE == nodeType(pNode) || QUERY_NODE_NODE_LIST == nodeType(pNode) || - QUERY_NODE_COLUMN == nodeType(pNode) || QUERY_NODE_LEFT_VALUE == nodeType(pNode)) { + if (QUERY_NODE_VALUE == nodeType(pNode) || QUERY_NODE_NODE_LIST == nodeType(pNode) + || QUERY_NODE_COLUMN == nodeType(pNode) || QUERY_NODE_LEFT_VALUE == nodeType(pNode) + || QUERY_NODE_WHEN_THEN == nodeType(pNode)) { return DEAL_RES_CONTINUE; } SScalarCtx *ctx = (SScalarCtx *)pContext; + if (QUERY_NODE_OPERATOR == nodeType(pNode)) { + return sclWalkOperator(pNode, ctx); + } + if (QUERY_NODE_FUNCTION == nodeType(pNode)) { return sclWalkFunction(pNode, ctx); } @@ -1097,38 +1424,19 @@ EDealRes sclCalcWalker(SNode *pNode, void *pContext) { return sclWalkLogic(pNode, ctx); } - if (QUERY_NODE_OPERATOR == nodeType(pNode)) { - return sclWalkOperator(pNode, ctx); - } - if (QUERY_NODE_TARGET == nodeType(pNode)) { return sclWalkTarget(pNode, ctx); } + if (QUERY_NODE_CASE_WHEN == nodeType(pNode)) { + return sclWalkCaseWhen(pNode, ctx); + } + sclError("invalid node type for scalar calculating, type:%d", nodeType(pNode)); ctx->code = TSDB_CODE_QRY_INVALID_INPUT; return DEAL_RES_ERROR; } -int32_t sclExtendResRows(SScalarParam *pDst, SScalarParam *pSrc, SArray *pBlockList) { - SSDataBlock *pb = taosArrayGetP(pBlockList, 0); - SScalarParam *pLeft = taosMemoryCalloc(1, sizeof(SScalarParam)); - if (NULL == pLeft) { - sclError("calloc %d failed", (int32_t)sizeof(SScalarParam)); - SCL_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY); - } - - pLeft->numOfRows = pb->info.rows; - colInfoDataEnsureCapacity(pDst->columnData, pb->info.rows); - - _bin_scalar_fn_t OperatorFn = getBinScalarOperatorFn(OP_TYPE_ASSIGN); - OperatorFn(pLeft, pSrc, pDst, TSDB_ORDER_ASC); - - taosMemoryFree(pLeft); - - return TSDB_CODE_SUCCESS; -} - int32_t sclCalcConstants(SNode *pNode, bool dual, SNode **pRes) { if (NULL == pNode) { SCL_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT); diff --git a/source/libs/scalar/src/sclvector.c b/source/libs/scalar/src/sclvector.c index e83fe7ecd0..f467721248 100644 --- a/source/libs/scalar/src/sclvector.c +++ b/source/libs/scalar/src/sclvector.c @@ -367,46 +367,45 @@ static FORCE_INLINE void ncharToVar(char *buf, SScalarParam *pOut, int32_t rowIn taosMemoryFree(t); } -// TODO opt performance, tmp is not needed. -int32_t vectorConvertFromVarData(const SScalarParam *pIn, SScalarParam *pOut, int32_t inType, int32_t outType, - int32_t *overflow) { +//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 == outType) { + if (TSDB_DATA_TYPE_BOOL == pCtx->outType) { func = varToBool; - } else if (IS_SIGNED_NUMERIC_TYPE(outType)) { + } else if (IS_SIGNED_NUMERIC_TYPE(pCtx->outType)) { func = varToSigned; - } else if (IS_UNSIGNED_NUMERIC_TYPE(outType)) { + } else if (IS_UNSIGNED_NUMERIC_TYPE(pCtx->outType)) { func = varToUnsigned; - } else if (IS_FLOAT_TYPE(outType)) { + } else if (IS_FLOAT_TYPE(pCtx->outType)) { func = varToFloat; - } else if (outType == TSDB_DATA_TYPE_BINARY) { // nchar -> binary - ASSERT(inType == TSDB_DATA_TYPE_NCHAR); + } else if (pCtx->outType == TSDB_DATA_TYPE_BINARY) { // nchar -> binary + ASSERT(pCtx->inType == TSDB_DATA_TYPE_NCHAR); func = ncharToVar; vton = true; - } else if (outType == TSDB_DATA_TYPE_NCHAR) { // binary -> nchar - ASSERT(inType == TSDB_DATA_TYPE_VARCHAR); + } else if (pCtx->outType == TSDB_DATA_TYPE_NCHAR) { // binary -> nchar + ASSERT(pCtx->inType == TSDB_DATA_TYPE_VARCHAR); func = varToNchar; vton = true; - } else if (TSDB_DATA_TYPE_TIMESTAMP == outType) { + } else if (TSDB_DATA_TYPE_TIMESTAMP == pCtx->outType) { func = varToTimestamp; } else { - sclError("invalid convert outType:%d", outType); + sclError("invalid convert outType:%d", pCtx->outType); return TSDB_CODE_QRY_APP_ERROR; } - pOut->numOfRows = pIn->numOfRows; - for (int32_t i = 0; i < pIn->numOfRows; ++i) { - if (IS_HELPER_NULL(pIn->columnData, i)) { - colDataAppendNULL(pOut->columnData, i); + pCtx->pOut->numOfRows = pCtx->pIn->numOfRows; + for (int32_t i = pCtx->startIndex; i <= pCtx->endIndex; ++i) { + if (IS_HELPER_NULL(pCtx->pIn->columnData, i)) { + colDataAppendNULL(pCtx->pOut->columnData, i); continue; } - char *data = colDataGetVarData(pIn->columnData, i); - int32_t convertType = inType; - if (inType == TSDB_DATA_TYPE_JSON) { - if (*data == TSDB_DATA_TYPE_NULL) { + char* data = colDataGetVarData(pCtx->pIn->columnData, i); + int32_t convertType = pCtx->inType; + if(pCtx->inType == TSDB_DATA_TYPE_JSON){ + if(*data == TSDB_DATA_TYPE_NULL) { ASSERT(0); } else if (*data == TSDB_DATA_TYPE_NCHAR) { data += CHAR_BYTES; @@ -415,13 +414,13 @@ int32_t vectorConvertFromVarData(const SScalarParam *pIn, SScalarParam *pOut, in terrno = TSDB_CODE_QRY_JSON_NOT_SUPPORT_ERROR; return terrno; } else { - convertNumberToNumber(data + CHAR_BYTES, colDataGetNumData(pOut->columnData, i), *data, outType); + convertNumberToNumber(data+CHAR_BYTES, colDataGetNumData(pCtx->pOut->columnData, i), *data, pCtx->outType); continue; } } - int32_t bufSize = pIn->columnData->info.bytes; - char *tmp = taosMemoryMalloc(varDataTLen(data)); - if (!tmp) { + int32_t bufSize = pCtx->pIn->columnData->info.bytes; + char *tmp = taosMemoryMalloc(varDataTLen(data)); + if(!tmp){ sclError("out of memory in vectorConvertFromVarData"); return TSDB_CODE_OUT_OF_MEMORY; } @@ -444,8 +443,8 @@ int32_t vectorConvertFromVarData(const SScalarParam *pIn, SScalarParam *pOut, in tmp[len] = 0; } } - - (*func)(tmp, pOut, i, overflow); + + (*func)(tmp, pCtx->pOut, i, overflow); taosMemoryFreeClear(tmp); } @@ -581,64 +580,64 @@ bool convertJsonValue(__compar_fn_t *fp, int32_t optr, int8_t typeLeft, int8_t t return true; } -int32_t vectorConvertToVarData(const SScalarParam *pIn, SScalarParam *pOut, int16_t inType, int16_t outType) { - SColumnInfoData *pInputCol = pIn->columnData; - SColumnInfoData *pOutputCol = pOut->columnData; - char tmp[128] = {0}; +int32_t vectorConvertToVarData(SSclVectorConvCtx *pCtx) { + SColumnInfoData* pInputCol = pCtx->pIn->columnData; + SColumnInfoData* pOutputCol = pCtx->pOut->columnData; + char tmp[128] = {0}; - if (IS_SIGNED_NUMERIC_TYPE(inType) || inType == TSDB_DATA_TYPE_BOOL || inType == TSDB_DATA_TYPE_TIMESTAMP) { - for (int32_t i = 0; i < pIn->numOfRows; ++i) { + 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)) { colDataAppendNULL(pOutputCol, i); continue; } int64_t value = 0; - GET_TYPED_DATA(value, int64_t, inType, colDataGetData(pInputCol, i)); + GET_TYPED_DATA(value, int64_t, pCtx->inType, colDataGetData(pInputCol, i)); int32_t len = sprintf(varDataVal(tmp), "%" PRId64, value); varDataLen(tmp) = len; - if (outType == TSDB_DATA_TYPE_NCHAR) { - varToNchar(tmp, pOut, i, NULL); + if (pCtx->outType == TSDB_DATA_TYPE_NCHAR) { + varToNchar(tmp, pCtx->pOut, i, NULL); } else { colDataAppend(pOutputCol, i, (char *)tmp, false); } } - } else if (IS_UNSIGNED_NUMERIC_TYPE(inType)) { - for (int32_t i = 0; i < pIn->numOfRows; ++i) { + } else if (IS_UNSIGNED_NUMERIC_TYPE(pCtx->inType)) { + for (int32_t i = pCtx->startIndex; i <= pCtx->endIndex; ++i) { if (colDataIsNull_f(pInputCol->nullbitmap, i)) { colDataAppendNULL(pOutputCol, i); continue; } uint64_t value = 0; - GET_TYPED_DATA(value, uint64_t, inType, colDataGetData(pInputCol, i)); + GET_TYPED_DATA(value, uint64_t, pCtx->inType, colDataGetData(pInputCol, i)); int32_t len = sprintf(varDataVal(tmp), "%" PRIu64, value); varDataLen(tmp) = len; - if (outType == TSDB_DATA_TYPE_NCHAR) { - varToNchar(tmp, pOut, i, NULL); + if (pCtx->outType == TSDB_DATA_TYPE_NCHAR) { + varToNchar(tmp, pCtx->pOut, i, NULL); } else { colDataAppend(pOutputCol, i, (char *)tmp, false); } } - } else if (IS_FLOAT_TYPE(inType)) { - for (int32_t i = 0; i < pIn->numOfRows; ++i) { + } else if (IS_FLOAT_TYPE(pCtx->inType)) { + for (int32_t i = pCtx->startIndex; i <= pCtx->endIndex; ++i) { if (colDataIsNull_f(pInputCol->nullbitmap, i)) { colDataAppendNULL(pOutputCol, i); continue; } double value = 0; - GET_TYPED_DATA(value, double, inType, colDataGetData(pInputCol, i)); + GET_TYPED_DATA(value, double, pCtx->inType, colDataGetData(pInputCol, i)); int32_t len = sprintf(varDataVal(tmp), "%lf", value); varDataLen(tmp) = len; - if (outType == TSDB_DATA_TYPE_NCHAR) { - varToNchar(tmp, pOut, i, NULL); + if (pCtx->outType == TSDB_DATA_TYPE_NCHAR) { + varToNchar(tmp, pCtx->pOut, i, NULL); } else { colDataAppend(pOutputCol, i, (char *)tmp, false); } } } else { - sclError("not supported input type:%d", inType); + sclError("not supported input type:%d", pCtx->inType); return TSDB_CODE_QRY_APP_ERROR; } @@ -646,34 +645,35 @@ int32_t vectorConvertToVarData(const SScalarParam *pIn, SScalarParam *pOut, int1 } // TODO opt performance -int32_t vectorConvertImpl(const SScalarParam *pIn, SScalarParam *pOut, int32_t *overflow) { - SColumnInfoData *pInputCol = pIn->columnData; - SColumnInfoData *pOutputCol = pOut->columnData; +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; } - int16_t inType = pInputCol->info.type; - int16_t outType = pOutputCol->info.type; + int32_t rstart = startIndex >= 0 ? 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(inType)) { - return vectorConvertFromVarData(pIn, pOut, inType, outType, overflow); + if (IS_VAR_DATA_TYPE(cCtx.inType)) { + return vectorConvertFromVarData(&cCtx, overflow); } if (overflow) { ASSERT(1 == pIn->numOfRows); pOut->numOfRows = 0; - - if (IS_SIGNED_NUMERIC_TYPE(outType)) { - int64_t minValue = tDataTypes[outType].minValue; - int64_t maxValue = tDataTypes[outType].maxValue; - + + 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, inType, colDataGetData(pInputCol, 0)); - + GET_TYPED_DATA(value, double, cCtx.inType, colDataGetData(pInputCol, 0)); + if (value > maxValue) { *overflow = 1; return TSDB_CODE_SUCCESS; @@ -683,13 +683,13 @@ int32_t vectorConvertImpl(const SScalarParam *pIn, SScalarParam *pOut, int32_t * } else { *overflow = 0; } - } else if (IS_UNSIGNED_NUMERIC_TYPE(outType)) { - uint64_t minValue = (uint64_t)tDataTypes[outType].minValue; - uint64_t maxValue = (uint64_t)tDataTypes[outType].maxValue; - + } 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, inType, colDataGetData(pInputCol, 0)); - + GET_TYPED_DATA(value, double, cCtx.inType, colDataGetData(pInputCol, 0)); + if (value > maxValue) { *overflow = 1; return TSDB_CODE_SUCCESS; @@ -703,157 +703,157 @@ int32_t vectorConvertImpl(const SScalarParam *pIn, SScalarParam *pOut, int32_t * } pOut->numOfRows = pIn->numOfRows; - switch (outType) { + switch (cCtx.outType) { case TSDB_DATA_TYPE_BOOL: { - for (int32_t i = 0; i < pIn->numOfRows; ++i) { + for (int32_t i = cCtx.startIndex; i <= cCtx.endIndex; ++i) { if (colDataIsNull_f(pInputCol->nullbitmap, i)) { colDataAppendNULL(pOutputCol, i); continue; } bool value = 0; - GET_TYPED_DATA(value, bool, inType, colDataGetData(pInputCol, i)); + GET_TYPED_DATA(value, bool, cCtx.inType, colDataGetData(pInputCol, i)); colDataAppendInt8(pOutputCol, i, (int8_t *)&value); } break; } case TSDB_DATA_TYPE_TINYINT: { - for (int32_t i = 0; i < pIn->numOfRows; ++i) { + for (int32_t i = cCtx.startIndex; i <= cCtx.endIndex; ++i) { if (colDataIsNull_f(pInputCol->nullbitmap, i)) { colDataAppendNULL(pOutputCol, i); continue; } int8_t value = 0; - GET_TYPED_DATA(value, int8_t, inType, colDataGetData(pInputCol, i)); + GET_TYPED_DATA(value, int8_t, cCtx.inType, colDataGetData(pInputCol, i)); colDataAppendInt8(pOutputCol, i, (int8_t *)&value); } break; } - case TSDB_DATA_TYPE_SMALLINT: { - for (int32_t i = 0; i < pIn->numOfRows; ++i) { + case TSDB_DATA_TYPE_SMALLINT:{ + for (int32_t i = cCtx.startIndex; i <= cCtx.endIndex; ++i) { if (colDataIsNull_f(pInputCol->nullbitmap, i)) { colDataAppendNULL(pOutputCol, i); continue; } int16_t value = 0; - GET_TYPED_DATA(value, int16_t, inType, colDataGetData(pInputCol, i)); + GET_TYPED_DATA(value, int16_t, cCtx.inType, colDataGetData(pInputCol, i)); colDataAppendInt16(pOutputCol, i, (int16_t *)&value); } break; } - case TSDB_DATA_TYPE_INT: { - for (int32_t i = 0; i < pIn->numOfRows; ++i) { + case TSDB_DATA_TYPE_INT:{ + for (int32_t i = cCtx.startIndex; i <= cCtx.endIndex; ++i) { if (colDataIsNull_f(pInputCol->nullbitmap, i)) { colDataAppendNULL(pOutputCol, i); continue; } int32_t value = 0; - GET_TYPED_DATA(value, int32_t, inType, colDataGetData(pInputCol, i)); + GET_TYPED_DATA(value, int32_t, cCtx.inType, colDataGetData(pInputCol, i)); colDataAppendInt32(pOutputCol, i, (int32_t *)&value); } break; } case TSDB_DATA_TYPE_BIGINT: case TSDB_DATA_TYPE_TIMESTAMP: { - for (int32_t i = 0; i < pIn->numOfRows; ++i) { + for (int32_t i = cCtx.startIndex; i <= cCtx.endIndex; ++i) { if (colDataIsNull_f(pInputCol->nullbitmap, i)) { colDataAppendNULL(pOutputCol, i); continue; } int64_t value = 0; - GET_TYPED_DATA(value, int64_t, inType, colDataGetData(pInputCol, i)); + GET_TYPED_DATA(value, int64_t, cCtx.inType, colDataGetData(pInputCol, i)); colDataAppendInt64(pOutputCol, i, (int64_t *)&value); } break; } - case TSDB_DATA_TYPE_UTINYINT: { - for (int32_t i = 0; i < pIn->numOfRows; ++i) { + case TSDB_DATA_TYPE_UTINYINT:{ + for (int32_t i = cCtx.startIndex; i <= cCtx.endIndex; ++i) { if (colDataIsNull_f(pInputCol->nullbitmap, i)) { colDataAppendNULL(pOutputCol, i); continue; } uint8_t value = 0; - GET_TYPED_DATA(value, uint8_t, inType, colDataGetData(pInputCol, i)); + GET_TYPED_DATA(value, uint8_t, cCtx.inType, colDataGetData(pInputCol, i)); colDataAppendInt8(pOutputCol, i, (int8_t *)&value); } break; } - case TSDB_DATA_TYPE_USMALLINT: { - for (int32_t i = 0; i < pIn->numOfRows; ++i) { + case TSDB_DATA_TYPE_USMALLINT:{ + for (int32_t i = cCtx.startIndex; i <= cCtx.endIndex; ++i) { if (colDataIsNull_f(pInputCol->nullbitmap, i)) { colDataAppendNULL(pOutputCol, i); continue; } uint16_t value = 0; - GET_TYPED_DATA(value, uint16_t, inType, colDataGetData(pInputCol, i)); + GET_TYPED_DATA(value, uint16_t, cCtx.inType, colDataGetData(pInputCol, i)); colDataAppendInt16(pOutputCol, i, (int16_t *)&value); } break; } - case TSDB_DATA_TYPE_UINT: { - for (int32_t i = 0; i < pIn->numOfRows; ++i) { + case TSDB_DATA_TYPE_UINT:{ + for (int32_t i = cCtx.startIndex; i <= cCtx.endIndex; ++i) { if (colDataIsNull_f(pInputCol->nullbitmap, i)) { colDataAppendNULL(pOutputCol, i); continue; } uint32_t value = 0; - GET_TYPED_DATA(value, uint32_t, inType, colDataGetData(pInputCol, i)); + GET_TYPED_DATA(value, uint32_t, cCtx.inType, colDataGetData(pInputCol, i)); colDataAppendInt32(pOutputCol, i, (int32_t *)&value); } break; } case TSDB_DATA_TYPE_UBIGINT: { - for (int32_t i = 0; i < pIn->numOfRows; ++i) { + for (int32_t i = cCtx.startIndex; i <= cCtx.endIndex; ++i) { if (colDataIsNull_f(pInputCol->nullbitmap, i)) { colDataAppendNULL(pOutputCol, i); continue; } uint64_t value = 0; - GET_TYPED_DATA(value, uint64_t, inType, colDataGetData(pInputCol, i)); - colDataAppendInt64(pOutputCol, i, (int64_t *)&value); + GET_TYPED_DATA(value, uint64_t, cCtx.inType, colDataGetData(pInputCol, i)); + colDataAppendInt64(pOutputCol, i, (int64_t*)&value); } break; } - case TSDB_DATA_TYPE_FLOAT: { - for (int32_t i = 0; i < pIn->numOfRows; ++i) { + case TSDB_DATA_TYPE_FLOAT:{ + for (int32_t i = cCtx.startIndex; i <= cCtx.endIndex; ++i) { if (colDataIsNull_f(pInputCol->nullbitmap, i)) { colDataAppendNULL(pOutputCol, i); continue; } float value = 0; - GET_TYPED_DATA(value, float, inType, colDataGetData(pInputCol, i)); - colDataAppendFloat(pOutputCol, i, (float *)&value); + GET_TYPED_DATA(value, float, cCtx.inType, colDataGetData(pInputCol, i)); + colDataAppendFloat(pOutputCol, i, (float*)&value); } break; } case TSDB_DATA_TYPE_DOUBLE: { - for (int32_t i = 0; i < pIn->numOfRows; ++i) { + for (int32_t i = cCtx.startIndex; i <= cCtx.endIndex; ++i) { if (colDataIsNull_f(pInputCol->nullbitmap, i)) { colDataAppendNULL(pOutputCol, i); continue; } double value = 0; - GET_TYPED_DATA(value, double, inType, colDataGetData(pInputCol, i)); - colDataAppendDouble(pOutputCol, i, (double *)&value); + GET_TYPED_DATA(value, double, cCtx.inType, colDataGetData(pInputCol, i)); + colDataAppendDouble(pOutputCol, i, (double*)&value); } break; } case TSDB_DATA_TYPE_BINARY: case TSDB_DATA_TYPE_NCHAR: { - return vectorConvertToVarData(pIn, pOut, inType, outType); + return vectorConvertToVarData(&cCtx); } default: - sclError("invalid convert output type:%d", outType); + sclError("invalid convert output type:%d", cCtx.outType); return TSDB_CODE_QRY_APP_ERROR; } @@ -894,7 +894,7 @@ int32_t vectorGetConvertType(int32_t type1, int32_t type2) { return gConvertTypes[type2][type1]; } -int32_t vectorConvertScalarParam(SScalarParam *input, SScalarParam *output, int32_t type) { +int32_t vectorConvertSingleCol(SScalarParam *input, SScalarParam *output, int32_t type, int32_t startIndex, int32_t numOfRows) { SDataType t = {.type = type, .bytes = tDataTypes[type].bytes}; output->numOfRows = input->numOfRows; @@ -903,17 +903,16 @@ int32_t vectorConvertScalarParam(SScalarParam *input, SScalarParam *output, int3 return TSDB_CODE_OUT_OF_MEMORY; } - code = vectorConvertImpl(input, output, NULL); + code = vectorConvertSingleColImpl(input, output, NULL, startIndex, numOfRows); if (code) { - // taosMemoryFreeClear(paramOut1->data); return code; } return TSDB_CODE_SUCCESS; } -int32_t vectorConvert(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pLeftOut, SScalarParam *pRightOut) { - int32_t leftType = GET_PARAM_TYPE(pLeft); +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; @@ -941,14 +940,14 @@ int32_t vectorConvert(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *p } if (type != GET_PARAM_TYPE(param1)) { - code = vectorConvertScalarParam(param1, paramOut1, type); + code = vectorConvertSingleCol(param1, paramOut1, type, startIndex, numOfRows); if (code) { return code; } } if (type != GET_PARAM_TYPE(param2)) { - code = vectorConvertScalarParam(param2, paramOut2, type); + code = vectorConvertSingleCol(param2, paramOut2, type, startIndex, numOfRows); if (code) { return code; } @@ -962,31 +961,6 @@ enum { VECTOR_UN_CONVERT = 0x2, }; -static int32_t doConvertHelper(SScalarParam *pDest, int32_t *convert, const SScalarParam *pParam, int32_t type) { - SColumnInfoData *pCol = pParam->columnData; - - if (IS_VAR_DATA_TYPE(pCol->info.type) && pCol->info.type != TSDB_DATA_TYPE_JSON) { - pDest->numOfRows = pParam->numOfRows; - - SDataType t = {.type = type, .bytes = tDataTypes[type].bytes}; - int32_t code = sclCreateColumnInfoData(&t, pParam->numOfRows, pDest); - if (code != TSDB_CODE_SUCCESS) { - return code; - } - - code = vectorConvertImpl(pParam, pDest, NULL); - if (code != TSDB_CODE_SUCCESS) { - return code; - } - - *convert = VECTOR_DO_CONVERT; - } else { - *convert = VECTOR_UN_CONVERT; - } - - return TSDB_CODE_SUCCESS; -} - // 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) { @@ -1030,20 +1004,25 @@ static void vectorMathTsAddHelper(SColumnInfoData *pLeftCol, SColumnInfoData *pR } } -static SColumnInfoData *doVectorConvert(SScalarParam *pInput, int32_t *doConvert) { - SScalarParam convertParam = {0}; +static SColumnInfoData* vectorConvertVarToDouble(SScalarParam* pInput, int32_t* converted) { + SScalarParam output = {0}; + SColumnInfoData* pCol = pInput->columnData; - int32_t code = doConvertHelper(&convertParam, doConvert, pInput, TSDB_DATA_TYPE_DOUBLE); - if (code != TSDB_CODE_SUCCESS) { - terrno = code; - return NULL; + 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; } - if (*doConvert == VECTOR_DO_CONVERT) { - return convertParam.columnData; - } else { - return pInput->columnData; - } + *converted = VECTOR_UN_CONVERT; + + return pInput->columnData; } static void doReleaseVec(SColumnInfoData *pCol, int32_t type) { @@ -1061,9 +1040,9 @@ void vectorMathAdd(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pOut pOut->numOfRows = TMAX(pLeft->numOfRows, pRight->numOfRows); - int32_t leftConvert = 0, rightConvert = 0; - SColumnInfoData *pLeftCol = doVectorConvert(pLeft, &leftConvert); - SColumnInfoData *pRightCol = doVectorConvert(pRight, &rightConvert); + 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))) || @@ -1168,9 +1147,9 @@ void vectorMathSub(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pOut 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 = doVectorConvert(pLeft, &leftConvert); - SColumnInfoData *pRightCol = doVectorConvert(pRight, &rightConvert); + 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 && @@ -1246,9 +1225,9 @@ void vectorMathMultiply(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam 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 = doVectorConvert(pLeft, &leftConvert); - SColumnInfoData *pRightCol = doVectorConvert(pRight, &rightConvert); + 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); @@ -1279,9 +1258,9 @@ void vectorMathDivide(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *p 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 = doVectorConvert(pLeft, &leftConvert); - SColumnInfoData *pRightCol = doVectorConvert(pRight, &rightConvert); + 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); @@ -1333,9 +1312,9 @@ void vectorMathRemainder(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam 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 = doVectorConvert(pLeft, &leftConvert); - SColumnInfoData *pRightCol = doVectorConvert(pRight, &rightConvert); + 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); @@ -1412,8 +1391,8 @@ void vectorMathMinus(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pO 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 = doVectorConvert(pLeft, &leftConvert); + int32_t leftConvert = 0; + SColumnInfoData *pLeftCol = vectorConvertVarToDouble(pLeft, &leftConvert); _getDoubleValue_fn_t getVectorDoubleValueFnLeft = getVectorDoubleValueFn(pLeftCol->info.type); @@ -1525,9 +1504,9 @@ void vectorBitAnd(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pOut, 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 = doVectorConvert(pLeft, &leftConvert); - SColumnInfoData *pRightCol = doVectorConvert(pRight, &rightConvert); + 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); @@ -1579,9 +1558,9 @@ void vectorBitOr(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pOut, 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 = doVectorConvert(pLeft, &leftConvert); - SColumnInfoData *pRightCol = doVectorConvert(pRight, &rightConvert); + 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); @@ -1605,8 +1584,8 @@ void vectorBitOr(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pOut, doReleaseVec(pRightCol, rightConvert); } -int32_t doVectorCompareImpl(int32_t numOfRows, SScalarParam *pOut, int32_t startIndex, int32_t step, __compar_fn_t fp, - SScalarParam *pLeft, SScalarParam *pRight, int32_t optr) { +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; for (int32_t i = startIndex; i < numOfRows && i >= 0; i += step) { @@ -1659,20 +1638,29 @@ int32_t doVectorCompareImpl(int32_t numOfRows, SScalarParam *pOut, int32_t start return num; } -void vectorCompareImpl(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pOut, int32_t _ord, int32_t optr) { - int32_t i = ((_ord) == TSDB_ORDER_ASC) ? 0 : TMAX(pLeft->numOfRows, pRight->numOfRows) - 1; +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); } - pOut->numOfRows = TMAX(pLeft->numOfRows, pRight->numOfRows); + 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) { @@ -1690,13 +1678,14 @@ void vectorCompareImpl(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam * } } } else { // normal compare - pOut->numOfQualified = doVectorCompareImpl(pOut->numOfRows, pOut, i, step, fp, pLeft, pRight, optr); + pOut->numOfQualified = doVectorCompareImpl(pLeft, pRight, pOut, i, compRows, step, fp, optr); } } -void vectorCompare(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pOut, int32_t _ord, int32_t optr) { - SScalarParam pLeftOut = {0}; - SScalarParam pRightOut = {0}; +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; @@ -1704,7 +1693,7 @@ void vectorCompare(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pOut param1 = pLeft; param2 = pRight; } else { - vectorConvert(pLeft, pRight, &pLeftOut, &pRightOut); + vectorConvertCols(pLeft, pRight, &pLeftOut, &pRightOut, startIndex, numOfRows); if (pLeftOut.columnData != NULL) { param1 = &pLeftOut; @@ -1719,12 +1708,17 @@ void vectorCompare(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pOut } } - vectorCompareImpl(param1, param2, pOut, _ord, optr); + doVectorCompare(param1, param2, pOut, startIndex, numOfRows, _ord, optr); + sclFreeParam(&pLeftOut); sclFreeParam(&pRightOut); } -void vectorGreater(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pOut, int32_t _ord) { +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); } @@ -1788,10 +1782,10 @@ void vectorNotNull(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pOut pOut->numOfRows = pLeft->numOfRows; } -void vectorIsTrue(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pOut, int32_t _ord) { - vectorConvertImpl(pLeft, pOut, NULL); - for (int32_t i = 0; i < pOut->numOfRows; ++i) { - if (colDataIsNull_s(pOut->columnData, i)) { +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; colDataAppendInt8(pOut->columnData, i, &v); colDataSetNotNull_f(pOut->columnData->nullbitmap, i); diff --git a/tests/script/jenkins/basic.txt b/tests/script/jenkins/basic.txt index 82f73a4fdd..89e26e785b 100644 --- a/tests/script/jenkins/basic.txt +++ b/tests/script/jenkins/basic.txt @@ -352,6 +352,7 @@ ./test.sh -f tsim/scalar/in.sim ./test.sh -f tsim/scalar/scalar.sim ./test.sh -f tsim/scalar/filter.sim +./test.sh -f tsim/scalar/caseWhen.sim # ---- alter ---- ./test.sh -f tsim/alter/cached_schema_after_alter.sim diff --git a/tests/script/tsim/scalar/caseWhen.sim b/tests/script/tsim/scalar/caseWhen.sim new file mode 100644 index 0000000000..f6b9c3ff08 --- /dev/null +++ b/tests/script/tsim/scalar/caseWhen.sim @@ -0,0 +1,1064 @@ +system sh/stop_dnodes.sh +system sh/deploy.sh -n dnode1 -i 1 +system sh/exec.sh -n dnode1 -s start +sql connect + +print ======== prepare data + +sql drop database if exists db1; +sql create database db1 vgroups 5; +sql use db1; +sql create stable sta (ts timestamp, f1 int, f2 binary(10), f3 bool) tags(t1 int, t2 bool, t3 binary(10)); +sql create table tba1 using sta tags(0, false, '0'); +sql create table tba2 using sta tags(1, true, '1'); +sql create table tba3 using sta tags(null, null, ''); +sql create table tba4 using sta tags(1, false, null); +sql create table tba5 using sta tags(3, true, 'aa'); +sql insert into tba1 values ('2022-09-26 15:15:01', 0, "a", false); +sql insert into tba1 values ('2022-09-26 15:15:02', 1, "0", true); +sql insert into tba1 values ('2022-09-26 15:15:03', 5, "5", false); +sql insert into tba1 values ('2022-09-26 15:15:04', null, null, null); +sql insert into tba2 values ('2022-09-27 15:15:01', 0, "a", false); +sql insert into tba2 values ('2022-09-27 15:15:02', 1, "0", true); +sql insert into tba2 values ('2022-09-27 15:15:03', 5, "5", false); +sql insert into tba2 values ('2022-09-27 15:15:04', null, null, null); +sql insert into tba3 values ('2022-09-28 15:15:01', 0, "a", false); +sql insert into tba3 values ('2022-09-28 15:15:02', 1, "0", true); +sql insert into tba3 values ('2022-09-28 15:15:03', 5, "5", false); +sql insert into tba3 values ('2022-09-28 15:15:04', null, null, null); +sql insert into tba4 values ('2022-09-29 15:15:01', 0, "a", false); +sql insert into tba4 values ('2022-09-29 15:15:02', 1, "0", true); +sql insert into tba4 values ('2022-09-29 15:15:03', 5, "5", false); +sql insert into tba4 values ('2022-09-29 15:15:04', null, null, null); +sql insert into tba5 values ('2022-09-30 15:15:01', 0, "a", false); +sql insert into tba5 values ('2022-09-30 15:15:02', 1, "0", true); +sql insert into tba5 values ('2022-09-30 15:15:03', 5, "5", false); +sql insert into tba5 values ('2022-09-30 15:15:04', null, null, null); + +print ======== case when xx + +sql select case when 3 then 4 end from tba1; +if $rows != 4 then + return -1 +endi +if $data00 != 4 then + return -1 +endi +if $data10 != 4 then + return -1 +endi +if $data20 != 4 then + return -1 +endi +if $data30 != 4 then + return -1 +endi + +sql select case when 0 then 4 end from tba1; +if $rows != 4 then + return -1 +endi +if $data00 != NULL then + return -1 +endi +if $data10 != NULL then + return -1 +endi +if $data20 != NULL then + return -1 +endi +if $data30 != NULL then + return -1 +endi + +sql select case when null then 4 end from tba1; +if $rows != 4 then + return -1 +endi +if $data00 != NULL then + return -1 +endi +if $data10 != NULL then + return -1 +endi +if $data20 != NULL then + return -1 +endi +if $data30 != NULL then + return -1 +endi + +sql select case when 1 then 4+1 end from tba1; +if $rows != 4 then + return -1 +endi +if $data00 != 5.000000000 then + return -1 +endi +if $data10 != 5.000000000 then + return -1 +endi +if $data20 != 5.000000000 then + return -1 +endi +if $data30 != 5.000000000 then + return -1 +endi + +sql select case when 1-1 then 0 end from tba1; +if $rows != 4 then + return -1 +endi +if $data00 != NULL then + return -1 +endi +if $data10 != NULL then + return -1 +endi +if $data20 != NULL then + return -1 +endi +if $data30 != NULL then + return -1 +endi + +sql select case when 1+1 then 0 end from tba1; +if $rows != 4 then + return -1 +endi +if $data00 != 0 then + return -1 +endi +if $data10 != 0 then + return -1 +endi +if $data20 != 0 then + return -1 +endi +if $data30 != 0 then + return -1 +endi + +sql select case when 1 then 1-1+2 end from tba1; +if $rows != 4 then + return -1 +endi +if $data00 != 2.000000000 then + return -1 +endi +if $data10 != 2.000000000 then + return -1 +endi +if $data20 != 2.000000000 then + return -1 +endi +if $data30 != 2.000000000 then + return -1 +endi + +sql select case when 1 > 0 then 1 < 2 end from tba1; +if $rows != 4 then + return -1 +endi +if $data00 != 1 then + return -1 +endi +if $data10 != 1 then + return -1 +endi +if $data20 != 1 then + return -1 +endi +if $data30 != 1 then + return -1 +endi + +sql select case when 1 > 2 then 1 < 2 end from tba1; +if $rows != 4 then + return -1 +endi +if $data00 != NULL then + return -1 +endi +if $data10 != NULL then + return -1 +endi +if $data20 != NULL then + return -1 +endi +if $data30 != NULL then + return -1 +endi + +sql select case when abs(3) then abs(-1) end from tba1; +if $rows != 4 then + return -1 +endi +if $data00 != 1 then + return -1 +endi +if $data10 != 1 then + return -1 +endi +if $data20 != 1 then + return -1 +endi +if $data30 != 1 then + return -1 +endi + +sql select case when abs(1+1) then abs(-1)+abs(3) end from tba1; +if $rows != 4 then + return -1 +endi +if $data00 != 4.000000000 then + return -1 +endi +if $data10 != 4.000000000 then + return -1 +endi +if $data20 != 4.000000000 then + return -1 +endi +if $data30 != 4.000000000 then + return -1 +endi + +sql select case when 0 then 1 else 3 end from tba1; +if $rows != 4 then + return -1 +endi +if $data00 != 3 then + return -1 +endi +if $data10 != 3 then + return -1 +endi +if $data20 != 3 then + return -1 +endi +if $data30 != 3 then + return -1 +endi + +sql select case when 0 then 1 when 1 then 0 else 3 end from tba1; +if $rows != 4 then + return -1 +endi +if $data00 != 0 then + return -1 +endi +if $data10 != 0 then + return -1 +endi +if $data20 != 0 then + return -1 +endi +if $data30 != 0 then + return -1 +endi + +sql select case when 0 then 1 when 1 then 0 when 2 then 3 end from tba1; +if $rows != 4 then + return -1 +endi +if $data00 != 0 then + return -1 +endi +if $data10 != 0 then + return -1 +endi +if $data20 != 0 then + return -1 +endi +if $data30 != 0 then + return -1 +endi + +sql select case when 'a' then 'b' when null then 0 end from tba1; +if $rows != 4 then + return -1 +endi +if $data00 != NULL then + return -1 +endi +if $data10 != NULL then + return -1 +endi +if $data20 != NULL then + return -1 +endi +if $data30 != NULL then + return -1 +endi + +sql select case when '2' then 'b' when null then 0 end from tba1; +if $rows != 4 then + return -1 +endi +if $data00 != b then + return -1 +endi +if $data10 != b then + return -1 +endi +if $data20 != b then + return -1 +endi +if $data30 != b then + return -1 +endi + +sql select case when 0 then 'b' else null end from tba1; +if $rows != 4 then + return -1 +endi +if $data00 != NULL then + return -1 +endi +if $data10 != NULL then + return -1 +endi +if $data20 != NULL then + return -1 +endi +if $data30 != NULL then + return -1 +endi + +sql select case when 0 then 'b' else 2 end from tba1; +if $rows != 4 then + return -1 +endi +if $data00 != 2 then + return -1 +endi +if $data10 != 2 then + return -1 +endi +if $data20 != 2 then + return -1 +endi +if $data30 != 2 then + return -1 +endi + +sql select case when sum(2) then sum(2)-sum(1) end from tba1; +if $rows != 1 then + return -1 +endi +if $data00 != 4.000000000 then + return -1 +endi + +sql select case when sum(2) then abs(-2) end from tba1; +if $rows != 1 then + return -1 +endi +if $data00 != 2 then + return -1 +endi + +sql select case when ts then ts end from tba1; +if $rows != 4 then + return -1 +endi +if $data00 != @22-09-26 15:15:01.000@ then + return -1 +endi +if $data10 != @22-09-26 15:15:02.000@ then + return -1 +endi +if $data20 != @22-09-26 15:15:03.000@ then + return -1 +endi +if $data30 != @22-09-26 15:15:04.000@ then + return -1 +endi + +sql select case when f1 then ts end from tba1; +if $rows != 4 then + return -1 +endi +if $data00 != NULL then + return -1 +endi +if $data10 != @22-09-26 15:15:02.000@ then + return -1 +endi +if $data20 != @22-09-26 15:15:03.000@ then + return -1 +endi +if $data30 != NULL then + return -1 +endi + +sql select case when f1 then f1 when f1 + 1 then f1 + 1 else f1 is null end from tba1; +if $rows != 4 then + return -1 +endi +if $data00 != 1 then + return -1 +endi +if $data10 != 1 then + return -1 +endi +if $data20 != 5 then + return -1 +endi +if $data30 != 1 then + return -1 +endi + +sql select case when f1 then 3 when ts then ts end from tba1; +if $rows != 4 then + return -1 +endi +if $data00 != 1664176501000 then + return -1 +endi +if $data10 != 3 then + return -1 +endi +if $data20 != 3 then + return -1 +endi +if $data30 != 1664176504000 then + return -1 +endi + +sql select case when 3 then f1 end from tba1; +if $rows != 4 then + return -1 +endi +if $data00 != 0 then + return -1 +endi +if $data10 != 1 then + return -1 +endi +if $data20 != 5 then + return -1 +endi +if $data30 != NULL then + return -1 +endi + +sql select case when f1 then 3 when 1 then 2 end from tba1; +if $rows != 4 then + return -1 +endi +if $data00 != 2 then + return -1 +endi +if $data10 != 3 then + return -1 +endi +if $data20 != 3 then + return -1 +endi +if $data30 != 2 then + return -1 +endi + +sql select case when sum(f1) then sum(f1)-abs(-1) end from tba1; +if $rows != 1 then + return -1 +endi +if $data00 != 5.000000000 then + return -1 +endi + +sql select case when sum(f1) then sum(f1)-abs(f1) end from tba1 group by f1 order by f1; +if $rows != 4 then + return -1 +endi +if $data00 != NULL then + return -1 +endi +if $data10 != NULL then + return -1 +endi +if $data20 != 0.000000000 then + return -1 +endi +if $data30 != 0.000000000 then + return -1 +endi + +sql select case when f1 then sum(f1) when f1 is not null then 9 else 8 end from tba1 group by f1 order by f1; +if $rows != 4 then + return -1 +endi +if $data00 != 8 then + return -1 +endi +if $data10 != 9 then + return -1 +endi +if $data20 != 1 then + return -1 +endi +if $data30 != 5 then + return -1 +endi + +sql select f1 from tba1 where f1 > case when f1 then 0 else 3 end; +if $rows != 2 then + return -1 +endi +if $data00 != 1 then + return -1 +endi +if $data10 != 5 then + return -1 +endi + +sql select f1 from tba1 where ts > case when ts then ts end; +if $rows != 0 then + return -1 +endi + +sql select sum(f1),count(f1) from tba1 partition by case when f1 then f1 when 1 then 1 end; +if $rows != 2 then + return -1 +endi +if $data00 != 1 then + return -1 +endi +if $data01 != 2 then + return -1 +endi +if $data10 != 5 then + return -1 +endi +if $data11 != 1 then + return -1 +endi + +sql select case when f1 < 3 then 1 when f1 >= 3 then 2 else 3 end caseWhen, sum(f1),count(f1) from tba1 group by case when f1 < 3 then 1 when f1 >= 3 then 2 else 3 end order by caseWhen; +if $rows != 3 then + return -1 +endi +if $data00 != 1 then + return -1 +endi +if $data01 != 1 then + return -1 +endi +if $data02 != 2 then + return -1 +endi +if $data10 != 2 then + return -1 +endi +if $data11 != 5 then + return -1 +endi +if $data12 != 1 then + return -1 +endi +if $data20 != 3 then + return -1 +endi +if $data21 != NULL then + return -1 +endi +if $data22 != 0 then + return -1 +endi + +sql select f1 from tba1 order by case when f1 <= 0 then 3 when f1 = 1 then 4 when f1 >= 3 then 2 else 1 end desc; +if $rows != 4 then + return -1 +endi +if $data00 != 1 then + return -1 +endi +if $data10 != 0 then + return -1 +endi +if $data20 != 5 then + return -1 +endi +if $data30 != NULL then + return -1 +endi + +sql select cast(case f1 when f1 then f1 + 1 else f1 is null end as double) from tba1; +if $rows != 4 then + return -1 +endi +if $data00 != 1.000000000 then + return -1 +endi +if $data10 != 2.000000000 then + return -1 +endi +if $data20 != 6.000000000 then + return -1 +endi +if $data30 != 1.000000000 then + return -1 +endi + +sql select sum(case f1 when f1 then f1 + 1 else f1 is null end + 1) from tba1; +if $rows != 1 then + return -1 +endi +if $data00 != 14.000000000 then + return -1 +endi + +sql select case when f1 < 3 then 1 when f1 >= 3 then 2 else 3 end,sum(f1),count(f1) from tba1 state_window(case when f1 < 3 then 1 when f1 >= 3 then 2 else 3 end); +if $rows != 3 then + return -1 +endi +if $data00 != 1 then + return -1 +endi +if $data01 != 1 then + return -1 +endi +if $data02 != 2 then + return -1 +endi +if $data10 != 2 then + return -1 +endi +if $data11 != 5 then + return -1 +endi +if $data12 != 1 then + return -1 +endi +if $data20 != 3 then + return -1 +endi +if $data21 != NULL then + return -1 +endi +if $data22 != 0 then + return -1 +endi + +sql select f1 from tba1 where case when case when f1 <= 0 then 3 when f1 = 1 then 4 when f1 >= 3 then 2 else 1 end > 2 then 1 else 0 end > 0; +if $rows != 2 then + return -1 +endi +if $data00 != 0 then + return -1 +endi +if $data10 != 1 then + return -1 +endi + +sql select case when f1 is not null then case when f1 <= 0 then f1 else f1 * 10 end else -1 end from tba1; +if $rows != 4 then + return -1 +endi +if $data00 != 0 then + return -1 +endi +if $data10 != 10 then + return -1 +endi +if $data20 != 50 then + return -1 +endi +if $data30 != -1 then + return -1 +endi + + +print ======== case xx when xx + +sql select case 3 when 3 then 4 end from tba1; +if $rows != 4 then + return -1 +endi +if $data00 != 4 then + return -1 +endi +if $data10 != 4 then + return -1 +endi +if $data20 != 4 then + return -1 +endi +if $data30 != 4 then + return -1 +endi + +sql select case 3 when 1 then 4 end from tba1; +if $rows != 4 then + return -1 +endi +if $data00 != NULL then + return -1 +endi +if $data10 != NULL then + return -1 +endi +if $data20 != NULL then + return -1 +endi +if $data30 != NULL then + return -1 +endi + +sql select case 3 when 1 then 4 else 2 end from tba1; +if $rows != 4 then + return -1 +endi +if $data00 != 2 then + return -1 +endi +if $data10 != 2 then + return -1 +endi +if $data20 != 2 then + return -1 +endi +if $data30 != 2 then + return -1 +endi + +sql select case 3 when null then 4 when '3' then 1 end from tba1; +if $rows != 4 then + return -1 +endi +if $data00 != 1 then + return -1 +endi +if $data10 != 1 then + return -1 +endi +if $data20 != 1 then + return -1 +endi +if $data30 != 1 then + return -1 +endi + +sql select case '3' when null then 4 when 3 then 1 end from tba1; +if $rows != 4 then + return -1 +endi +if $data00 != 1 then + return -1 +endi +if $data10 != 1 then + return -1 +endi +if $data20 != 1 then + return -1 +endi +if $data30 != 1 then + return -1 +endi + +sql select case null when null then 4 when 3 then 1 end from tba1; +if $rows != 4 then + return -1 +endi +if $data00 != NULL then + return -1 +endi +if $data10 != NULL then + return -1 +endi +if $data20 != NULL then + return -1 +endi +if $data30 != NULL then + return -1 +endi + +sql select case 3.0 when null then 4 when '3' then 1 end from tba1; +if $rows != 4 then + return -1 +endi +if $data00 != 1 then + return -1 +endi +if $data10 != 1 then + return -1 +endi +if $data20 != 1 then + return -1 +endi +if $data30 != 1 then + return -1 +endi + +sql select case f2 when 'a' then 4 when '0' then 1 end from tba1; +if $rows != 4 then + return -1 +endi +if $data00 != 4 then + return -1 +endi +if $data10 != 1 then + return -1 +endi +if $data20 != NULL then + return -1 +endi +if $data30 != NULL then + return -1 +endi + +sql select case f2 when f1 then f1 when f1 - 1 then f1 else 99 end from tba1; +if $rows != 4 then + return -1 +endi +if $data00 != 0 then + return -1 +endi +if $data10 != 1 then + return -1 +endi +if $data20 != 5 then + return -1 +endi +if $data30 != 99 then + return -1 +endi + +sql select case cast(f2 as int) when 0 then f2 when f1 then 11 else ts end from tba1; +if $rows != 4 then + return -1 +endi +if $data00 != a then + return -1 +endi +if $data10 != 0 then + return -1 +endi +if $data20 != 11 then + return -1 +endi +if $data30 != 1664176504 then + return -1 +endi + +sql select case f1 + 1 when 1 then 1 when 2 then 2 else 3 end from tba1; +if $rows != 4 then + return -1 +endi +if $data00 != 1 then + return -1 +endi +if $data10 != 2 then + return -1 +endi +if $data20 != 3 then + return -1 +endi +if $data30 != 3 then + return -1 +endi + +sql select case f1 when sum(f1) then sum(f1)-abs(f1) end from tba1 group by f1 order by f1; +if $rows != 4 then + return -1 +endi +if $data00 != NULL then + return -1 +endi +if $data10 != 0.000000000 then + return -1 +endi +if $data20 != 0.000000000 then + return -1 +endi +if $data30 != 0.000000000 then + return -1 +endi + +sql select f1, case sum(f1) when 1 then f1 + 99 when f1 then f1 -99 else f1 end from tba1 group by f1 order by f1; +if $rows != 4 then + return -1 +endi +if $data00 != NULL then + return -1 +endi +if $data01 != NULL then + return -1 +endi +if $data10 != 0 then + return -1 +endi +if $data11 != -99.000000000 then + return -1 +endi +if $data20 != 1 then + return -1 +endi +if $data21 != 100.000000000 then + return -1 +endi +if $data30 != 5 then + return -1 +endi +if $data31 != -94.000000000 then + return -1 +endi + +sql select case when 3 then 4 end from sta; +if $rows != 20 then + return -1 +endi +sql select case when 0 then 4 end from sta; +if $rows != 20 then + return -1 +endi +sql select case when null then 4 end from sta; +if $rows != 20 then + return -1 +endi +sql select case when 1 then 4+1 end from sta; +if $rows != 20 then + return -1 +endi +sql select case when 1-1 then 0 end from sta; +if $rows != 20 then + return -1 +endi +sql select case when 1+1 then 0 end from sta; +if $rows != 20 then + return -1 +endi +sql select case when abs(3) then abs(-1) end from sta; +if $rows != 20 then + return -1 +endi +sql select case when abs(1+1) then abs(-1)+abs(3) end from sta; +if $rows != 20 then + return -1 +endi +sql select case when 0 then 1 else 3 end from sta; +if $rows != 20 then + return -1 +endi +sql select case when 0 then 1 when 1 then 0 else 3 end from sta; +if $rows != 20 then + return -1 +endi +sql select case when 0 then 1 when 1 then 0 when 2 then 3 end from sta; +if $rows != 20 then + return -1 +endi +sql select case when 'a' then 'b' when null then 0 end from sta; +if $rows != 20 then + return -1 +endi +sql select case when '2' then 'b' when null then 0 end from sta; +if $rows != 20 then + return -1 +endi +sql select case when 0 then 'b' else null end from sta; +if $rows != 20 then + return -1 +endi +sql select case when 0 then 'b' else 2+abs(-2) end from sta; +if $rows != 20 then + return -1 +endi +sql select case 3 when 3 then 4 end from sta; +if $rows != 20 then + return -1 +endi +sql select case 3 when 1 then 4 end from sta; +if $rows != 20 then + return -1 +endi +sql select case 3 when 1 then 4 else 2 end from sta; +if $rows != 20 then + return -1 +endi +sql select case 3 when null then 4 when '3' then 1 end from sta; +if $rows != 20 then + return -1 +endi +sql select case null when null then 4 when 3 then 1 end from sta; +if $rows != 20 then + return -1 +endi +sql select case 3.0 when null then 4 when '3' then 1 end from sta; +if $rows != 20 then + return -1 +endi +sql select f2,case f2 when 'a' then 4 when '0' then 1 end from sta order by f2; +if $rows != 20 then + return -1 +endi +sql select f2,f1,case f2 when f1 then f1 when f1 - 1 then f1 else 99 end from sta order by f2; +if $rows != 20 then + return -1 +endi +sql select case cast(f2 as int) when 0 then f2 when f1 then 11 else ts end from sta; +if $rows != 20 then + return -1 +endi +sql select f1, case f1 + 1 when 1 then 1 when 2 then 2 else 3 end from sta order by f1; +if $rows != 20 then + return -1 +endi +sql select case f1 when sum(f1) then sum(f1)-abs(f1) end from sta group by f1 order by f1; +if $rows != 4 then + return -1 +endi +if $data00 != NULL then + return -1 +endi +if $data10 != 0.000000000 then + return -1 +endi +if $data20 != NULL then + return -1 +endi +if $data30 != NULL then + return -1 +endi +sql select case sum(f1) when 1 then f1 + 99 when f1 then f1 -99 else f1 end from sta group by f1 order by f1; +if $rows != 4 then + return -1 +endi +if $data00 != NULL then + return -1 +endi +if $data10 != -99.000000000 then + return -1 +endi +if $data20 != 1.000000000 then + return -1 +endi +if $data30 != 5.000000000 then + return -1 +endi + +sql select distinct tbname, case t1 when t2 then t1 else t1 + 100 end from sta order by tbname; +if $rows != 5 then + return -1 +endi +if $data01 != 0 then + return -1 +endi +if $data11 != 1 then + return -1 +endi +if $data21 != NULL then + return -1 +endi +if $data31 != 101 then + return -1 +endi +if $data41 != 103 then + return -1 +endi + +sql_error select case when sum(f1) then sum(f1)-abs(f1) end from tba1; + +system sh/exec.sh -n dnode1 -s stop -x SIGINT