enh: optimize time line function validation

This commit is contained in:
dapan1121 2023-05-09 16:37:08 +08:00
parent e5bae30acf
commit 7ea23a33bc
7 changed files with 98 additions and 60 deletions

View File

@ -241,6 +241,12 @@ typedef enum EFillMode {
FILL_MODE_NEXT FILL_MODE_NEXT
} EFillMode; } EFillMode;
typedef enum ETimeLineMode {
TIME_LINE_NONE = 1,
TIME_LINE_MULTI,
TIME_LINE_GLOBAL,
} ETimeLineMode;
typedef struct SFillNode { typedef struct SFillNode {
ENodeType type; // QUERY_NODE_FILL ENodeType type; // QUERY_NODE_FILL
EFillMode mode; EFillMode mode;
@ -263,50 +269,50 @@ typedef struct SCaseWhenNode {
} SCaseWhenNode; } SCaseWhenNode;
typedef struct SSelectStmt { typedef struct SSelectStmt {
ENodeType type; // QUERY_NODE_SELECT_STMT ENodeType type; // QUERY_NODE_SELECT_STMT
bool isDistinct; bool isDistinct;
SNodeList* pProjectionList; SNodeList* pProjectionList;
SNode* pFromTable; SNode* pFromTable;
SNode* pWhere; SNode* pWhere;
SNodeList* pPartitionByList; SNodeList* pPartitionByList;
SNodeList* pTags; // for create stream SNodeList* pTags; // for create stream
SNode* pSubtable; // for create stream SNode* pSubtable; // for create stream
SNode* pWindow; SNode* pWindow;
SNodeList* pGroupByList; // SGroupingSetNode SNodeList* pGroupByList; // SGroupingSetNode
SNode* pHaving; SNode* pHaving;
SNode* pRange; SNode* pRange;
SNode* pEvery; SNode* pEvery;
SNode* pFill; SNode* pFill;
SNodeList* pOrderByList; // SOrderByExprNode SNodeList* pOrderByList; // SOrderByExprNode
SLimitNode* pLimit; SLimitNode* pLimit;
SLimitNode* pSlimit; SLimitNode* pSlimit;
STimeWindow timeRange; STimeWindow timeRange;
char stmtName[TSDB_TABLE_NAME_LEN]; char stmtName[TSDB_TABLE_NAME_LEN];
uint8_t precision; uint8_t precision;
int32_t selectFuncNum; int32_t selectFuncNum;
int32_t returnRows; // EFuncReturnRows int32_t returnRows; // EFuncReturnRows
bool isEmptyResult; ETimeLineMode timeLineResMode;
bool isTimeLineResult; bool isEmptyResult;
bool isSubquery; bool isSubquery;
bool hasAggFuncs; bool hasAggFuncs;
bool hasRepeatScanFuncs; bool hasRepeatScanFuncs;
bool hasIndefiniteRowsFunc; bool hasIndefiniteRowsFunc;
bool hasMultiRowsFunc; bool hasMultiRowsFunc;
bool hasSelectFunc; bool hasSelectFunc;
bool hasSelectValFunc; bool hasSelectValFunc;
bool hasOtherVectorFunc; bool hasOtherVectorFunc;
bool hasUniqueFunc; bool hasUniqueFunc;
bool hasTailFunc; bool hasTailFunc;
bool hasInterpFunc; bool hasInterpFunc;
bool hasInterpPseudoColFunc; bool hasInterpPseudoColFunc;
bool hasLastRowFunc; bool hasLastRowFunc;
bool hasLastFunc; bool hasLastFunc;
bool hasTimeLineFunc; bool hasTimeLineFunc;
bool hasUdaf; bool hasUdaf;
bool hasStateKey; bool hasStateKey;
bool onlyHasKeepOrderFunc; bool onlyHasKeepOrderFunc;
bool groupSort; bool groupSort;
bool tagScan; bool tagScan;
} SSelectStmt; } SSelectStmt;
typedef enum ESetOperatorType { SET_OP_TYPE_UNION_ALL = 1, SET_OP_TYPE_UNION } ESetOperatorType; typedef enum ESetOperatorType { SET_OP_TYPE_UNION_ALL = 1, SET_OP_TYPE_UNION } ESetOperatorType;

View File

@ -667,7 +667,7 @@ static int32_t selectStmtCopy(const SSelectStmt* pSrc, SSelectStmt* pDst) {
COPY_CHAR_ARRAY_FIELD(stmtName); COPY_CHAR_ARRAY_FIELD(stmtName);
COPY_SCALAR_FIELD(precision); COPY_SCALAR_FIELD(precision);
COPY_SCALAR_FIELD(isEmptyResult); COPY_SCALAR_FIELD(isEmptyResult);
COPY_SCALAR_FIELD(isTimeLineResult); COPY_SCALAR_FIELD(timeLineResMode);
COPY_SCALAR_FIELD(hasAggFuncs); COPY_SCALAR_FIELD(hasAggFuncs);
COPY_SCALAR_FIELD(hasRepeatScanFuncs); COPY_SCALAR_FIELD(hasRepeatScanFuncs);
return TSDB_CODE_SUCCESS; return TSDB_CODE_SUCCESS;

View File

@ -84,6 +84,7 @@ int32_t getNumOfColumns(const STableMeta* pTableMeta);
int32_t getNumOfTags(const STableMeta* pTableMeta); int32_t getNumOfTags(const STableMeta* pTableMeta);
STableComInfo getTableInfo(const STableMeta* pTableMeta); STableComInfo getTableInfo(const STableMeta* pTableMeta);
STableMeta* tableMetaDup(const STableMeta* pTableMeta); STableMeta* tableMetaDup(const STableMeta* pTableMeta);
int32_t getTableTypeFromTableNode(SNode *pTable);
int32_t trimString(const char* src, int32_t len, char* dst, int32_t dlen); int32_t trimString(const char* src, int32_t len, char* dst, int32_t dlen);
int32_t getVnodeSysTableTargetName(int32_t acctId, SNode* pWhere, SName* pName); int32_t getVnodeSysTableTargetName(int32_t acctId, SNode* pWhere, SName* pName);

View File

@ -828,7 +828,7 @@ SNode* createSelectStmt(SAstCreateContext* pCxt, bool isDistinct, SNodeList* pPr
select->pProjectionList = pProjectionList; select->pProjectionList = pProjectionList;
select->pFromTable = pTable; select->pFromTable = pTable;
sprintf(select->stmtName, "%p", select); sprintf(select->stmtName, "%p", select);
select->isTimeLineResult = true; select->timeLineResMode = TIME_LINE_GLOBAL;
select->onlyHasKeepOrderFunc = true; select->onlyHasKeepOrderFunc = true;
select->timeRange = TSWINDOW_INITIALIZER; select->timeRange = TSWINDOW_INITIALIZER;
return (SNode*)select; return (SNode*)select;

View File

@ -746,18 +746,18 @@ static SNodeList* getProjectList(const SNode* pNode) {
static bool isTimeLineQuery(SNode* pStmt) { static bool isTimeLineQuery(SNode* pStmt) {
if (QUERY_NODE_SELECT_STMT == nodeType(pStmt)) { if (QUERY_NODE_SELECT_STMT == nodeType(pStmt)) {
return ((SSelectStmt*)pStmt)->isTimeLineResult; return (TIME_LINE_MULTI == ((SSelectStmt*)pStmt)->timeLineResMode) || (TIME_LINE_GLOBAL == ((SSelectStmt*)pStmt)->timeLineResMode);
} else { } else {
return false; return false;
} }
} }
static bool isGlobalTimeLineQuery(SNode* pStmt) { static bool isGlobalTimeLineQuery(SNode* pStmt) {
if (!isTimeLineQuery(pStmt)) { if (QUERY_NODE_SELECT_STMT == nodeType(pStmt)) {
return TIME_LINE_GLOBAL == ((SSelectStmt*)pStmt)->timeLineResMode;
} else {
return false; return false;
} }
SSelectStmt* pSelect = (SSelectStmt*)pStmt;
return NULL == pSelect->pPartitionByList || NULL != pSelect->pOrderByList;
} }
static bool isPrimaryKeyImpl(SNode* pExpr) { static bool isPrimaryKeyImpl(SNode* pExpr) {
@ -1563,7 +1563,7 @@ static int32_t translateTimelineFunc(STranslateContext* pCxt, SFunctionNode* pFu
} }
SSelectStmt* pSelect = (SSelectStmt*)pCxt->pCurrStmt; SSelectStmt* pSelect = (SSelectStmt*)pCxt->pCurrStmt;
if (NULL != pSelect->pFromTable && QUERY_NODE_TEMP_TABLE == nodeType(pSelect->pFromTable) && if (NULL != pSelect->pFromTable && QUERY_NODE_TEMP_TABLE == nodeType(pSelect->pFromTable) &&
!isTimeLineQuery(((STempTableNode*)pSelect->pFromTable)->pSubquery)) { !isGlobalTimeLineQuery(((STempTableNode*)pSelect->pFromTable)->pSubquery)) {
return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_NOT_ALLOWED_FUNC, return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_NOT_ALLOWED_FUNC,
"%s function requires valid time series input", pFunc->functionName); "%s function requires valid time series input", pFunc->functionName);
} }
@ -2273,7 +2273,7 @@ static int32_t checkAggColCoexist(STranslateContext* pCxt, SSelectStmt* pSelect)
return TSDB_CODE_SUCCESS; return TSDB_CODE_SUCCESS;
} }
if (!pSelect->onlyHasKeepOrderFunc) { if (!pSelect->onlyHasKeepOrderFunc) {
pSelect->isTimeLineResult = false; pSelect->timeLineResMode = TIME_LINE_NONE;
} }
CheckAggColCoexistCxt cxt = {.pTranslateCxt = pCxt, .existCol = false}; CheckAggColCoexistCxt cxt = {.pTranslateCxt = pCxt, .existCol = false};
nodesRewriteExprs(pSelect->pProjectionList, doCheckAggColCoexist, &cxt); nodesRewriteExprs(pSelect->pProjectionList, doCheckAggColCoexist, &cxt);
@ -2562,9 +2562,9 @@ static int32_t setTableCacheLastMode(STranslateContext* pCxt, SSelectStmt* pSele
static int32_t checkJoinTable(STranslateContext* pCxt, SJoinTableNode* pJoinTable) { static int32_t checkJoinTable(STranslateContext* pCxt, SJoinTableNode* pJoinTable) {
if ((QUERY_NODE_TEMP_TABLE == nodeType(pJoinTable->pLeft) && if ((QUERY_NODE_TEMP_TABLE == nodeType(pJoinTable->pLeft) &&
!isTimeLineQuery(((STempTableNode*)pJoinTable->pLeft)->pSubquery)) || !isGlobalTimeLineQuery(((STempTableNode*)pJoinTable->pLeft)->pSubquery)) ||
(QUERY_NODE_TEMP_TABLE == nodeType(pJoinTable->pRight) && (QUERY_NODE_TEMP_TABLE == nodeType(pJoinTable->pRight) &&
!isTimeLineQuery(((STempTableNode*)pJoinTable->pRight)->pSubquery))) { !isGlobalTimeLineQuery(((STempTableNode*)pJoinTable->pRight)->pSubquery))) {
return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_NOT_SUPPORT_JOIN, return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_NOT_SUPPORT_JOIN,
"Join requires valid time series input"); "Join requires valid time series input");
} }
@ -2598,7 +2598,7 @@ static int32_t translateTable(STranslateContext* pCxt, SNode* pTable) {
pCxt->stableQuery = true; pCxt->stableQuery = true;
} }
if (TSDB_SYSTEM_TABLE == pRealTable->pMeta->tableType && isSelectStmt(pCxt->pCurrStmt)) { if (TSDB_SYSTEM_TABLE == pRealTable->pMeta->tableType && isSelectStmt(pCxt->pCurrStmt)) {
((SSelectStmt*)pCxt->pCurrStmt)->isTimeLineResult = false; ((SSelectStmt*)pCxt->pCurrStmt)->timeLineResMode = TIME_LINE_NONE;
} }
code = addNamespace(pCxt, pRealTable); code = addNamespace(pCxt, pRealTable);
} }
@ -3071,7 +3071,7 @@ static int32_t translateGroupBy(STranslateContext* pCxt, SSelectStmt* pSelect) {
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_GROUPBY_WINDOW_COEXIST); return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_GROUPBY_WINDOW_COEXIST);
} }
pCxt->currClause = SQL_CLAUSE_GROUP_BY; pCxt->currClause = SQL_CLAUSE_GROUP_BY;
pSelect->isTimeLineResult = false; pSelect->timeLineResMode = TIME_LINE_NONE;
return translateExprList(pCxt, pSelect->pGroupByList); return translateExprList(pCxt, pSelect->pGroupByList);
} }
@ -3471,7 +3471,18 @@ static int32_t translateInterp(STranslateContext* pCxt, SSelectStmt* pSelect) {
static int32_t translatePartitionBy(STranslateContext* pCxt, SSelectStmt* pSelect) { static int32_t translatePartitionBy(STranslateContext* pCxt, SSelectStmt* pSelect) {
pCxt->currClause = SQL_CLAUSE_PARTITION_BY; pCxt->currClause = SQL_CLAUSE_PARTITION_BY;
int32_t code = translateExprList(pCxt, pSelect->pPartitionByList); int32_t code = TSDB_CODE_SUCCESS;
if (pSelect->pPartitionByList) {
int8_t typeType = getTableTypeFromTableNode(pSelect->pFromTable);
SNode* pPar = nodesListGetNode(pSelect->pPartitionByList, 0);
if (!((TSDB_NORMAL_TABLE == typeType || TSDB_CHILD_TABLE == typeType) &&
1 == pSelect->pPartitionByList->length && (QUERY_NODE_FUNCTION == nodeType(pPar) && FUNCTION_TYPE_TBNAME == ((SFunctionNode*)pPar)->funcType))) {
pSelect->timeLineResMode = TIME_LINE_MULTI;
}
code = translateExprList(pCxt, pSelect->pPartitionByList);
}
if (TSDB_CODE_SUCCESS == code) { if (TSDB_CODE_SUCCESS == code) {
code = translateExprList(pCxt, pSelect->pTags); code = translateExprList(pCxt, pSelect->pTags);
} }
@ -3600,9 +3611,9 @@ static void resetResultTimeline(SSelectStmt* pSelect) {
if ((QUERY_NODE_TEMP_TABLE == nodeType(pSelect->pFromTable) && if ((QUERY_NODE_TEMP_TABLE == nodeType(pSelect->pFromTable) &&
isPrimaryKey((STempTableNode*)pSelect->pFromTable, pOrder)) || isPrimaryKey((STempTableNode*)pSelect->pFromTable, pOrder)) ||
(QUERY_NODE_TEMP_TABLE != nodeType(pSelect->pFromTable) && isPrimaryKeyImpl(pOrder))) { (QUERY_NODE_TEMP_TABLE != nodeType(pSelect->pFromTable) && isPrimaryKeyImpl(pOrder))) {
pSelect->isTimeLineResult = true; pSelect->timeLineResMode = TIME_LINE_GLOBAL;
} else { } else {
pSelect->isTimeLineResult = false; pSelect->timeLineResMode = TIME_LINE_NONE;
} }
} }
@ -6057,7 +6068,7 @@ static bool isEventWindowQuery(SSelectStmt* pSelect) {
static int32_t checkStreamQuery(STranslateContext* pCxt, SCreateStreamStmt* pStmt) { static int32_t checkStreamQuery(STranslateContext* pCxt, SCreateStreamStmt* pStmt) {
SSelectStmt* pSelect = (SSelectStmt*)pStmt->pQuery; SSelectStmt* pSelect = (SSelectStmt*)pStmt->pQuery;
if (TSDB_DATA_TYPE_TIMESTAMP != ((SExprNode*)nodesListGetNode(pSelect->pProjectionList, 0))->resType.type || if (TSDB_DATA_TYPE_TIMESTAMP != ((SExprNode*)nodesListGetNode(pSelect->pProjectionList, 0))->resType.type ||
!pSelect->isTimeLineResult || crossTableWithoutAggOper(pSelect) || NULL != pSelect->pOrderByList || !isTimeLineQuery(pStmt->pQuery) || crossTableWithoutAggOper(pSelect) || NULL != pSelect->pOrderByList ||
crossTableWithUdaf(pSelect) || isEventWindowQuery(pSelect)) { crossTableWithUdaf(pSelect) || isEventWindowQuery(pSelect)) {
return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_STREAM_QUERY, "Unsupported stream query"); return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_STREAM_QUERY, "Unsupported stream query");
} }

View File

@ -249,6 +249,17 @@ int32_t getNumOfTags(const STableMeta* pTableMeta) { return getTableInfo(pTableM
STableComInfo getTableInfo(const STableMeta* pTableMeta) { return pTableMeta->tableInfo; } STableComInfo getTableInfo(const STableMeta* pTableMeta) { return pTableMeta->tableInfo; }
int32_t getTableTypeFromTableNode(SNode *pTable) {
if (NULL == pTable) {
return -1;
}
if (QUERY_NODE_REAL_TABLE != nodeType(pTable)) {
return -1;
}
return ((SRealTableNode *)pTable)->pMeta->tableType;
}
STableMeta* tableMetaDup(const STableMeta* pTableMeta) { STableMeta* tableMetaDup(const STableMeta* pTableMeta) {
int32_t numOfFields = TABLE_TOTAL_COL_NUM(pTableMeta); int32_t numOfFields = TABLE_TOTAL_COL_NUM(pTableMeta);
if (numOfFields > TSDB_MAX_COLUMNS || numOfFields < TSDB_MIN_COLUMNS) { if (numOfFields > TSDB_MAX_COLUMNS || numOfFields < TSDB_MIN_COLUMNS) {

View File

@ -117,6 +117,15 @@ TEST_F(ParserSelectTest, timelineFunc) {
run("SELECT LAST(*), FIRST(*) FROM t1 INTERVAL(10s)"); run("SELECT LAST(*), FIRST(*) FROM t1 INTERVAL(10s)");
run("SELECT diff(c1) FROM t1"); run("SELECT diff(c1) FROM t1");
run("select diff(ts) from (select _wstart as ts, count(*) from st1 partition by tbname interval(1d))", TSDB_CODE_PAR_NOT_ALLOWED_FUNC);
run("select diff(ts) from (select _wstart as ts, count(*) from st1 partition by tbname interval(1d) order by ts)");
run("select t1.* from st1s1 t1, (select _wstart as ts, count(*) from st1s2 partition by tbname interval(1d)) WHERE t1.ts = t2.ts", TSDB_CODE_PAR_NOT_SUPPORT_JOIN);
run("select t1.* from st1s1 t1, (select _wstart as ts, count(*) from st1s2 partition by tbname interval(1d) order by ts) t2 WHERE t1.ts = t2.ts");
} }
TEST_F(ParserSelectTest, selectFunc) { TEST_F(ParserSelectTest, selectFunc) {