diff --git a/include/libs/executor/storageapi.h b/include/libs/executor/storageapi.h index 7a4401827c..3cc2acf30f 100644 --- a/include/libs/executor/storageapi.h +++ b/include/libs/executor/storageapi.h @@ -268,7 +268,7 @@ typedef struct SStoreMeta { const void* (*extractTagVal)(const void* tag, int16_t type, STagVal* tagVal); // todo remove it int32_t (*getTableUidByName)(void* pVnode, char* tbName, uint64_t* uid); - int32_t (*getTableTypeByName)(void* pVnode, char* tbName, ETableType* tbType); + int32_t (*getTableTypeSuidByName)(void* pVnode, char* tbName, ETableType* tbType, uint64_t* suid); int32_t (*getTableNameByUid)(void* pVnode, uint64_t uid, char* tbName); bool (*isTableExisted)(void* pVnode, tb_uid_t uid); diff --git a/source/dnode/vnode/inc/vnode.h b/source/dnode/vnode/inc/vnode.h index b33bdb0976..475f8c9814 100644 --- a/source/dnode/vnode/inc/vnode.h +++ b/source/dnode/vnode/inc/vnode.h @@ -130,7 +130,7 @@ int32_t metaGetTableNameByUid(void *pVnode, uint64_t uid, char *tbName); int metaGetTableSzNameByUid(void *meta, uint64_t uid, char *tbName); int metaGetTableUidByName(void *pVnode, char *tbName, uint64_t *uid); -int metaGetTableTypeByName(void *meta, char *tbName, ETableType *tbType); +int metaGetTableTypeSuidByName(void *meta, char *tbName, ETableType *tbType, uint64_t* suid); int metaGetTableTtlByUid(void *meta, uint64_t uid, int64_t *ttlDays); bool metaIsTableExist(void *pVnode, tb_uid_t uid); int32_t metaGetCachedTableUidList(void *pVnode, tb_uid_t suid, const uint8_t *key, int32_t keyLen, SArray *pList, diff --git a/source/dnode/vnode/src/meta/metaQuery.c b/source/dnode/vnode/src/meta/metaQuery.c index c19a2e3ce2..b367232e2d 100644 --- a/source/dnode/vnode/src/meta/metaQuery.c +++ b/source/dnode/vnode/src/meta/metaQuery.c @@ -190,13 +190,20 @@ int metaGetTableUidByName(void *pVnode, char *tbName, uint64_t *uid) { return 0; } -int metaGetTableTypeByName(void *pVnode, char *tbName, ETableType *tbType) { +int metaGetTableTypeSuidByName(void *pVnode, char *tbName, ETableType *tbType, uint64_t* suid) { int code = 0; SMetaReader mr = {0}; metaReaderDoInit(&mr, ((SVnode *)pVnode)->pMeta, META_READER_LOCK); code = metaGetTableEntryByName(&mr, tbName); if (code == 0) *tbType = mr.me.type; + if (TSDB_CHILD_TABLE == mr.me.type) { + *suid = mr.me.ctbEntry.suid; + } else if (TSDB_SUPER_TABLE == mr.me.type) { + *suid = mr.me.uid; + } else { + *suid = 0; + } metaReaderClear(&mr); return code; diff --git a/source/dnode/vnode/src/vnd/vnodeInitApi.c b/source/dnode/vnode/src/vnd/vnodeInitApi.c index 41e6c6c2c5..b8682028cf 100644 --- a/source/dnode/vnode/src/vnd/vnodeInitApi.c +++ b/source/dnode/vnode/src/vnd/vnodeInitApi.c @@ -94,7 +94,7 @@ void initMetadataAPI(SStoreMeta* pMeta) { pMeta->getTableTagsByUid = metaGetTableTagsByUids; pMeta->getTableUidByName = metaGetTableUidByName; - pMeta->getTableTypeByName = metaGetTableTypeByName; + pMeta->getTableTypeSuidByName = metaGetTableTypeSuidByName; pMeta->getTableNameByUid = metaGetTableNameByUid; pMeta->getTableSchema = vnodeGetTableSchema; diff --git a/source/libs/executor/src/executil.c b/source/libs/executor/src/executil.c index cce754a8c8..4e8c563644 100644 --- a/source/libs/executor/src/executil.c +++ b/source/libs/executor/src/executil.c @@ -49,7 +49,7 @@ typedef enum { static FilterCondType checkTagCond(SNode* cond); static int32_t optimizeTbnameInCond(void* metaHandle, int64_t suid, SArray* list, SNode* pTagCond, SStorageAPI* pAPI); -static int32_t optimizeTbnameInCondImpl(void* metaHandle, SArray* list, SNode* pTagCond, SStorageAPI* pStoreAPI); +static int32_t optimizeTbnameInCondImpl(void* metaHandle, SArray* list, SNode* pTagCond, SStorageAPI* pStoreAPI, uint64_t suid); static int32_t getTableList(void* pVnode, SScanPhysiNode* pScanNode, SNode* pTagCond, SNode* pTagIndexCond, STableListInfo* pListInfo, uint8_t* digest, const char* idstr, SStorageAPI* pStorageAPI); @@ -1061,7 +1061,7 @@ static int32_t optimizeTbnameInCond(void* pVnode, int64_t suid, SArray* list, SN int32_t ntype = nodeType(cond); if (ntype == QUERY_NODE_OPERATOR) { - ret = optimizeTbnameInCondImpl(pVnode, list, cond, pAPI); + ret = optimizeTbnameInCondImpl(pVnode, list, cond, pAPI, suid); } if (ntype != QUERY_NODE_LOGIC_CONDITION || ((SLogicConditionNode*)cond)->condType != LOGIC_COND_TYPE_AND) { @@ -1080,7 +1080,7 @@ static int32_t optimizeTbnameInCond(void* pVnode, int64_t suid, SArray* list, SN SListCell* cell = pList->pHead; for (int i = 0; i < len; i++) { if (cell == NULL) break; - if (optimizeTbnameInCondImpl(pVnode, list, cell->pNode, pAPI) == 0) { + if (optimizeTbnameInCondImpl(pVnode, list, cell->pNode, pAPI, suid) == 0) { hasTbnameCond = true; break; } @@ -1099,7 +1099,7 @@ static int32_t optimizeTbnameInCond(void* pVnode, int64_t suid, SArray* list, SN // only return uid that does not contained in pExistedUidList static int32_t optimizeTbnameInCondImpl(void* pVnode, SArray* pExistedUidList, SNode* pTagCond, - SStorageAPI* pStoreAPI) { + SStorageAPI* pStoreAPI, uint64_t suid) { if (nodeType(pTagCond) != QUERY_NODE_OPERATOR) { return -1; } @@ -1148,10 +1148,13 @@ static int32_t optimizeTbnameInCondImpl(void* pVnode, SArray* pExistedUidList, S for (int i = 0; i < numOfTables; i++) { char* name = taosArrayGetP(pTbList, i); - uint64_t uid = 0; + uint64_t uid = 0, csuid = 0; if (pStoreAPI->metaFn.getTableUidByName(pVnode, name, &uid) == 0) { ETableType tbType = TSDB_TABLE_MAX; - if (pStoreAPI->metaFn.getTableTypeByName(pVnode, name, &tbType) == 0 && tbType == TSDB_CHILD_TABLE) { + if (pStoreAPI->metaFn.getTableTypeSuidByName(pVnode, name, &tbType, &csuid) == 0 && tbType == TSDB_CHILD_TABLE) { + if (suid != csuid) { + continue; + } if (NULL == uHash || taosHashGet(uHash, &uid, sizeof(uid)) == NULL) { STUidTagInfo s = {.uid = uid, .name = name, .pTagVal = NULL}; void* tmp = taosArrayPush(pExistedUidList, &s); diff --git a/tests/parallel_test/cases.task b/tests/parallel_test/cases.task index 77efa823be..ebec0ad38e 100644 --- a/tests/parallel_test/cases.task +++ b/tests/parallel_test/cases.task @@ -176,6 +176,11 @@ ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/tsma2.py -Q 2 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/tsma2.py -Q 3 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/tsma2.py -Q 4 +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/tbnameIn.py +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/tbnameIn.py -R +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/tbnameIn.py -Q 2 +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/tbnameIn.py -Q 3 +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/tbnameIn.py -Q 4 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/nestedQuery2.py ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/interp_extension.py ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/interp_extension.py -R diff --git a/tests/system-test/2-query/tbnameIn.py b/tests/system-test/2-query/tbnameIn.py new file mode 100644 index 0000000000..91fdf9f73e --- /dev/null +++ b/tests/system-test/2-query/tbnameIn.py @@ -0,0 +1,145 @@ +################################################################### +# Copyright (c) 2016 by TAOS Technologies, Inc. +# All rights reserved. +# +# This file is proprietary and confidential to TAOS Technologies. +# No part of this file may be reproduced, stored, transmitted, +# disclosed or used in any form or by any means other than as +# expressly provided by the written permission from Jianhui Tao +# +################################################################### + +# -*- coding: utf-8 -*- + +import sys +import taos +from util.log import * +from util.cases import * +from util.sql import * + + +class TDTestCase: + def init(self, conn, logSql, replicaVar=1): + self.replicaVar = int(replicaVar) + tdLog.debug(f"start to excute {__file__}") + tdSql.init(conn.cursor()) + + def inTest(self, dbname="db"): + tdSql.execute(f'drop database if exists {dbname}') + tdSql.execute(f'create database {dbname}') + tdSql.execute(f'use {dbname}') + tdSql.execute(f'CREATE STABLE {dbname}.`st1` (`ts` TIMESTAMP, `v1` INT) TAGS (`t1` INT);') + tdSql.execute(f'CREATE STABLE {dbname}.`st2` (`ts` TIMESTAMP, `v1` INT) TAGS (`t1` INT);') + tdSql.execute(f'CREATE TABLE {dbname}.`t11` USING {dbname}.`st1` (`t1`) TAGS (11);') + tdSql.execute(f'CREATE TABLE {dbname}.`t12` USING {dbname}.`st1` (`t1`) TAGS (12);') + tdSql.execute(f'CREATE TABLE {dbname}.`t21` USING {dbname}.`st2` (`t1`) TAGS (21);') + tdSql.execute(f'CREATE TABLE {dbname}.`t22` USING {dbname}.`st2` (`t1`) TAGS (22);') + tdSql.execute(f'CREATE TABLE {dbname}.`ta` (`ts` TIMESTAMP, `v1` INT);') + + tdSql.execute(f"insert into {dbname}.t11 values ( '2025-01-21 00:11:01', 111 )") + tdSql.execute(f"insert into {dbname}.t11 values ( '2025-01-21 00:11:02', 112 )") + tdSql.execute(f"insert into {dbname}.t11 values ( '2025-01-21 00:11:03', 113 )") + tdSql.execute(f"insert into {dbname}.t12 values ( '2025-01-21 00:12:01', 121 )") + tdSql.execute(f"insert into {dbname}.t12 values ( '2025-01-21 00:12:02', 122 )") + tdSql.execute(f"insert into {dbname}.t12 values ( '2025-01-21 00:12:03', 123 )") + + tdSql.execute(f"insert into {dbname}.t21 values ( '2025-01-21 00:21:01', 211 )") + tdSql.execute(f"insert into {dbname}.t21 values ( '2025-01-21 00:21:02', 212 )") + tdSql.execute(f"insert into {dbname}.t21 values ( '2025-01-21 00:21:03', 213 )") + tdSql.execute(f"insert into {dbname}.t22 values ( '2025-01-21 00:22:01', 221 )") + tdSql.execute(f"insert into {dbname}.t22 values ( '2025-01-21 00:22:02', 222 )") + tdSql.execute(f"insert into {dbname}.t22 values ( '2025-01-21 00:22:03', 223 )") + + tdSql.execute(f"insert into {dbname}.ta values ( '2025-01-21 00:00:01', 1 )") + tdSql.execute(f"insert into {dbname}.ta values ( '2025-01-21 00:00:02', 2 )") + tdSql.execute(f"insert into {dbname}.ta values ( '2025-01-21 00:00:03', 3 )") + + tdLog.debug(f"-------------- step1: normal table test ------------------") + tdSql.query(f"select last(*) from {dbname}.ta where tbname in ('ta');") + tdSql.checkRows(1) + tdSql.checkData(0, 0, '2025-01-21 00:00:03') + tdSql.checkData(0, 1, 3) + + tdSql.query(f"select last(*) from {dbname}.ta where tbname in ('ta', 't21');") + tdSql.checkRows(1) + tdSql.checkData(0, 0, '2025-01-21 00:00:03') + tdSql.checkData(0, 1, 3) + + tdSql.query(f"select last(*) from {dbname}.ta where tbname in ('t21');") + tdSql.checkRows(0) + + tdSql.query(f"select last(*) from {dbname}.ta where tbname in ('ta') and tbname in ('ta');") + tdSql.checkRows(1) + tdSql.checkData(0, 0, '2025-01-21 00:00:03') + tdSql.checkData(0, 1, 3) + + tdSql.query(f"select last(*) from {dbname}.ta where tbname in ('ta') or tbname in ('ta');") + tdSql.checkRows(1) + tdSql.checkData(0, 0, '2025-01-21 00:00:03') + tdSql.checkData(0, 1, 3) + + tdSql.query(f"select last(*) from {dbname}.ta where tbname in ('ta') or tbname in ('tb');") + tdSql.checkRows(1) + tdSql.checkData(0, 0, '2025-01-21 00:00:03') + tdSql.checkData(0, 1, 3) + + tdSql.query(f"select last(*) from {dbname}.ta where tbname in ('ta', 't21') and tbname in ('ta');") + tdSql.checkRows(1) + tdSql.checkData(0, 0, '2025-01-21 00:00:03') + tdSql.checkData(0, 1, 3) + + tdSql.query(f"select last(*) from {dbname}.ta where tbname in ('ta', 't21') and tbname in ('t21');") + tdSql.checkRows(0) + + tdSql.query(f"select last(*) from {dbname}.ta where tbname in ('t21') or tbname in ('ta');") + tdSql.checkRows(1) + tdSql.checkData(0, 0, '2025-01-21 00:00:03') + tdSql.checkData(0, 1, 3) + + tdLog.debug(f"-------------- step2: super table test ------------------") + tdSql.query(f"select last(*) from {dbname}.st1 where tbname in ('t11');") + tdSql.checkRows(1) + tdSql.checkData(0, 0, '2025-01-21 00:11:03') + tdSql.checkData(0, 1, 113) + + tdSql.query(f"select last(*) from {dbname}.st1 where tbname in ('t21');") + tdSql.checkRows(0) + + tdSql.query(f"select last(*) from {dbname}.st1 where tbname in ('ta', 't21');") + tdSql.checkRows(0) + + tdSql.query(f"select last(*) from {dbname}.st1 where tbname in ('t21', 't12');") + tdSql.checkRows(1) + tdSql.checkData(0, 0, '2025-01-21 00:12:03') + tdSql.checkData(0, 1, 123) + + tdSql.query(f"select last(*) from {dbname}.st1 where tbname in ('ta') and tbname in ('t12');") + tdSql.checkRows(0) + + tdSql.query(f"select last(*) from {dbname}.st1 where tbname in ('t12') or tbname in ('t11');") + tdSql.checkRows(1) + tdSql.checkData(0, 0, '2025-01-21 00:12:03') + tdSql.checkData(0, 1, 123) + + tdSql.query(f"select last(*) from {dbname}.st1 where tbname in ('ta') or tbname in ('t21');") + tdSql.checkRows(0) + + tdSql.query(f"select last(*) from {dbname}.st1 where tbname in ('t12', 't21') and tbname in ('t21');") + tdSql.checkRows(0) + + tdSql.query(f"select last(*) from {dbname}.st1 where tbname in ('t12', 't11') and tbname in ('t11');") + tdSql.checkRows(1) + tdSql.checkData(0, 0, '2025-01-21 00:11:03') + tdSql.checkData(0, 1, 113) + + + def run(self): + self.inTest() + + def stop(self): + tdSql.close() + tdLog.success("%s successfully executed" % __file__) + + +tdCases.addWindows(__file__, TDTestCase()) +tdCases.addLinux(__file__, TDTestCase())