diff --git a/source/libs/scalar/inc/filterInt.h b/source/libs/scalar/inc/filterInt.h index 9adc9ee99c..ed07592c73 100644 --- a/source/libs/scalar/inc/filterInt.h +++ b/source/libs/scalar/inc/filterInt.h @@ -236,6 +236,7 @@ typedef struct SFltBuildGroupCtx { SFilterInfo *info; SArray *group; int32_t code; + bool ignore; } SFltBuildGroupCtx; typedef struct { diff --git a/source/libs/scalar/src/filter.c b/source/libs/scalar/src/filter.c index 45260b69cc..10850aab9a 100644 --- a/source/libs/scalar/src/filter.c +++ b/source/libs/scalar/src/filter.c @@ -1284,7 +1284,8 @@ static void filterFreeGroup(void *pItem) { taosMemoryFreeClear(p->unitFlags); } -int32_t fltAddGroupUnitFromNode(SFilterInfo *info, SNode *tree, SArray *group) { +int32_t fltAddGroupUnitFromNode(void *pContext, SFilterInfo *info, SNode *tree, SArray *group) { + SFltBuildGroupCtx *ctx = (SFltBuildGroupCtx *)pContext; SOperatorNode *node = (SOperatorNode *)tree; int32_t ret = TSDB_CODE_SUCCESS; SFilterFieldId left = {0}, right = {0}; @@ -1360,7 +1361,7 @@ int32_t fltAddGroupUnitFromNode(SFilterInfo *info, SNode *tree, SArray *group) { cell = cell->pNext; } if(overflowCount == listNode->pNodeList->length) { - FILTER_SET_FLAG(info->status, FI_STATUS_EMPTY); + ctx->ignore = true; } colDataDestroy(out.columnData); taosMemoryFree(out.columnData); @@ -1697,10 +1698,17 @@ EDealRes fltTreeToGroup(SNode *pNode, void *pContext) { FLT_ERR_RET(terrno); } - SFltBuildGroupCtx tctx = {.info = ctx->info, .group = newGroup}; + SFltBuildGroupCtx tctx = {.info = ctx->info, .group = newGroup, .ignore = false}; nodesWalkExpr(cell->pNode, fltTreeToGroup, (void *)&tctx); FLT_ERR_JRET(tctx.code); - + if(tctx.ignore) { + ctx->ignore = true; + taosArrayDestroyEx(newGroup, filterFreeGroup); + newGroup = NULL; + taosArrayDestroyEx(resGroup, filterFreeGroup); + resGroup = NULL; + break; + } FLT_ERR_JRET(filterDetachCnfGroups(resGroup, preGroup, newGroup)); taosArrayDestroyEx(newGroup, filterFreeGroup); @@ -1712,9 +1720,10 @@ EDealRes fltTreeToGroup(SNode *pNode, void *pContext) { cell = cell->pNext; } - - if (NULL == taosArrayAddAll(ctx->group, preGroup)) { - FLT_ERR_JRET(terrno); + if (!ctx->ignore) { + if (NULL == taosArrayAddAll(ctx->group, preGroup)) { + FLT_ERR_JRET(terrno); + } } taosArrayDestroy(preGroup); @@ -1726,6 +1735,9 @@ EDealRes fltTreeToGroup(SNode *pNode, void *pContext) { SListCell *cell = node->pParameterList->pHead; for (int32_t i = 0; i < node->pParameterList->length; ++i) { nodesWalkExpr(cell->pNode, fltTreeToGroup, (void *)pContext); + if(ctx->ignore) { + ctx->ignore = false; + } FLT_ERR_JRET(ctx->code); cell = cell->pNext; @@ -1740,7 +1752,7 @@ EDealRes fltTreeToGroup(SNode *pNode, void *pContext) { } if (QUERY_NODE_OPERATOR == nType) { - FLT_ERR_JRET(fltAddGroupUnitFromNode(ctx->info, pNode, ctx->group)); + FLT_ERR_JRET(fltAddGroupUnitFromNode(ctx, ctx->info, pNode, ctx->group)); return DEAL_RES_IGNORE_CHILD; } @@ -3836,13 +3848,16 @@ int32_t fltInitFromNode(SNode *tree, SFilterInfo *info, uint32_t options) { goto _return; } - SFltBuildGroupCtx tctx = {.info = info, .group = group}; + SFltBuildGroupCtx tctx = {.info = info, .group = group, .ignore = false}; nodesWalkExpr(tree, fltTreeToGroup, (void *)&tctx); if (TSDB_CODE_SUCCESS != tctx.code) { taosArrayDestroyEx(group, filterFreeGroup); code = tctx.code; goto _return; } + if (tctx.ignore) { + FILTER_SET_FLAG(info->status, FI_STATUS_EMPTY); + } code = filterConvertGroupFromArray(info, group); if (TSDB_CODE_SUCCESS != code) { taosArrayDestroyEx(group, filterFreeGroup); @@ -3876,7 +3891,7 @@ int32_t fltInitFromNode(SNode *tree, SFilterInfo *info, uint32_t options) { _return: if (code) { - qInfo("init from node failed, code:%d", code); + qInfo("init from node failed, code:%d, %s", code, tstrerror(code)); } return code; } diff --git a/tests/system-test/2-query/operator.py b/tests/system-test/2-query/operator.py new file mode 100644 index 0000000000..edfd023b7c --- /dev/null +++ b/tests/system-test/2-query/operator.py @@ -0,0 +1,114 @@ +from wsgiref.headers import tspecials +from util.log import * +from util.cases import * +from util.sql import * +from util.common import tdCom +import numpy as np + + +class TDTestCase: + def init(self, conn, logSql, replicaVar=1): + self.replicaVar = int(replicaVar) + tdLog.debug("start to execute %s" % __file__) + tdSql.init(conn.cursor()) + + self.dbname = "db" + self.rowNum = 10 + self.ts = 1537146000000 + + # test in/not in contidion with invalid value + def ts5757(self): + + tdSql.execute(f"create database if not exists {self.dbname}") + + tdSql.execute(f"DROP STABLE IF EXISTS {self.dbname}.super_t1;") + tdSql.execute(f"DROP TABLE IF EXISTS {self.dbname}.t1;") + tdSql.execute(f"CREATE STABLE IF NOT EXISTS {self.dbname}.super_t1(time TIMESTAMP, c0 BIGINT UNSIGNED) TAGS (location BINARY(64))") + tdSql.execute(f"CREATE TABLE {self.dbname}.t1 USING {self.dbname}.super_t1 TAGS ('ek')") + tdSql.execute(f"INSERT INTO {self.dbname}.t1(time, c0) VALUES (1641024000000, 1);") + tdSql.execute(f"INSERT INTO {self.dbname}.t1(time, c0) VALUES (1641024005000, 2);") + tdSql.execute(f"INSERT INTO {self.dbname}.t1(time, c0) VALUES (1641024010000, NULL);") + + tdSql.query(f"SELECT * FROM {self.dbname}.t1 WHERE c0 IS NOT NULL AND c0 IN (-1);") + tdSql.checkRows(0) + tdSql.query(f"SELECT * FROM {self.dbname}.t1 WHERE c0 IS NULL AND c0 IN (-1);") + tdSql.checkRows(0) + tdSql.query(f"SELECT * FROM {self.dbname}.t1 WHERE c0 IS NOT NULL AND c0 IN (-1, 1);") + tdSql.checkRows(1) + tdSql.query(f"SELECT * FROM {self.dbname}.t1 WHERE c0 IS NULL AND c0 IN (2, -1, 1);") + tdSql.checkRows(0) + tdSql.query(f"SELECT * FROM {self.dbname}.t1 WHERE c0 IS NOT NULL AND c0 NOT IN (-1);") + tdSql.checkRows(2) + tdSql.query(f"SELECT * FROM {self.dbname}.t1 WHERE c0 IS NULL AND c0 NOT IN (-1);") + tdSql.checkRows(0) + tdSql.query(f"SELECT * FROM {self.dbname}.t1 WHERE c0 IS NULL AND c0 NOT IN (3);") + tdSql.checkRows(0) + tdSql.query(f"SELECT * FROM {self.dbname}.t1 WHERE c0 IS NOT NULL AND c0 NOT IN (-1, 1);") + tdSql.checkRows(1) + tdSql.query(f"SELECT * FROM {self.dbname}.t1 WHERE c0 IS NULL AND c0 NOT IN (2, -1, 1);") + tdSql.checkRows(0) + tdSql.query(f"SELECT * FROM {self.dbname}.t1 WHERE (c0 IS NULL AND c0 IN (-1)) or c0 in(1)") + tdSql.checkRows(1) + + tdSql.query(f"SELECT * FROM {self.dbname}.t1 WHERE c0 IS NOT NULL OR c0 IN (-1);") + tdSql.checkRows(2) + tdSql.query(f"SELECT * FROM {self.dbname}.t1 WHERE c0 IS NULL OR c0 IN (-1);") + tdSql.checkRows(1) + tdSql.query(f"SELECT * FROM {self.dbname}.t1 WHERE c0 IS NOT NULL OR c0 IN (-1, 1);") + tdSql.checkRows(2) + tdSql.query(f"SELECT * FROM {self.dbname}.t1 WHERE c0 IS NULL OR c0 IN (2, -1, 1);") + tdSql.checkRows(3) + tdSql.query(f"SELECT * FROM {self.dbname}.t1 WHERE c0 IS NOT NULL OR c0 NOT IN (-1);") + tdSql.checkRows(2) + tdSql.query(f"SELECT * FROM {self.dbname}.t1 WHERE c0 IS NULL OR c0 NOT IN (-1);") + tdSql.checkRows(3) + tdSql.query(f"SELECT * FROM {self.dbname}.t1 WHERE c0 IS NULL OR c0 NOT IN (3);") + tdSql.checkRows(3) + tdSql.query(f"SELECT * FROM {self.dbname}.t1 WHERE c0 IS NOT NULL OR c0 NOT IN (-1, 1);") + tdSql.checkRows(2) + tdSql.query(f"SELECT * FROM {self.dbname}.t1 WHERE c0 IS NOT NULL OR c0 NOT IN (-1);") + tdSql.checkRows(2) + tdSql.query(f"SELECT * FROM {self.dbname}.t1 WHERE c0 IS NULL OR c0 NOT IN (2, -1, 1);") + tdSql.checkRows(1) + + tdSql.query(f"SELECT * FROM {self.dbname}.t1 WHERE ((c0 is NULL) AND (c0 in (-1)) )") + tdSql.checkRows(0) + tdSql.query(f"SELECT * FROM {self.dbname}.t1 WHERE ((c0 in (-1)) AND (c0 is NULL) )") + tdSql.checkRows(0) + tdSql.query(f"SELECT * FROM {self.dbname}.t1 WHERE ((c0 in (-1)) AND (c0 is NULL) ) OR c0 in(1)") + tdSql.checkRows(1) + + tdSql.query(f"SELECT * FROM {self.dbname}.t1 WHERE c0 IN (-1);") + tdSql.checkRows(0) + tdSql.query(f"SELECT * FROM {self.dbname}.t1 WHERE c0 IS NOT NULL;") + tdSql.checkRows(2) + tdSql.query(f"SELECT * FROM {self.dbname}.t1 WHERE c0 IN (-1) or c0 in(1);") + tdSql.checkRows(1) + tdSql.query(f"SELECT * FROM {self.dbname}.t1 WHERE c0 IN (1) or c0 in(-1);") + tdSql.checkRows(1) + tdSql.query(f"SELECT * FROM {self.dbname}.t1 WHERE c0 IN (-1) or c0 in(-1);") + tdSql.checkRows(0) + tdSql.query(f"SELECT * FROM {self.dbname}.t1 WHERE c0 IN (-1) and c0 in(1);") + tdSql.checkRows(0) + tdSql.query(f"SELECT * FROM {self.dbname}.t1 WHERE c0 IN (1) and c0 in(-1);") + tdSql.checkRows(0) + tdSql.query(f"SELECT * FROM {self.dbname}.t1 WHERE c0 IN (-1) and c0 in(-1);") + tdSql.checkRows(0) + + def run(self): + dbname = "db" + tdSql.prepare() + tdSql.execute(f"create database if not exists {self.dbname}") + + self.ts5757() + + + + + def stop(self): + tdSql.close() + tdLog.success("%s successfully executed" % __file__) + +tdCases.addWindows(__file__, TDTestCase()) + +tdCases.addLinux(__file__, TDTestCase())