fix: csum/diff/mavg support subquery
This commit is contained in:
parent
a94e5f9bec
commit
ec7bfd9eba
|
@ -1031,13 +1031,7 @@ static int32_t translateFirstLast(SFunctionNode* pFunc, char* pErrBuf, int32_t l
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
SNode* pPara = nodesListGetNode(pFunc->pParameterList, 0);
|
pFunc->node.resType = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 0))->resType;
|
||||||
if (QUERY_NODE_COLUMN != nodeType(pPara)) {
|
|
||||||
return buildFuncErrMsg(pErrBuf, len, TSDB_CODE_FUNC_FUNTION_ERROR,
|
|
||||||
"The parameters of first/last can only be columns");
|
|
||||||
}
|
|
||||||
|
|
||||||
pFunc->node.resType = ((SExprNode*)pPara)->resType;
|
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1051,11 +1045,6 @@ static int32_t translateFirstLastImpl(SFunctionNode* pFunc, char* pErrBuf, int32
|
||||||
uint8_t paraType = ((SExprNode*)pPara)->resType.type;
|
uint8_t paraType = ((SExprNode*)pPara)->resType.type;
|
||||||
int32_t paraBytes = ((SExprNode*)pPara)->resType.bytes;
|
int32_t paraBytes = ((SExprNode*)pPara)->resType.bytes;
|
||||||
if (isPartial) {
|
if (isPartial) {
|
||||||
if (QUERY_NODE_COLUMN != nodeType(pPara)) {
|
|
||||||
return buildFuncErrMsg(pErrBuf, len, TSDB_CODE_FUNC_FUNTION_ERROR,
|
|
||||||
"The parameters of first/last can only be columns");
|
|
||||||
}
|
|
||||||
|
|
||||||
pFunc->node.resType =
|
pFunc->node.resType =
|
||||||
(SDataType){.bytes = getFirstLastInfoSize(paraBytes) + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_BINARY};
|
(SDataType){.bytes = getFirstLastInfoSize(paraBytes) + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_BINARY};
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -483,6 +483,35 @@ static SNodeList* getProjectList(const SNode* pNode) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool isTimeLineQuery(SNode* pStmt) {
|
||||||
|
if (QUERY_NODE_SELECT_STMT == nodeType(pStmt)) {
|
||||||
|
return ((SSelectStmt*)pStmt)->isTimeLineResult;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isPrimaryKeyImpl(SNode* pExpr) {
|
||||||
|
if (QUERY_NODE_COLUMN == nodeType(pExpr)) {
|
||||||
|
return (PRIMARYKEY_TIMESTAMP_COL_ID == ((SColumnNode*)pExpr)->colId);
|
||||||
|
} else if (QUERY_NODE_FUNCTION == nodeType(pExpr)) {
|
||||||
|
SFunctionNode* pFunc = (SFunctionNode*)pExpr;
|
||||||
|
if (FUNCTION_TYPE_SELECT_VALUE == pFunc->funcType) {
|
||||||
|
return isPrimaryKeyImpl(nodesListGetNode(pFunc->pParameterList, 0));
|
||||||
|
} else if (FUNCTION_TYPE_WSTARTTS == pFunc->funcType || FUNCTION_TYPE_WENDTS == pFunc->funcType) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isPrimaryKey(STempTableNode* pTable, SNode* pExpr) {
|
||||||
|
if (!isTimeLineQuery(pTable->pSubquery)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return isPrimaryKeyImpl(pExpr);
|
||||||
|
}
|
||||||
|
|
||||||
static void setColumnInfoBySchema(const SRealTableNode* pTable, const SSchema* pColSchema, int32_t tagFlag,
|
static void setColumnInfoBySchema(const SRealTableNode* pTable, const SSchema* pColSchema, int32_t tagFlag,
|
||||||
SColumnNode* pCol) {
|
SColumnNode* pCol) {
|
||||||
strcpy(pCol->dbName, pTable->table.dbName);
|
strcpy(pCol->dbName, pTable->table.dbName);
|
||||||
|
@ -504,7 +533,7 @@ static void setColumnInfoBySchema(const SRealTableNode* pTable, const SSchema* p
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void setColumnInfoByExpr(const STableNode* pTable, SExprNode* pExpr, SColumnNode** pColRef) {
|
static void setColumnInfoByExpr(STempTableNode* pTable, SExprNode* pExpr, SColumnNode** pColRef) {
|
||||||
SColumnNode* pCol = *pColRef;
|
SColumnNode* pCol = *pColRef;
|
||||||
|
|
||||||
// pCol->pProjectRef = (SNode*)pExpr;
|
// pCol->pProjectRef = (SNode*)pExpr;
|
||||||
|
@ -512,13 +541,8 @@ static void setColumnInfoByExpr(const STableNode* pTable, SExprNode* pExpr, SCol
|
||||||
pExpr->pAssociation = taosArrayInit(TARRAY_MIN_SIZE, POINTER_BYTES);
|
pExpr->pAssociation = taosArrayInit(TARRAY_MIN_SIZE, POINTER_BYTES);
|
||||||
}
|
}
|
||||||
taosArrayPush(pExpr->pAssociation, &pColRef);
|
taosArrayPush(pExpr->pAssociation, &pColRef);
|
||||||
strcpy(pCol->tableAlias, pTable->tableAlias);
|
strcpy(pCol->tableAlias, pTable->table.tableAlias);
|
||||||
if (QUERY_NODE_COLUMN == nodeType(pExpr)) {
|
pCol->colId = isPrimaryKey(pTable, (SNode*)pExpr) ? PRIMARYKEY_TIMESTAMP_COL_ID : 0;
|
||||||
SColumnNode* pProjCol = (SColumnNode*)pExpr;
|
|
||||||
pCol->tableId = pProjCol->tableId;
|
|
||||||
pCol->colId = pProjCol->colId;
|
|
||||||
pCol->colType = pProjCol->colType;
|
|
||||||
}
|
|
||||||
strcpy(pCol->colName, pExpr->aliasName);
|
strcpy(pCol->colName, pExpr->aliasName);
|
||||||
if ('\0' == pCol->node.aliasName[0]) {
|
if ('\0' == pCol->node.aliasName[0]) {
|
||||||
strcpy(pCol->node.aliasName, pCol->colName);
|
strcpy(pCol->node.aliasName, pCol->colName);
|
||||||
|
@ -540,7 +564,8 @@ static int32_t createColumnsByTable(STranslateContext* pCxt, const STableNode* p
|
||||||
nodesListAppend(pList, (SNode*)pCol);
|
nodesListAppend(pList, (SNode*)pCol);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
SNodeList* pProjectList = getProjectList(((STempTableNode*)pTable)->pSubquery);
|
STempTableNode* pTempTable = (STempTableNode*)pTable;
|
||||||
|
SNodeList* pProjectList = getProjectList(pTempTable->pSubquery);
|
||||||
SNode* pNode;
|
SNode* pNode;
|
||||||
FOREACH(pNode, pProjectList) {
|
FOREACH(pNode, pProjectList) {
|
||||||
SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN);
|
SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN);
|
||||||
|
@ -549,7 +574,7 @@ static int32_t createColumnsByTable(STranslateContext* pCxt, const STableNode* p
|
||||||
}
|
}
|
||||||
nodesListAppend(pList, (SNode*)pCol);
|
nodesListAppend(pList, (SNode*)pCol);
|
||||||
SListCell* pCell = nodesListGetCell(pList, LIST_LENGTH(pList) - 1);
|
SListCell* pCell = nodesListGetCell(pList, LIST_LENGTH(pList) - 1);
|
||||||
setColumnInfoByExpr(pTable, (SExprNode*)pNode, (SColumnNode**)&pCell->pNode);
|
setColumnInfoByExpr(pTempTable, (SExprNode*)pNode, (SColumnNode**)&pCell->pNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
|
@ -559,35 +584,6 @@ static bool isInternalPrimaryKey(const SColumnNode* pCol) {
|
||||||
return PRIMARYKEY_TIMESTAMP_COL_ID == pCol->colId && 0 == strcmp(pCol->colName, PK_TS_COL_INTERNAL_NAME);
|
return PRIMARYKEY_TIMESTAMP_COL_ID == pCol->colId && 0 == strcmp(pCol->colName, PK_TS_COL_INTERNAL_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool isTimeLineQuery(SNode* pStmt) {
|
|
||||||
if (QUERY_NODE_SELECT_STMT == nodeType(pStmt)) {
|
|
||||||
return ((SSelectStmt*)pStmt)->isTimeLineResult;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool isPrimaryKeyImpl(STempTableNode* pTable, SNode* pExpr) {
|
|
||||||
if (QUERY_NODE_COLUMN == nodeType(pExpr)) {
|
|
||||||
return (PRIMARYKEY_TIMESTAMP_COL_ID == ((SColumnNode*)pExpr)->colId);
|
|
||||||
} else if (QUERY_NODE_FUNCTION == nodeType(pExpr)) {
|
|
||||||
SFunctionNode* pFunc = (SFunctionNode*)pExpr;
|
|
||||||
if (FUNCTION_TYPE_SELECT_VALUE == pFunc->funcType) {
|
|
||||||
return isPrimaryKeyImpl(pTable, nodesListGetNode(pFunc->pParameterList, 0));
|
|
||||||
} else if (FUNCTION_TYPE_WSTARTTS == pFunc->funcType || FUNCTION_TYPE_WENDTS == pFunc->funcType) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool isPrimaryKey(STempTableNode* pTable, SNode* pExpr) {
|
|
||||||
if (!isTimeLineQuery(pTable->pSubquery)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return isPrimaryKeyImpl(pTable, pExpr);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int32_t findAndSetColumn(STranslateContext* pCxt, SColumnNode** pColRef, const STableNode* pTable,
|
static int32_t findAndSetColumn(STranslateContext* pCxt, SColumnNode** pColRef, const STableNode* pTable,
|
||||||
bool* pFound) {
|
bool* pFound) {
|
||||||
SColumnNode* pCol = *pColRef;
|
SColumnNode* pCol = *pColRef;
|
||||||
|
@ -608,7 +604,8 @@ static int32_t findAndSetColumn(STranslateContext* pCxt, SColumnNode** pColRef,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
SNodeList* pProjectList = getProjectList(((STempTableNode*)pTable)->pSubquery);
|
STempTableNode* pTempTable = (STempTableNode*)pTable;
|
||||||
|
SNodeList* pProjectList = getProjectList(pTempTable->pSubquery);
|
||||||
SNode* pNode;
|
SNode* pNode;
|
||||||
FOREACH(pNode, pProjectList) {
|
FOREACH(pNode, pProjectList) {
|
||||||
SExprNode* pExpr = (SExprNode*)pNode;
|
SExprNode* pExpr = (SExprNode*)pNode;
|
||||||
|
@ -616,10 +613,10 @@ static int32_t findAndSetColumn(STranslateContext* pCxt, SColumnNode** pColRef,
|
||||||
if (*pFound) {
|
if (*pFound) {
|
||||||
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_AMBIGUOUS_COLUMN, pCol->colName);
|
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_AMBIGUOUS_COLUMN, pCol->colName);
|
||||||
}
|
}
|
||||||
setColumnInfoByExpr(pTable, pExpr, pColRef);
|
setColumnInfoByExpr(pTempTable, pExpr, pColRef);
|
||||||
*pFound = true;
|
*pFound = true;
|
||||||
} else if (isPrimaryKey((STempTableNode*)pTable, pNode) && isInternalPrimaryKey(pCol)) {
|
} else if (isPrimaryKey(pTempTable, pNode) && isInternalPrimaryKey(pCol)) {
|
||||||
setColumnInfoByExpr(pTable, pExpr, pColRef);
|
setColumnInfoByExpr(pTempTable, pExpr, pColRef);
|
||||||
*pFound = true;
|
*pFound = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -185,15 +185,15 @@ static char* getSyntaxErrFormat(int32_t errCode) {
|
||||||
case TSDB_CODE_PAR_INVALID_REDISTRIBUTE_VG:
|
case TSDB_CODE_PAR_INVALID_REDISTRIBUTE_VG:
|
||||||
return "The REDISTRIBUTE VGROUP statement only support 1 to 3 dnodes";
|
return "The REDISTRIBUTE VGROUP statement only support 1 to 3 dnodes";
|
||||||
case TSDB_CODE_PAR_FILL_NOT_ALLOWED_FUNC:
|
case TSDB_CODE_PAR_FILL_NOT_ALLOWED_FUNC:
|
||||||
return "%s function does not supportted in fill query";
|
return "%s function is not supported in fill query";
|
||||||
case TSDB_CODE_PAR_INVALID_WINDOW_PC:
|
case TSDB_CODE_PAR_INVALID_WINDOW_PC:
|
||||||
return "_WSTARTTS, _WENDTS and _WDURATION can only be used in window query";
|
return "_WSTARTTS, _WENDTS and _WDURATION can only be used in window query";
|
||||||
case TSDB_CODE_PAR_WINDOW_NOT_ALLOWED_FUNC:
|
case TSDB_CODE_PAR_WINDOW_NOT_ALLOWED_FUNC:
|
||||||
return "%s function does not supportted in time window query";
|
return "%s function is not supported in time window query";
|
||||||
case TSDB_CODE_PAR_STREAM_NOT_ALLOWED_FUNC:
|
case TSDB_CODE_PAR_STREAM_NOT_ALLOWED_FUNC:
|
||||||
return "%s function does not supportted in stream query";
|
return "%s function is not supported in stream query";
|
||||||
case TSDB_CODE_PAR_GROUP_BY_NOT_ALLOWED_FUNC:
|
case TSDB_CODE_PAR_GROUP_BY_NOT_ALLOWED_FUNC:
|
||||||
return "%s function does not supportted in group query";
|
return "%s function is not supported in group query";
|
||||||
case TSDB_CODE_PAR_INVALID_TABLE_OPTION:
|
case TSDB_CODE_PAR_INVALID_TABLE_OPTION:
|
||||||
return "Invalid option %s";
|
return "Invalid option %s";
|
||||||
case TSDB_CODE_PAR_INVALID_INTERP_CLAUSE:
|
case TSDB_CODE_PAR_INVALID_INTERP_CLAUSE:
|
||||||
|
|
|
@ -35,6 +35,8 @@ TEST_F(PlanBasicTest, whereClause) {
|
||||||
run("SELECT * FROM t1 WHERE c1 > 10");
|
run("SELECT * FROM t1 WHERE c1 > 10");
|
||||||
|
|
||||||
run("SELECT * FROM t1 WHERE ts > TIMESTAMP '2022-04-01 00:00:00' and ts < TIMESTAMP '2022-04-30 23:59:59'");
|
run("SELECT * FROM t1 WHERE ts > TIMESTAMP '2022-04-01 00:00:00' and ts < TIMESTAMP '2022-04-30 23:59:59'");
|
||||||
|
|
||||||
|
run("SELECT ts, c1 FROM t1 WHERE ts > NOW AND ts IS NULL AND (c1 > 0 OR c3 < 20)");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(PlanBasicTest, func) {
|
TEST_F(PlanBasicTest, func) {
|
||||||
|
@ -111,6 +113,14 @@ TEST_F(PlanBasicTest, timeLineFunc) {
|
||||||
run("SELECT CSUM(c1) FROM st1");
|
run("SELECT CSUM(c1) FROM st1");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(PlanBasicTest, multiResFunc) {
|
||||||
|
useDb("root", "test");
|
||||||
|
|
||||||
|
run("SELECT LAST(*) FROM t1");
|
||||||
|
|
||||||
|
run("SELECT LAST(c1 + 10, c2) FROM st1");
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(PlanBasicTest, sampleFunc) {
|
TEST_F(PlanBasicTest, sampleFunc) {
|
||||||
useDb("root", "test");
|
useDb("root", "test");
|
||||||
|
|
||||||
|
|
|
@ -1397,9 +1397,9 @@ class TDTestCase:
|
||||||
tdSql.error(sql2)
|
tdSql.error(sql2)
|
||||||
tdSql.error(sql3)
|
tdSql.error(sql3)
|
||||||
|
|
||||||
tdSql.error("select elapsed(ts,10s) from (select ts,tbname from regular_table_1 order by ts ) where ts>=\"2015-01-01 00:00:00.000\" and ts < \"2015-01-01 00:10:00.000\" interval(1s) fill(prev);")
|
tdSql.query("select elapsed(ts,10s) from (select ts,tbname from regular_table_1 order by ts ) where ts>=\"2015-01-01 00:00:00.000\" and ts < \"2015-01-01 00:10:00.000\" interval(1s) fill(prev);")
|
||||||
|
|
||||||
tdSql.error("select elapsed(ts,10s) from (select ts ,max(q_int),tbname from regular_table_1 order by ts ) where ts>=\"2015-01-01 00:00:00.000\" and ts < \"2015-01-01 00:10:00.000\" interval(1s) fill(prev);")
|
tdSql.query("select elapsed(ts,10s) from (select ts ,max(q_int),tbname from regular_table_1 order by ts ) where ts>=\"2015-01-01 00:00:00.000\" and ts < \"2015-01-01 00:10:00.000\" interval(1s) fill(prev);")
|
||||||
|
|
||||||
# ===============================================inner nest============================================
|
# ===============================================inner nest============================================
|
||||||
|
|
||||||
|
@ -1486,9 +1486,9 @@ class TDTestCase:
|
||||||
tdSql.checkRows(1)
|
tdSql.checkRows(1)
|
||||||
tdSql.checkData(0,0,9)
|
tdSql.checkData(0,0,9)
|
||||||
|
|
||||||
tdSql.error('select elapsed(ts,10s) from ( select * from sub_table1_1 where ts>="2015-01-01 00:00:00.000" and ts < "2015-01-01 00:10:00.000") session(ts,1w) ; ')
|
tdSql.query('select elapsed(ts,10s) from ( select * from sub_table1_1 where ts>="2015-01-01 00:00:00.000" and ts < "2015-01-01 00:10:00.000") session(ts,1w) ; ')
|
||||||
|
|
||||||
tdSql.error('select elapsed(ts,10s) from ( select ts ,q_int from sub_table1_1 where ts>="2015-01-01 00:00:00.000" and ts < "2015-01-01 00:10:00.000") session(ts,1w) ; ')
|
tdSql.query('select elapsed(ts,10s) from ( select ts ,q_int from sub_table1_1 where ts>="2015-01-01 00:00:00.000" and ts < "2015-01-01 00:10:00.000") session(ts,1w) ; ')
|
||||||
|
|
||||||
tdSql.error('select elapsed(ts,10s) from sub_table1_1 where ts>="2015-01-01 00:00:00.000" and ts < "2015-01-01 00:10:00.000" interval(20s) fill (next) session(ts,1w) ; ')
|
tdSql.error('select elapsed(ts,10s) from sub_table1_1 where ts>="2015-01-01 00:00:00.000" and ts < "2015-01-01 00:10:00.000" interval(20s) fill (next) session(ts,1w) ; ')
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue