enh: optimize time line function validation
This commit is contained in:
parent
e5bae30acf
commit
7ea23a33bc
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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");
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
Loading…
Reference in New Issue