fix: some problems of planner
This commit is contained in:
parent
1e391ad27c
commit
b08a28d559
|
@ -418,8 +418,6 @@ void nodesValueNodeToVariant(const SValueNode* pNode, SVariant* pVal);
|
||||||
|
|
||||||
char* nodesGetFillModeString(EFillMode mode);
|
char* nodesGetFillModeString(EFillMode mode);
|
||||||
int32_t nodesMergeConds(SNode** pDst, SNodeList** pSrc);
|
int32_t nodesMergeConds(SNode** pDst, SNodeList** pSrc);
|
||||||
int32_t nodesPartitionCond(SNode** pCondition, SNode** pPrimaryKeyCond, SNode** pTagIndexCond, SNode** pTagCond,
|
|
||||||
SNode** pOtherCond);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,10 @@ extern int32_t filterFreeNcharColumns(SFilterInfo *pFilterInfo);
|
||||||
extern void filterFreeInfo(SFilterInfo *info);
|
extern void filterFreeInfo(SFilterInfo *info);
|
||||||
extern bool filterRangeExecute(SFilterInfo *info, SColumnDataAgg *pDataStatis, int32_t numOfCols, int32_t numOfRows);
|
extern bool filterRangeExecute(SFilterInfo *info, SColumnDataAgg *pDataStatis, int32_t numOfCols, int32_t numOfRows);
|
||||||
|
|
||||||
|
/* condition split interface */
|
||||||
|
int32_t filterPartitionCond(SNode **pCondition, SNode **pPrimaryKeyCond, SNode **pTagIndexCond, SNode **pTagCond,
|
||||||
|
SNode **pOtherCond);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -25,7 +25,7 @@ extern "C" {
|
||||||
|
|
||||||
typedef struct SFilterInfo SFilterInfo;
|
typedef struct SFilterInfo SFilterInfo;
|
||||||
|
|
||||||
int32_t scalarGetOperatorResultType(SOperatorNode* pOp);
|
int32_t scalarGetOperatorResultType(SOperatorNode *pOp);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
pNode will be freed in API;
|
pNode will be freed in API;
|
||||||
|
@ -43,7 +43,7 @@ int32_t scalarGetOperatorParamNum(EOperatorType type);
|
||||||
int32_t scalarGenerateSetFromList(void **data, void *pNode, uint32_t type);
|
int32_t scalarGenerateSetFromList(void **data, void *pNode, uint32_t type);
|
||||||
|
|
||||||
int32_t vectorGetConvertType(int32_t type1, int32_t type2);
|
int32_t vectorGetConvertType(int32_t type1, int32_t type2);
|
||||||
int32_t vectorConvertImpl(const SScalarParam* pIn, SScalarParam* pOut, int32_t* overflow);
|
int32_t vectorConvertImpl(const SScalarParam *pIn, SScalarParam *pOut, int32_t *overflow);
|
||||||
|
|
||||||
/* Math functions */
|
/* Math functions */
|
||||||
int32_t absFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput);
|
int32_t absFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput);
|
||||||
|
@ -86,7 +86,7 @@ int32_t nowFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutpu
|
||||||
int32_t todayFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput);
|
int32_t todayFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput);
|
||||||
int32_t timezoneFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput);
|
int32_t timezoneFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput);
|
||||||
|
|
||||||
bool getTimePseudoFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv);
|
bool getTimePseudoFuncEnv(struct SFunctionNode *pFunc, SFuncExecEnv *pEnv);
|
||||||
|
|
||||||
int32_t winStartTsFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput);
|
int32_t winStartTsFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput);
|
||||||
int32_t winEndTsFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput);
|
int32_t winEndTsFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput);
|
||||||
|
|
|
@ -1816,187 +1816,3 @@ int32_t nodesMergeConds(SNode** pDst, SNodeList** pSrc) {
|
||||||
|
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct SClassifyConditionCxt {
|
|
||||||
bool hasPrimaryKey;
|
|
||||||
bool hasTagIndexCol;
|
|
||||||
bool hasTagCol;
|
|
||||||
bool hasOtherCol;
|
|
||||||
} SClassifyConditionCxt;
|
|
||||||
|
|
||||||
static EDealRes classifyConditionImpl(SNode* pNode, void* pContext) {
|
|
||||||
SClassifyConditionCxt* pCxt = (SClassifyConditionCxt*)pContext;
|
|
||||||
if (QUERY_NODE_COLUMN == nodeType(pNode)) {
|
|
||||||
SColumnNode* pCol = (SColumnNode*)pNode;
|
|
||||||
if (PRIMARYKEY_TIMESTAMP_COL_ID == pCol->colId && TSDB_SYSTEM_TABLE != pCol->tableType) {
|
|
||||||
pCxt->hasPrimaryKey = true;
|
|
||||||
} else if (pCol->hasIndex) {
|
|
||||||
pCxt->hasTagIndexCol = true;
|
|
||||||
pCxt->hasTagCol = true;
|
|
||||||
} else if (COLUMN_TYPE_TAG == pCol->colType || COLUMN_TYPE_TBNAME == pCol->colType) {
|
|
||||||
pCxt->hasTagCol = true;
|
|
||||||
} else {
|
|
||||||
pCxt->hasOtherCol = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return DEAL_RES_CONTINUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef enum EConditionType {
|
|
||||||
COND_TYPE_PRIMARY_KEY = 1,
|
|
||||||
COND_TYPE_TAG_INDEX,
|
|
||||||
COND_TYPE_TAG,
|
|
||||||
COND_TYPE_NORMAL
|
|
||||||
} EConditionType;
|
|
||||||
|
|
||||||
static EConditionType classifyCondition(SNode* pNode) {
|
|
||||||
SClassifyConditionCxt cxt = {.hasPrimaryKey = false, .hasTagIndexCol = false, .hasOtherCol = false};
|
|
||||||
nodesWalkExpr(pNode, classifyConditionImpl, &cxt);
|
|
||||||
return cxt.hasOtherCol ? COND_TYPE_NORMAL
|
|
||||||
: (cxt.hasPrimaryKey && cxt.hasTagCol
|
|
||||||
? COND_TYPE_NORMAL
|
|
||||||
: (cxt.hasPrimaryKey ? COND_TYPE_PRIMARY_KEY
|
|
||||||
: (cxt.hasTagIndexCol ? COND_TYPE_TAG_INDEX : COND_TYPE_TAG)));
|
|
||||||
}
|
|
||||||
|
|
||||||
static int32_t partitionLogicCond(SNode** pCondition, SNode** pPrimaryKeyCond, SNode** pTagIndexCond, SNode** pTagCond,
|
|
||||||
SNode** pOtherCond) {
|
|
||||||
SLogicConditionNode* pLogicCond = (SLogicConditionNode*)(*pCondition);
|
|
||||||
|
|
||||||
int32_t code = TSDB_CODE_SUCCESS;
|
|
||||||
|
|
||||||
SNodeList* pPrimaryKeyConds = NULL;
|
|
||||||
SNodeList* pTagIndexConds = NULL;
|
|
||||||
SNodeList* pTagConds = NULL;
|
|
||||||
SNodeList* pOtherConds = NULL;
|
|
||||||
SNode* pCond = NULL;
|
|
||||||
FOREACH(pCond, pLogicCond->pParameterList) {
|
|
||||||
switch (classifyCondition(pCond)) {
|
|
||||||
case COND_TYPE_PRIMARY_KEY:
|
|
||||||
if (NULL != pPrimaryKeyCond) {
|
|
||||||
code = nodesListMakeAppend(&pPrimaryKeyConds, nodesCloneNode(pCond));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case COND_TYPE_TAG_INDEX:
|
|
||||||
if (NULL != pTagIndexCond) {
|
|
||||||
code = nodesListMakeAppend(&pTagIndexConds, nodesCloneNode(pCond));
|
|
||||||
}
|
|
||||||
if (NULL != pTagCond) {
|
|
||||||
code = nodesListMakeAppend(&pTagConds, nodesCloneNode(pCond));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case COND_TYPE_TAG:
|
|
||||||
if (NULL != pTagCond) {
|
|
||||||
code = nodesListMakeAppend(&pTagConds, nodesCloneNode(pCond));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case COND_TYPE_NORMAL:
|
|
||||||
default:
|
|
||||||
if (NULL != pOtherCond) {
|
|
||||||
code = nodesListMakeAppend(&pOtherConds, nodesCloneNode(pCond));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (TSDB_CODE_SUCCESS != code) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SNode* pTempPrimaryKeyCond = NULL;
|
|
||||||
SNode* pTempTagIndexCond = NULL;
|
|
||||||
SNode* pTempTagCond = NULL;
|
|
||||||
SNode* pTempOtherCond = NULL;
|
|
||||||
if (TSDB_CODE_SUCCESS == code) {
|
|
||||||
code = nodesMergeConds(&pTempPrimaryKeyCond, &pPrimaryKeyConds);
|
|
||||||
}
|
|
||||||
if (TSDB_CODE_SUCCESS == code) {
|
|
||||||
code = nodesMergeConds(&pTempTagIndexCond, &pTagIndexConds);
|
|
||||||
}
|
|
||||||
if (TSDB_CODE_SUCCESS == code) {
|
|
||||||
code = nodesMergeConds(&pTempTagCond, &pTagConds);
|
|
||||||
}
|
|
||||||
if (TSDB_CODE_SUCCESS == code) {
|
|
||||||
code = nodesMergeConds(&pTempOtherCond, &pOtherConds);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TSDB_CODE_SUCCESS == code) {
|
|
||||||
if (NULL != pPrimaryKeyCond) {
|
|
||||||
*pPrimaryKeyCond = pTempPrimaryKeyCond;
|
|
||||||
}
|
|
||||||
if (NULL != pTagIndexCond) {
|
|
||||||
*pTagIndexCond = pTempTagIndexCond;
|
|
||||||
}
|
|
||||||
if (NULL != pTagCond) {
|
|
||||||
*pTagCond = pTempTagCond;
|
|
||||||
}
|
|
||||||
if (NULL != pOtherCond) {
|
|
||||||
*pOtherCond = pTempOtherCond;
|
|
||||||
}
|
|
||||||
nodesDestroyNode(*pCondition);
|
|
||||||
*pCondition = NULL;
|
|
||||||
} else {
|
|
||||||
nodesDestroyList(pPrimaryKeyConds);
|
|
||||||
nodesDestroyList(pTagIndexConds);
|
|
||||||
nodesDestroyList(pTagConds);
|
|
||||||
nodesDestroyList(pOtherConds);
|
|
||||||
nodesDestroyNode(pTempPrimaryKeyCond);
|
|
||||||
nodesDestroyNode(pTempTagIndexCond);
|
|
||||||
nodesDestroyNode(pTempTagCond);
|
|
||||||
nodesDestroyNode(pTempOtherCond);
|
|
||||||
}
|
|
||||||
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t nodesPartitionCond(SNode** pCondition, SNode** pPrimaryKeyCond, SNode** pTagIndexCond, SNode** pTagCond,
|
|
||||||
SNode** pOtherCond) {
|
|
||||||
if (QUERY_NODE_LOGIC_CONDITION == nodeType(*pCondition) &&
|
|
||||||
LOGIC_COND_TYPE_AND == ((SLogicConditionNode*)*pCondition)->condType) {
|
|
||||||
return partitionLogicCond(pCondition, pPrimaryKeyCond, pTagIndexCond, pTagCond, pOtherCond);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool needOutput = false;
|
|
||||||
switch (classifyCondition(*pCondition)) {
|
|
||||||
case COND_TYPE_PRIMARY_KEY:
|
|
||||||
if (NULL != pPrimaryKeyCond) {
|
|
||||||
*pPrimaryKeyCond = *pCondition;
|
|
||||||
needOutput = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case COND_TYPE_TAG_INDEX:
|
|
||||||
if (NULL != pTagIndexCond) {
|
|
||||||
*pTagIndexCond = *pCondition;
|
|
||||||
needOutput = true;
|
|
||||||
}
|
|
||||||
if (NULL != pTagCond) {
|
|
||||||
SNode* pTempCond = *pCondition;
|
|
||||||
if (NULL != pTagIndexCond) {
|
|
||||||
pTempCond = nodesCloneNode(*pCondition);
|
|
||||||
if (NULL == pTempCond) {
|
|
||||||
return TSDB_CODE_OUT_OF_MEMORY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*pTagCond = pTempCond;
|
|
||||||
needOutput = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case COND_TYPE_TAG:
|
|
||||||
if (NULL != pTagCond) {
|
|
||||||
*pTagCond = *pCondition;
|
|
||||||
needOutput = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case COND_TYPE_NORMAL:
|
|
||||||
default:
|
|
||||||
if (NULL != pOtherCond) {
|
|
||||||
*pOtherCond = *pCondition;
|
|
||||||
needOutput = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (needOutput) {
|
|
||||||
*pCondition = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TSDB_CODE_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
|
@ -233,18 +233,22 @@ SNode* createRawExprNodeExt(SAstCreateContext* pCxt, const SToken* pStart, const
|
||||||
SNode* releaseRawExprNode(SAstCreateContext* pCxt, SNode* pNode) {
|
SNode* releaseRawExprNode(SAstCreateContext* pCxt, SNode* pNode) {
|
||||||
CHECK_PARSER_STATUS(pCxt);
|
CHECK_PARSER_STATUS(pCxt);
|
||||||
SRawExprNode* pRawExpr = (SRawExprNode*)pNode;
|
SRawExprNode* pRawExpr = (SRawExprNode*)pNode;
|
||||||
SNode* pExpr = pRawExpr->pNode;
|
SNode* pRealizedExpr = pRawExpr->pNode;
|
||||||
if (nodesIsExprNode(pExpr)) {
|
if (nodesIsExprNode(pRealizedExpr)) {
|
||||||
|
SExprNode* pExpr = (SExprNode*)pRealizedExpr;
|
||||||
if (QUERY_NODE_COLUMN == nodeType(pExpr)) {
|
if (QUERY_NODE_COLUMN == nodeType(pExpr)) {
|
||||||
strcpy(((SExprNode*)pExpr)->aliasName, ((SColumnNode*)pExpr)->colName);
|
strcpy(pExpr->aliasName, ((SColumnNode*)pExpr)->colName);
|
||||||
|
strcpy(pExpr->userAlias, ((SColumnNode*)pExpr)->colName);
|
||||||
} else {
|
} else {
|
||||||
int32_t len = TMIN(sizeof(((SExprNode*)pExpr)->aliasName) - 1, pRawExpr->n);
|
int32_t len = TMIN(sizeof(pExpr->aliasName) - 1, pRawExpr->n);
|
||||||
strncpy(((SExprNode*)pExpr)->aliasName, pRawExpr->p, len);
|
strncpy(pExpr->aliasName, pRawExpr->p, len);
|
||||||
((SExprNode*)pExpr)->aliasName[len] = '\0';
|
pExpr->aliasName[len] = '\0';
|
||||||
|
strncpy(pExpr->userAlias, pRawExpr->p, len);
|
||||||
|
pExpr->userAlias[len] = '\0';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
taosMemoryFreeClear(pNode);
|
taosMemoryFreeClear(pNode);
|
||||||
return pExpr;
|
return pRealizedExpr;
|
||||||
}
|
}
|
||||||
|
|
||||||
SToken getTokenFromRawExprNode(SAstCreateContext* pCxt, SNode* pNode) {
|
SToken getTokenFromRawExprNode(SAstCreateContext* pCxt, SNode* pNode) {
|
||||||
|
@ -641,11 +645,12 @@ SNode* createInterpTimeRange(SAstCreateContext* pCxt, SNode* pStart, SNode* pEnd
|
||||||
SNode* setProjectionAlias(SAstCreateContext* pCxt, SNode* pNode, SToken* pAlias) {
|
SNode* setProjectionAlias(SAstCreateContext* pCxt, SNode* pNode, SToken* pAlias) {
|
||||||
CHECK_PARSER_STATUS(pCxt);
|
CHECK_PARSER_STATUS(pCxt);
|
||||||
trimEscape(pAlias);
|
trimEscape(pAlias);
|
||||||
int32_t len = TMIN(sizeof(((SExprNode*)pNode)->aliasName) - 1, pAlias->n);
|
SExprNode* pExpr = (SExprNode*)pNode;
|
||||||
strncpy(((SExprNode*)pNode)->aliasName, pAlias->z, len);
|
int32_t len = TMIN(sizeof(pExpr->aliasName) - 1, pAlias->n);
|
||||||
((SExprNode*)pNode)->aliasName[len] = '\0';
|
strncpy(pExpr->aliasName, pAlias->z, len);
|
||||||
strncpy(((SExprNode*)pNode)->userAlias, pAlias->z, len);
|
pExpr->aliasName[len] = '\0';
|
||||||
((SExprNode*)pNode)->userAlias[len] = '\0';
|
strncpy(pExpr->userAlias, pAlias->z, len);
|
||||||
|
pExpr->userAlias[len] = '\0';
|
||||||
return pNode;
|
return pNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -766,13 +771,21 @@ SNode* createSelectStmt(SAstCreateContext* pCxt, bool isDistinct, SNodeList* pPr
|
||||||
return (SNode*)select;
|
return (SNode*)select;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void setSubquery(SNode* pStmt) {
|
||||||
|
if (QUERY_NODE_SELECT_STMT == nodeType(pStmt)) {
|
||||||
|
((SSelectStmt*)pStmt)->isSubquery = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SNode* createSetOperator(SAstCreateContext* pCxt, ESetOperatorType type, SNode* pLeft, SNode* pRight) {
|
SNode* createSetOperator(SAstCreateContext* pCxt, ESetOperatorType type, SNode* pLeft, SNode* pRight) {
|
||||||
CHECK_PARSER_STATUS(pCxt);
|
CHECK_PARSER_STATUS(pCxt);
|
||||||
SSetOperator* setOp = (SSetOperator*)nodesMakeNode(QUERY_NODE_SET_OPERATOR);
|
SSetOperator* setOp = (SSetOperator*)nodesMakeNode(QUERY_NODE_SET_OPERATOR);
|
||||||
CHECK_OUT_OF_MEM(setOp);
|
CHECK_OUT_OF_MEM(setOp);
|
||||||
setOp->opType = type;
|
setOp->opType = type;
|
||||||
setOp->pLeft = pLeft;
|
setOp->pLeft = pLeft;
|
||||||
|
setSubquery(setOp->pLeft);
|
||||||
setOp->pRight = pRight;
|
setOp->pRight = pRight;
|
||||||
|
setSubquery(setOp->pRight);
|
||||||
sprintf(setOp->stmtName, "%p", setOp);
|
sprintf(setOp->stmtName, "%p", setOp);
|
||||||
return (SNode*)setOp;
|
return (SNode*)setOp;
|
||||||
}
|
}
|
||||||
|
|
|
@ -691,7 +691,7 @@ static EDealRes translateColumnUseAlias(STranslateContext* pCxt, SColumnNode** p
|
||||||
SNode* pNode;
|
SNode* pNode;
|
||||||
FOREACH(pNode, pProjectionList) {
|
FOREACH(pNode, pProjectionList) {
|
||||||
SExprNode* pExpr = (SExprNode*)pNode;
|
SExprNode* pExpr = (SExprNode*)pNode;
|
||||||
if (0 == strcmp((*pCol)->colName, pExpr->aliasName)) {
|
if (0 == strcmp((*pCol)->colName, pExpr->userAlias)) {
|
||||||
SColumnRefNode* pColRef = (SColumnRefNode*)nodesMakeNode(QUERY_NODE_COLUMN_REF);
|
SColumnRefNode* pColRef = (SColumnRefNode*)nodesMakeNode(QUERY_NODE_COLUMN_REF);
|
||||||
if (NULL == pColRef) {
|
if (NULL == pColRef) {
|
||||||
pCxt->errCode = TSDB_CODE_OUT_OF_MEMORY;
|
pCxt->errCode = TSDB_CODE_OUT_OF_MEMORY;
|
||||||
|
@ -1535,6 +1535,7 @@ static EDealRes rewriteColToSelectValFunc(STranslateContext* pCxt, SNode** pNode
|
||||||
}
|
}
|
||||||
strcpy(pFunc->functionName, "_select_value");
|
strcpy(pFunc->functionName, "_select_value");
|
||||||
strcpy(pFunc->node.aliasName, ((SExprNode*)*pNode)->aliasName);
|
strcpy(pFunc->node.aliasName, ((SExprNode*)*pNode)->aliasName);
|
||||||
|
strcpy(pFunc->node.userAlias, ((SExprNode*)*pNode)->userAlias);
|
||||||
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);
|
||||||
|
@ -2171,12 +2172,45 @@ static int32_t translateFillValues(STranslateContext* pCxt, SSelectStmt* pSelect
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int32_t rewriteProjectAlias(SNodeList* pProjectionList) {
|
||||||
|
int32_t no = 1;
|
||||||
|
SNode* pProject = NULL;
|
||||||
|
FOREACH(pProject, pProjectionList) { sprintf(((SExprNode*)pProject)->aliasName, "#expr_%d", no++); }
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t checkProjectAlias(STranslateContext* pCxt, SNodeList* pProjectionList) {
|
||||||
|
SHashObj* pUserAliasSet = taosHashInit(LIST_LENGTH(pProjectionList),
|
||||||
|
taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_NO_LOCK);
|
||||||
|
SNode* pProject = NULL;
|
||||||
|
FOREACH(pProject, pProjectionList) {
|
||||||
|
SExprNode* pExpr = (SExprNode*)pProject;
|
||||||
|
if (NULL != taosHashGet(pUserAliasSet, pExpr->userAlias, strlen(pExpr->userAlias))) {
|
||||||
|
taosHashCleanup(pUserAliasSet);
|
||||||
|
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_AMBIGUOUS_COLUMN, pExpr->userAlias);
|
||||||
|
}
|
||||||
|
taosHashPut(pUserAliasSet, pExpr->userAlias, strlen(pExpr->userAlias), &pExpr, POINTER_BYTES);
|
||||||
|
}
|
||||||
|
taosHashCleanup(pUserAliasSet);
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t translateProjectionList(STranslateContext* pCxt, SSelectStmt* pSelect) {
|
||||||
|
if (pSelect->isSubquery) {
|
||||||
|
return checkProjectAlias(pCxt, pSelect->pProjectionList);
|
||||||
|
}
|
||||||
|
return rewriteProjectAlias(pSelect->pProjectionList);
|
||||||
|
}
|
||||||
|
|
||||||
static int32_t translateSelectList(STranslateContext* pCxt, SSelectStmt* pSelect) {
|
static int32_t translateSelectList(STranslateContext* pCxt, SSelectStmt* pSelect) {
|
||||||
pCxt->currClause = SQL_CLAUSE_SELECT;
|
pCxt->currClause = SQL_CLAUSE_SELECT;
|
||||||
int32_t code = translateExprList(pCxt, pSelect->pProjectionList);
|
int32_t code = translateExprList(pCxt, pSelect->pProjectionList);
|
||||||
if (TSDB_CODE_SUCCESS == code) {
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
code = translateStar(pCxt, pSelect);
|
code = translateStar(pCxt, pSelect);
|
||||||
}
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = translateProjectionList(pCxt, pSelect);
|
||||||
|
}
|
||||||
if (TSDB_CODE_SUCCESS == code) {
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
code = checkExprListForGroupBy(pCxt, pSelect, pSelect->pProjectionList);
|
code = checkExprListForGroupBy(pCxt, pSelect, pSelect->pProjectionList);
|
||||||
}
|
}
|
||||||
|
@ -2232,7 +2266,7 @@ static int32_t getQueryTimeRange(STranslateContext* pCxt, SNode* pWhere, STimeWi
|
||||||
}
|
}
|
||||||
|
|
||||||
SNode* pPrimaryKeyCond = NULL;
|
SNode* pPrimaryKeyCond = NULL;
|
||||||
nodesPartitionCond(&pCond, &pPrimaryKeyCond, NULL, NULL, NULL);
|
filterPartitionCond(&pCond, &pPrimaryKeyCond, NULL, NULL, NULL);
|
||||||
|
|
||||||
int32_t code = TSDB_CODE_SUCCESS;
|
int32_t code = TSDB_CODE_SUCCESS;
|
||||||
if (NULL != pPrimaryKeyCond) {
|
if (NULL != pPrimaryKeyCond) {
|
||||||
|
@ -2699,6 +2733,7 @@ static SNode* createSetOperProject(const char* pTableAlias, SNode* pNode) {
|
||||||
strcpy(pCol->tableAlias, pTableAlias);
|
strcpy(pCol->tableAlias, pTableAlias);
|
||||||
strcpy(pCol->colName, ((SExprNode*)pNode)->aliasName);
|
strcpy(pCol->colName, ((SExprNode*)pNode)->aliasName);
|
||||||
strcpy(pCol->node.aliasName, pCol->colName);
|
strcpy(pCol->node.aliasName, pCol->colName);
|
||||||
|
strcpy(pCol->node.userAlias, ((SExprNode*)pNode)->userAlias);
|
||||||
return (SNode*)pCol;
|
return (SNode*)pCol;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2810,7 +2845,7 @@ static int32_t partitionDeleteWhere(STranslateContext* pCxt, SDeleteStmt* pDelet
|
||||||
|
|
||||||
SNode* pPrimaryKeyCond = NULL;
|
SNode* pPrimaryKeyCond = NULL;
|
||||||
SNode* pOtherCond = NULL;
|
SNode* pOtherCond = NULL;
|
||||||
int32_t code = nodesPartitionCond(&pDelete->pWhere, &pPrimaryKeyCond, NULL, &pDelete->pTagCond, &pOtherCond);
|
int32_t code = filterPartitionCond(&pDelete->pWhere, &pPrimaryKeyCond, NULL, &pDelete->pTagCond, &pOtherCond);
|
||||||
if (TSDB_CODE_SUCCESS == code && NULL != pOtherCond) {
|
if (TSDB_CODE_SUCCESS == code && NULL != pOtherCond) {
|
||||||
code = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_DELETE_WHERE);
|
code = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_DELETE_WHERE);
|
||||||
}
|
}
|
||||||
|
@ -4983,7 +5018,7 @@ static int32_t translateSubquery(STranslateContext* pCxt, SNode* pNode) {
|
||||||
SNode* pCurrStmt = pCxt->pCurrStmt;
|
SNode* pCurrStmt = pCxt->pCurrStmt;
|
||||||
int32_t currLevel = pCxt->currLevel;
|
int32_t currLevel = pCxt->currLevel;
|
||||||
pCxt->currLevel = ++(pCxt->levelNo);
|
pCxt->currLevel = ++(pCxt->levelNo);
|
||||||
int32_t code = translateQuery(pCxt, pNode);
|
int32_t code = translateQuery(pCxt, pNode);
|
||||||
pCxt->currClause = currClause;
|
pCxt->currClause = currClause;
|
||||||
pCxt->pCurrStmt = pCurrStmt;
|
pCxt->pCurrStmt = pCurrStmt;
|
||||||
pCxt->currLevel = currLevel;
|
pCxt->currLevel = currLevel;
|
||||||
|
|
|
@ -70,6 +70,8 @@ TEST_F(ParserSelectTest, condition) {
|
||||||
run("SELECT c1 FROM t1 WHERE NOT ts in (true, false)");
|
run("SELECT c1 FROM t1 WHERE NOT ts in (true, false)");
|
||||||
|
|
||||||
run("SELECT * FROM t1 WHERE c1 > 10 and c1 is not null");
|
run("SELECT * FROM t1 WHERE c1 > 10 and c1 is not null");
|
||||||
|
|
||||||
|
run("SELECT * FROM t1 WHERE TBNAME like 'fda%' or TS > '2021-05-05 18:19:01.000'");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserSelectTest, pseudoColumn) {
|
TEST_F(ParserSelectTest, pseudoColumn) {
|
||||||
|
|
|
@ -436,7 +436,7 @@ static int32_t pushDownCondOptDealScan(SOptimizeContext* pCxt, SScanLogicNode* p
|
||||||
|
|
||||||
SNode* pPrimaryKeyCond = NULL;
|
SNode* pPrimaryKeyCond = NULL;
|
||||||
SNode* pOtherCond = NULL;
|
SNode* pOtherCond = NULL;
|
||||||
int32_t code = nodesPartitionCond(&pScan->node.pConditions, &pPrimaryKeyCond, &pScan->pTagIndexCond, &pScan->pTagCond,
|
int32_t code = filterPartitionCond(&pScan->node.pConditions, &pPrimaryKeyCond, &pScan->pTagIndexCond, &pScan->pTagCond,
|
||||||
&pOtherCond);
|
&pOtherCond);
|
||||||
if (TSDB_CODE_SUCCESS == code && NULL != pScan->pTagCond) {
|
if (TSDB_CODE_SUCCESS == code && NULL != pScan->pTagCond) {
|
||||||
code = pushDownCondOptRebuildTbanme(&pScan->pTagCond);
|
code = pushDownCondOptRebuildTbanme(&pScan->pTagCond);
|
||||||
|
|
|
@ -763,6 +763,8 @@ static SNode* stbSplCreateColumnNode(SExprNode* pExpr) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (QUERY_NODE_COLUMN == nodeType(pExpr)) {
|
if (QUERY_NODE_COLUMN == nodeType(pExpr)) {
|
||||||
|
strcpy(pCol->dbName, ((SColumnNode*)pExpr)->dbName);
|
||||||
|
strcpy(pCol->tableName, ((SColumnNode*)pExpr)->tableName);
|
||||||
strcpy(pCol->tableAlias, ((SColumnNode*)pExpr)->tableAlias);
|
strcpy(pCol->tableAlias, ((SColumnNode*)pExpr)->tableAlias);
|
||||||
}
|
}
|
||||||
strcpy(pCol->colName, pExpr->aliasName);
|
strcpy(pCol->colName, pExpr->aliasName);
|
||||||
|
|
|
@ -39,6 +39,8 @@ TEST_F(PlanOrderByTest, expr) {
|
||||||
useDb("root", "test");
|
useDb("root", "test");
|
||||||
|
|
||||||
run("SELECT * FROM t1 ORDER BY c1 + 10, c2");
|
run("SELECT * FROM t1 ORDER BY c1 + 10, c2");
|
||||||
|
|
||||||
|
run("SELECT c1 FROM st1 ORDER BY ts, _C0");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(PlanOrderByTest, nullsOrder) {
|
TEST_F(PlanOrderByTest, nullsOrder) {
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "tcompare.h"
|
#include "tcompare.h"
|
||||||
#include "tdatablock.h"
|
#include "tdatablock.h"
|
||||||
#include "ttime.h"
|
#include "ttime.h"
|
||||||
|
#include "functionMgt.h"
|
||||||
|
|
||||||
OptrStr gOptrStr[] = {
|
OptrStr gOptrStr[] = {
|
||||||
{0, "invalid"},
|
{0, "invalid"},
|
||||||
|
@ -3877,4 +3878,195 @@ bool filterExecute(SFilterInfo *info, SSDataBlock *pSrc, int8_t** p, SColumnData
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct SClassifyConditionCxt {
|
||||||
|
bool hasPrimaryKey;
|
||||||
|
bool hasTagIndexCol;
|
||||||
|
bool hasTagCol;
|
||||||
|
bool hasOtherCol;
|
||||||
|
} SClassifyConditionCxt;
|
||||||
|
|
||||||
|
static EDealRes classifyConditionImpl(SNode* pNode, void* pContext) {
|
||||||
|
SClassifyConditionCxt* pCxt = (SClassifyConditionCxt*)pContext;
|
||||||
|
if (QUERY_NODE_COLUMN == nodeType(pNode)) {
|
||||||
|
SColumnNode* pCol = (SColumnNode*)pNode;
|
||||||
|
if (PRIMARYKEY_TIMESTAMP_COL_ID == pCol->colId && TSDB_SYSTEM_TABLE != pCol->tableType) {
|
||||||
|
pCxt->hasPrimaryKey = true;
|
||||||
|
} else if (pCol->hasIndex) {
|
||||||
|
pCxt->hasTagIndexCol = true;
|
||||||
|
pCxt->hasTagCol = true;
|
||||||
|
} else if (COLUMN_TYPE_TAG == pCol->colType || COLUMN_TYPE_TBNAME == pCol->colType) {
|
||||||
|
pCxt->hasTagCol = true;
|
||||||
|
} else {
|
||||||
|
pCxt->hasOtherCol = true;
|
||||||
|
}
|
||||||
|
} else if (QUERY_NODE_FUNCTION == nodeType(pNode)) {
|
||||||
|
SFunctionNode* pFunc = (SFunctionNode*)pNode;
|
||||||
|
if (fmIsPseudoColumnFunc(pFunc->funcId)) {
|
||||||
|
if (FUNCTION_TYPE_TBNAME==pFunc->funcType) {
|
||||||
|
pCxt->hasTagCol = true;
|
||||||
|
} else {
|
||||||
|
pCxt->hasOtherCol = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return DEAL_RES_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef enum EConditionType {
|
||||||
|
COND_TYPE_PRIMARY_KEY = 1,
|
||||||
|
COND_TYPE_TAG_INDEX,
|
||||||
|
COND_TYPE_TAG,
|
||||||
|
COND_TYPE_NORMAL
|
||||||
|
} EConditionType;
|
||||||
|
|
||||||
|
static EConditionType classifyCondition(SNode* pNode) {
|
||||||
|
SClassifyConditionCxt cxt = {.hasPrimaryKey = false, .hasTagIndexCol = false, .hasOtherCol = false};
|
||||||
|
nodesWalkExpr(pNode, classifyConditionImpl, &cxt);
|
||||||
|
return cxt.hasOtherCol ? COND_TYPE_NORMAL
|
||||||
|
: (cxt.hasPrimaryKey && cxt.hasTagCol
|
||||||
|
? COND_TYPE_NORMAL
|
||||||
|
: (cxt.hasPrimaryKey ? COND_TYPE_PRIMARY_KEY
|
||||||
|
: (cxt.hasTagIndexCol ? COND_TYPE_TAG_INDEX : COND_TYPE_TAG)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t partitionLogicCond(SNode** pCondition, SNode** pPrimaryKeyCond, SNode** pTagIndexCond, SNode** pTagCond,
|
||||||
|
SNode** pOtherCond) {
|
||||||
|
SLogicConditionNode* pLogicCond = (SLogicConditionNode*)(*pCondition);
|
||||||
|
|
||||||
|
int32_t code = TSDB_CODE_SUCCESS;
|
||||||
|
|
||||||
|
SNodeList* pPrimaryKeyConds = NULL;
|
||||||
|
SNodeList* pTagIndexConds = NULL;
|
||||||
|
SNodeList* pTagConds = NULL;
|
||||||
|
SNodeList* pOtherConds = NULL;
|
||||||
|
SNode* pCond = NULL;
|
||||||
|
FOREACH(pCond, pLogicCond->pParameterList) {
|
||||||
|
switch (classifyCondition(pCond)) {
|
||||||
|
case COND_TYPE_PRIMARY_KEY:
|
||||||
|
if (NULL != pPrimaryKeyCond) {
|
||||||
|
code = nodesListMakeAppend(&pPrimaryKeyConds, nodesCloneNode(pCond));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case COND_TYPE_TAG_INDEX:
|
||||||
|
if (NULL != pTagIndexCond) {
|
||||||
|
code = nodesListMakeAppend(&pTagIndexConds, nodesCloneNode(pCond));
|
||||||
|
}
|
||||||
|
if (NULL != pTagCond) {
|
||||||
|
code = nodesListMakeAppend(&pTagConds, nodesCloneNode(pCond));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case COND_TYPE_TAG:
|
||||||
|
if (NULL != pTagCond) {
|
||||||
|
code = nodesListMakeAppend(&pTagConds, nodesCloneNode(pCond));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case COND_TYPE_NORMAL:
|
||||||
|
default:
|
||||||
|
if (NULL != pOtherCond) {
|
||||||
|
code = nodesListMakeAppend(&pOtherConds, nodesCloneNode(pCond));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS != code) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SNode* pTempPrimaryKeyCond = NULL;
|
||||||
|
SNode* pTempTagIndexCond = NULL;
|
||||||
|
SNode* pTempTagCond = NULL;
|
||||||
|
SNode* pTempOtherCond = NULL;
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = nodesMergeConds(&pTempPrimaryKeyCond, &pPrimaryKeyConds);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = nodesMergeConds(&pTempTagIndexCond, &pTagIndexConds);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = nodesMergeConds(&pTempTagCond, &pTagConds);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = nodesMergeConds(&pTempOtherCond, &pOtherConds);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
if (NULL != pPrimaryKeyCond) {
|
||||||
|
*pPrimaryKeyCond = pTempPrimaryKeyCond;
|
||||||
|
}
|
||||||
|
if (NULL != pTagIndexCond) {
|
||||||
|
*pTagIndexCond = pTempTagIndexCond;
|
||||||
|
}
|
||||||
|
if (NULL != pTagCond) {
|
||||||
|
*pTagCond = pTempTagCond;
|
||||||
|
}
|
||||||
|
if (NULL != pOtherCond) {
|
||||||
|
*pOtherCond = pTempOtherCond;
|
||||||
|
}
|
||||||
|
nodesDestroyNode(*pCondition);
|
||||||
|
*pCondition = NULL;
|
||||||
|
} else {
|
||||||
|
nodesDestroyList(pPrimaryKeyConds);
|
||||||
|
nodesDestroyList(pTagIndexConds);
|
||||||
|
nodesDestroyList(pTagConds);
|
||||||
|
nodesDestroyList(pOtherConds);
|
||||||
|
nodesDestroyNode(pTempPrimaryKeyCond);
|
||||||
|
nodesDestroyNode(pTempTagIndexCond);
|
||||||
|
nodesDestroyNode(pTempTagCond);
|
||||||
|
nodesDestroyNode(pTempOtherCond);
|
||||||
|
}
|
||||||
|
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t filterPartitionCond(SNode** pCondition, SNode** pPrimaryKeyCond, SNode** pTagIndexCond, SNode** pTagCond,
|
||||||
|
SNode** pOtherCond) {
|
||||||
|
if (QUERY_NODE_LOGIC_CONDITION == nodeType(*pCondition) &&
|
||||||
|
LOGIC_COND_TYPE_AND == ((SLogicConditionNode*)*pCondition)->condType) {
|
||||||
|
return partitionLogicCond(pCondition, pPrimaryKeyCond, pTagIndexCond, pTagCond, pOtherCond);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool needOutput = false;
|
||||||
|
switch (classifyCondition(*pCondition)) {
|
||||||
|
case COND_TYPE_PRIMARY_KEY:
|
||||||
|
if (NULL != pPrimaryKeyCond) {
|
||||||
|
*pPrimaryKeyCond = *pCondition;
|
||||||
|
needOutput = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case COND_TYPE_TAG_INDEX:
|
||||||
|
if (NULL != pTagIndexCond) {
|
||||||
|
*pTagIndexCond = *pCondition;
|
||||||
|
needOutput = true;
|
||||||
|
}
|
||||||
|
if (NULL != pTagCond) {
|
||||||
|
SNode* pTempCond = *pCondition;
|
||||||
|
if (NULL != pTagIndexCond) {
|
||||||
|
pTempCond = nodesCloneNode(*pCondition);
|
||||||
|
if (NULL == pTempCond) {
|
||||||
|
return TSDB_CODE_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*pTagCond = pTempCond;
|
||||||
|
needOutput = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case COND_TYPE_TAG:
|
||||||
|
if (NULL != pTagCond) {
|
||||||
|
*pTagCond = *pCondition;
|
||||||
|
needOutput = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case COND_TYPE_NORMAL:
|
||||||
|
default:
|
||||||
|
if (NULL != pOtherCond) {
|
||||||
|
*pOtherCond = *pCondition;
|
||||||
|
needOutput = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (needOutput) {
|
||||||
|
*pCondition = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue