Merge remote-tracking branch 'origin/3.0' into fix/tsim
This commit is contained in:
commit
6aa602e468
|
@ -103,6 +103,7 @@ typedef struct SIndefRowsFuncLogicNode {
|
||||||
SLogicNode node;
|
SLogicNode node;
|
||||||
SNodeList* pFuncs;
|
SNodeList* pFuncs;
|
||||||
bool isTailFunc;
|
bool isTailFunc;
|
||||||
|
bool isUniqueFunc;
|
||||||
} SIndefRowsFuncLogicNode;
|
} SIndefRowsFuncLogicNode;
|
||||||
|
|
||||||
typedef struct SInterpFuncLogicNode {
|
typedef struct SInterpFuncLogicNode {
|
||||||
|
|
|
@ -50,6 +50,7 @@ typedef struct SExprNode {
|
||||||
char aliasName[TSDB_COL_NAME_LEN];
|
char aliasName[TSDB_COL_NAME_LEN];
|
||||||
char userAlias[TSDB_COL_NAME_LEN];
|
char userAlias[TSDB_COL_NAME_LEN];
|
||||||
SArray* pAssociation;
|
SArray* pAssociation;
|
||||||
|
bool orderAlias;
|
||||||
} SExprNode;
|
} SExprNode;
|
||||||
|
|
||||||
typedef enum EColumnType { COLUMN_TYPE_COLUMN = 1, COLUMN_TYPE_TAG, COLUMN_TYPE_TBNAME } EColumnType;
|
typedef enum EColumnType { COLUMN_TYPE_COLUMN = 1, COLUMN_TYPE_TAG, COLUMN_TYPE_TBNAME } EColumnType;
|
||||||
|
|
|
@ -48,6 +48,8 @@ int32_t qCreateQueryPlan(SPlanContext* pCxt, SQueryPlan** pPlan, SArray* pExecNo
|
||||||
// @pSource one execution location of this group of datasource subplans
|
// @pSource one execution location of this group of datasource subplans
|
||||||
int32_t qSetSubplanExecutionNode(SSubplan* pSubplan, int32_t groupId, SDownstreamSourceNode* pSource);
|
int32_t qSetSubplanExecutionNode(SSubplan* pSubplan, int32_t groupId, SDownstreamSourceNode* pSource);
|
||||||
|
|
||||||
|
int32_t qClearSubplanExecutionNode(SSubplan* pSubplan, int32_t groupId);
|
||||||
|
|
||||||
// Convert to subplan to string for the scheduler to send to the executor
|
// Convert to subplan to string for the scheduler to send to the executor
|
||||||
int32_t qSubPlanToString(const SSubplan* pSubplan, char** pStr, int32_t* pLen);
|
int32_t qSubPlanToString(const SSubplan* pSubplan, char** pStr, int32_t* pLen);
|
||||||
int32_t qStringToSubplan(const char* pStr, SSubplan** pSubplan);
|
int32_t qStringToSubplan(const char* pStr, SSubplan** pSubplan);
|
||||||
|
|
|
@ -271,19 +271,19 @@ extern int32_t (*queryProcessMsgRsp[TDMT_MAX])(void* output, char* msg, int32_t
|
||||||
#define qDebug(...) \
|
#define qDebug(...) \
|
||||||
do { \
|
do { \
|
||||||
if (qDebugFlag & DEBUG_DEBUG) { \
|
if (qDebugFlag & DEBUG_DEBUG) { \
|
||||||
taosPrintLog("QRY ", DEBUG_DEBUG, qDebugFlag, __VA_ARGS__); \
|
taosPrintLog("QRY ", DEBUG_DEBUG, tsLogEmbedded ? 255 : qDebugFlag, __VA_ARGS__); \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
#define qTrace(...) \
|
#define qTrace(...) \
|
||||||
do { \
|
do { \
|
||||||
if (qDebugFlag & DEBUG_TRACE) { \
|
if (qDebugFlag & DEBUG_TRACE) { \
|
||||||
taosPrintLog("QRY ", DEBUG_TRACE, qDebugFlag, __VA_ARGS__); \
|
taosPrintLog("QRY ", DEBUG_TRACE, tsLogEmbedded ? 255 : qDebugFlag, __VA_ARGS__); \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
#define qDebugL(...) \
|
#define qDebugL(...) \
|
||||||
do { \
|
do { \
|
||||||
if (qDebugFlag & DEBUG_DEBUG) { \
|
if (qDebugFlag & DEBUG_DEBUG) { \
|
||||||
taosPrintLongString("QRY ", DEBUG_DEBUG, qDebugFlag, __VA_ARGS__); \
|
taosPrintLongString("QRY ", DEBUG_DEBUG, tsLogEmbedded ? 255 : qDebugFlag, __VA_ARGS__); \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
|
|
@ -1052,7 +1052,8 @@ static int32_t translateUniqueMode(SFunctionNode* pFunc, char* pErrBuf, int32_t
|
||||||
|
|
||||||
SNode* pPara = nodesListGetNode(pFunc->pParameterList, 0);
|
SNode* pPara = nodesListGetNode(pFunc->pParameterList, 0);
|
||||||
if (!nodesExprHasColumn(pPara)) {
|
if (!nodesExprHasColumn(pPara)) {
|
||||||
return buildFuncErrMsg(pErrBuf, len, TSDB_CODE_FUNC_FUNTION_ERROR, "The parameters of %s must contain columns", isUnique ? "UNIQUE" : "MODE");
|
return buildFuncErrMsg(pErrBuf, len, TSDB_CODE_FUNC_FUNTION_ERROR, "The parameters of %s must contain columns",
|
||||||
|
isUnique ? "UNIQUE" : "MODE");
|
||||||
}
|
}
|
||||||
|
|
||||||
pFunc->node.resType = ((SExprNode*)pPara)->resType;
|
pFunc->node.resType = ((SExprNode*)pPara)->resType;
|
||||||
|
@ -1228,19 +1229,19 @@ static int32_t translateSubstr(SFunctionNode* pFunc, char* pErrBuf, int32_t len)
|
||||||
|
|
||||||
static int32_t translateCast(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
|
static int32_t translateCast(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
|
||||||
// The number of parameters has been limited by the syntax definition
|
// The number of parameters has been limited by the syntax definition
|
||||||
//uint8_t para1Type = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 0))->resType.type;
|
// uint8_t para1Type = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 0))->resType.type;
|
||||||
|
|
||||||
// The function return type has been set during syntax parsing
|
// The function return type has been set during syntax parsing
|
||||||
uint8_t para2Type = pFunc->node.resType.type;
|
uint8_t para2Type = pFunc->node.resType.type;
|
||||||
//if (para2Type != TSDB_DATA_TYPE_BIGINT && para2Type != TSDB_DATA_TYPE_UBIGINT &&
|
// if (para2Type != TSDB_DATA_TYPE_BIGINT && para2Type != TSDB_DATA_TYPE_UBIGINT &&
|
||||||
// para2Type != TSDB_DATA_TYPE_VARCHAR && para2Type != TSDB_DATA_TYPE_NCHAR &&
|
// para2Type != TSDB_DATA_TYPE_VARCHAR && para2Type != TSDB_DATA_TYPE_NCHAR &&
|
||||||
// para2Type != TSDB_DATA_TYPE_TIMESTAMP) {
|
// para2Type != TSDB_DATA_TYPE_TIMESTAMP) {
|
||||||
// return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
|
// return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
|
||||||
//}
|
// }
|
||||||
//if ((para2Type == TSDB_DATA_TYPE_TIMESTAMP && IS_VAR_DATA_TYPE(para1Type)) ||
|
// if ((para2Type == TSDB_DATA_TYPE_TIMESTAMP && IS_VAR_DATA_TYPE(para1Type)) ||
|
||||||
// (para2Type == TSDB_DATA_TYPE_BINARY && para1Type == TSDB_DATA_TYPE_NCHAR)) {
|
// (para2Type == TSDB_DATA_TYPE_BINARY && para1Type == TSDB_DATA_TYPE_NCHAR)) {
|
||||||
// return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
|
// return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
|
||||||
//}
|
// }
|
||||||
|
|
||||||
int32_t para2Bytes = pFunc->node.resType.bytes;
|
int32_t para2Bytes = pFunc->node.resType.bytes;
|
||||||
if (IS_VAR_DATA_TYPE(para2Type)) {
|
if (IS_VAR_DATA_TYPE(para2Type)) {
|
||||||
|
@ -1890,7 +1891,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
||||||
{
|
{
|
||||||
.name = "first",
|
.name = "first",
|
||||||
.type = FUNCTION_TYPE_FIRST,
|
.type = FUNCTION_TYPE_FIRST,
|
||||||
.classification = FUNC_MGT_AGG_FUNC | FUNC_MGT_MULTI_RES_FUNC | FUNC_MGT_TIMELINE_FUNC,
|
.classification = FUNC_MGT_AGG_FUNC | FUNC_MGT_SELECT_FUNC | FUNC_MGT_MULTI_RES_FUNC | FUNC_MGT_TIMELINE_FUNC,
|
||||||
.translateFunc = translateFirstLast,
|
.translateFunc = translateFirstLast,
|
||||||
.getEnvFunc = getFirstLastFuncEnv,
|
.getEnvFunc = getFirstLastFuncEnv,
|
||||||
.initFunc = functionSetup,
|
.initFunc = functionSetup,
|
||||||
|
@ -1925,7 +1926,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
||||||
{
|
{
|
||||||
.name = "last",
|
.name = "last",
|
||||||
.type = FUNCTION_TYPE_LAST,
|
.type = FUNCTION_TYPE_LAST,
|
||||||
.classification = FUNC_MGT_AGG_FUNC | FUNC_MGT_MULTI_RES_FUNC | FUNC_MGT_TIMELINE_FUNC,
|
.classification = FUNC_MGT_AGG_FUNC | FUNC_MGT_SELECT_FUNC | FUNC_MGT_MULTI_RES_FUNC | FUNC_MGT_TIMELINE_FUNC,
|
||||||
.translateFunc = translateFirstLast,
|
.translateFunc = translateFirstLast,
|
||||||
.getEnvFunc = getFirstLastFuncEnv,
|
.getEnvFunc = getFirstLastFuncEnv,
|
||||||
.initFunc = functionSetup,
|
.initFunc = functionSetup,
|
||||||
|
@ -2117,7 +2118,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
||||||
{
|
{
|
||||||
.name = "unique",
|
.name = "unique",
|
||||||
.type = FUNCTION_TYPE_UNIQUE,
|
.type = FUNCTION_TYPE_UNIQUE,
|
||||||
.classification = FUNC_MGT_AGG_FUNC | FUNC_MGT_SELECT_FUNC | FUNC_MGT_INDEFINITE_ROWS_FUNC | FUNC_MGT_TIMELINE_FUNC |
|
.classification = FUNC_MGT_SELECT_FUNC | FUNC_MGT_INDEFINITE_ROWS_FUNC | FUNC_MGT_TIMELINE_FUNC |
|
||||||
FUNC_MGT_FORBID_STREAM_FUNC | FUNC_MGT_FORBID_WINDOW_FUNC | FUNC_MGT_FORBID_GROUP_BY_FUNC,
|
FUNC_MGT_FORBID_STREAM_FUNC | FUNC_MGT_FORBID_WINDOW_FUNC | FUNC_MGT_FORBID_GROUP_BY_FUNC,
|
||||||
.translateFunc = translateUnique,
|
.translateFunc = translateUnique,
|
||||||
.getEnvFunc = getUniqueFuncEnv,
|
.getEnvFunc = getUniqueFuncEnv,
|
||||||
|
|
|
@ -100,6 +100,7 @@ static int32_t exprNodeCopy(const SExprNode* pSrc, SExprNode* pDst) {
|
||||||
COPY_OBJECT_FIELD(resType, sizeof(SDataType));
|
COPY_OBJECT_FIELD(resType, sizeof(SDataType));
|
||||||
COPY_CHAR_ARRAY_FIELD(aliasName);
|
COPY_CHAR_ARRAY_FIELD(aliasName);
|
||||||
COPY_CHAR_ARRAY_FIELD(userAlias);
|
COPY_CHAR_ARRAY_FIELD(userAlias);
|
||||||
|
COPY_SCALAR_FIELD(orderAlias);
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1500,7 +1500,8 @@ typedef struct SCollectFuncsCxt {
|
||||||
|
|
||||||
static EDealRes collectFuncs(SNode* pNode, void* pContext) {
|
static EDealRes collectFuncs(SNode* pNode, void* pContext) {
|
||||||
SCollectFuncsCxt* pCxt = (SCollectFuncsCxt*)pContext;
|
SCollectFuncsCxt* pCxt = (SCollectFuncsCxt*)pContext;
|
||||||
if (QUERY_NODE_FUNCTION == nodeType(pNode) && pCxt->classifier(((SFunctionNode*)pNode)->funcId)) {
|
if (QUERY_NODE_FUNCTION == nodeType(pNode) && pCxt->classifier(((SFunctionNode*)pNode)->funcId) &&
|
||||||
|
!(((SExprNode*)pNode)->orderAlias)) {
|
||||||
pCxt->errCode = nodesListStrictAppend(pCxt->pFuncs, nodesCloneNode(pNode));
|
pCxt->errCode = nodesListStrictAppend(pCxt->pFuncs, nodesCloneNode(pNode));
|
||||||
return (TSDB_CODE_SUCCESS == pCxt->errCode ? DEAL_RES_IGNORE_CHILD : DEAL_RES_ERROR);
|
return (TSDB_CODE_SUCCESS == pCxt->errCode ? DEAL_RES_IGNORE_CHILD : DEAL_RES_ERROR);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1355,25 +1355,6 @@ static EDealRes rewriteColToSelectValFunc(STranslateContext* pCxt, SNode** pNode
|
||||||
return TSDB_CODE_SUCCESS == pCxt->errCode ? DEAL_RES_IGNORE_CHILD : DEAL_RES_ERROR;
|
return TSDB_CODE_SUCCESS == pCxt->errCode ? DEAL_RES_IGNORE_CHILD : DEAL_RES_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
static EDealRes rewriteExprToGroupKeyFunc(STranslateContext* pCxt, SNode** pNode) {
|
|
||||||
SFunctionNode* pFunc = (SFunctionNode*)nodesMakeNode(QUERY_NODE_FUNCTION);
|
|
||||||
if (NULL == pFunc) {
|
|
||||||
pCxt->errCode = TSDB_CODE_OUT_OF_MEMORY;
|
|
||||||
return DEAL_RES_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
strcpy(pFunc->functionName, "_group_key");
|
|
||||||
strcpy(pFunc->node.aliasName, ((SExprNode*)*pNode)->aliasName);
|
|
||||||
pCxt->errCode = nodesListMakeAppend(&pFunc->pParameterList, *pNode);
|
|
||||||
if (TSDB_CODE_SUCCESS == pCxt->errCode) {
|
|
||||||
*pNode = (SNode*)pFunc;
|
|
||||||
pCxt->errCode = fmGetFuncInfo(pFunc, pCxt->msgBuf.buf, pCxt->msgBuf.len);
|
|
||||||
}
|
|
||||||
pCxt->pCurrSelectStmt->hasAggFuncs = true;
|
|
||||||
|
|
||||||
return (TSDB_CODE_SUCCESS == pCxt->errCode ? DEAL_RES_IGNORE_CHILD : DEAL_RES_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
static EDealRes doCheckExprForGroupBy(SNode** pNode, void* pContext) {
|
static EDealRes doCheckExprForGroupBy(SNode** pNode, void* pContext) {
|
||||||
SCheckExprForGroupByCxt* pCxt = (SCheckExprForGroupByCxt*)pContext;
|
SCheckExprForGroupByCxt* pCxt = (SCheckExprForGroupByCxt*)pContext;
|
||||||
if (!nodesIsExprNode(*pNode) || isAliasColumn(*pNode)) {
|
if (!nodesIsExprNode(*pNode) || isAliasColumn(*pNode)) {
|
||||||
|
@ -1393,7 +1374,13 @@ static EDealRes doCheckExprForGroupBy(SNode** pNode, void* pContext) {
|
||||||
SNode* pGroupNode = NULL;
|
SNode* pGroupNode = NULL;
|
||||||
FOREACH(pGroupNode, getGroupByList(pCxt->pTranslateCxt)) {
|
FOREACH(pGroupNode, getGroupByList(pCxt->pTranslateCxt)) {
|
||||||
if (nodesEqualNode(getGroupByNode(pGroupNode), *pNode)) {
|
if (nodesEqualNode(getGroupByNode(pGroupNode), *pNode)) {
|
||||||
return rewriteExprToGroupKeyFunc(pCxt->pTranslateCxt, pNode);
|
return DEAL_RES_IGNORE_CHILD;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SNode* pPartKey = NULL;
|
||||||
|
FOREACH(pPartKey, pCxt->pTranslateCxt->pCurrSelectStmt->pPartitionByList) {
|
||||||
|
if (nodesEqualNode(pPartKey, *pNode)) {
|
||||||
|
return DEAL_RES_IGNORE_CHILD;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (isScanPseudoColumnFunc(*pNode) || QUERY_NODE_COLUMN == nodeType(*pNode)) {
|
if (isScanPseudoColumnFunc(*pNode) || QUERY_NODE_COLUMN == nodeType(*pNode)) {
|
||||||
|
@ -1451,25 +1438,6 @@ static int32_t rewriteColsToSelectValFunc(STranslateContext* pCxt, SSelectStmt*
|
||||||
return pCxt->errCode;
|
return pCxt->errCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
static EDealRes rewriteExprsToGroupKeyFuncImpl(SNode** pNode, void* pContext) {
|
|
||||||
STranslateContext* pCxt = pContext;
|
|
||||||
SNode* pPartKey = NULL;
|
|
||||||
FOREACH(pPartKey, pCxt->pCurrSelectStmt->pPartitionByList) {
|
|
||||||
if (nodesEqualNode(pPartKey, *pNode)) {
|
|
||||||
return rewriteExprToGroupKeyFunc(pCxt, pNode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return DEAL_RES_CONTINUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int32_t rewriteExprsToGroupKeyFunc(STranslateContext* pCxt, SSelectStmt* pSelect) {
|
|
||||||
nodesRewriteExprs(pSelect->pProjectionList, rewriteExprsToGroupKeyFuncImpl, pCxt);
|
|
||||||
if (TSDB_CODE_SUCCESS == pCxt->errCode && !pSelect->isDistinct) {
|
|
||||||
nodesRewriteExprs(pSelect->pOrderByList, rewriteExprsToGroupKeyFuncImpl, pCxt);
|
|
||||||
}
|
|
||||||
return pCxt->errCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct CheckAggColCoexistCxt {
|
typedef struct CheckAggColCoexistCxt {
|
||||||
STranslateContext* pTranslateCxt;
|
STranslateContext* pTranslateCxt;
|
||||||
bool existAggFunc;
|
bool existAggFunc;
|
||||||
|
@ -1529,9 +1497,6 @@ static int32_t checkAggColCoexist(STranslateContext* pCxt, SSelectStmt* pSelect)
|
||||||
if (cxt.existIndefiniteRowsFunc && cxt.existCol) {
|
if (cxt.existIndefiniteRowsFunc && cxt.existCol) {
|
||||||
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_NOT_ALLOWED_FUNC);
|
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_NOT_ALLOWED_FUNC);
|
||||||
}
|
}
|
||||||
if (cxt.existAggFunc && NULL != pSelect->pPartitionByList) {
|
|
||||||
return rewriteExprsToGroupKeyFunc(pCxt, pSelect);
|
|
||||||
}
|
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2408,54 +2373,6 @@ static EDealRes rewriteSeletcValueFunc(STranslateContext* pCxt, SNode** pNode) {
|
||||||
return TSDB_CODE_SUCCESS == pCxt->errCode ? DEAL_RES_IGNORE_CHILD : DEAL_RES_ERROR;
|
return TSDB_CODE_SUCCESS == pCxt->errCode ? DEAL_RES_IGNORE_CHILD : DEAL_RES_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
static EDealRes rewriteUniqueFunc(SNode** pNode, void* pContext) {
|
|
||||||
SRwriteUniqueCxt* pCxt = pContext;
|
|
||||||
if (QUERY_NODE_FUNCTION == nodeType(*pNode)) {
|
|
||||||
SFunctionNode* pFunc = (SFunctionNode*)*pNode;
|
|
||||||
if (FUNCTION_TYPE_UNIQUE == pFunc->funcType) {
|
|
||||||
SNode* pExpr = nodesListGetNode(pFunc->pParameterList, 0);
|
|
||||||
NODES_CLEAR_LIST(pFunc->pParameterList);
|
|
||||||
strcpy(((SExprNode*)pExpr)->aliasName, ((SExprNode*)*pNode)->aliasName);
|
|
||||||
nodesDestroyNode(*pNode);
|
|
||||||
*pNode = pExpr;
|
|
||||||
pCxt->pExpr = pExpr;
|
|
||||||
return DEAL_RES_IGNORE_CHILD;
|
|
||||||
} else if (FUNCTION_TYPE_SELECT_VALUE == pFunc->funcType) {
|
|
||||||
return rewriteSeletcValueFunc(pCxt->pTranslateCxt, pNode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return DEAL_RES_CONTINUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static SNode* createGroupingSet(SNode* pExpr) {
|
|
||||||
SGroupingSetNode* pGroupingSet = (SGroupingSetNode*)nodesMakeNode(QUERY_NODE_GROUPING_SET);
|
|
||||||
if (NULL == pGroupingSet) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
pGroupingSet->groupingSetType = GP_TYPE_NORMAL;
|
|
||||||
if (TSDB_CODE_SUCCESS != nodesListMakeStrictAppend(&pGroupingSet->pParameterList, nodesCloneNode(pExpr))) {
|
|
||||||
nodesDestroyNode((SNode*)pGroupingSet);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return (SNode*)pGroupingSet;
|
|
||||||
}
|
|
||||||
|
|
||||||
// from: select unique(expr), col1 + col2 from t where_clause partition_by_clause order_by_clause ...
|
|
||||||
// to: select expr, first(col1) + first(col2) from t where_clause partition_by_clause group by expr order_by_clause ...
|
|
||||||
static int32_t rewriteUniqueStmt(STranslateContext* pCxt, SSelectStmt* pSelect) {
|
|
||||||
if (!pSelect->hasUniqueFunc) {
|
|
||||||
return TSDB_CODE_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
SRwriteUniqueCxt cxt = {.pTranslateCxt = pCxt, .pExpr = NULL};
|
|
||||||
nodesRewriteExprs(pSelect->pProjectionList, rewriteUniqueFunc, &cxt);
|
|
||||||
if (TSDB_CODE_SUCCESS == cxt.pTranslateCxt->errCode) {
|
|
||||||
cxt.pTranslateCxt->errCode = nodesListMakeStrictAppend(&pSelect->pGroupByList, createGroupingSet(cxt.pExpr));
|
|
||||||
}
|
|
||||||
pSelect->hasIndefiniteRowsFunc = false;
|
|
||||||
return cxt.pTranslateCxt->errCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct SReplaceOrderByAliasCxt {
|
typedef struct SReplaceOrderByAliasCxt {
|
||||||
STranslateContext* pTranslateCxt;
|
STranslateContext* pTranslateCxt;
|
||||||
SNodeList* pProjectionList;
|
SNodeList* pProjectionList;
|
||||||
|
@ -2474,6 +2391,7 @@ static EDealRes replaceOrderByAliasImpl(SNode** pNode, void* pContext) {
|
||||||
pCxt->pTranslateCxt->errCode = TSDB_CODE_OUT_OF_MEMORY;
|
pCxt->pTranslateCxt->errCode = TSDB_CODE_OUT_OF_MEMORY;
|
||||||
return DEAL_RES_ERROR;
|
return DEAL_RES_ERROR;
|
||||||
}
|
}
|
||||||
|
((SExprNode*)pNew)->orderAlias = true;
|
||||||
nodesDestroyNode(*pNode);
|
nodesDestroyNode(*pNode);
|
||||||
*pNode = pNew;
|
*pNode = pNew;
|
||||||
return DEAL_RES_CONTINUE;
|
return DEAL_RES_CONTINUE;
|
||||||
|
@ -2529,9 +2447,6 @@ static int32_t translateSelectFrom(STranslateContext* pCxt, SSelectStmt* pSelect
|
||||||
if (TSDB_CODE_SUCCESS == code) {
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
code = translateInterp(pCxt, pSelect);
|
code = translateInterp(pCxt, pSelect);
|
||||||
}
|
}
|
||||||
if (TSDB_CODE_SUCCESS == code) {
|
|
||||||
code = rewriteUniqueStmt(pCxt, pSelect);
|
|
||||||
}
|
|
||||||
if (TSDB_CODE_SUCCESS == code) {
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
code = rewriteTimelineFunc(pCxt, pSelect);
|
code = rewriteTimelineFunc(pCxt, pSelect);
|
||||||
}
|
}
|
||||||
|
|
|
@ -232,8 +232,6 @@ TEST_F(ParserSelectTest, groupBySemanticCheck) {
|
||||||
|
|
||||||
run("SELECT COUNT(*) cnt, c1 FROM t1 WHERE c1 > 0", TSDB_CODE_PAR_NOT_SINGLE_GROUP);
|
run("SELECT COUNT(*) cnt, c1 FROM t1 WHERE c1 > 0", TSDB_CODE_PAR_NOT_SINGLE_GROUP);
|
||||||
run("SELECT COUNT(*) cnt, c2 FROM t1 WHERE c1 > 0 GROUP BY c1", TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION);
|
run("SELECT COUNT(*) cnt, c2 FROM t1 WHERE c1 > 0 GROUP BY c1", TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION);
|
||||||
run("SELECT COUNT(*) cnt, c2 FROM t1 WHERE c1 > 0 PARTITION BY c2 GROUP BY c1",
|
|
||||||
TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserSelectTest, orderBy) {
|
TEST_F(ParserSelectTest, orderBy) {
|
||||||
|
|
|
@ -437,6 +437,33 @@ static SColumnNode* createColumnByExpr(const char* pStmtName, SExprNode* pExpr)
|
||||||
return pCol;
|
return pCol;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static SNode* createGroupingSetNode(SNode* pExpr) {
|
||||||
|
SGroupingSetNode* pGroupingSet = (SGroupingSetNode*)nodesMakeNode(QUERY_NODE_GROUPING_SET);
|
||||||
|
if (NULL == pGroupingSet) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
pGroupingSet->groupingSetType = GP_TYPE_NORMAL;
|
||||||
|
if (TSDB_CODE_SUCCESS != nodesListMakeStrictAppend(&pGroupingSet->pParameterList, nodesCloneNode(pExpr))) {
|
||||||
|
nodesDestroyNode((SNode*)pGroupingSet);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return (SNode*)pGroupingSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t createGroupKeysFromPartKeys(SNodeList* pPartKeys, SNodeList** pOutput) {
|
||||||
|
SNodeList* pGroupKeys = NULL;
|
||||||
|
SNode* pPartKey = NULL;
|
||||||
|
FOREACH(pPartKey, pPartKeys) {
|
||||||
|
int32_t code = nodesListMakeStrictAppend(&pGroupKeys, createGroupingSetNode(pPartKey));
|
||||||
|
if (TSDB_CODE_SUCCESS != code) {
|
||||||
|
nodesDestroyList(pGroupKeys);
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*pOutput = pGroupKeys;
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
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) {
|
if (!pSelect->hasAggFuncs && NULL == pSelect->pGroupByList) {
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
|
@ -459,10 +486,18 @@ static int32_t createAggLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect,
|
||||||
code = rewriteExprsForSelect(pAgg->pAggFuncs, pSelect, SQL_CLAUSE_GROUP_BY);
|
code = rewriteExprsForSelect(pAgg->pAggFuncs, pSelect, SQL_CLAUSE_GROUP_BY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (NULL != pSelect->pPartitionByList) {
|
||||||
|
code = createGroupKeysFromPartKeys(pSelect->pPartitionByList, &pAgg->pGroupKeys);
|
||||||
|
}
|
||||||
|
|
||||||
if (NULL != pSelect->pGroupByList) {
|
if (NULL != pSelect->pGroupByList) {
|
||||||
pAgg->pGroupKeys = nodesCloneList(pSelect->pGroupByList);
|
if (NULL != pAgg->pGroupKeys) {
|
||||||
if (NULL == pAgg->pGroupKeys) {
|
code = nodesListStrictAppendList(pAgg->pGroupKeys, nodesCloneList(pSelect->pGroupByList));
|
||||||
code = TSDB_CODE_OUT_OF_MEMORY;
|
} else {
|
||||||
|
pAgg->pGroupKeys = nodesCloneList(pSelect->pGroupByList);
|
||||||
|
if (NULL == pAgg->pGroupKeys) {
|
||||||
|
code = TSDB_CODE_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -508,6 +543,7 @@ static int32_t createIndefRowsFuncLogicNode(SLogicPlanContext* pCxt, SSelectStmt
|
||||||
}
|
}
|
||||||
|
|
||||||
pIdfRowsFunc->isTailFunc = pSelect->hasTailFunc;
|
pIdfRowsFunc->isTailFunc = pSelect->hasTailFunc;
|
||||||
|
pIdfRowsFunc->isUniqueFunc = pSelect->hasUniqueFunc;
|
||||||
|
|
||||||
// indefinite rows functions and _select_values functions
|
// indefinite rows functions and _select_values functions
|
||||||
int32_t code = nodesCollectFuncs(pSelect, SQL_CLAUSE_SELECT, fmIsVectorFunc, &pIdfRowsFunc->pFuncs);
|
int32_t code = nodesCollectFuncs(pSelect, SQL_CLAUSE_SELECT, fmIsVectorFunc, &pIdfRowsFunc->pFuncs);
|
||||||
|
@ -809,7 +845,8 @@ static int32_t createProjectLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSel
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t createPartitionLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SLogicNode** pLogicNode) {
|
static int32_t createPartitionLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SLogicNode** pLogicNode) {
|
||||||
if (NULL == pSelect->pPartitionByList) {
|
if (NULL == pSelect->pPartitionByList || (pSelect->hasAggFuncs && NULL == pSelect->pWindow) ||
|
||||||
|
NULL != pSelect->pGroupByList) {
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -987,6 +987,7 @@ static int32_t smaIndexOptimizeImpl(SOptimizeContext* pCxt, SLogicSubplan* pLogi
|
||||||
code = smaIndexOptApplyIndex(pLogicSubplan, pScan, pIndex, pSmaCols, wstrartIndex);
|
code = smaIndexOptApplyIndex(pLogicSubplan, pScan, pIndex, pSmaCols, wstrartIndex);
|
||||||
taosArrayDestroyEx(pScan->pSmaIndexes, smaIndexOptDestroySmaIndex);
|
taosArrayDestroyEx(pScan->pSmaIndexes, smaIndexOptDestroySmaIndex);
|
||||||
pScan->pSmaIndexes = NULL;
|
pScan->pSmaIndexes = NULL;
|
||||||
|
pCxt->optimized = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1033,12 +1034,30 @@ static SNodeList* partTagsGetPartKeys(SLogicNode* pNode) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static SNodeList* partTagsGetFuncs(SLogicNode* pNode) {
|
||||||
|
if (QUERY_NODE_LOGIC_PLAN_PARTITION == nodeType(pNode)) {
|
||||||
|
return NULL;
|
||||||
|
} else {
|
||||||
|
return ((SAggLogicNode*)pNode)->pAggFuncs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool partTagsOptAreSupportedFuncs(SNodeList* pFuncs) {
|
||||||
|
SNode* pFunc = NULL;
|
||||||
|
FOREACH(pFunc, pFuncs) {
|
||||||
|
if (fmIsIndefiniteRowsFunc(((SFunctionNode*)pFunc)->funcId) && !fmIsSelectFunc(((SFunctionNode*)pFunc)->funcId)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static bool partTagsOptMayBeOptimized(SLogicNode* pNode) {
|
static bool partTagsOptMayBeOptimized(SLogicNode* pNode) {
|
||||||
if (!partTagsIsOptimizableNode(pNode)) {
|
if (!partTagsIsOptimizableNode(pNode)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return !partTagsOptHasCol(partTagsGetPartKeys(pNode));
|
return !partTagsOptHasCol(partTagsGetPartKeys(pNode)) && partTagsOptAreSupportedFuncs(partTagsGetFuncs(pNode));
|
||||||
}
|
}
|
||||||
|
|
||||||
static EDealRes partTagsOptRebuildTbanmeImpl(SNode** pNode, void* pContext) {
|
static EDealRes partTagsOptRebuildTbanmeImpl(SNode** pNode, void* pContext) {
|
||||||
|
@ -1064,6 +1083,59 @@ static int32_t partTagsOptRebuildTbanme(SNodeList* pPartKeys) {
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static SNode* partTagsCreateWrapperFunc(const char* pFuncName, SNode* pNode) {
|
||||||
|
SFunctionNode* pFunc = (SFunctionNode*)nodesMakeNode(QUERY_NODE_FUNCTION);
|
||||||
|
if (NULL == pFunc) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(pFunc->functionName, pFuncName);
|
||||||
|
if (QUERY_NODE_COLUMN == nodeType(pNode)) {
|
||||||
|
SColumnNode* pCol = (SColumnNode*)pNode;
|
||||||
|
sprintf(pFunc->node.aliasName, "%s.%s", pCol->tableAlias, pCol->colName);
|
||||||
|
} else {
|
||||||
|
strcpy(pFunc->node.aliasName, ((SExprNode*)pNode)->aliasName);
|
||||||
|
}
|
||||||
|
int32_t code = nodesListMakeStrictAppend(&pFunc->pParameterList, nodesCloneNode(pNode));
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = fmGetFuncInfo(pFunc, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TSDB_CODE_SUCCESS != code) {
|
||||||
|
nodesDestroyNode((SNode*)pFunc);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (SNode*)pFunc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool partTagsHasIndefRowsSelectFunc(SNodeList* pFuncs) {
|
||||||
|
SNode* pFunc = NULL;
|
||||||
|
FOREACH(pFunc, pFuncs) {
|
||||||
|
if (fmIsIndefiniteRowsFunc(((SFunctionNode*)pFunc)->funcId)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t partTagsRewriteGroupTagsToFuncs(SNodeList* pGroupTags, SNodeList* pAggFuncs) {
|
||||||
|
bool hasIndefRowsSelectFunc = partTagsHasIndefRowsSelectFunc(pAggFuncs);
|
||||||
|
int32_t code = TSDB_CODE_SUCCESS;
|
||||||
|
SNode* pNode = NULL;
|
||||||
|
FOREACH(pNode, pGroupTags) {
|
||||||
|
if (hasIndefRowsSelectFunc) {
|
||||||
|
code = nodesListStrictAppend(pAggFuncs, partTagsCreateWrapperFunc("_select_value", pNode));
|
||||||
|
} else {
|
||||||
|
code = nodesListStrictAppend(pAggFuncs, partTagsCreateWrapperFunc("_group_key", pNode));
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS != code) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
static int32_t partTagsOptimize(SOptimizeContext* pCxt, SLogicSubplan* pLogicSubplan) {
|
static int32_t partTagsOptimize(SOptimizeContext* pCxt, SLogicSubplan* pLogicSubplan) {
|
||||||
SLogicNode* pNode = optFindPossibleNode(pLogicSubplan->pNode, partTagsOptMayBeOptimized);
|
SLogicNode* pNode = optFindPossibleNode(pLogicSubplan->pNode, partTagsOptMayBeOptimized);
|
||||||
if (NULL == pNode) {
|
if (NULL == pNode) {
|
||||||
|
@ -1080,15 +1152,17 @@ static int32_t partTagsOptimize(SOptimizeContext* pCxt, SLogicSubplan* pLogicSub
|
||||||
nodesDestroyNode((SNode*)pNode);
|
nodesDestroyNode((SNode*)pNode);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
SNode* pGroupKey = NULL;
|
SAggLogicNode* pAgg = (SAggLogicNode*)pNode;
|
||||||
FOREACH(pGroupKey, ((SAggLogicNode*)pNode)->pGroupKeys) {
|
SNode* pGroupKey = NULL;
|
||||||
|
FOREACH(pGroupKey, pAgg->pGroupKeys) {
|
||||||
code = nodesListMakeStrictAppend(
|
code = nodesListMakeStrictAppend(
|
||||||
&pScan->pGroupTags, nodesCloneNode(nodesListGetNode(((SGroupingSetNode*)pGroupKey)->pParameterList, 0)));
|
&pScan->pGroupTags, nodesCloneNode(nodesListGetNode(((SGroupingSetNode*)pGroupKey)->pParameterList, 0)));
|
||||||
if (TSDB_CODE_SUCCESS != code) {
|
if (TSDB_CODE_SUCCESS != code) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NODES_DESTORY_LIST(((SAggLogicNode*)pNode)->pGroupKeys);
|
NODES_DESTORY_LIST(pAgg->pGroupKeys);
|
||||||
|
code = partTagsRewriteGroupTagsToFuncs(pScan->pGroupTags, pAgg->pAggFuncs);
|
||||||
}
|
}
|
||||||
if (TSDB_CODE_SUCCESS == code) {
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
code = partTagsOptRebuildTbanme(pScan->pGroupTags);
|
code = partTagsOptRebuildTbanme(pScan->pGroupTags);
|
||||||
|
@ -1125,7 +1199,8 @@ static bool eliminateProjOptMayBeOptimized(SLogicNode* pNode) {
|
||||||
}
|
}
|
||||||
|
|
||||||
SProjectLogicNode* pProjectNode = (SProjectLogicNode*)pNode;
|
SProjectLogicNode* pProjectNode = (SProjectLogicNode*)pNode;
|
||||||
if (NULL != pProjectNode->node.pLimit || NULL != pProjectNode->node.pSlimit) {
|
if (NULL != pProjectNode->node.pLimit || NULL != pProjectNode->node.pSlimit ||
|
||||||
|
NULL != pProjectNode->node.pConditions) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1163,6 +1238,7 @@ static int32_t eliminateProjOptimizeImpl(SOptimizeContext* pCxt, SLogicSubplan*
|
||||||
NODES_CLEAR_LIST(pProjectNode->node.pChildren);
|
NODES_CLEAR_LIST(pProjectNode->node.pChildren);
|
||||||
nodesDestroyNode((SNode*)pProjectNode);
|
nodesDestroyNode((SNode*)pProjectNode);
|
||||||
}
|
}
|
||||||
|
pCxt->optimized = true;
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1306,6 +1382,7 @@ static int32_t rewriteTailOptimizeImpl(SOptimizeContext* pCxt, SLogicSubplan* pL
|
||||||
nodesDestroyNode((SNode*)pSort);
|
nodesDestroyNode((SNode*)pSort);
|
||||||
nodesDestroyNode((SNode*)pProject);
|
nodesDestroyNode((SNode*)pProject);
|
||||||
}
|
}
|
||||||
|
pCxt->optimized = true;
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1344,6 +1421,7 @@ static int32_t eliminateSetOpOptimizeImpl(SOptimizeContext* pCxt, SLogicSubplan*
|
||||||
|
|
||||||
pSetOpNode->pChildren = NULL;
|
pSetOpNode->pChildren = NULL;
|
||||||
ERASE_NODE(pSetOpNode->pParent->pChildren);
|
ERASE_NODE(pSetOpNode->pParent->pChildren);
|
||||||
|
pCxt->optimized = true;
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1360,15 +1438,192 @@ static int32_t eliminateSetOpOptimize(SOptimizeContext* pCxt, SLogicSubplan* pLo
|
||||||
return eliminateSetOpOptimizeImpl(pCxt, pLogicSubplan, pSetOpNode);
|
return eliminateSetOpOptimizeImpl(pCxt, pLogicSubplan, pSetOpNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
//===================================================================================================================
|
static bool rewriteUniqueOptMayBeOptimized(SLogicNode* pNode) {
|
||||||
|
return QUERY_NODE_LOGIC_PLAN_INDEF_ROWS_FUNC == nodeType(pNode) && ((SIndefRowsFuncLogicNode*)pNode)->isUniqueFunc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SNode* rewriteUniqueOptCreateGroupingSet(SNode* pExpr) {
|
||||||
|
SGroupingSetNode* pGroupingSet = (SGroupingSetNode*)nodesMakeNode(QUERY_NODE_GROUPING_SET);
|
||||||
|
if (NULL == pGroupingSet) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
pGroupingSet->groupingSetType = GP_TYPE_NORMAL;
|
||||||
|
SExprNode* pGroupExpr = (SExprNode*)nodesCloneNode(pExpr);
|
||||||
|
if (TSDB_CODE_SUCCESS != nodesListMakeStrictAppend(&pGroupingSet->pParameterList, (SNode*)pGroupExpr)) {
|
||||||
|
nodesDestroyNode((SNode*)pGroupingSet);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return (SNode*)pGroupingSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SNode* rewriteUniqueOptCreateFirstFunc(SFunctionNode* pSelectValue, SNode* pCol) {
|
||||||
|
SFunctionNode* pFunc = (SFunctionNode*)nodesMakeNode(QUERY_NODE_FUNCTION);
|
||||||
|
if (NULL == pFunc) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(pFunc->functionName, "first");
|
||||||
|
if (NULL != pSelectValue) {
|
||||||
|
sprintf(pFunc->node.aliasName, "%s", pSelectValue->node.aliasName);
|
||||||
|
} else {
|
||||||
|
sprintf(pFunc->node.aliasName, "%s.%p", pFunc->functionName, pFunc);
|
||||||
|
}
|
||||||
|
int32_t code = nodesListMakeStrictAppend(&pFunc->pParameterList, nodesCloneNode(pCol));
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = fmGetFuncInfo(pFunc, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TSDB_CODE_SUCCESS != code) {
|
||||||
|
nodesDestroyNode((SNode*)pFunc);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (SNode*)pFunc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t rewriteUniqueOptCreateAgg(SIndefRowsFuncLogicNode* pIndef, SLogicNode** pOutput) {
|
||||||
|
SAggLogicNode* pAgg = (SAggLogicNode*)nodesMakeNode(QUERY_NODE_LOGIC_PLAN_AGG);
|
||||||
|
if (NULL == pAgg) {
|
||||||
|
return TSDB_CODE_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
TSWAP(pAgg->node.pChildren, pIndef->node.pChildren);
|
||||||
|
pAgg->node.precision = pIndef->node.precision;
|
||||||
|
|
||||||
|
int32_t code = TSDB_CODE_SUCCESS;
|
||||||
|
bool hasSelectPrimaryKey = false;
|
||||||
|
SNode* pPrimaryKey = NULL;
|
||||||
|
SNode* pNode = NULL;
|
||||||
|
FOREACH(pNode, pIndef->pFuncs) {
|
||||||
|
SFunctionNode* pFunc = (SFunctionNode*)pNode;
|
||||||
|
SNode* pExpr = nodesListGetNode(pFunc->pParameterList, 0);
|
||||||
|
if (FUNCTION_TYPE_UNIQUE == pFunc->funcType) {
|
||||||
|
pPrimaryKey = nodesListGetNode(pFunc->pParameterList, 1);
|
||||||
|
code = nodesListMakeStrictAppend(&pAgg->pGroupKeys, rewriteUniqueOptCreateGroupingSet(pExpr));
|
||||||
|
} else if (PRIMARYKEY_TIMESTAMP_COL_ID == ((SColumnNode*)pExpr)->colId) { // _select_value(ts) => first(ts)
|
||||||
|
hasSelectPrimaryKey = true;
|
||||||
|
code = nodesListMakeStrictAppend(&pAgg->pAggFuncs, rewriteUniqueOptCreateFirstFunc(pFunc, pExpr));
|
||||||
|
} else { // _select_value(other_col)
|
||||||
|
code = nodesListMakeStrictAppend(&pAgg->pAggFuncs, nodesCloneNode(pNode));
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS != code) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = createColumnByRewriteExprs(pAgg->pGroupKeys, &pAgg->node.pTargets);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code && NULL != pAgg->pAggFuncs) {
|
||||||
|
code = createColumnByRewriteExprs(pAgg->pAggFuncs, &pAgg->node.pTargets);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TSDB_CODE_SUCCESS == code && !hasSelectPrimaryKey && NULL != pAgg->pAggFuncs) {
|
||||||
|
code = nodesListMakeStrictAppend(&pAgg->pAggFuncs, rewriteUniqueOptCreateFirstFunc(NULL, pPrimaryKey));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
*pOutput = (SLogicNode*)pAgg;
|
||||||
|
} else {
|
||||||
|
nodesDestroyNode((SNode*)pAgg);
|
||||||
|
}
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SNode* rewriteUniqueOptCreateProjectCol(SFunctionNode* pFunc) {
|
||||||
|
SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN);
|
||||||
|
if (NULL == pCol) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pCol->node.resType = pFunc->node.resType;
|
||||||
|
if (FUNCTION_TYPE_UNIQUE == pFunc->funcType) {
|
||||||
|
SExprNode* pExpr = (SExprNode*)nodesListGetNode(pFunc->pParameterList, 0);
|
||||||
|
if (QUERY_NODE_COLUMN == nodeType(pExpr)) {
|
||||||
|
strcpy(pCol->tableAlias, ((SColumnNode*)pExpr)->tableAlias);
|
||||||
|
strcpy(pCol->colName, ((SColumnNode*)pExpr)->colName);
|
||||||
|
} else {
|
||||||
|
strcpy(pCol->colName, pExpr->aliasName);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
strcpy(pCol->colName, pFunc->node.aliasName);
|
||||||
|
}
|
||||||
|
strcpy(pCol->node.aliasName, pFunc->node.aliasName);
|
||||||
|
|
||||||
|
return (SNode*)pCol;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t rewriteUniqueOptCreateProject(SIndefRowsFuncLogicNode* pIndef, SLogicNode** pOutput) {
|
||||||
|
SProjectLogicNode* pProject = (SProjectLogicNode*)nodesMakeNode(QUERY_NODE_LOGIC_PLAN_PROJECT);
|
||||||
|
if (NULL == pProject) {
|
||||||
|
return TSDB_CODE_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
TSWAP(pProject->node.pTargets, pIndef->node.pTargets);
|
||||||
|
pProject->node.precision = pIndef->node.precision;
|
||||||
|
|
||||||
|
int32_t code = TSDB_CODE_SUCCESS;
|
||||||
|
SNode* pNode = NULL;
|
||||||
|
FOREACH(pNode, pIndef->pFuncs) {
|
||||||
|
code = nodesListMakeStrictAppend(&pProject->pProjections, rewriteUniqueOptCreateProjectCol((SFunctionNode*)pNode));
|
||||||
|
if (TSDB_CODE_SUCCESS != code) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
*pOutput = (SLogicNode*)pProject;
|
||||||
|
} else {
|
||||||
|
nodesDestroyNode((SNode*)pProject);
|
||||||
|
}
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t rewriteUniqueOptimizeImpl(SOptimizeContext* pCxt, SLogicSubplan* pLogicSubplan,
|
||||||
|
SIndefRowsFuncLogicNode* pIndef) {
|
||||||
|
SLogicNode* pAgg = NULL;
|
||||||
|
SLogicNode* pProject = NULL;
|
||||||
|
int32_t code = rewriteUniqueOptCreateAgg(pIndef, &pAgg);
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = rewriteUniqueOptCreateProject(pIndef, &pProject);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = nodesListMakeAppend(&pProject->pChildren, (SNode*)pAgg);
|
||||||
|
pAgg->pParent = pProject;
|
||||||
|
pAgg = NULL;
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = replaceLogicNode(pLogicSubplan, (SLogicNode*)pIndef, pProject);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
nodesDestroyNode((SNode*)pIndef);
|
||||||
|
} else {
|
||||||
|
nodesDestroyNode((SNode*)pAgg);
|
||||||
|
nodesDestroyNode((SNode*)pProject);
|
||||||
|
}
|
||||||
|
pCxt->optimized = true;
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t rewriteUniqueOptimize(SOptimizeContext* pCxt, SLogicSubplan* pLogicSubplan) {
|
||||||
|
SIndefRowsFuncLogicNode* pIndef =
|
||||||
|
(SIndefRowsFuncLogicNode*)optFindPossibleNode(pLogicSubplan->pNode, rewriteUniqueOptMayBeOptimized);
|
||||||
|
|
||||||
|
if (NULL == pIndef) {
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rewriteUniqueOptimizeImpl(pCxt, pLogicSubplan, pIndef);
|
||||||
|
}
|
||||||
|
|
||||||
// merge projects
|
// merge projects
|
||||||
static bool mergeProjectsMayBeOptimized(SLogicNode* pNode) {
|
static bool mergeProjectsMayBeOptimized(SLogicNode* pNode) {
|
||||||
if (QUERY_NODE_LOGIC_PLAN_PROJECT != nodeType(pNode) || 1 != LIST_LENGTH(pNode->pChildren)) {
|
if (QUERY_NODE_LOGIC_PLAN_PROJECT != nodeType(pNode) || 1 != LIST_LENGTH(pNode->pChildren)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
SLogicNode *pChild = (SLogicNode*)nodesListGetNode(pNode->pChildren, 0);
|
SLogicNode* pChild = (SLogicNode*)nodesListGetNode(pNode->pChildren, 0);
|
||||||
if (QUERY_NODE_LOGIC_PLAN_PROJECT != nodeType(pChild) || 1 < LIST_LENGTH(pChild->pChildren) ||
|
if (QUERY_NODE_LOGIC_PLAN_PROJECT != nodeType(pChild) || 1 < LIST_LENGTH(pChild->pChildren) ||
|
||||||
NULL != pChild->pConditions || NULL != pNode->pLimit || NULL != pNode->pSlimit) {
|
NULL != pChild->pConditions || NULL != pChild->pLimit || NULL != pChild->pSlimit) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -1376,12 +1631,12 @@ static bool mergeProjectsMayBeOptimized(SLogicNode* pNode) {
|
||||||
|
|
||||||
typedef struct SMergeProjectionsContext {
|
typedef struct SMergeProjectionsContext {
|
||||||
SProjectLogicNode* pChildProj;
|
SProjectLogicNode* pChildProj;
|
||||||
int32_t errCode;
|
int32_t errCode;
|
||||||
} SMergeProjectionsContext;
|
} SMergeProjectionsContext;
|
||||||
|
|
||||||
static EDealRes mergeProjectionsExpr(SNode** pNode, void* pContext) {
|
static EDealRes mergeProjectionsExpr(SNode** pNode, void* pContext) {
|
||||||
SMergeProjectionsContext* pCxt = pContext;
|
SMergeProjectionsContext* pCxt = pContext;
|
||||||
SProjectLogicNode* pChildProj = pCxt->pChildProj;
|
SProjectLogicNode* pChildProj = pCxt->pChildProj;
|
||||||
if (QUERY_NODE_COLUMN == nodeType(*pNode)) {
|
if (QUERY_NODE_COLUMN == nodeType(*pNode)) {
|
||||||
SNode* pTarget;
|
SNode* pTarget;
|
||||||
FOREACH(pTarget, ((SLogicNode*)pChildProj)->pTargets) {
|
FOREACH(pTarget, ((SLogicNode*)pChildProj)->pTargets) {
|
||||||
|
@ -1406,7 +1661,7 @@ static EDealRes mergeProjectionsExpr(SNode** pNode, void* pContext) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t mergeProjectsOptimizeImpl(SOptimizeContext* pCxt, SLogicSubplan* pLogicSubplan, SLogicNode* pSelfNode) {
|
static int32_t mergeProjectsOptimizeImpl(SOptimizeContext* pCxt, SLogicSubplan* pLogicSubplan, SLogicNode* pSelfNode) {
|
||||||
SLogicNode* pChild = (SLogicNode*)nodesListGetNode(pSelfNode->pChildren, 0);
|
SLogicNode* pChild = (SLogicNode*)nodesListGetNode(pSelfNode->pChildren, 0);
|
||||||
SMergeProjectionsContext cxt = {.pChildProj = (SProjectLogicNode*)pChild, .errCode = TSDB_CODE_SUCCESS};
|
SMergeProjectionsContext cxt = {.pChildProj = (SProjectLogicNode*)pChild, .errCode = TSDB_CODE_SUCCESS};
|
||||||
|
|
||||||
nodesRewriteExprs(((SProjectLogicNode*)pSelfNode)->pProjections, mergeProjectionsExpr, &cxt);
|
nodesRewriteExprs(((SProjectLogicNode*)pSelfNode)->pProjections, mergeProjectionsExpr, &cxt);
|
||||||
|
@ -1425,6 +1680,7 @@ static int32_t mergeProjectsOptimizeImpl(SOptimizeContext* pCxt, SLogicSubplan*
|
||||||
NODES_CLEAR_LIST(pChild->pChildren);
|
NODES_CLEAR_LIST(pChild->pChildren);
|
||||||
}
|
}
|
||||||
nodesDestroyNode((SNode*)pChild);
|
nodesDestroyNode((SNode*)pChild);
|
||||||
|
pCxt->optimized = true;
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1447,23 +1703,37 @@ static const SOptimizeRule optimizeRuleSet[] = {
|
||||||
{.pName = "MergeProjects", .optimizeFunc = mergeProjectsOptimize},
|
{.pName = "MergeProjects", .optimizeFunc = mergeProjectsOptimize},
|
||||||
{.pName = "EliminateProject", .optimizeFunc = eliminateProjOptimize},
|
{.pName = "EliminateProject", .optimizeFunc = eliminateProjOptimize},
|
||||||
{.pName = "EliminateSetOperator", .optimizeFunc = eliminateSetOpOptimize},
|
{.pName = "EliminateSetOperator", .optimizeFunc = eliminateSetOpOptimize},
|
||||||
{.pName = "RewriteTail", .optimizeFunc = rewriteTailOptimize}
|
{.pName = "RewriteTail", .optimizeFunc = rewriteTailOptimize},
|
||||||
|
{.pName = "RewriteUnique", .optimizeFunc = rewriteUniqueOptimize}
|
||||||
};
|
};
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
static const int32_t optimizeRuleNum = (sizeof(optimizeRuleSet) / sizeof(SOptimizeRule));
|
static const int32_t optimizeRuleNum = (sizeof(optimizeRuleSet) / sizeof(SOptimizeRule));
|
||||||
|
|
||||||
|
static void dumpLogicSubplan(const char* pRuleName, SLogicSubplan* pSubplan) {
|
||||||
|
char* pStr = NULL;
|
||||||
|
nodesNodeToString((SNode*)pSubplan, false, &pStr, NULL);
|
||||||
|
qDebugL("apply optimize %s rule: %s", pRuleName, pStr);
|
||||||
|
taosMemoryFree(pStr);
|
||||||
|
}
|
||||||
|
|
||||||
static int32_t applyOptimizeRule(SPlanContext* pCxt, SLogicSubplan* pLogicSubplan) {
|
static int32_t applyOptimizeRule(SPlanContext* pCxt, SLogicSubplan* pLogicSubplan) {
|
||||||
SOptimizeContext cxt = {.pPlanCxt = pCxt, .optimized = false};
|
SOptimizeContext cxt = {.pPlanCxt = pCxt, .optimized = false};
|
||||||
|
bool optimized = false;
|
||||||
do {
|
do {
|
||||||
cxt.optimized = false;
|
optimized = false;
|
||||||
for (int32_t i = 0; i < optimizeRuleNum; ++i) {
|
for (int32_t i = 0; i < optimizeRuleNum; ++i) {
|
||||||
|
cxt.optimized = false;
|
||||||
int32_t code = optimizeRuleSet[i].optimizeFunc(&cxt, pLogicSubplan);
|
int32_t code = optimizeRuleSet[i].optimizeFunc(&cxt, pLogicSubplan);
|
||||||
if (TSDB_CODE_SUCCESS != code) {
|
if (TSDB_CODE_SUCCESS != code) {
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
if (cxt.optimized) {
|
||||||
|
optimized = true;
|
||||||
|
dumpLogicSubplan(optimizeRuleSet[i].pName, pLogicSubplan);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} while (cxt.optimized);
|
} while (optimized);
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1237,7 +1237,7 @@ static const int32_t splitRuleNum = (sizeof(splitRuleSet) / sizeof(SSplitRule));
|
||||||
static void dumpLogicSubplan(const char* pRuleName, SLogicSubplan* pSubplan) {
|
static void dumpLogicSubplan(const char* pRuleName, SLogicSubplan* pSubplan) {
|
||||||
char* pStr = NULL;
|
char* pStr = NULL;
|
||||||
nodesNodeToString((SNode*)pSubplan, false, &pStr, NULL);
|
nodesNodeToString((SNode*)pSubplan, false, &pStr, NULL);
|
||||||
qDebugL("apply %s rule: %s", pRuleName, pStr);
|
qDebugL("apply split %s rule: %s", pRuleName, pStr);
|
||||||
taosMemoryFree(pStr);
|
taosMemoryFree(pStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -85,6 +85,11 @@ int32_t qSetSubplanExecutionNode(SSubplan* subplan, int32_t groupId, SDownstream
|
||||||
return setSubplanExecutionNode(subplan->pNode, groupId, pSource);
|
return setSubplanExecutionNode(subplan->pNode, groupId, pSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32_t qClearSubplanExecutionNode(SSubplan* pSubplan, int32_t groupId) {
|
||||||
|
// todo
|
||||||
|
return TSDB_CODE_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
int32_t qSubPlanToString(const SSubplan* pSubplan, char** pStr, int32_t* pLen) {
|
int32_t qSubPlanToString(const SSubplan* pSubplan, char** pStr, int32_t* pLen) {
|
||||||
if (SUBPLAN_TYPE_MODIFY == pSubplan->subplanType && NULL == pSubplan->pNode) {
|
if (SUBPLAN_TYPE_MODIFY == pSubplan->subplanType && NULL == pSubplan->pNode) {
|
||||||
SDataInserterNode* insert = (SDataInserterNode*)pSubplan->pDataSink;
|
SDataInserterNode* insert = (SDataInserterNode*)pSubplan->pDataSink;
|
||||||
|
|
|
@ -56,6 +56,8 @@ TEST_F(PlanBasicTest, uniqueFunc) {
|
||||||
|
|
||||||
run("SELECT UNIQUE(c2 + 10) FROM t1 WHERE c1 > 10");
|
run("SELECT UNIQUE(c2 + 10) FROM t1 WHERE c1 > 10");
|
||||||
|
|
||||||
|
run("SELECT UNIQUE(c2 + 10), c2 FROM t1 WHERE c1 > 10");
|
||||||
|
|
||||||
run("SELECT UNIQUE(c2 + 10), ts, c2 FROM t1 WHERE c1 > 10");
|
run("SELECT UNIQUE(c2 + 10), ts, c2 FROM t1 WHERE c1 > 10");
|
||||||
|
|
||||||
run("SELECT UNIQUE(c1) a FROM t1 ORDER BY a");
|
run("SELECT UNIQUE(c1) a FROM t1 ORDER BY a");
|
||||||
|
@ -75,6 +77,8 @@ TEST_F(PlanBasicTest, tailFunc) {
|
||||||
run("SELECT TAIL(c2 + 10, 10, 80) FROM t1 WHERE c1 > 10 LIMIT 5");
|
run("SELECT TAIL(c2 + 10, 10, 80) FROM t1 WHERE c1 > 10 LIMIT 5");
|
||||||
|
|
||||||
run("SELECT TAIL(c2 + 10, 10, 80) FROM t1 WHERE c1 > 10 PARTITION BY c1 LIMIT 5");
|
run("SELECT TAIL(c2 + 10, 10, 80) FROM t1 WHERE c1 > 10 PARTITION BY c1 LIMIT 5");
|
||||||
|
|
||||||
|
run("SELECT TAIL(c1, 2, 1) FROM st1s1 UNION ALL SELECT c1 FROM st1s2");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(PlanBasicTest, interpFunc) {
|
TEST_F(PlanBasicTest, interpFunc) {
|
||||||
|
@ -97,6 +101,16 @@ TEST_F(PlanBasicTest, lastRowFunc) {
|
||||||
run("SELECT LAST_ROW(c1) FROM st1");
|
run("SELECT LAST_ROW(c1) FROM st1");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(PlanBasicTest, sampleFunc) {
|
||||||
|
useDb("root", "test");
|
||||||
|
|
||||||
|
run("SELECT SAMPLE(c1, 10) FROM t1");
|
||||||
|
|
||||||
|
run("SELECT SAMPLE(c1, 10) FROM st1");
|
||||||
|
|
||||||
|
run("SELECT SAMPLE(c1, 10) FROM st1 PARTITION BY TBNAME");
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(PlanBasicTest, withoutFrom) {
|
TEST_F(PlanBasicTest, withoutFrom) {
|
||||||
useDb("root", "test");
|
useDb("root", "test");
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ using namespace std;
|
||||||
|
|
||||||
class PlanOptimizeTest : public PlannerTestBase {};
|
class PlanOptimizeTest : public PlannerTestBase {};
|
||||||
|
|
||||||
TEST_F(PlanOptimizeTest, optimizeScanData) {
|
TEST_F(PlanOptimizeTest, scanPath) {
|
||||||
useDb("root", "test");
|
useDb("root", "test");
|
||||||
|
|
||||||
run("SELECT COUNT(*) FROM t1");
|
run("SELECT COUNT(*) FROM t1");
|
||||||
|
@ -32,7 +32,7 @@ TEST_F(PlanOptimizeTest, optimizeScanData) {
|
||||||
run("SELECT PERCENTILE(c1, 40), COUNT(*) FROM t1");
|
run("SELECT PERCENTILE(c1, 40), COUNT(*) FROM t1");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(PlanOptimizeTest, ConditionPushDown) {
|
TEST_F(PlanOptimizeTest, pushDownCondition) {
|
||||||
useDb("root", "test");
|
useDb("root", "test");
|
||||||
|
|
||||||
run("SELECT ts, c1 FROM st1 WHERE tag1 > 4");
|
run("SELECT ts, c1 FROM st1 WHERE tag1 > 4");
|
||||||
|
@ -42,9 +42,11 @@ TEST_F(PlanOptimizeTest, ConditionPushDown) {
|
||||||
run("SELECT ts, c1 FROM st1 WHERE tag1 > 4 AND tag2 = 'hello'");
|
run("SELECT ts, c1 FROM st1 WHERE tag1 > 4 AND tag2 = 'hello'");
|
||||||
|
|
||||||
run("SELECT ts, c1 FROM st1 WHERE tag1 > 4 AND tag2 = 'hello' AND c1 > 10");
|
run("SELECT ts, c1 FROM st1 WHERE tag1 > 4 AND tag2 = 'hello' AND c1 > 10");
|
||||||
|
|
||||||
|
run("SELECT ts, c1 FROM (SELECT * FROM st1) WHERE tag1 > 4");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(PlanOptimizeTest, orderByPrimaryKey) {
|
TEST_F(PlanOptimizeTest, sortPrimaryKey) {
|
||||||
useDb("root", "test");
|
useDb("root", "test");
|
||||||
|
|
||||||
run("SELECT c1 FROM t1 ORDER BY ts");
|
run("SELECT c1 FROM t1 ORDER BY ts");
|
||||||
|
|
|
@ -1488,18 +1488,6 @@ char* syncNode2SimpleStr(const SSyncNode* pSyncNode) {
|
||||||
pSyncNode->commitIndex, logBeginIndex, logLastIndex, snapshot.lastApplyIndex, pSyncNode->pRaftCfg->isStandBy,
|
pSyncNode->commitIndex, logBeginIndex, logLastIndex, snapshot.lastApplyIndex, pSyncNode->pRaftCfg->isStandBy,
|
||||||
pSyncNode->replicaNum, pSyncNode->pRaftCfg->lastConfigIndex, pSyncNode->changing, pSyncNode->restoreFinish);
|
pSyncNode->replicaNum, pSyncNode->pRaftCfg->lastConfigIndex, pSyncNode->changing, pSyncNode->restoreFinish);
|
||||||
|
|
||||||
/*
|
|
||||||
snprintf(s, len,
|
|
||||||
"syncNode: vgId:%d, term:%lu, commit:%ld, state:%d %s, standby:%d, "
|
|
||||||
"lc:%lu, "
|
|
||||||
"lc-user:%lu, "
|
|
||||||
"ems:%d, replica-num:%d, restore:%d, changing:%d",
|
|
||||||
pSyncNode->vgId, pSyncNode->pRaftStore->currentTerm, pSyncNode->commitIndex, pSyncNode->state,
|
|
||||||
syncUtilState2String(pSyncNode->state), pSyncNode->pRaftCfg->isStandBy, pSyncNode->electTimerLogicClock,
|
|
||||||
pSyncNode->electTimerLogicClockUser, pSyncNode->electTimerMS, pSyncNode->replicaNum,
|
|
||||||
pSyncNode->restoreFinish, pSyncNode->changing);
|
|
||||||
*/
|
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -683,7 +683,16 @@ int32_t syncNodeOnSnapshotSendCb(SSyncNode *pSyncNode, SyncSnapshotSend *pMsg) {
|
||||||
needRsp = true;
|
needRsp = true;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
ASSERT(0);
|
// error log
|
||||||
|
do {
|
||||||
|
char logBuf[96];
|
||||||
|
snprintf(logBuf, sizeof(logBuf), "snapshot receiver recv error seq:%d, my ack:%d", pMsg->seq, pReceiver->ack);
|
||||||
|
char *eventLog = snapshotReceiver2SimpleStr(pReceiver, logBuf);
|
||||||
|
syncNodeErrorLog(pSyncNode, eventLog);
|
||||||
|
taosMemoryFree(eventLog);
|
||||||
|
} while (0);
|
||||||
|
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// send ack
|
// send ack
|
||||||
|
@ -764,8 +773,8 @@ int32_t syncNodeOnSnapshotRspCb(SSyncNode *pSyncNode, SyncSnapshotRsp *pMsg) {
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
do {
|
do {
|
||||||
char logBuf[64];
|
char logBuf[96];
|
||||||
snprintf(logBuf, sizeof(logBuf), "error ack, recv ack:%d, my seq:%d", pMsg->ack, pSender->seq);
|
snprintf(logBuf, sizeof(logBuf), "snapshot sender recv error ack:%d, my seq:%d", pMsg->ack, pSender->seq);
|
||||||
char *eventLog = snapshotSender2SimpleStr(pSender, logBuf);
|
char *eventLog = snapshotSender2SimpleStr(pSender, logBuf);
|
||||||
syncNodeErrorLog(pSyncNode, eventLog);
|
syncNodeErrorLog(pSyncNode, eventLog);
|
||||||
taosMemoryFree(eventLog);
|
taosMemoryFree(eventLog);
|
||||||
|
|
|
@ -301,13 +301,13 @@ class TDTestCase:
|
||||||
tdSql.checkRows(1)
|
tdSql.checkRows(1)
|
||||||
tdSql.query("select ceil(num1) , min(num1) from tb;")
|
tdSql.query("select ceil(num1) , min(num1) from tb;")
|
||||||
tdSql.checkRows(1)
|
tdSql.checkRows(1)
|
||||||
tdSql.error("select udf1(num1) , first(num1) from tb;")
|
tdSql.query("select udf1(num1) , first(num1) from tb;")
|
||||||
|
|
||||||
tdSql.error("select abs(num1) , first(num1) from tb;")
|
tdSql.query("select abs(num1) , first(num1) from tb;")
|
||||||
|
|
||||||
tdSql.error("select udf1(num1) , last(num1) from tb;")
|
tdSql.query("select udf1(num1) , last(num1) from tb;")
|
||||||
|
|
||||||
tdSql.error("select round(num1) , last(num1) from tb;")
|
tdSql.query("select round(num1) , last(num1) from tb;")
|
||||||
|
|
||||||
tdSql.query("select udf1(num1) , top(num1,1) from tb;")
|
tdSql.query("select udf1(num1) , top(num1,1) from tb;")
|
||||||
tdSql.checkRows(1)
|
tdSql.checkRows(1)
|
||||||
|
@ -327,9 +327,9 @@ class TDTestCase:
|
||||||
tdSql.checkRows(1)
|
tdSql.checkRows(1)
|
||||||
tdSql.query("select floor(c1) , min(c1) from stb1;")
|
tdSql.query("select floor(c1) , min(c1) from stb1;")
|
||||||
tdSql.checkRows(1)
|
tdSql.checkRows(1)
|
||||||
tdSql.error("select udf1(c1) , first(c1) from stb1;")
|
tdSql.query("select udf1(c1) , first(c1) from stb1;")
|
||||||
|
|
||||||
tdSql.error("select udf1(c1) , last(c1) from stb1;")
|
tdSql.query("select udf1(c1) , last(c1) from stb1;")
|
||||||
|
|
||||||
tdSql.query("select udf1(c1) , top(c1 ,1) from stb1;")
|
tdSql.query("select udf1(c1) , top(c1 ,1) from stb1;")
|
||||||
tdSql.checkRows(1)
|
tdSql.checkRows(1)
|
||||||
|
|
|
@ -303,13 +303,13 @@ class TDTestCase:
|
||||||
tdSql.checkRows(1)
|
tdSql.checkRows(1)
|
||||||
tdSql.query("select ceil(num1) , min(num1) from tb;")
|
tdSql.query("select ceil(num1) , min(num1) from tb;")
|
||||||
tdSql.checkRows(1)
|
tdSql.checkRows(1)
|
||||||
tdSql.error("select udf1(num1) , first(num1) from tb;")
|
tdSql.query("select udf1(num1) , first(num1) from tb;")
|
||||||
|
|
||||||
tdSql.error("select abs(num1) , first(num1) from tb;")
|
tdSql.query("select abs(num1) , first(num1) from tb;")
|
||||||
|
|
||||||
tdSql.error("select udf1(num1) , last(num1) from tb;")
|
tdSql.query("select udf1(num1) , last(num1) from tb;")
|
||||||
|
|
||||||
tdSql.error("select round(num1) , last(num1) from tb;")
|
tdSql.query("select round(num1) , last(num1) from tb;")
|
||||||
|
|
||||||
tdSql.query("select udf1(num1) , top(num1,1) from tb;")
|
tdSql.query("select udf1(num1) , top(num1,1) from tb;")
|
||||||
tdSql.checkRows(1)
|
tdSql.checkRows(1)
|
||||||
|
@ -329,9 +329,9 @@ class TDTestCase:
|
||||||
tdSql.checkRows(1)
|
tdSql.checkRows(1)
|
||||||
tdSql.query("select floor(c1) , min(c1) from stb1;")
|
tdSql.query("select floor(c1) , min(c1) from stb1;")
|
||||||
tdSql.checkRows(1)
|
tdSql.checkRows(1)
|
||||||
tdSql.error("select udf1(c1) , first(c1) from stb1;")
|
tdSql.query("select udf1(c1) , first(c1) from stb1;")
|
||||||
|
|
||||||
tdSql.error("select udf1(c1) , last(c1) from stb1;")
|
tdSql.query("select udf1(c1) , last(c1) from stb1;")
|
||||||
|
|
||||||
tdSql.query("select udf1(c1) , top(c1 ,1) from stb1;")
|
tdSql.query("select udf1(c1) , top(c1 ,1) from stb1;")
|
||||||
tdSql.checkRows(1)
|
tdSql.checkRows(1)
|
||||||
|
|
|
@ -300,13 +300,13 @@ class TDTestCase:
|
||||||
tdSql.checkRows(1)
|
tdSql.checkRows(1)
|
||||||
tdSql.query("select ceil(num1) , min(num1) from tb;")
|
tdSql.query("select ceil(num1) , min(num1) from tb;")
|
||||||
tdSql.checkRows(1)
|
tdSql.checkRows(1)
|
||||||
tdSql.error("select udf1(num1) , first(num1) from tb;")
|
tdSql.query("select udf1(num1) , first(num1) from tb;")
|
||||||
|
|
||||||
tdSql.error("select abs(num1) , first(num1) from tb;")
|
tdSql.query("select abs(num1) , first(num1) from tb;")
|
||||||
|
|
||||||
tdSql.error("select udf1(num1) , last(num1) from tb;")
|
tdSql.query("select udf1(num1) , last(num1) from tb;")
|
||||||
|
|
||||||
tdSql.error("select round(num1) , last(num1) from tb;")
|
tdSql.query("select round(num1) , last(num1) from tb;")
|
||||||
|
|
||||||
tdSql.query("select udf1(num1) , top(num1,1) from tb;")
|
tdSql.query("select udf1(num1) , top(num1,1) from tb;")
|
||||||
tdSql.checkRows(1)
|
tdSql.checkRows(1)
|
||||||
|
@ -326,9 +326,9 @@ class TDTestCase:
|
||||||
tdSql.checkRows(1)
|
tdSql.checkRows(1)
|
||||||
tdSql.query("select floor(c1) , min(c1) from stb1;")
|
tdSql.query("select floor(c1) , min(c1) from stb1;")
|
||||||
tdSql.checkRows(1)
|
tdSql.checkRows(1)
|
||||||
tdSql.error("select udf1(c1) , first(c1) from stb1;")
|
tdSql.query("select udf1(c1) , first(c1) from stb1;")
|
||||||
|
|
||||||
tdSql.error("select udf1(c1) , last(c1) from stb1;")
|
tdSql.query("select udf1(c1) , last(c1) from stb1;")
|
||||||
|
|
||||||
tdSql.query("select udf1(c1) , top(c1 ,1) from stb1;")
|
tdSql.query("select udf1(c1) , top(c1 ,1) from stb1;")
|
||||||
tdSql.checkRows(1)
|
tdSql.checkRows(1)
|
||||||
|
|
|
@ -266,7 +266,7 @@ class TDTestCase:
|
||||||
tdSql.query("select unique(c1) from ct4")
|
tdSql.query("select unique(c1) from ct4")
|
||||||
tdSql.checkRows(10)
|
tdSql.checkRows(10)
|
||||||
|
|
||||||
tdSql.error("select unique(c1),tbname from ct1")
|
#tdSql.error("select unique(c1),tbname from ct1") #support
|
||||||
#tdSql.error("select unique(c1),t1 from ct1") #support
|
#tdSql.error("select unique(c1),t1 from ct1") #support
|
||||||
|
|
||||||
# unique with common col
|
# unique with common col
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit a875a057d1225d85c6323b9edaccc2b1a9641987
|
Subproject commit 28a49b447f71c4f014ebbac858b7215b897d57fd
|
Loading…
Reference in New Issue