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