cols: use aggfunc
This commit is contained in:
parent
26fb867d4c
commit
c4cc51b583
|
@ -276,14 +276,14 @@ typedef struct tExprNode {
|
|||
int32_t num;
|
||||
struct SFunctionNode *pFunctNode;
|
||||
int32_t functionType;
|
||||
int32_t bindTupleFuncIdx;
|
||||
int32_t bindExprID;
|
||||
} _function;
|
||||
|
||||
struct {
|
||||
struct SNode *pRootNode;
|
||||
} _optrRoot;
|
||||
};
|
||||
int32_t tupleFuncIdx;
|
||||
int32_t relatedTo;
|
||||
} tExprNode;
|
||||
|
||||
struct SScalarParam {
|
||||
|
|
|
@ -62,8 +62,8 @@ typedef struct SExprNode {
|
|||
bool asParam;
|
||||
bool asPosition;
|
||||
int32_t projIdx;
|
||||
int32_t bindTupleFuncIdx;
|
||||
int32_t tupleFuncIdx;
|
||||
int32_t relatedTo;
|
||||
int32_t bindExprID;
|
||||
} SExprNode;
|
||||
|
||||
typedef enum EColumnType {
|
||||
|
@ -701,6 +701,7 @@ char* getFullJoinTypeString(EJoinType type, EJoinSubType stype);
|
|||
int32_t mergeJoinConds(SNode** ppDst, SNode** ppSrc);
|
||||
|
||||
int32_t rewriteExprAliasName(SExprNode* pNode, int64_t num);
|
||||
bool isRelatedToOtherExpr(SExprNode* pExpr);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -397,7 +397,7 @@ static int32_t createDataBlockForEmptyInput(SOperatorInfo* pOperator, SSDataBloc
|
|||
|
||||
// if the last expression is a tuple function, we don't need to create a empty data block
|
||||
int32_t lastExprIndex = pOperator->exprSupp.numOfExprs - 1;
|
||||
if(pOperator->exprSupp.pExprInfo[lastExprIndex].pExpr->tupleFuncIdx > 0) {
|
||||
if(pOperator->exprSupp.pExprInfo[lastExprIndex].pExpr->_function.bindExprID > 0) {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
@ -1992,10 +1992,10 @@ int32_t createExprFromOneNode(SExprInfo* pExp, SNode* pNode, int16_t slotId) {
|
|||
code = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
|
||||
QUERY_CHECK_CODE(code, lino, _end);
|
||||
}
|
||||
if(type == QUERY_NODE_FUNCTION) {
|
||||
pExp->pExpr->_function.bindTupleFuncIdx = ((SExprNode*)pNode)->bindTupleFuncIdx;
|
||||
if (type == QUERY_NODE_FUNCTION) {
|
||||
pExp->pExpr->_function.bindExprID = ((SExprNode*)pNode)->bindExprID;
|
||||
}
|
||||
pExp->pExpr->tupleFuncIdx = ((SExprNode*)pNode)->tupleFuncIdx;
|
||||
pExp->pExpr->relatedTo = ((SExprNode*)pNode)->relatedTo;
|
||||
_end:
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
|
||||
|
@ -2091,7 +2091,7 @@ static int32_t setSelectValueColumnInfo(SqlFunctionCtx* pCtx, int32_t numOfOutpu
|
|||
|
||||
SArray* pValCtxArray = NULL;
|
||||
for (int32_t i = numOfOutput - 1; i > 0; --i) { // select Func is at the end of the list
|
||||
int32_t funcIdx = pCtx[i].pExpr->pExpr->tupleFuncIdx;
|
||||
int32_t funcIdx = pCtx[i].pExpr->pExpr->_function.bindExprID;
|
||||
if (funcIdx > 0) {
|
||||
if (pValCtxArray == NULL) {
|
||||
// the end of the list is the select function of biggest index
|
||||
|
@ -2134,7 +2134,7 @@ static int32_t setSelectValueColumnInfo(SqlFunctionCtx* pCtx, int32_t numOfOutpu
|
|||
if (pValCtxArray == NULL) {
|
||||
pValCtx[num++] = &pCtx[i];
|
||||
} else {
|
||||
int32_t bindFuncIndex = pCtx[i].pExpr->pExpr->_function.bindTupleFuncIdx; // start from index 1;
|
||||
int32_t bindFuncIndex = pCtx[i].pExpr->pExpr->relatedTo; // start from index 1;
|
||||
if (bindFuncIndex > 0) { // 0 is default index related to the select function
|
||||
bindFuncIndex -= 1;
|
||||
}
|
||||
|
|
|
@ -443,8 +443,8 @@ int32_t createFunctionWithSrcFunc(const char* pName, const SFunctionNode* pSrcFu
|
|||
return code;
|
||||
}
|
||||
resetOutputChangedFunc(*ppFunc, pSrcFunc);
|
||||
(*ppFunc)->node.bindTupleFuncIdx = pSrcFunc->node.bindTupleFuncIdx;
|
||||
(*ppFunc)->node.tupleFuncIdx = pSrcFunc->node.tupleFuncIdx;
|
||||
(*ppFunc)->node.relatedTo = pSrcFunc->node.relatedTo;
|
||||
(*ppFunc)->node.bindExprID = pSrcFunc->node.bindExprID;
|
||||
return code;
|
||||
}
|
||||
|
||||
|
|
|
@ -106,8 +106,8 @@ static int32_t exprNodeCopy(const SExprNode* pSrc, SExprNode* pDst) {
|
|||
COPY_SCALAR_FIELD(asParam);
|
||||
COPY_SCALAR_FIELD(asPosition);
|
||||
COPY_SCALAR_FIELD(projIdx);
|
||||
COPY_SCALAR_FIELD(bindTupleFuncIdx);
|
||||
COPY_SCALAR_FIELD(tupleFuncIdx);
|
||||
COPY_SCALAR_FIELD(relatedTo);
|
||||
COPY_SCALAR_FIELD(bindExprID);
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
@ -139,10 +139,10 @@ static bool functionNodeEqual(const SFunctionNode* a, const SFunctionNode* b) {
|
|||
COMPARE_STRING_FIELD(functionName);
|
||||
COMPARE_NODE_LIST_FIELD(pParameterList);
|
||||
if (a->funcType == FUNCTION_TYPE_SELECT_VALUE) {
|
||||
if ((a->node.bindTupleFuncIdx != b->node.bindTupleFuncIdx)) return false;
|
||||
if ((a->node.relatedTo != b->node.relatedTo)) return false;
|
||||
} else {
|
||||
// select cols(cols(first(c0), ts), first(c0) from meters;
|
||||
if ((a->node.tupleFuncIdx != b->node.tupleFuncIdx)) {
|
||||
if ((a->node.bindExprID != b->node.bindExprID)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -670,10 +670,10 @@ static int32_t exprNodeToMsg(const void* pObj, STlvEncoder* pEncoder) {
|
|||
const SExprNode* pNode = (const SExprNode*)pObj;
|
||||
int32_t code = tlvEncodeObj(pEncoder, EXPR_CODE_RES_TYPE, dataTypeToMsg, &pNode->resType);
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = tlvEncodeI32(pEncoder, EXPR_CODE_BIND_TUPLE_FUNC_IDX, pNode->bindTupleFuncIdx);
|
||||
code = tlvEncodeI32(pEncoder, EXPR_CODE_BIND_TUPLE_FUNC_IDX, pNode->relatedTo);
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = tlvEncodeI32(pEncoder, EXPR_CODE_TUPLE_FUNC_IDX, pNode->tupleFuncIdx);
|
||||
code = tlvEncodeI32(pEncoder, EXPR_CODE_TUPLE_FUNC_IDX, pNode->bindExprID);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
@ -689,10 +689,10 @@ static int32_t msgToExprNode(STlvDecoder* pDecoder, void* pObj) {
|
|||
code = tlvDecodeObjFromTlv(pTlv, msgToDataType, &pNode->resType);
|
||||
break;
|
||||
case EXPR_CODE_BIND_TUPLE_FUNC_IDX:
|
||||
code = tlvDecodeI32(pTlv, &pNode->bindTupleFuncIdx);
|
||||
code = tlvDecodeI32(pTlv, &pNode->relatedTo);
|
||||
break;
|
||||
case EXPR_CODE_TUPLE_FUNC_IDX:
|
||||
code = tlvDecodeI32(pTlv, &pNode->tupleFuncIdx);
|
||||
code = tlvDecodeI32(pTlv, &pNode->bindExprID);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -709,10 +709,10 @@ static int32_t columnNodeInlineToMsg(const void* pObj, STlvEncoder* pEncoder) {
|
|||
|
||||
int32_t code = dataTypeInlineToMsg(&pNode->node.resType, pEncoder);
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = tlvEncodeValueI32(pEncoder, pNode->node.bindTupleFuncIdx);
|
||||
code = tlvEncodeValueI32(pEncoder, pNode->node.relatedTo);
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = tlvEncodeValueI32(pEncoder, pNode->node.tupleFuncIdx);
|
||||
code = tlvEncodeValueI32(pEncoder, pNode->node.bindExprID);
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = tlvEncodeValueU64(pEncoder, pNode->tableId);
|
||||
|
@ -765,10 +765,10 @@ static int32_t msgToColumnNodeInline(STlvDecoder* pDecoder, void* pObj) {
|
|||
|
||||
int32_t code = msgToDataTypeInline(pDecoder, &pNode->node.resType);
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = tlvDecodeValueI32(pDecoder, &pNode->node.bindTupleFuncIdx);
|
||||
code = tlvDecodeValueI32(pDecoder, &pNode->node.relatedTo);
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = tlvDecodeValueI32(pDecoder, &pNode->node.tupleFuncIdx);
|
||||
code = tlvDecodeValueI32(pDecoder, &pNode->node.bindExprID);
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = tlvDecodeValueU64(pDecoder, &pNode->tableId);
|
||||
|
|
|
@ -3243,3 +3243,7 @@ int32_t nodesListDeduplicate(SNodeList** ppList) {
|
|||
int32_t rewriteExprAliasName(SExprNode* pNode, int64_t num) {
|
||||
return tsnprintf(pNode->aliasName, TSDB_COL_NAME_LEN, "expr_%ld", num);
|
||||
}
|
||||
|
||||
bool isRelatedToOtherExpr(SExprNode* pExpr) {
|
||||
return pExpr->relatedTo != 0;
|
||||
}
|
||||
|
|
|
@ -1105,11 +1105,11 @@ static bool isForecastPseudoColumnFunc(const SNode* pNode) {
|
|||
}
|
||||
|
||||
static bool isColsFunctionResult(const SNode* pNode) {
|
||||
return ((nodesIsExprNode(pNode)) && ((SExprNode*)pNode)->bindTupleFuncIdx > 0);
|
||||
return ((nodesIsExprNode(pNode)) && ((SExprNode*)pNode)->relatedTo > 0);
|
||||
}
|
||||
|
||||
static bool isInvalidColsBindFunction(const SFunctionNode* pFunc) {
|
||||
return (!fmIsSelectFunc(pFunc->funcId) && pFunc->node.tupleFuncIdx != 0);
|
||||
return (!fmIsSelectFunc(pFunc->funcId) && pFunc->node.bindExprID != 0);
|
||||
}
|
||||
|
||||
#ifdef BUILD_NO_CALL
|
||||
|
@ -3582,8 +3582,8 @@ static EDealRes rewriteColToSelectValFunc(STranslateContext* pCxt, SNode** pNode
|
|||
tstrncpy(pFunc->functionName, "_select_value", TSDB_FUNC_NAME_LEN);
|
||||
tstrncpy(pFunc->node.aliasName, ((SExprNode*)*pNode)->aliasName, TSDB_COL_NAME_LEN);
|
||||
tstrncpy(pFunc->node.userAlias, ((SExprNode*)*pNode)->userAlias, TSDB_COL_NAME_LEN);
|
||||
pFunc->node.bindTupleFuncIdx = ((SExprNode*)*pNode)->bindTupleFuncIdx;
|
||||
pFunc->node.tupleFuncIdx = ((SExprNode*)*pNode)->tupleFuncIdx;
|
||||
pFunc->node.relatedTo = ((SExprNode*)*pNode)->relatedTo;
|
||||
pFunc->node.bindExprID = ((SExprNode*)*pNode)->bindExprID;
|
||||
pCxt->errCode = nodesListMakeAppend(&pFunc->pParameterList, *pNode);
|
||||
if (TSDB_CODE_SUCCESS == pCxt->errCode) {
|
||||
pCxt->errCode = getFuncInfo(pCxt, pFunc);
|
||||
|
@ -3894,7 +3894,7 @@ static EDealRes doCheckExprForGroupBy(SNode** pNode, void* pContext) {
|
|||
|
||||
if (isScanPseudoColumnFunc(*pNode) || QUERY_NODE_COLUMN == nodeType(*pNode)) {
|
||||
if ((pSelect->selectFuncNum > 1 || (isDistinctOrderBy(pCxt) && pCxt->currClause == SQL_CLAUSE_ORDER_BY)) &&
|
||||
((SExprNode*)*pNode)->bindTupleFuncIdx == 0) {
|
||||
!isRelatedToOtherExpr((SExprNode*)*pNode)) {
|
||||
return generateDealNodeErrMsg(pCxt, getGroupByErrorCode(pCxt), ((SExprNode*)(*pNode))->userAlias);
|
||||
}
|
||||
if (isWindowJoinStmt(pSelect) &&
|
||||
|
@ -3903,7 +3903,7 @@ static EDealRes doCheckExprForGroupBy(SNode** pNode, void* pContext) {
|
|||
return rewriteExprToGroupKeyFunc(pCxt, pNode);
|
||||
}
|
||||
|
||||
if ((pSelect->hasOtherVectorFunc || !pSelect->hasSelectFunc) && ((SExprNode*)*pNode)->bindTupleFuncIdx == 0) {
|
||||
if ((pSelect->hasOtherVectorFunc || !pSelect->hasSelectFunc) && !isRelatedToOtherExpr((SExprNode*)*pNode)) {
|
||||
return generateDealNodeErrMsg(pCxt, getGroupByErrorCode(pCxt), ((SExprNode*)(*pNode))->userAlias);
|
||||
}
|
||||
|
||||
|
@ -3983,7 +3983,7 @@ static EDealRes doCheckAggColCoexist(SNode** pNode, void* pContext) {
|
|||
return rewriteExprToSelectTagFunc(pCxt->pTranslateCxt, pNode);
|
||||
}
|
||||
if ((isScanPseudoColumnFunc(*pNode) || QUERY_NODE_COLUMN == nodeType(*pNode)) &&
|
||||
((!nodesIsExprNode(*pNode) || ((SExprNode*)*pNode)->bindTupleFuncIdx == 0))) {
|
||||
((!nodesIsExprNode(*pNode) || !isRelatedToOtherExpr((SExprNode*)*pNode)))) {
|
||||
pCxt->existCol = true;
|
||||
}
|
||||
return DEAL_RES_CONTINUE;
|
||||
|
@ -5466,16 +5466,18 @@ static int32_t prepareColumnExpansion(STranslateContext* pCxt, ESqlClause clause
|
|||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
if (clause == SQL_CLAUSE_SELECT) {
|
||||
code = rewriteColsFunction(pCxt, &pSelect->pProjectionList, &pSelect->pProjectionBindList);
|
||||
code = translateExprList(pCxt, pSelect->pProjectionBindList);
|
||||
} else if (clause == SQL_CLAUSE_ORDER_BY) {
|
||||
code = rewriteColsFunction(pCxt, &pSelect->pOrderByList, &pSelect->pProjectionBindList);
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = translateExprList(pCxt, pSelect->pProjectionBindList);
|
||||
}
|
||||
} else {
|
||||
code =
|
||||
generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_WRONG_VALUE_TYPE, "Invalid clause for column expansion");
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = translateExprList(pCxt, pSelect->pProjectionBindList);
|
||||
}
|
||||
if (pSelect->pProjectionBindList != NULL) {
|
||||
pSelect->hasAggFuncs = true;
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
|
@ -7391,19 +7393,19 @@ static bool isMultiColsFuncNode(SNode* pNode) {
|
|||
}
|
||||
|
||||
typedef struct SBindTupleFuncCxt {
|
||||
int32_t bindTupleFuncIdx;
|
||||
int32_t bindExprID;
|
||||
} SBindTupleFuncCxt;
|
||||
|
||||
static EDealRes pushDownBindSelectFunc(SNode** pNode, void* pContext) {
|
||||
SBindTupleFuncCxt* pCxt = pContext;
|
||||
if (nodesIsExprNode(*pNode)) {
|
||||
((SExprNode*)*pNode)->bindTupleFuncIdx = pCxt->bindTupleFuncIdx;
|
||||
((SExprNode*)*pNode)->relatedTo = pCxt->bindExprID;
|
||||
int32_t len = strlen(((SExprNode*)*pNode)->aliasName);
|
||||
if (len + TSDB_COL_NAME_EXLEN >= TSDB_COL_NAME_LEN) {
|
||||
parserError("%s The alias name is too long, the extra part will be truncated", __func__);
|
||||
return DEAL_RES_ERROR;
|
||||
} else {
|
||||
tsnprintf(((SExprNode*)*pNode)->aliasName + len, TSDB_COL_NAME_EXLEN, ".%d", pCxt->bindTupleFuncIdx);
|
||||
tsnprintf(((SExprNode*)*pNode)->aliasName + len, TSDB_COL_NAME_EXLEN, ".%d", pCxt->bindExprID);
|
||||
}
|
||||
SFunctionNode* pFunc = (SFunctionNode*)*pNode;
|
||||
}
|
||||
|
@ -7512,7 +7514,7 @@ static EDealRes rewriteSingleColsFunc(SNode** pNode, void* pContext) {
|
|||
selectFuncIndex = selectFuncCount;
|
||||
SNode* pNewNode = NULL;
|
||||
code = nodesCloneNode(pSelectFunc, &pNewNode);
|
||||
((SExprNode*)pNewNode)->tupleFuncIdx = selectFuncIndex;
|
||||
((SExprNode*)pNewNode)->bindExprID = selectFuncIndex;
|
||||
nodesListMakeStrictAppend(pCxt->selectFuncList, pNewNode);
|
||||
}
|
||||
|
||||
|
@ -7595,7 +7597,7 @@ static int32_t rewriteColsFunction(STranslateContext* pCxt, SNodeList** nodeList
|
|||
++selectFuncCount;
|
||||
selectFuncIndex = selectFuncCount;
|
||||
code = nodesCloneNode(pSelectFunc, &pNewNode);
|
||||
((SExprNode*)pNewNode)->tupleFuncIdx = selectFuncIndex;
|
||||
((SExprNode*)pNewNode)->bindExprID = selectFuncIndex;
|
||||
nodesListMakeStrictAppend(selectFuncList, pNewNode);
|
||||
}
|
||||
// start from index 1, because the first parameter is select function which needn't to output.
|
||||
|
@ -13905,10 +13907,6 @@ static int32_t extractQueryResultSchema(const SNodeList* pProjections, int32_t*
|
|||
int32_t index = 0;
|
||||
FOREACH(pNode, pProjections) {
|
||||
SExprNode* pExpr = (SExprNode*)pNode;
|
||||
if(pExpr->tupleFuncIdx != 0) {
|
||||
*numOfCols -= 1;
|
||||
continue;
|
||||
}
|
||||
if (TSDB_DATA_TYPE_NULL == pExpr->resType.type) {
|
||||
(*pSchema)[index].type = TSDB_DATA_TYPE_VARCHAR;
|
||||
(*pSchema)[index].bytes = VARSTR_HEADER_SIZE;
|
||||
|
|
|
@ -123,8 +123,8 @@ static EDealRes doRewriteExpr(SNode** pNode, void* pContext) {
|
|||
tstrncpy(pCol->node.userAlias, ((SExprNode*)pExpr)->userAlias, TSDB_COL_NAME_LEN);
|
||||
tstrncpy(pCol->colName, ((SExprNode*)pExpr)->aliasName, TSDB_COL_NAME_LEN);
|
||||
pCol->node.projIdx = ((SExprNode*)(*pNode))->projIdx;
|
||||
pCol->node.bindTupleFuncIdx = ((SExprNode*)(*pNode))->bindTupleFuncIdx;
|
||||
pCol->node.tupleFuncIdx = ((SExprNode*)(*pNode))->tupleFuncIdx;
|
||||
pCol->node.relatedTo = ((SExprNode*)(*pNode))->relatedTo;
|
||||
//pCol->node.bindExprID = ((SExprNode*)(*pNode))->bindExprID;
|
||||
if (QUERY_NODE_FUNCTION == nodeType(pExpr)) {
|
||||
setColumnInfo((SFunctionNode*)pExpr, pCol, pCxt->isPartitionBy);
|
||||
}
|
||||
|
@ -712,7 +712,7 @@ static SColumnNode* createColumnByExpr(const char* pStmtName, SExprNode* pExpr)
|
|||
if (NULL != pStmtName) {
|
||||
snprintf(pCol->tableAlias, sizeof(pCol->tableAlias), "%s", pStmtName);
|
||||
}
|
||||
pCol->node.bindTupleFuncIdx = pExpr->bindTupleFuncIdx;
|
||||
pCol->node.relatedTo = pExpr->relatedTo;
|
||||
return pCol;
|
||||
}
|
||||
|
||||
|
@ -818,7 +818,7 @@ static int32_t addWinJoinPrimKeyToAggFuncs(SSelectStmt* pSelect, SNodeList** pLi
|
|||
}
|
||||
|
||||
static int32_t createAggLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SLogicNode** pLogicNode) {
|
||||
if (!pSelect->hasAggFuncs && NULL == pSelect->pGroupByList && !pSelect->pProjectionBindList) {
|
||||
if (!pSelect->hasAggFuncs && NULL == pSelect->pGroupByList) {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -1598,9 +1598,6 @@ static int32_t createColumnByProjections(SLogicPlanContext* pCxt, const char* pS
|
|||
SNode* pNode;
|
||||
int32_t projIdx = 1;
|
||||
FOREACH(pNode, pExprs) {
|
||||
if (((SExprNode*)pNode)->tupleFuncIdx != 0) {
|
||||
continue;
|
||||
}
|
||||
SColumnNode* pCol = createColumnByExpr(pStmtName, (SExprNode*)pNode);
|
||||
if (TSDB_CODE_SUCCESS != (code = nodesListStrictAppend(pList, (SNode*)pCol))) {
|
||||
nodesDestroyList(pList);
|
||||
|
|
|
@ -3606,8 +3606,7 @@ static int32_t eliminateProjOptimizeImpl(SOptimizeContext* pCxt, SLogicSubplan*
|
|||
} else {
|
||||
FOREACH(pProjection, pProjectNode->pProjections) {
|
||||
FOREACH(pChildTarget, pChild->pTargets) {
|
||||
if (0 == strcmp(((SColumnNode*)pProjection)->colName, ((SColumnNode*)pChildTarget)->colName)
|
||||
&& ((SColumnNode*)pProjection)->node.tupleFuncIdx == 0) {
|
||||
if (0 == strcmp(((SColumnNode*)pProjection)->colName, ((SColumnNode*)pChildTarget)->colName)) {
|
||||
SNode* pNew = NULL;
|
||||
code = nodesCloneNode(pChildTarget, &pNew);
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
|
|
|
@ -79,8 +79,7 @@ static EDealRes doCreateColumn(SNode* pNode, void* pContext) {
|
|||
}
|
||||
}
|
||||
}
|
||||
pCol->node.bindTupleFuncIdx = pExpr->bindTupleFuncIdx;
|
||||
pCol->node.tupleFuncIdx = pExpr->tupleFuncIdx;
|
||||
pCol->node.relatedTo = pExpr->relatedTo;
|
||||
return (TSDB_CODE_SUCCESS == nodesListStrictAppend(pCxt->pList, (SNode*)pCol) ? DEAL_RES_IGNORE_CHILD
|
||||
: DEAL_RES_ERROR);
|
||||
}
|
||||
|
|
|
@ -522,6 +522,12 @@ class TDTestCase:
|
|||
tdSql.checkCols(2)
|
||||
tdSql.checkData(0, 0, 3)
|
||||
tdSql.checkData(0, 1, 1)
|
||||
tdSql.query(f'select * from (select cols(last_row(c0), ts as t1, c1), cols(first(c0), ts as t2, c1 c21), first(c0) from test.meters where c0 < 4)')
|
||||
tdSql.checkRows(1)
|
||||
tdSql.checkCols(5)
|
||||
tdSql.checkData(0, 1, 3)
|
||||
tdSql.checkData(0, 3, 1)
|
||||
tdSql.checkData(0, 4, 1)
|
||||
tdSql.error(f'select c1 from (select cols(last_row(c0), ts as t1, c1), cols(first(c0), ts as t2, c1), first(c0) from test.meters where c0 < 4)')
|
||||
|
||||
# cols on system table
|
||||
|
@ -966,11 +972,12 @@ class TDTestCase:
|
|||
self.one_cols_1output_test()
|
||||
self.multi_cols_output_test()
|
||||
self.subquery_test()
|
||||
#self.window_test()
|
||||
self.window_test()
|
||||
self.join_test()
|
||||
self.stream_cols_test()
|
||||
self.include_null_test()
|
||||
|
||||
|
||||
def stop(self):
|
||||
tdSql.close()
|
||||
tdLog.success("%s successfully executed" % __file__)
|
||||
|
|
Loading…
Reference in New Issue