Merge pull request #18618 from taosdata/enh/3.0_planner_optimize
enh: ins_table count optimize
This commit is contained in:
commit
30e124a56d
|
@ -163,6 +163,7 @@ typedef struct tExprNode {
|
||||||
int32_t functionId;
|
int32_t functionId;
|
||||||
int32_t num;
|
int32_t num;
|
||||||
struct SFunctionNode *pFunctNode;
|
struct SFunctionNode *pFunctNode;
|
||||||
|
int32_t functionType;
|
||||||
} _function;
|
} _function;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
|
|
@ -130,6 +130,7 @@ typedef enum EFunctionType {
|
||||||
FUNCTION_TYPE_GROUP_KEY,
|
FUNCTION_TYPE_GROUP_KEY,
|
||||||
FUNCTION_TYPE_CACHE_LAST_ROW,
|
FUNCTION_TYPE_CACHE_LAST_ROW,
|
||||||
FUNCTION_TYPE_CACHE_LAST,
|
FUNCTION_TYPE_CACHE_LAST,
|
||||||
|
FUNCTION_TYPE_TABLE_COUNT,
|
||||||
|
|
||||||
// distributed splitting functions
|
// distributed splitting functions
|
||||||
FUNCTION_TYPE_APERCENTILE_PARTIAL = 4000,
|
FUNCTION_TYPE_APERCENTILE_PARTIAL = 4000,
|
||||||
|
|
|
@ -60,6 +60,12 @@ extern "C" {
|
||||||
for (SListCell* cell = (NULL != (list) ? (list)->pHead : NULL); \
|
for (SListCell* cell = (NULL != (list) ? (list)->pHead : NULL); \
|
||||||
(NULL != cell ? (node = &(cell->pNode), true) : (node = NULL, false)); cell = cell->pNext)
|
(NULL != cell ? (node = &(cell->pNode), true) : (node = NULL, false)); cell = cell->pNext)
|
||||||
|
|
||||||
|
#define NODES_DESTORY_NODE(node) \
|
||||||
|
do { \
|
||||||
|
nodesDestroyNode((node)); \
|
||||||
|
(node) = NULL; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
#define NODES_DESTORY_LIST(list) \
|
#define NODES_DESTORY_LIST(list) \
|
||||||
do { \
|
do { \
|
||||||
nodesDestroyList((list)); \
|
nodesDestroyList((list)); \
|
||||||
|
@ -228,6 +234,7 @@ typedef enum ENodeType {
|
||||||
QUERY_NODE_PHYSICAL_PLAN_SYSTABLE_SCAN,
|
QUERY_NODE_PHYSICAL_PLAN_SYSTABLE_SCAN,
|
||||||
QUERY_NODE_PHYSICAL_PLAN_BLOCK_DIST_SCAN,
|
QUERY_NODE_PHYSICAL_PLAN_BLOCK_DIST_SCAN,
|
||||||
QUERY_NODE_PHYSICAL_PLAN_LAST_ROW_SCAN,
|
QUERY_NODE_PHYSICAL_PLAN_LAST_ROW_SCAN,
|
||||||
|
QUERY_NODE_PHYSICAL_PLAN_TABLE_COUNT_SCAN,
|
||||||
QUERY_NODE_PHYSICAL_PLAN_PROJECT,
|
QUERY_NODE_PHYSICAL_PLAN_PROJECT,
|
||||||
QUERY_NODE_PHYSICAL_PLAN_MERGE_JOIN,
|
QUERY_NODE_PHYSICAL_PLAN_MERGE_JOIN,
|
||||||
QUERY_NODE_PHYSICAL_PLAN_HASH_AGG,
|
QUERY_NODE_PHYSICAL_PLAN_HASH_AGG,
|
||||||
|
|
|
@ -62,7 +62,8 @@ typedef enum EScanType {
|
||||||
SCAN_TYPE_STREAM,
|
SCAN_TYPE_STREAM,
|
||||||
SCAN_TYPE_TABLE_MERGE,
|
SCAN_TYPE_TABLE_MERGE,
|
||||||
SCAN_TYPE_BLOCK_INFO,
|
SCAN_TYPE_BLOCK_INFO,
|
||||||
SCAN_TYPE_LAST_ROW
|
SCAN_TYPE_LAST_ROW,
|
||||||
|
SCAN_TYPE_TABLE_COUNT
|
||||||
} EScanType;
|
} EScanType;
|
||||||
|
|
||||||
typedef struct SScanLogicNode {
|
typedef struct SScanLogicNode {
|
||||||
|
@ -323,6 +324,8 @@ typedef struct SLastRowScanPhysiNode {
|
||||||
bool ignoreNull;
|
bool ignoreNull;
|
||||||
} SLastRowScanPhysiNode;
|
} SLastRowScanPhysiNode;
|
||||||
|
|
||||||
|
typedef SLastRowScanPhysiNode STableCountScanPhysiNode;
|
||||||
|
|
||||||
typedef struct SSystemTableScanPhysiNode {
|
typedef struct SSystemTableScanPhysiNode {
|
||||||
SScanPhysiNode scan;
|
SScanPhysiNode scan;
|
||||||
SEpSet mgmtEpSet;
|
SEpSet mgmtEpSet;
|
||||||
|
|
|
@ -106,14 +106,24 @@ int32_t metaGetTableTagsByUids(SMeta *pMeta, int64_t suid, SArray *uidList,
|
||||||
int32_t metaReadNext(SMetaReader *pReader);
|
int32_t metaReadNext(SMetaReader *pReader);
|
||||||
const void *metaGetTableTagVal(void *tag, int16_t type, STagVal *tagVal);
|
const void *metaGetTableTagVal(void *tag, int16_t type, STagVal *tagVal);
|
||||||
int metaGetTableNameByUid(void *meta, uint64_t uid, char *tbName);
|
int metaGetTableNameByUid(void *meta, uint64_t uid, char *tbName);
|
||||||
int metaGetTableUidByName(void *meta, char *tbName, uint64_t *uid);
|
|
||||||
int metaGetTableTypeByName(void *meta, char *tbName, ETableType *tbType);
|
int metaGetTableSzNameByUid(void *meta, uint64_t uid, char *tbName);
|
||||||
bool metaIsTableExist(SMeta *pMeta, tb_uid_t uid);
|
int metaGetTableUidByName(void *meta, char *tbName, uint64_t *uid);
|
||||||
int32_t metaGetCachedTableUidList(SMeta *pMeta, tb_uid_t suid, const uint8_t *key, int32_t keyLen, SArray *pList,
|
int metaGetTableTypeByName(void *meta, char *tbName, ETableType *tbType);
|
||||||
bool *acquired);
|
bool metaIsTableExist(SMeta *pMeta, tb_uid_t uid);
|
||||||
int32_t metaUidFilterCachePut(SMeta *pMeta, uint64_t suid, const void *pKey, int32_t keyLen, void *pPayload,
|
int32_t metaGetCachedTableUidList(SMeta *pMeta, tb_uid_t suid, const uint8_t *key, int32_t keyLen, SArray *pList,
|
||||||
int32_t payloadLen, double selectivityRatio);
|
bool *acquired);
|
||||||
int32_t metaUidCacheClear(SMeta *pMeta, uint64_t suid);
|
int32_t metaUidFilterCachePut(SMeta *pMeta, uint64_t suid, const void *pKey, int32_t keyLen, void *pPayload,
|
||||||
|
int32_t payloadLen, double selectivityRatio);
|
||||||
|
int32_t metaUidCacheClear(SMeta *pMeta, uint64_t suid);
|
||||||
|
tb_uid_t metaGetTableEntryUidByName(SMeta *pMeta, const char *name);
|
||||||
|
int64_t metaGetTbNum(SMeta *pMeta);
|
||||||
|
int64_t metaGetNtbNum(SMeta *pMeta);
|
||||||
|
typedef struct {
|
||||||
|
int64_t uid;
|
||||||
|
int64_t ctbNum;
|
||||||
|
} SMetaStbStats;
|
||||||
|
int32_t metaGetStbStats(SMeta *pMeta, int64_t uid, SMetaStbStats *pInfo);
|
||||||
|
|
||||||
typedef struct SMetaFltParam {
|
typedef struct SMetaFltParam {
|
||||||
tb_uid_t suid;
|
tb_uid_t suid;
|
||||||
|
|
|
@ -116,8 +116,6 @@ int32_t metaGetTbTSchemaEx(SMeta* pMeta, tb_uid_t suid, tb_uid_t uid, in
|
||||||
int metaGetTableEntryByName(SMetaReader* pReader, const char* name);
|
int metaGetTableEntryByName(SMetaReader* pReader, const char* name);
|
||||||
int metaAlterCache(SMeta* pMeta, int32_t nPage);
|
int metaAlterCache(SMeta* pMeta, int32_t nPage);
|
||||||
|
|
||||||
tb_uid_t metaGetTableEntryUidByName(SMeta* pMeta, const char* name);
|
|
||||||
int64_t metaGetTbNum(SMeta* pMeta);
|
|
||||||
int64_t metaGetTimeSeriesNum(SMeta* pMeta);
|
int64_t metaGetTimeSeriesNum(SMeta* pMeta);
|
||||||
SMCtbCursor* metaOpenCtbCursor(SMeta* pMeta, tb_uid_t uid, int lock);
|
SMCtbCursor* metaOpenCtbCursor(SMeta* pMeta, tb_uid_t uid, int lock);
|
||||||
void metaCloseCtbCursor(SMCtbCursor* pCtbCur, int lock);
|
void metaCloseCtbCursor(SMCtbCursor* pCtbCur, int lock);
|
||||||
|
@ -144,12 +142,6 @@ typedef struct SMetaInfo {
|
||||||
} SMetaInfo;
|
} SMetaInfo;
|
||||||
int32_t metaGetInfo(SMeta* pMeta, int64_t uid, SMetaInfo* pInfo, SMetaReader* pReader);
|
int32_t metaGetInfo(SMeta* pMeta, int64_t uid, SMetaInfo* pInfo, SMetaReader* pReader);
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int64_t uid;
|
|
||||||
int64_t ctbNum;
|
|
||||||
} SMetaStbStats;
|
|
||||||
int32_t metaGetStbStats(SMeta* pMeta, int64_t uid, SMetaStbStats* pInfo);
|
|
||||||
|
|
||||||
// tsdb
|
// tsdb
|
||||||
int tsdbOpen(SVnode* pVnode, STsdb** ppTsdb, const char* dir, STsdbKeepCfg* pKeepCfg, int8_t rollback);
|
int tsdbOpen(SVnode* pVnode, STsdb** ppTsdb, const char* dir, STsdbKeepCfg* pKeepCfg, int8_t rollback);
|
||||||
int tsdbClose(STsdb** pTsdb);
|
int tsdbClose(STsdb** pTsdb);
|
||||||
|
|
|
@ -223,6 +223,23 @@ int metaGetTableNameByUid(void *meta, uint64_t uid, char *tbName) {
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int metaGetTableSzNameByUid(void *meta, uint64_t uid, char *tbName) {
|
||||||
|
int code = 0;
|
||||||
|
SMetaReader mr = {0};
|
||||||
|
metaReaderInit(&mr, (SMeta *)meta, 0);
|
||||||
|
code = metaGetTableEntryByUid(&mr, uid);
|
||||||
|
if (code < 0) {
|
||||||
|
metaReaderClear(&mr);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
strncpy(tbName, mr.me.name, TSDB_TABLE_NAME_LEN);
|
||||||
|
metaReaderClear(&mr);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int metaGetTableUidByName(void *meta, char *tbName, uint64_t *uid) {
|
int metaGetTableUidByName(void *meta, char *tbName, uint64_t *uid) {
|
||||||
int code = 0;
|
int code = 0;
|
||||||
SMetaReader mr = {0};
|
SMetaReader mr = {0};
|
||||||
|
@ -739,6 +756,10 @@ int64_t metaGetTimeSeriesNum(SMeta *pMeta) {
|
||||||
return pMeta->pVnode->config.vndStats.numOfTimeSeries + pMeta->pVnode->config.vndStats.numOfNTimeSeries;
|
return pMeta->pVnode->config.vndStats.numOfTimeSeries + pMeta->pVnode->config.vndStats.numOfNTimeSeries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int64_t metaGetNtbNum(SMeta *pMeta) {
|
||||||
|
return pMeta->pVnode->config.vndStats.numOfNTables;
|
||||||
|
}
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
SMeta *pMeta;
|
SMeta *pMeta;
|
||||||
TBC *pCur;
|
TBC *pCur;
|
||||||
|
|
|
@ -34,6 +34,7 @@ extern "C" {
|
||||||
#define EXPLAIN_SYSTBL_SCAN_FORMAT "System Table Scan on %s"
|
#define EXPLAIN_SYSTBL_SCAN_FORMAT "System Table Scan on %s"
|
||||||
#define EXPLAIN_DISTBLK_SCAN_FORMAT "Block Dist Scan on %s"
|
#define EXPLAIN_DISTBLK_SCAN_FORMAT "Block Dist Scan on %s"
|
||||||
#define EXPLAIN_LASTROW_SCAN_FORMAT "Last Row Scan on %s"
|
#define EXPLAIN_LASTROW_SCAN_FORMAT "Last Row Scan on %s"
|
||||||
|
#define EXPLAIN_TABLE_COUNT_SCAN_FORMAT "Table Count Row Scan on %s"
|
||||||
#define EXPLAIN_PROJECTION_FORMAT "Projection"
|
#define EXPLAIN_PROJECTION_FORMAT "Projection"
|
||||||
#define EXPLAIN_JOIN_FORMAT "%s"
|
#define EXPLAIN_JOIN_FORMAT "%s"
|
||||||
#define EXPLAIN_AGG_FORMAT "Aggragate"
|
#define EXPLAIN_AGG_FORMAT "Aggragate"
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include "query.h"
|
#include "query.h"
|
||||||
#include "tcommon.h"
|
#include "tcommon.h"
|
||||||
#include "tdatablock.h"
|
#include "tdatablock.h"
|
||||||
|
#include "systable.h"
|
||||||
|
|
||||||
int32_t qExplainGenerateResNode(SPhysiNode *pNode, SExplainGroup *group, SExplainResNode **pRes);
|
int32_t qExplainGenerateResNode(SPhysiNode *pNode, SExplainGroup *group, SExplainResNode **pRes);
|
||||||
int32_t qExplainAppendGroupResRows(void *pCtx, int32_t groupId, int32_t level, bool singleChannel);
|
int32_t qExplainAppendGroupResRows(void *pCtx, int32_t groupId, int32_t level, bool singleChannel);
|
||||||
|
@ -212,6 +213,11 @@ int32_t qExplainGenerateResChildren(SPhysiNode *pNode, SExplainGroup *group, SNo
|
||||||
pPhysiChildren = lastRowPhysiNode->scan.node.pChildren;
|
pPhysiChildren = lastRowPhysiNode->scan.node.pChildren;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case QUERY_NODE_PHYSICAL_PLAN_TABLE_COUNT_SCAN: {
|
||||||
|
STableCountScanPhysiNode *tableCountPhysiNode = (STableCountScanPhysiNode *)pNode;
|
||||||
|
pPhysiChildren = tableCountPhysiNode->scan.node.pChildren;
|
||||||
|
break;
|
||||||
|
}
|
||||||
case QUERY_NODE_PHYSICAL_PLAN_GROUP_SORT: {
|
case QUERY_NODE_PHYSICAL_PLAN_GROUP_SORT: {
|
||||||
SGroupSortPhysiNode *groupSortPhysiNode = (SGroupSortPhysiNode *)pNode;
|
SGroupSortPhysiNode *groupSortPhysiNode = (SGroupSortPhysiNode *)pNode;
|
||||||
pPhysiChildren = groupSortPhysiNode->node.pChildren;
|
pPhysiChildren = groupSortPhysiNode->node.pChildren;
|
||||||
|
@ -1355,6 +1361,48 @@ int32_t qExplainResNodeToRowsImpl(SExplainResNode *pResNode, SExplainCtx *ctx, i
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case QUERY_NODE_PHYSICAL_PLAN_TABLE_COUNT_SCAN: {
|
||||||
|
STableCountScanPhysiNode *pLastRowNode = (STableCountScanPhysiNode *)pNode;
|
||||||
|
EXPLAIN_ROW_NEW(level, EXPLAIN_TABLE_COUNT_SCAN_FORMAT,
|
||||||
|
('\0' != pLastRowNode->scan.tableName.tname[0] ? pLastRowNode->scan.tableName.tname : TSDB_INS_TABLE_TABLES));
|
||||||
|
EXPLAIN_ROW_APPEND(EXPLAIN_LEFT_PARENTHESIS_FORMAT);
|
||||||
|
if (pResNode->pExecInfo) {
|
||||||
|
QRY_ERR_RET(qExplainBufAppendExecInfo(pResNode->pExecInfo, tbuf, &tlen));
|
||||||
|
EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
|
||||||
|
}
|
||||||
|
EXPLAIN_ROW_APPEND(EXPLAIN_COLUMNS_FORMAT, LIST_LENGTH(pLastRowNode->scan.pScanCols));
|
||||||
|
EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
|
||||||
|
if (pLastRowNode->scan.pScanPseudoCols) {
|
||||||
|
EXPLAIN_ROW_APPEND(EXPLAIN_PSEUDO_COLUMNS_FORMAT, pLastRowNode->scan.pScanPseudoCols->length);
|
||||||
|
EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
|
||||||
|
}
|
||||||
|
EXPLAIN_ROW_APPEND(EXPLAIN_WIDTH_FORMAT, pLastRowNode->scan.node.pOutputDataBlockDesc->totalRowSize);
|
||||||
|
EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
|
||||||
|
EXPLAIN_ROW_APPEND(EXPLAIN_RIGHT_PARENTHESIS_FORMAT);
|
||||||
|
EXPLAIN_ROW_END();
|
||||||
|
QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level));
|
||||||
|
|
||||||
|
if (verbose) {
|
||||||
|
EXPLAIN_ROW_NEW(level + 1, EXPLAIN_OUTPUT_FORMAT);
|
||||||
|
EXPLAIN_ROW_APPEND(EXPLAIN_COLUMNS_FORMAT,
|
||||||
|
nodesGetOutputNumFromSlotList(pLastRowNode->scan.node.pOutputDataBlockDesc->pSlots));
|
||||||
|
EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
|
||||||
|
EXPLAIN_ROW_APPEND(EXPLAIN_WIDTH_FORMAT, pLastRowNode->scan.node.pOutputDataBlockDesc->outputRowSize);
|
||||||
|
EXPLAIN_ROW_APPEND_LIMIT(pLastRowNode->scan.node.pLimit);
|
||||||
|
EXPLAIN_ROW_APPEND_SLIMIT(pLastRowNode->scan.node.pSlimit);
|
||||||
|
EXPLAIN_ROW_END();
|
||||||
|
QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
|
||||||
|
|
||||||
|
if (pLastRowNode->scan.node.pConditions) {
|
||||||
|
EXPLAIN_ROW_NEW(level + 1, EXPLAIN_FILTER_FORMAT);
|
||||||
|
QRY_ERR_RET(nodesNodeToSQL(pLastRowNode->scan.node.pConditions, tbuf + VARSTR_HEADER_SIZE,
|
||||||
|
TSDB_EXPLAIN_RESULT_ROW_SIZE, &tlen));
|
||||||
|
EXPLAIN_ROW_END();
|
||||||
|
QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
case QUERY_NODE_PHYSICAL_PLAN_GROUP_SORT: {
|
case QUERY_NODE_PHYSICAL_PLAN_GROUP_SORT: {
|
||||||
SGroupSortPhysiNode *pSortNode = (SGroupSortPhysiNode *)pNode;
|
SGroupSortPhysiNode *pSortNode = (SGroupSortPhysiNode *)pNode;
|
||||||
EXPLAIN_ROW_NEW(level, EXPLAIN_GROUP_SORT_FORMAT);
|
EXPLAIN_ROW_NEW(level, EXPLAIN_GROUP_SORT_FORMAT);
|
||||||
|
|
|
@ -482,6 +482,34 @@ typedef struct {
|
||||||
SSnapContext* sContext;
|
SSnapContext* sContext;
|
||||||
} SStreamRawScanInfo;
|
} SStreamRawScanInfo;
|
||||||
|
|
||||||
|
typedef struct STableCountScanSupp {
|
||||||
|
int16_t dbNameSlotId;
|
||||||
|
int16_t stbNameSlotId;
|
||||||
|
int16_t tbCountSlotId;
|
||||||
|
|
||||||
|
bool groupByDbName;
|
||||||
|
bool groupByStbName;
|
||||||
|
char dbName[TSDB_DB_NAME_LEN];
|
||||||
|
char stbName[TSDB_TABLE_NAME_LEN];
|
||||||
|
|
||||||
|
} STableCountScanSupp;
|
||||||
|
|
||||||
|
typedef struct STableCountScanOperatorInfo {
|
||||||
|
SReadHandle readHandle;
|
||||||
|
SSDataBlock* pRes;
|
||||||
|
|
||||||
|
SName tableName;
|
||||||
|
|
||||||
|
SNodeList* groupTags;
|
||||||
|
SNodeList* scanCols;
|
||||||
|
SNodeList* pseudoCols;
|
||||||
|
|
||||||
|
STableCountScanSupp supp;
|
||||||
|
|
||||||
|
int32_t currGrpIdx;
|
||||||
|
SArray* stbUidList; // when group by db_name and stable_name
|
||||||
|
} STableCountScanOperatorInfo;
|
||||||
|
|
||||||
typedef struct SOptrBasicInfo {
|
typedef struct SOptrBasicInfo {
|
||||||
SResultRowInfo resultRowInfo;
|
SResultRowInfo resultRowInfo;
|
||||||
SSDataBlock* pRes;
|
SSDataBlock* pRes;
|
||||||
|
|
|
@ -1348,6 +1348,7 @@ void createExprFromOneNode(SExprInfo* pExp, SNode* pNode, int16_t slotId) {
|
||||||
|
|
||||||
pExprNode->_function.functionId = pFuncNode->funcId;
|
pExprNode->_function.functionId = pFuncNode->funcId;
|
||||||
pExprNode->_function.pFunctNode = pFuncNode;
|
pExprNode->_function.pFunctNode = pFuncNode;
|
||||||
|
pExprNode->_function.functionType = pFuncNode->funcType;
|
||||||
|
|
||||||
tstrncpy(pExprNode->_function.functionName, pFuncNode->functionName, tListLen(pExprNode->_function.functionName));
|
tstrncpy(pExprNode->_function.functionName, pFuncNode->functionName, tListLen(pExprNode->_function.functionName));
|
||||||
|
|
||||||
|
|
|
@ -1370,7 +1370,8 @@ int32_t getTableScanInfo(SOperatorInfo* pOperator, int32_t* order, int32_t* scan
|
||||||
int32_t type = pOperator->operatorType;
|
int32_t type = pOperator->operatorType;
|
||||||
if (type == QUERY_NODE_PHYSICAL_PLAN_EXCHANGE || type == QUERY_NODE_PHYSICAL_PLAN_SYSTABLE_SCAN ||
|
if (type == QUERY_NODE_PHYSICAL_PLAN_EXCHANGE || type == QUERY_NODE_PHYSICAL_PLAN_SYSTABLE_SCAN ||
|
||||||
type == QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN || type == QUERY_NODE_PHYSICAL_PLAN_TAG_SCAN ||
|
type == QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN || type == QUERY_NODE_PHYSICAL_PLAN_TAG_SCAN ||
|
||||||
type == QUERY_NODE_PHYSICAL_PLAN_BLOCK_DIST_SCAN || type == QUERY_NODE_PHYSICAL_PLAN_LAST_ROW_SCAN) {
|
type == QUERY_NODE_PHYSICAL_PLAN_BLOCK_DIST_SCAN || type == QUERY_NODE_PHYSICAL_PLAN_LAST_ROW_SCAN ||
|
||||||
|
type == QUERY_NODE_PHYSICAL_PLAN_TABLE_COUNT_SCAN) {
|
||||||
*order = TSDB_ORDER_ASC;
|
*order = TSDB_ORDER_ASC;
|
||||||
*scanFlag = MAIN_SCAN;
|
*scanFlag = MAIN_SCAN;
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
|
@ -1872,6 +1873,8 @@ static SExecTaskInfo* createExecTaskInfo(uint64_t queryId, uint64_t taskId, EOPT
|
||||||
|
|
||||||
SSchemaWrapper* extractQueriedColumnSchema(SScanPhysiNode* pScanNode);
|
SSchemaWrapper* extractQueriedColumnSchema(SScanPhysiNode* pScanNode);
|
||||||
|
|
||||||
|
SOperatorInfo* createTableCountScanOperatorInfo(SReadHandle* handle, STableCountScanPhysiNode* pNode,
|
||||||
|
SExecTaskInfo* pTaskInfo);
|
||||||
int32_t extractTableSchemaInfo(SReadHandle* pHandle, SScanPhysiNode* pScanNode, SExecTaskInfo* pTaskInfo) {
|
int32_t extractTableSchemaInfo(SReadHandle* pHandle, SScanPhysiNode* pScanNode, SExecTaskInfo* pTaskInfo) {
|
||||||
SMetaReader mr = {0};
|
SMetaReader mr = {0};
|
||||||
metaReaderInit(&mr, pHandle->meta, 0);
|
metaReaderInit(&mr, pHandle->meta, 0);
|
||||||
|
@ -2062,6 +2065,9 @@ SOperatorInfo* createOperatorTree(SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo
|
||||||
} else if (QUERY_NODE_PHYSICAL_PLAN_SYSTABLE_SCAN == type) {
|
} else if (QUERY_NODE_PHYSICAL_PLAN_SYSTABLE_SCAN == type) {
|
||||||
SSystemTableScanPhysiNode* pSysScanPhyNode = (SSystemTableScanPhysiNode*)pPhyNode;
|
SSystemTableScanPhysiNode* pSysScanPhyNode = (SSystemTableScanPhysiNode*)pPhyNode;
|
||||||
pOperator = createSysTableScanOperatorInfo(pHandle, pSysScanPhyNode, pUser, pTaskInfo);
|
pOperator = createSysTableScanOperatorInfo(pHandle, pSysScanPhyNode, pUser, pTaskInfo);
|
||||||
|
} else if (QUERY_NODE_PHYSICAL_PLAN_TABLE_COUNT_SCAN == type) {
|
||||||
|
STableCountScanPhysiNode* pTblCountScanNode = (STableCountScanPhysiNode*)pPhyNode;
|
||||||
|
pOperator = createTableCountScanOperatorInfo(pHandle, pTblCountScanNode, pTaskInfo);
|
||||||
} else if (QUERY_NODE_PHYSICAL_PLAN_TAG_SCAN == type) {
|
} else if (QUERY_NODE_PHYSICAL_PLAN_TAG_SCAN == type) {
|
||||||
STagScanPhysiNode* pScanPhyNode = (STagScanPhysiNode*)pPhyNode;
|
STagScanPhysiNode* pScanPhyNode = (STagScanPhysiNode*)pPhyNode;
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,6 @@
|
||||||
#include "tcompare.h"
|
#include "tcompare.h"
|
||||||
#include "thash.h"
|
#include "thash.h"
|
||||||
#include "ttypes.h"
|
#include "ttypes.h"
|
||||||
#include "vnode.h"
|
|
||||||
|
|
||||||
#define SET_REVERSE_SCAN_FLAG(_info) ((_info)->scanFlag = REVERSE_SCAN)
|
#define SET_REVERSE_SCAN_FLAG(_info) ((_info)->scanFlag = REVERSE_SCAN)
|
||||||
#define SWITCH_ORDER(n) (((n) = ((n) == TSDB_ORDER_ASC) ? TSDB_ORDER_DESC : TSDB_ORDER_ASC))
|
#define SWITCH_ORDER(n) (((n) = ((n) == TSDB_ORDER_ASC) ? TSDB_ORDER_DESC : TSDB_ORDER_ASC))
|
||||||
|
@ -2913,3 +2912,305 @@ _error:
|
||||||
taosMemoryFree(pOperator);
|
taosMemoryFree(pOperator);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ====================================================================================================================
|
||||||
|
// TableCountScanOperator
|
||||||
|
static SSDataBlock* doTableCountScan(SOperatorInfo* pOperator);
|
||||||
|
static void destoryTableCountScanOperator(void* param);
|
||||||
|
static const char* GROUP_TAG_DB_NAME = "db_name";
|
||||||
|
static const char* GROUP_TAG_STABLE_NAME = "stable_name";
|
||||||
|
|
||||||
|
int32_t tblCountScanGetGroupTagsSlotId(const SNodeList* scanCols, STableCountScanSupp* supp) {
|
||||||
|
if (scanCols != NULL) {
|
||||||
|
SNode* pNode = NULL;
|
||||||
|
FOREACH(pNode, scanCols) {
|
||||||
|
if (nodeType(pNode) != QUERY_NODE_TARGET) {
|
||||||
|
return TSDB_CODE_QRY_SYS_ERROR;
|
||||||
|
}
|
||||||
|
STargetNode* targetNode = (STargetNode*)pNode;
|
||||||
|
if (nodeType(targetNode->pExpr) != QUERY_NODE_COLUMN) {
|
||||||
|
return TSDB_CODE_QRY_SYS_ERROR;
|
||||||
|
}
|
||||||
|
SColumnNode* colNode = (SColumnNode*)(targetNode->pExpr);
|
||||||
|
if (strcmp(colNode->colName, GROUP_TAG_DB_NAME) == 0) {
|
||||||
|
supp->dbNameSlotId = targetNode->slotId;
|
||||||
|
} else if (strcmp(colNode->colName, GROUP_TAG_STABLE_NAME) == 0) {
|
||||||
|
supp->stbNameSlotId = targetNode->slotId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t tblCountScanGetCountSlotId(const SNodeList* pseudoCols, STableCountScanSupp* supp) {
|
||||||
|
if (pseudoCols != NULL) {
|
||||||
|
SNode* pNode = NULL;
|
||||||
|
FOREACH(pNode, pseudoCols) {
|
||||||
|
if (nodeType(pNode) != QUERY_NODE_TARGET) {
|
||||||
|
return TSDB_CODE_QRY_SYS_ERROR;
|
||||||
|
}
|
||||||
|
STargetNode* targetNode = (STargetNode*)pNode;
|
||||||
|
if (nodeType(targetNode->pExpr) != QUERY_NODE_FUNCTION) {
|
||||||
|
return TSDB_CODE_QRY_SYS_ERROR;
|
||||||
|
}
|
||||||
|
SFunctionNode* funcNode = (SFunctionNode*)(targetNode->pExpr);
|
||||||
|
if (funcNode->funcType == FUNCTION_TYPE_TABLE_COUNT) {
|
||||||
|
supp->tbCountSlotId = targetNode->slotId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t tblCountScanGetInputs(SNodeList* groupTags, SName* tableName, STableCountScanSupp* supp) {
|
||||||
|
if (groupTags != NULL) {
|
||||||
|
SNode* pNode = NULL;
|
||||||
|
FOREACH(pNode, groupTags) {
|
||||||
|
if (nodeType(pNode) != QUERY_NODE_COLUMN) {
|
||||||
|
return TSDB_CODE_QRY_SYS_ERROR;
|
||||||
|
}
|
||||||
|
SColumnNode* colNode = (SColumnNode*)pNode;
|
||||||
|
if (strcmp(colNode->colName, GROUP_TAG_DB_NAME) == 0) {
|
||||||
|
supp->groupByDbName = true;
|
||||||
|
}
|
||||||
|
if (strcmp(colNode->colName, GROUP_TAG_STABLE_NAME) == 0) {
|
||||||
|
supp->groupByStbName = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
strncpy(supp->dbName, tNameGetDbNameP(tableName), TSDB_DB_NAME_LEN);
|
||||||
|
strncpy(supp->stbName, tNameGetTableName(tableName), TSDB_TABLE_NAME_LEN);
|
||||||
|
}
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t getTableCountScanSupp(SNodeList* groupTags, SName* tableName, SNodeList* scanCols, SNodeList* pseudoCols,
|
||||||
|
STableCountScanSupp* supp, SExecTaskInfo* taskInfo) {
|
||||||
|
int32_t code = 0;
|
||||||
|
code = tblCountScanGetInputs(groupTags, tableName, supp);
|
||||||
|
if (code != TSDB_CODE_SUCCESS) {
|
||||||
|
qError("%s get table count scan supp. get inputs error", GET_TASKID(taskInfo));
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
supp->dbNameSlotId = -1;
|
||||||
|
supp->stbNameSlotId = -1;
|
||||||
|
supp->tbCountSlotId = -1;
|
||||||
|
|
||||||
|
code = tblCountScanGetGroupTagsSlotId(scanCols, supp);
|
||||||
|
if (code != TSDB_CODE_SUCCESS) {
|
||||||
|
qError("%s get table count scan supp. get group tags slot id error", GET_TASKID(taskInfo));
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
code = tblCountScanGetCountSlotId(pseudoCols, supp);
|
||||||
|
if (code != TSDB_CODE_SUCCESS) {
|
||||||
|
qError("%s get table count scan supp. get count error", GET_TASKID(taskInfo));
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
SOperatorInfo* createTableCountScanOperatorInfo(SReadHandle* readHandle, STableCountScanPhysiNode* pTblCountScanNode,
|
||||||
|
SExecTaskInfo* pTaskInfo) {
|
||||||
|
int32_t code = TSDB_CODE_SUCCESS;
|
||||||
|
|
||||||
|
SScanPhysiNode* pScanNode = &pTblCountScanNode->scan;
|
||||||
|
STableCountScanOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(STableCountScanOperatorInfo));
|
||||||
|
SOperatorInfo* pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
|
||||||
|
|
||||||
|
if (!pInfo || !pOperator) {
|
||||||
|
goto _error;
|
||||||
|
}
|
||||||
|
|
||||||
|
pInfo->readHandle = *readHandle;
|
||||||
|
|
||||||
|
SDataBlockDescNode* pDescNode = pScanNode->node.pOutputDataBlockDesc;
|
||||||
|
initResultSizeInfo(&pOperator->resultInfo, 1);
|
||||||
|
pInfo->pRes = createDataBlockFromDescNode(pDescNode);
|
||||||
|
blockDataEnsureCapacity(pInfo->pRes, pOperator->resultInfo.capacity);
|
||||||
|
|
||||||
|
getTableCountScanSupp(pTblCountScanNode->pGroupTags, &pTblCountScanNode->scan.tableName,
|
||||||
|
pTblCountScanNode->scan.pScanCols, pTblCountScanNode->scan.pScanPseudoCols, &pInfo->supp,
|
||||||
|
pTaskInfo);
|
||||||
|
|
||||||
|
setOperatorInfo(pOperator, "TableCountScanOperator", QUERY_NODE_PHYSICAL_PLAN_TABLE_COUNT_SCAN, false, OP_NOT_OPENED,
|
||||||
|
pInfo, pTaskInfo);
|
||||||
|
pOperator->fpSet =
|
||||||
|
createOperatorFpSet(operatorDummyOpenFn, doTableCountScan, NULL, destoryTableCountScanOperator, NULL);
|
||||||
|
return pOperator;
|
||||||
|
|
||||||
|
_error:
|
||||||
|
if (pInfo != NULL) {
|
||||||
|
destoryTableCountScanOperator(pInfo);
|
||||||
|
}
|
||||||
|
taosMemoryFreeClear(pOperator);
|
||||||
|
pTaskInfo->code = code;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fillTableCountScanDataBlock(STableCountScanSupp* pSupp, char* dbName, char* stbName, int64_t count,
|
||||||
|
SSDataBlock* pRes) {
|
||||||
|
if (pSupp->dbNameSlotId != -1) {
|
||||||
|
ASSERT(strlen(dbName));
|
||||||
|
SColumnInfoData* colInfoData = taosArrayGet(pRes->pDataBlock, pSupp->dbNameSlotId);
|
||||||
|
char varDbName[TSDB_DB_NAME_LEN + VARSTR_HEADER_SIZE] = {0};
|
||||||
|
strncpy(varDataVal(varDbName), dbName, strlen(dbName));
|
||||||
|
varDataSetLen(varDbName, strlen(dbName));
|
||||||
|
colDataAppend(colInfoData, 0, varDbName, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pSupp->stbNameSlotId != -1) {
|
||||||
|
SColumnInfoData* colInfoData = taosArrayGet(pRes->pDataBlock, pSupp->stbNameSlotId);
|
||||||
|
if (strlen(stbName) != 0) {
|
||||||
|
char varStbName[TSDB_TABLE_NAME_LEN + VARSTR_HEADER_SIZE] = {0};
|
||||||
|
strncpy(varDataVal(varStbName), stbName, strlen(stbName));
|
||||||
|
varDataSetLen(varStbName, strlen(stbName));
|
||||||
|
colDataAppend(colInfoData, 0, varStbName, false);
|
||||||
|
} else {
|
||||||
|
colDataAppendNULL(colInfoData, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pSupp->tbCountSlotId != -1) {
|
||||||
|
SColumnInfoData* colInfoData = taosArrayGet(pRes->pDataBlock, pSupp->tbCountSlotId);
|
||||||
|
colDataAppend(colInfoData, 0, (char*)&count, false);
|
||||||
|
}
|
||||||
|
pRes->info.rows = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SSDataBlock* buildSysDbTableCount(SOperatorInfo* pOperator, STableCountScanOperatorInfo* pInfo) {
|
||||||
|
STableCountScanSupp* pSupp = &pInfo->supp;
|
||||||
|
SSDataBlock* pRes = pInfo->pRes;
|
||||||
|
|
||||||
|
size_t infodbTableNum;
|
||||||
|
getInfosDbMeta(NULL, &infodbTableNum);
|
||||||
|
size_t perfdbTableNum;
|
||||||
|
getPerfDbMeta(NULL, &perfdbTableNum);
|
||||||
|
|
||||||
|
if (pSupp->groupByDbName) {
|
||||||
|
if (pInfo->currGrpIdx == 0) {
|
||||||
|
uint64_t groupId = calcGroupId(TSDB_INFORMATION_SCHEMA_DB, strlen(TSDB_INFORMATION_SCHEMA_DB));
|
||||||
|
pRes->info.id.groupId = groupId;
|
||||||
|
fillTableCountScanDataBlock(pSupp, TSDB_INFORMATION_SCHEMA_DB, "", infodbTableNum, pRes);
|
||||||
|
} else if (pInfo->currGrpIdx == 1) {
|
||||||
|
uint64_t groupId = calcGroupId(TSDB_PERFORMANCE_SCHEMA_DB, strlen(TSDB_PERFORMANCE_SCHEMA_DB));
|
||||||
|
pRes->info.id.groupId = groupId;
|
||||||
|
fillTableCountScanDataBlock(pSupp, TSDB_PERFORMANCE_SCHEMA_DB, "", perfdbTableNum, pRes);
|
||||||
|
} else {
|
||||||
|
setOperatorCompleted(pOperator);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
pInfo->currGrpIdx++;
|
||||||
|
return (pRes->info.rows > 0) ? pRes : NULL;
|
||||||
|
} else {
|
||||||
|
if (strcmp(pSupp->dbName, TSDB_INFORMATION_SCHEMA_DB) == 0) {
|
||||||
|
fillTableCountScanDataBlock(pSupp, TSDB_INFORMATION_SCHEMA_DB, "", infodbTableNum, pRes);
|
||||||
|
} else if (strcmp(pSupp->dbName, TSDB_PERFORMANCE_SCHEMA_DB) == 0) {
|
||||||
|
fillTableCountScanDataBlock(pSupp, TSDB_PERFORMANCE_SCHEMA_DB, "", perfdbTableNum, pRes);
|
||||||
|
} else if (strlen(pSupp->dbName) == 0) {
|
||||||
|
fillTableCountScanDataBlock(pSupp, "", "", infodbTableNum + perfdbTableNum, pRes);
|
||||||
|
}
|
||||||
|
setOperatorCompleted(pOperator);
|
||||||
|
return (pRes->info.rows > 0) ? pRes : NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static SSDataBlock* doTableCountScan(SOperatorInfo* pOperator) {
|
||||||
|
SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
|
||||||
|
STableCountScanOperatorInfo* pInfo = pOperator->info;
|
||||||
|
STableCountScanSupp* pSupp = &pInfo->supp;
|
||||||
|
SSDataBlock* pRes = pInfo->pRes;
|
||||||
|
blockDataCleanup(pRes);
|
||||||
|
|
||||||
|
if (pOperator->status == OP_EXEC_DONE) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (pInfo->readHandle.mnd != NULL) {
|
||||||
|
return buildSysDbTableCount(pOperator, pInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* db = NULL;
|
||||||
|
int32_t vgId = 0;
|
||||||
|
char dbName[TSDB_DB_NAME_LEN] = {0};
|
||||||
|
|
||||||
|
{
|
||||||
|
// get dbname
|
||||||
|
vnodeGetInfo(pInfo->readHandle.vnode, &db, &vgId);
|
||||||
|
SName sn = {0};
|
||||||
|
tNameFromString(&sn, db, T_NAME_ACCT | T_NAME_DB);
|
||||||
|
tNameGetDbName(&sn, dbName);
|
||||||
|
}
|
||||||
|
if (pSupp->groupByDbName) {
|
||||||
|
if (pSupp->groupByStbName) {
|
||||||
|
if (pInfo->stbUidList == NULL) {
|
||||||
|
pInfo->stbUidList = taosArrayInit(16, sizeof(tb_uid_t));
|
||||||
|
if (vnodeGetStbIdList(pInfo->readHandle.vnode, 0, pInfo->stbUidList) < 0) {
|
||||||
|
qError("vgId:%d, failed to get stb id list error: %s", vgId, terrstr());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (pInfo->currGrpIdx < taosArrayGetSize(pInfo->stbUidList)) {
|
||||||
|
tb_uid_t stbUid = *(tb_uid_t*)taosArrayGet(pInfo->stbUidList, pInfo->currGrpIdx);
|
||||||
|
|
||||||
|
char stbName[TSDB_TABLE_NAME_LEN] = {0};
|
||||||
|
metaGetTableSzNameByUid(pInfo->readHandle.meta, stbUid, stbName);
|
||||||
|
|
||||||
|
char fullStbName[TSDB_TABLE_FNAME_LEN] = {0};
|
||||||
|
snprintf(fullStbName, TSDB_TABLE_FNAME_LEN, "%s.%s", dbName, stbName);
|
||||||
|
uint64_t groupId = calcGroupId(fullStbName, strlen(fullStbName));
|
||||||
|
pRes->info.id.groupId = groupId;
|
||||||
|
|
||||||
|
SMetaStbStats stats = {0};
|
||||||
|
metaGetStbStats(pInfo->readHandle.meta, stbUid, &stats);
|
||||||
|
int64_t ctbNum = stats.ctbNum;
|
||||||
|
|
||||||
|
fillTableCountScanDataBlock(pSupp, dbName, stbName, ctbNum, pRes);
|
||||||
|
|
||||||
|
pInfo->currGrpIdx++;
|
||||||
|
} else if (pInfo->currGrpIdx == taosArrayGetSize(pInfo->stbUidList)) {
|
||||||
|
char fullStbName[TSDB_TABLE_FNAME_LEN] = {0};
|
||||||
|
snprintf(fullStbName, TSDB_TABLE_FNAME_LEN, "%s.%s", dbName, "");
|
||||||
|
uint64_t groupId = calcGroupId(fullStbName, strlen(fullStbName));
|
||||||
|
pRes->info.id.groupId = groupId;
|
||||||
|
int64_t ntbNum = metaGetNtbNum(pInfo->readHandle.meta);
|
||||||
|
fillTableCountScanDataBlock(pSupp, dbName, "", ntbNum, pRes);
|
||||||
|
|
||||||
|
pInfo->currGrpIdx++;
|
||||||
|
} else {
|
||||||
|
setOperatorCompleted(pOperator);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
uint64_t groupId = calcGroupId(dbName, strlen(dbName));
|
||||||
|
pRes->info.id.groupId = groupId;
|
||||||
|
int64_t dbTableCount = metaGetTbNum(pInfo->readHandle.meta);
|
||||||
|
fillTableCountScanDataBlock(pSupp, dbName, "", dbTableCount, pRes);
|
||||||
|
setOperatorCompleted(pOperator);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (strlen(pSupp->dbName) != 0) {
|
||||||
|
if (strlen(pSupp->stbName) != 0) {
|
||||||
|
tb_uid_t uid = metaGetTableEntryUidByName(pInfo->readHandle.meta, pSupp->stbName);
|
||||||
|
SMetaStbStats stats = {0};
|
||||||
|
metaGetStbStats(pInfo->readHandle.meta, uid, &stats);
|
||||||
|
int64_t ctbNum = stats.ctbNum;
|
||||||
|
fillTableCountScanDataBlock(pSupp, dbName, pSupp->stbName, ctbNum, pRes);
|
||||||
|
} else {
|
||||||
|
int64_t tbNumVnode = metaGetTbNum(pInfo->readHandle.meta);
|
||||||
|
fillTableCountScanDataBlock(pSupp, dbName, "", tbNumVnode, pRes);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
int64_t tbNumVnode = metaGetTbNum(pInfo->readHandle.meta);
|
||||||
|
fillTableCountScanDataBlock(pSupp, dbName, "", tbNumVnode, pRes);
|
||||||
|
}
|
||||||
|
setOperatorCompleted(pOperator);
|
||||||
|
}
|
||||||
|
return pRes->info.rows > 0 ? pRes : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void destoryTableCountScanOperator(void* param) {
|
||||||
|
STableCountScanOperatorInfo* pTableCountScanInfo = param;
|
||||||
|
blockDataDestroy(pTableCountScanInfo->pRes);
|
||||||
|
|
||||||
|
nodesDestroyList(pTableCountScanInfo->groupTags);
|
||||||
|
taosArrayDestroy(pTableCountScanInfo->stbUidList);
|
||||||
|
taosMemoryFreeClear(param);
|
||||||
|
}
|
||||||
|
|
|
@ -2080,6 +2080,11 @@ static int32_t translateTagsPseudoColumn(SFunctionNode* pFunc, char* pErrBuf, in
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int32_t translateTableCountPseudoColumn(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
|
||||||
|
pFunc->node.resType = (SDataType){.bytes = tDataTypes[TSDB_DATA_TYPE_BIGINT].bytes, .type = TSDB_DATA_TYPE_BIGINT};
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
||||||
{
|
{
|
||||||
|
@ -3241,6 +3246,16 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
||||||
.sprocessFunc = NULL,
|
.sprocessFunc = NULL,
|
||||||
.finalizeFunc = NULL
|
.finalizeFunc = NULL
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.name = "_table_count",
|
||||||
|
.type = FUNCTION_TYPE_TABLE_COUNT,
|
||||||
|
.classification = FUNC_MGT_PSEUDO_COLUMN_FUNC | FUNC_MGT_SCAN_PC_FUNC,
|
||||||
|
.translateFunc = translateTableCountPseudoColumn,
|
||||||
|
.getEnvFunc = NULL,
|
||||||
|
.initFunc = NULL,
|
||||||
|
.sprocessFunc = NULL,
|
||||||
|
.finalizeFunc = NULL
|
||||||
|
},
|
||||||
};
|
};
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
|
|
|
@ -221,6 +221,8 @@ const char* nodesNodeName(ENodeType type) {
|
||||||
return "PhysiTableScan";
|
return "PhysiTableScan";
|
||||||
case QUERY_NODE_PHYSICAL_PLAN_TABLE_SEQ_SCAN:
|
case QUERY_NODE_PHYSICAL_PLAN_TABLE_SEQ_SCAN:
|
||||||
return "PhysiTableSeqScan";
|
return "PhysiTableSeqScan";
|
||||||
|
case QUERY_NODE_PHYSICAL_PLAN_TABLE_MERGE_SCAN:
|
||||||
|
return "PhysiTableMergeScan";
|
||||||
case QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN:
|
case QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN:
|
||||||
return "PhysiSreamScan";
|
return "PhysiSreamScan";
|
||||||
case QUERY_NODE_PHYSICAL_PLAN_SYSTABLE_SCAN:
|
case QUERY_NODE_PHYSICAL_PLAN_SYSTABLE_SCAN:
|
||||||
|
@ -229,8 +231,8 @@ const char* nodesNodeName(ENodeType type) {
|
||||||
return "PhysiBlockDistScan";
|
return "PhysiBlockDistScan";
|
||||||
case QUERY_NODE_PHYSICAL_PLAN_LAST_ROW_SCAN:
|
case QUERY_NODE_PHYSICAL_PLAN_LAST_ROW_SCAN:
|
||||||
return "PhysiLastRowScan";
|
return "PhysiLastRowScan";
|
||||||
case QUERY_NODE_PHYSICAL_PLAN_TABLE_MERGE_SCAN:
|
case QUERY_NODE_PHYSICAL_PLAN_TABLE_COUNT_SCAN:
|
||||||
return "PhysiTableMergeScan";
|
return "PhysiTableCountScan";
|
||||||
case QUERY_NODE_PHYSICAL_PLAN_PROJECT:
|
case QUERY_NODE_PHYSICAL_PLAN_PROJECT:
|
||||||
return "PhysiProject";
|
return "PhysiProject";
|
||||||
case QUERY_NODE_PHYSICAL_PLAN_MERGE_JOIN:
|
case QUERY_NODE_PHYSICAL_PLAN_MERGE_JOIN:
|
||||||
|
@ -4646,6 +4648,7 @@ static int32_t specificNodeToJson(const void* pObj, SJson* pJson) {
|
||||||
case QUERY_NODE_PHYSICAL_PLAN_BLOCK_DIST_SCAN:
|
case QUERY_NODE_PHYSICAL_PLAN_BLOCK_DIST_SCAN:
|
||||||
return physiScanNodeToJson(pObj, pJson);
|
return physiScanNodeToJson(pObj, pJson);
|
||||||
case QUERY_NODE_PHYSICAL_PLAN_LAST_ROW_SCAN:
|
case QUERY_NODE_PHYSICAL_PLAN_LAST_ROW_SCAN:
|
||||||
|
case QUERY_NODE_PHYSICAL_PLAN_TABLE_COUNT_SCAN:
|
||||||
return physiLastRowScanNodeToJson(pObj, pJson);
|
return physiLastRowScanNodeToJson(pObj, pJson);
|
||||||
case QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN:
|
case QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN:
|
||||||
case QUERY_NODE_PHYSICAL_PLAN_TABLE_MERGE_SCAN:
|
case QUERY_NODE_PHYSICAL_PLAN_TABLE_MERGE_SCAN:
|
||||||
|
@ -4800,6 +4803,7 @@ static int32_t jsonToSpecificNode(const SJson* pJson, void* pObj) {
|
||||||
return jsonToLogicPlan(pJson, pObj);
|
return jsonToLogicPlan(pJson, pObj);
|
||||||
case QUERY_NODE_PHYSICAL_PLAN_TAG_SCAN:
|
case QUERY_NODE_PHYSICAL_PLAN_TAG_SCAN:
|
||||||
case QUERY_NODE_PHYSICAL_PLAN_BLOCK_DIST_SCAN:
|
case QUERY_NODE_PHYSICAL_PLAN_BLOCK_DIST_SCAN:
|
||||||
|
case QUERY_NODE_PHYSICAL_PLAN_TABLE_COUNT_SCAN:
|
||||||
return jsonToPhysiScanNode(pJson, pObj);
|
return jsonToPhysiScanNode(pJson, pObj);
|
||||||
case QUERY_NODE_PHYSICAL_PLAN_LAST_ROW_SCAN:
|
case QUERY_NODE_PHYSICAL_PLAN_LAST_ROW_SCAN:
|
||||||
return jsonToPhysiLastRowScanNode(pJson, pObj);
|
return jsonToPhysiLastRowScanNode(pJson, pObj);
|
||||||
|
|
|
@ -3640,6 +3640,7 @@ static int32_t specificNodeToMsg(const void* pObj, STlvEncoder* pEncoder) {
|
||||||
code = physiScanNodeToMsg(pObj, pEncoder);
|
code = physiScanNodeToMsg(pObj, pEncoder);
|
||||||
break;
|
break;
|
||||||
case QUERY_NODE_PHYSICAL_PLAN_LAST_ROW_SCAN:
|
case QUERY_NODE_PHYSICAL_PLAN_LAST_ROW_SCAN:
|
||||||
|
case QUERY_NODE_PHYSICAL_PLAN_TABLE_COUNT_SCAN:
|
||||||
code = physiLastRowScanNodeToMsg(pObj, pEncoder);
|
code = physiLastRowScanNodeToMsg(pObj, pEncoder);
|
||||||
break;
|
break;
|
||||||
case QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN:
|
case QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN:
|
||||||
|
@ -3778,6 +3779,7 @@ static int32_t msgToSpecificNode(STlvDecoder* pDecoder, void* pObj) {
|
||||||
code = msgToPhysiScanNode(pDecoder, pObj);
|
code = msgToPhysiScanNode(pDecoder, pObj);
|
||||||
break;
|
break;
|
||||||
case QUERY_NODE_PHYSICAL_PLAN_LAST_ROW_SCAN:
|
case QUERY_NODE_PHYSICAL_PLAN_LAST_ROW_SCAN:
|
||||||
|
case QUERY_NODE_PHYSICAL_PLAN_TABLE_COUNT_SCAN:
|
||||||
code = msgToPhysiLastRowScanNode(pDecoder, pObj);
|
code = msgToPhysiLastRowScanNode(pDecoder, pObj);
|
||||||
break;
|
break;
|
||||||
case QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN:
|
case QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN:
|
||||||
|
|
|
@ -494,6 +494,8 @@ SNode* nodesMakeNode(ENodeType type) {
|
||||||
return makeNode(type, sizeof(SBlockDistScanPhysiNode));
|
return makeNode(type, sizeof(SBlockDistScanPhysiNode));
|
||||||
case QUERY_NODE_PHYSICAL_PLAN_LAST_ROW_SCAN:
|
case QUERY_NODE_PHYSICAL_PLAN_LAST_ROW_SCAN:
|
||||||
return makeNode(type, sizeof(SLastRowScanPhysiNode));
|
return makeNode(type, sizeof(SLastRowScanPhysiNode));
|
||||||
|
case QUERY_NODE_PHYSICAL_PLAN_TABLE_COUNT_SCAN:
|
||||||
|
return makeNode(type, sizeof(STableCountScanPhysiNode));
|
||||||
case QUERY_NODE_PHYSICAL_PLAN_PROJECT:
|
case QUERY_NODE_PHYSICAL_PLAN_PROJECT:
|
||||||
return makeNode(type, sizeof(SProjectPhysiNode));
|
return makeNode(type, sizeof(SProjectPhysiNode));
|
||||||
case QUERY_NODE_PHYSICAL_PLAN_MERGE_JOIN:
|
case QUERY_NODE_PHYSICAL_PLAN_MERGE_JOIN:
|
||||||
|
@ -1120,6 +1122,7 @@ void nodesDestroyNode(SNode* pNode) {
|
||||||
case QUERY_NODE_PHYSICAL_PLAN_TAG_SCAN:
|
case QUERY_NODE_PHYSICAL_PLAN_TAG_SCAN:
|
||||||
case QUERY_NODE_PHYSICAL_PLAN_SYSTABLE_SCAN:
|
case QUERY_NODE_PHYSICAL_PLAN_SYSTABLE_SCAN:
|
||||||
case QUERY_NODE_PHYSICAL_PLAN_BLOCK_DIST_SCAN:
|
case QUERY_NODE_PHYSICAL_PLAN_BLOCK_DIST_SCAN:
|
||||||
|
case QUERY_NODE_PHYSICAL_PLAN_TABLE_COUNT_SCAN:
|
||||||
destroyScanPhysiNode((SScanPhysiNode*)pNode);
|
destroyScanPhysiNode((SScanPhysiNode*)pNode);
|
||||||
break;
|
break;
|
||||||
case QUERY_NODE_PHYSICAL_PLAN_LAST_ROW_SCAN: {
|
case QUERY_NODE_PHYSICAL_PLAN_LAST_ROW_SCAN: {
|
||||||
|
|
|
@ -86,7 +86,7 @@ STableComInfo getTableInfo(const STableMeta* pTableMeta);
|
||||||
STableMeta* tableMetaDup(const STableMeta* pTableMeta);
|
STableMeta* tableMetaDup(const STableMeta* pTableMeta);
|
||||||
|
|
||||||
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 getInsTagsTableTargetName(int32_t acctId, SNode* pWhere, SName* pName);
|
int32_t getVnodeSysTableTargetName(int32_t acctId, SNode* pWhere, SName* pName);
|
||||||
|
|
||||||
int32_t buildCatalogReq(const SParseMetaCache* pMetaCache, SCatalogReq* pCatalogReq);
|
int32_t buildCatalogReq(const SParseMetaCache* pMetaCache, SCatalogReq* pCatalogReq);
|
||||||
int32_t putMetaDataToCache(const SCatalogReq* pCatalogReq, const SMetaData* pMetaData, SParseMetaCache* pMetaCache);
|
int32_t putMetaDataToCache(const SCatalogReq* pCatalogReq, const SMetaData* pMetaData, SParseMetaCache* pMetaCache);
|
||||||
|
|
|
@ -140,7 +140,7 @@ static int32_t collectMetaKeyFromInsTagsImpl(SCollectMetaKeyCxt* pCxt, SName* pN
|
||||||
static int32_t collectMetaKeyFromInsTags(SCollectMetaKeyCxt* pCxt) {
|
static int32_t collectMetaKeyFromInsTags(SCollectMetaKeyCxt* pCxt) {
|
||||||
SSelectStmt* pSelect = (SSelectStmt*)pCxt->pStmt;
|
SSelectStmt* pSelect = (SSelectStmt*)pCxt->pStmt;
|
||||||
SName name = {0};
|
SName name = {0};
|
||||||
int32_t code = getInsTagsTableTargetName(pCxt->pParseCxt->acctId, pSelect->pWhere, &name);
|
int32_t code = getVnodeSysTableTargetName(pCxt->pParseCxt->acctId, pSelect->pWhere, &name);
|
||||||
if (TSDB_CODE_SUCCESS == code) {
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
code = collectMetaKeyFromInsTagsImpl(pCxt, &name);
|
code = collectMetaKeyFromInsTagsImpl(pCxt, &name);
|
||||||
}
|
}
|
||||||
|
@ -165,7 +165,8 @@ static int32_t collectMetaKeyFromRealTableImpl(SCollectMetaKeyCxt* pCxt, const c
|
||||||
if (TSDB_CODE_SUCCESS == code && (0 == strcmp(pTable, TSDB_INS_TABLE_DNODE_VARIABLES))) {
|
if (TSDB_CODE_SUCCESS == code && (0 == strcmp(pTable, TSDB_INS_TABLE_DNODE_VARIABLES))) {
|
||||||
code = reserveDnodeRequiredInCache(pCxt->pMetaCache);
|
code = reserveDnodeRequiredInCache(pCxt->pMetaCache);
|
||||||
}
|
}
|
||||||
if (TSDB_CODE_SUCCESS == code && (0 == strcmp(pTable, TSDB_INS_TABLE_TAGS)) &&
|
if (TSDB_CODE_SUCCESS == code &&
|
||||||
|
(0 == strcmp(pTable, TSDB_INS_TABLE_TAGS) || 0 == strcmp(pTable, TSDB_INS_TABLE_TABLES)) &&
|
||||||
QUERY_NODE_SELECT_STMT == nodeType(pCxt->pStmt)) {
|
QUERY_NODE_SELECT_STMT == nodeType(pCxt->pStmt)) {
|
||||||
code = collectMetaKeyFromInsTags(pCxt);
|
code = collectMetaKeyFromInsTags(pCxt);
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,7 @@ typedef struct STranslateContext {
|
||||||
SParseMetaCache* pMetaCache;
|
SParseMetaCache* pMetaCache;
|
||||||
bool createStream;
|
bool createStream;
|
||||||
bool stableQuery;
|
bool stableQuery;
|
||||||
|
bool showRewrite;
|
||||||
} STranslateContext;
|
} STranslateContext;
|
||||||
|
|
||||||
typedef struct SFullDatabaseName {
|
typedef struct SFullDatabaseName {
|
||||||
|
@ -2209,22 +2210,28 @@ static int32_t dnodeToVgroupsInfo(SArray* pDnodes, SVgroupsInfo** pVgsInfo) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool sysTableFromVnode(const char* pTable) {
|
static bool sysTableFromVnode(const char* pTable) {
|
||||||
return (0 == strcmp(pTable, TSDB_INS_TABLE_TABLES)) ||
|
return ((0 == strcmp(pTable, TSDB_INS_TABLE_TABLES)) || (0 == strcmp(pTable, TSDB_INS_TABLE_TAGS)));
|
||||||
(0 == strcmp(pTable, TSDB_INS_TABLE_TABLE_DISTRIBUTED) || (0 == strcmp(pTable, TSDB_INS_TABLE_TAGS)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool sysTableFromDnode(const char* pTable) { return 0 == strcmp(pTable, TSDB_INS_TABLE_DNODE_VARIABLES); }
|
static bool sysTableFromDnode(const char* pTable) { return 0 == strcmp(pTable, TSDB_INS_TABLE_DNODE_VARIABLES); }
|
||||||
|
|
||||||
static int32_t getTagsTableVgroupListImpl(STranslateContext* pCxt, SName* pTargetName, SName* pName,
|
static int32_t getVnodeSysTableVgroupListImpl(STranslateContext* pCxt, SName* pTargetName, SName* pName,
|
||||||
SArray** pVgroupList) {
|
SArray** pVgroupList) {
|
||||||
if (0 == pTargetName->type) {
|
if (0 == pTargetName->type) {
|
||||||
return getDBVgInfoImpl(pCxt, pName, pVgroupList);
|
return getDBVgInfoImpl(pCxt, pName, pVgroupList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (0 == strcmp(pTargetName->dbname, TSDB_INFORMATION_SCHEMA_DB) ||
|
||||||
|
0 == strcmp(pTargetName->dbname, TSDB_PERFORMANCE_SCHEMA_DB)) {
|
||||||
|
pTargetName->type = 0;
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
if (TSDB_DB_NAME_T == pTargetName->type) {
|
if (TSDB_DB_NAME_T == pTargetName->type) {
|
||||||
int32_t code = getDBVgInfoImpl(pCxt, pTargetName, pVgroupList);
|
int32_t code = getDBVgInfoImpl(pCxt, pTargetName, pVgroupList);
|
||||||
if (TSDB_CODE_MND_DB_NOT_EXIST == code || TSDB_CODE_MND_DB_IN_CREATING == code ||
|
if (!pCxt->showRewrite && (TSDB_CODE_MND_DB_NOT_EXIST == code || TSDB_CODE_MND_DB_IN_CREATING == code ||
|
||||||
TSDB_CODE_MND_DB_IN_DROPPING == code) {
|
TSDB_CODE_MND_DB_IN_DROPPING == code)) {
|
||||||
|
// system table query should not report errors
|
||||||
code = TSDB_CODE_SUCCESS;
|
code = TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
return code;
|
return code;
|
||||||
|
@ -2241,50 +2248,44 @@ static int32_t getTagsTableVgroupListImpl(STranslateContext* pCxt, SName* pTarge
|
||||||
}
|
}
|
||||||
} else if (TSDB_CODE_MND_DB_NOT_EXIST == code || TSDB_CODE_MND_DB_IN_CREATING == code ||
|
} else if (TSDB_CODE_MND_DB_NOT_EXIST == code || TSDB_CODE_MND_DB_IN_CREATING == code ||
|
||||||
TSDB_CODE_MND_DB_IN_DROPPING == code) {
|
TSDB_CODE_MND_DB_IN_DROPPING == code) {
|
||||||
|
// system table query should not report errors
|
||||||
code = TSDB_CODE_SUCCESS;
|
code = TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t getTagsTableVgroupList(STranslateContext* pCxt, SName* pName, SArray** pVgroupList) {
|
static int32_t getVnodeSysTableVgroupList(STranslateContext* pCxt, SName* pName, SArray** pVgs, bool* pHasUserDbCond) {
|
||||||
if (!isSelectStmt(pCxt->pCurrStmt)) {
|
if (!isSelectStmt(pCxt->pCurrStmt)) {
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
SSelectStmt* pSelect = (SSelectStmt*)pCxt->pCurrStmt;
|
SSelectStmt* pSelect = (SSelectStmt*)pCxt->pCurrStmt;
|
||||||
SName targetName = {0};
|
SName targetName = {0};
|
||||||
int32_t code = getInsTagsTableTargetName(pCxt->pParseCxt->acctId, pSelect->pWhere, &targetName);
|
int32_t code = getVnodeSysTableTargetName(pCxt->pParseCxt->acctId, pSelect->pWhere, &targetName);
|
||||||
if (TSDB_CODE_SUCCESS == code) {
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
code = getTagsTableVgroupListImpl(pCxt, &targetName, pName, pVgroupList);
|
code = getVnodeSysTableVgroupListImpl(pCxt, &targetName, pName, pVgs);
|
||||||
}
|
}
|
||||||
|
*pHasUserDbCond = (0 != targetName.type && taosArrayGetSize(*pVgs) > 0);
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t setVnodeSysTableVgroupList(STranslateContext* pCxt, SName* pName, SRealTableNode* pRealTable) {
|
static int32_t setVnodeSysTableVgroupList(STranslateContext* pCxt, SName* pName, SRealTableNode* pRealTable) {
|
||||||
int32_t code = TSDB_CODE_SUCCESS;
|
bool hasUserDbCond = false;
|
||||||
SArray* vgroupList = NULL;
|
SArray* pVgs = NULL;
|
||||||
if (0 == strcmp(pRealTable->table.tableName, TSDB_INS_TABLE_TAGS)) {
|
int32_t code = getVnodeSysTableVgroupList(pCxt, pName, &pVgs, &hasUserDbCond);
|
||||||
code = getTagsTableVgroupList(pCxt, pName, &vgroupList);
|
|
||||||
} else if ('\0' != pRealTable->qualDbName[0]) {
|
|
||||||
if (0 != strcmp(pRealTable->qualDbName, TSDB_INFORMATION_SCHEMA_DB)) {
|
|
||||||
code = getDBVgInfo(pCxt, pRealTable->qualDbName, &vgroupList);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
code = getDBVgInfoImpl(pCxt, pName, &vgroupList);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TSDB_CODE_SUCCESS == code && 0 == strcmp(pRealTable->table.tableName, TSDB_INS_TABLE_TAGS) &&
|
if (TSDB_CODE_SUCCESS == code && 0 == strcmp(pRealTable->table.tableName, TSDB_INS_TABLE_TAGS) &&
|
||||||
isSelectStmt(pCxt->pCurrStmt) && 0 == taosArrayGetSize(vgroupList)) {
|
isSelectStmt(pCxt->pCurrStmt) && 0 == taosArrayGetSize(pVgs)) {
|
||||||
((SSelectStmt*)pCxt->pCurrStmt)->isEmptyResult = true;
|
((SSelectStmt*)pCxt->pCurrStmt)->isEmptyResult = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TSDB_CODE_SUCCESS == code && 0 == strcmp(pRealTable->table.tableName, TSDB_INS_TABLE_TABLES)) {
|
if (TSDB_CODE_SUCCESS == code && 0 == strcmp(pRealTable->table.tableName, TSDB_INS_TABLE_TABLES) && !hasUserDbCond) {
|
||||||
code = addMnodeToVgroupList(&pCxt->pParseCxt->mgmtEpSet, &vgroupList);
|
code = addMnodeToVgroupList(&pCxt->pParseCxt->mgmtEpSet, &pVgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TSDB_CODE_SUCCESS == code) {
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
code = toVgroupsInfo(vgroupList, &pRealTable->pVgroupList);
|
code = toVgroupsInfo(pVgs, &pRealTable->pVgroupList);
|
||||||
}
|
}
|
||||||
taosArrayDestroy(vgroupList);
|
taosArrayDestroy(pVgs);
|
||||||
|
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
@ -2309,30 +2310,39 @@ static int32_t setSysTableVgroupList(STranslateContext* pCxt, SName* pName, SRea
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int32_t setSuperTableVgroupList(STranslateContext* pCxt, SName* pName, SRealTableNode* pRealTable) {
|
||||||
|
SArray* vgroupList = NULL;
|
||||||
|
int32_t code = getDBVgInfoImpl(pCxt, pName, &vgroupList);
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = toVgroupsInfo(vgroupList, &pRealTable->pVgroupList);
|
||||||
|
}
|
||||||
|
taosArrayDestroy(vgroupList);
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t setNormalTableVgroupList(STranslateContext* pCxt, SName* pName, SRealTableNode* pRealTable) {
|
||||||
|
pRealTable->pVgroupList = taosMemoryCalloc(1, sizeof(SVgroupsInfo) + sizeof(SVgroupInfo));
|
||||||
|
if (NULL == pRealTable->pVgroupList) {
|
||||||
|
return TSDB_CODE_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
pRealTable->pVgroupList->numOfVgroups = 1;
|
||||||
|
return getTableHashVgroupImpl(pCxt, pName, pRealTable->pVgroupList->vgroups);
|
||||||
|
}
|
||||||
|
|
||||||
static int32_t setTableVgroupList(STranslateContext* pCxt, SName* pName, SRealTableNode* pRealTable) {
|
static int32_t setTableVgroupList(STranslateContext* pCxt, SName* pName, SRealTableNode* pRealTable) {
|
||||||
if (pCxt->pParseCxt->topicQuery) {
|
if (pCxt->pParseCxt->topicQuery) {
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t code = TSDB_CODE_SUCCESS;
|
|
||||||
if (TSDB_SUPER_TABLE == pRealTable->pMeta->tableType) {
|
if (TSDB_SUPER_TABLE == pRealTable->pMeta->tableType) {
|
||||||
SArray* vgroupList = NULL;
|
return setSuperTableVgroupList(pCxt, pName, pRealTable);
|
||||||
code = getDBVgInfoImpl(pCxt, pName, &vgroupList);
|
|
||||||
if (TSDB_CODE_SUCCESS == code) {
|
|
||||||
code = toVgroupsInfo(vgroupList, &pRealTable->pVgroupList);
|
|
||||||
}
|
|
||||||
taosArrayDestroy(vgroupList);
|
|
||||||
} else if (TSDB_SYSTEM_TABLE == pRealTable->pMeta->tableType) {
|
|
||||||
code = setSysTableVgroupList(pCxt, pName, pRealTable);
|
|
||||||
} else {
|
|
||||||
pRealTable->pVgroupList = taosMemoryCalloc(1, sizeof(SVgroupsInfo) + sizeof(SVgroupInfo));
|
|
||||||
if (NULL == pRealTable->pVgroupList) {
|
|
||||||
return TSDB_CODE_OUT_OF_MEMORY;
|
|
||||||
}
|
|
||||||
pRealTable->pVgroupList->numOfVgroups = 1;
|
|
||||||
code = getTableHashVgroupImpl(pCxt, pName, pRealTable->pVgroupList->vgroups);
|
|
||||||
}
|
}
|
||||||
return code;
|
|
||||||
|
if (TSDB_SYSTEM_TABLE == pRealTable->pMeta->tableType) {
|
||||||
|
return setSysTableVgroupList(pCxt, pName, pRealTable);
|
||||||
|
}
|
||||||
|
|
||||||
|
return setNormalTableVgroupList(pCxt, pName, pRealTable);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t getStmtPrecision(SNode* pStmt) {
|
static uint8_t getStmtPrecision(SNode* pStmt) {
|
||||||
|
@ -2366,7 +2376,6 @@ static bool isSingleTable(SRealTableNode* pRealTable) {
|
||||||
int8_t tableType = pRealTable->pMeta->tableType;
|
int8_t tableType = pRealTable->pMeta->tableType;
|
||||||
if (TSDB_SYSTEM_TABLE == tableType) {
|
if (TSDB_SYSTEM_TABLE == tableType) {
|
||||||
return 0 != strcmp(pRealTable->table.tableName, TSDB_INS_TABLE_TABLES) &&
|
return 0 != strcmp(pRealTable->table.tableName, TSDB_INS_TABLE_TABLES) &&
|
||||||
0 != strcmp(pRealTable->table.tableName, TSDB_INS_TABLE_TABLE_DISTRIBUTED) &&
|
|
||||||
0 != strcmp(pRealTable->table.tableName, TSDB_INS_TABLE_TAGS);
|
0 != strcmp(pRealTable->table.tableName, TSDB_INS_TABLE_TAGS);
|
||||||
}
|
}
|
||||||
return (TSDB_CHILD_TABLE == tableType || TSDB_NORMAL_TABLE == tableType);
|
return (TSDB_CHILD_TABLE == tableType || TSDB_NORMAL_TABLE == tableType);
|
||||||
|
@ -6296,6 +6305,7 @@ static int32_t rewriteShow(STranslateContext* pCxt, SQuery* pQuery) {
|
||||||
code = createShowCondition((SShowStmt*)pQuery->pRoot, pStmt);
|
code = createShowCondition((SShowStmt*)pQuery->pRoot, pStmt);
|
||||||
}
|
}
|
||||||
if (TSDB_CODE_SUCCESS == code) {
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
pCxt->showRewrite = true;
|
||||||
pQuery->showRewrite = true;
|
pQuery->showRewrite = true;
|
||||||
nodesDestroyNode(pQuery->pRoot);
|
nodesDestroyNode(pQuery->pRoot);
|
||||||
pQuery->pRoot = (SNode*)pStmt;
|
pQuery->pRoot = (SNode*)pStmt;
|
||||||
|
@ -6349,6 +6359,7 @@ static int32_t rewriteShowStableTags(STranslateContext* pCxt, SQuery* pQuery) {
|
||||||
code = createShowTableTagsProjections(&pSelect->pProjectionList, &pShow->pTags);
|
code = createShowTableTagsProjections(&pSelect->pProjectionList, &pShow->pTags);
|
||||||
}
|
}
|
||||||
if (TSDB_CODE_SUCCESS == code) {
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
pCxt->showRewrite = true;
|
||||||
pQuery->showRewrite = true;
|
pQuery->showRewrite = true;
|
||||||
pSelect->tagScan = true;
|
pSelect->tagScan = true;
|
||||||
nodesDestroyNode(pQuery->pRoot);
|
nodesDestroyNode(pQuery->pRoot);
|
||||||
|
@ -6379,6 +6390,7 @@ static int32_t rewriteShowDnodeVariables(STranslateContext* pCxt, SQuery* pQuery
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (TSDB_CODE_SUCCESS == code) {
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
pCxt->showRewrite = true;
|
||||||
pQuery->showRewrite = true;
|
pQuery->showRewrite = true;
|
||||||
nodesDestroyNode(pQuery->pRoot);
|
nodesDestroyNode(pQuery->pRoot);
|
||||||
pQuery->pRoot = (SNode*)pSelect;
|
pQuery->pRoot = (SNode*)pSelect;
|
||||||
|
@ -6398,6 +6410,7 @@ static int32_t rewriteShowVnodes(STranslateContext* pCxt, SQuery* pQuery) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (TSDB_CODE_SUCCESS == code) {
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
pCxt->showRewrite = true;
|
||||||
pQuery->showRewrite = true;
|
pQuery->showRewrite = true;
|
||||||
nodesDestroyNode(pQuery->pRoot);
|
nodesDestroyNode(pQuery->pRoot);
|
||||||
pQuery->pRoot = (SNode*)pStmt;
|
pQuery->pRoot = (SNode*)pStmt;
|
||||||
|
@ -6439,6 +6452,7 @@ static int32_t rewriteShowTableDist(STranslateContext* pCxt, SQuery* pQuery) {
|
||||||
code = nodesListMakeStrictAppend(&pStmt->pProjectionList, createBlockDistFunc());
|
code = nodesListMakeStrictAppend(&pStmt->pProjectionList, createBlockDistFunc());
|
||||||
}
|
}
|
||||||
if (TSDB_CODE_SUCCESS == code) {
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
pCxt->showRewrite = true;
|
||||||
pQuery->showRewrite = true;
|
pQuery->showRewrite = true;
|
||||||
nodesDestroyNode(pQuery->pRoot);
|
nodesDestroyNode(pQuery->pRoot);
|
||||||
pQuery->pRoot = (SNode*)pStmt;
|
pQuery->pRoot = (SNode*)pStmt;
|
||||||
|
|
|
@ -474,7 +474,7 @@ static int32_t getInsTagsTableTargetNameFromCond(int32_t acctId, SLogicCondition
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t getInsTagsTableTargetName(int32_t acctId, SNode* pWhere, SName* pName) {
|
int32_t getVnodeSysTableTargetName(int32_t acctId, SNode* pWhere, SName* pName) {
|
||||||
if (NULL == pWhere) {
|
if (NULL == pWhere) {
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,9 +65,10 @@ void generateInformationSchema(MockCatalogService* mcs) {
|
||||||
.addColumn("db_name", TSDB_DATA_TYPE_BINARY, TSDB_DB_NAME_LEN)
|
.addColumn("db_name", TSDB_DATA_TYPE_BINARY, TSDB_DB_NAME_LEN)
|
||||||
.addColumn("stable_name", TSDB_DATA_TYPE_BINARY, TSDB_TABLE_NAME_LEN)
|
.addColumn("stable_name", TSDB_DATA_TYPE_BINARY, TSDB_TABLE_NAME_LEN)
|
||||||
.done();
|
.done();
|
||||||
mcs->createTableBuilder(TSDB_INFORMATION_SCHEMA_DB, TSDB_INS_TABLE_TABLES, TSDB_SYSTEM_TABLE, 2)
|
mcs->createTableBuilder(TSDB_INFORMATION_SCHEMA_DB, TSDB_INS_TABLE_TABLES, TSDB_SYSTEM_TABLE, 3)
|
||||||
.addColumn("db_name", TSDB_DATA_TYPE_BINARY, TSDB_DB_NAME_LEN)
|
|
||||||
.addColumn("table_name", TSDB_DATA_TYPE_BINARY, TSDB_TABLE_NAME_LEN)
|
.addColumn("table_name", TSDB_DATA_TYPE_BINARY, TSDB_TABLE_NAME_LEN)
|
||||||
|
.addColumn("db_name", TSDB_DATA_TYPE_BINARY, TSDB_DB_NAME_LEN)
|
||||||
|
.addColumn("stable_name", TSDB_DATA_TYPE_BINARY, TSDB_TABLE_NAME_LEN)
|
||||||
.done();
|
.done();
|
||||||
mcs->createTableBuilder(TSDB_INFORMATION_SCHEMA_DB, TSDB_INS_TABLE_TABLE_DISTRIBUTED, TSDB_SYSTEM_TABLE, 2)
|
mcs->createTableBuilder(TSDB_INFORMATION_SCHEMA_DB, TSDB_INS_TABLE_TABLE_DISTRIBUTED, TSDB_SYSTEM_TABLE, 2)
|
||||||
.addColumn("db_name", TSDB_DATA_TYPE_BINARY, TSDB_DB_NAME_LEN)
|
.addColumn("db_name", TSDB_DATA_TYPE_BINARY, TSDB_DB_NAME_LEN)
|
||||||
|
@ -140,7 +141,7 @@ void generatePerformanceSchema(MockCatalogService* mcs) {
|
||||||
void generateTestTables(MockCatalogService* mcs, const std::string& db) {
|
void generateTestTables(MockCatalogService* mcs, const std::string& db) {
|
||||||
mcs->createTableBuilder(db, "t1", TSDB_NORMAL_TABLE, 6)
|
mcs->createTableBuilder(db, "t1", TSDB_NORMAL_TABLE, 6)
|
||||||
.setPrecision(TSDB_TIME_PRECISION_MILLI)
|
.setPrecision(TSDB_TIME_PRECISION_MILLI)
|
||||||
.setVgid(1)
|
.setVgid(2)
|
||||||
.addColumn("ts", TSDB_DATA_TYPE_TIMESTAMP)
|
.addColumn("ts", TSDB_DATA_TYPE_TIMESTAMP)
|
||||||
.addColumn("c1", TSDB_DATA_TYPE_INT)
|
.addColumn("c1", TSDB_DATA_TYPE_INT)
|
||||||
.addColumn("c2", TSDB_DATA_TYPE_BINARY, 20)
|
.addColumn("c2", TSDB_DATA_TYPE_BINARY, 20)
|
||||||
|
@ -182,9 +183,9 @@ void generateTestStables(MockCatalogService* mcs, const std::string& db) {
|
||||||
.addTag("tag2", TSDB_DATA_TYPE_BINARY, 20)
|
.addTag("tag2", TSDB_DATA_TYPE_BINARY, 20)
|
||||||
.addTag("tag3", TSDB_DATA_TYPE_TIMESTAMP);
|
.addTag("tag3", TSDB_DATA_TYPE_TIMESTAMP);
|
||||||
builder.done();
|
builder.done();
|
||||||
mcs->createSubTable(db, "st1", "st1s1", 1);
|
mcs->createSubTable(db, "st1", "st1s1", 2);
|
||||||
mcs->createSubTable(db, "st1", "st1s2", 2);
|
mcs->createSubTable(db, "st1", "st1s2", 3);
|
||||||
mcs->createSubTable(db, "st1", "st1s3", 1);
|
mcs->createSubTable(db, "st1", "st1s3", 2);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
ITableBuilder& builder = mcs->createTableBuilder(db, "st2", TSDB_SUPER_TABLE, 3, 1)
|
ITableBuilder& builder = mcs->createTableBuilder(db, "st2", TSDB_SUPER_TABLE, 3, 1)
|
||||||
|
@ -194,8 +195,8 @@ void generateTestStables(MockCatalogService* mcs, const std::string& db) {
|
||||||
.addColumn("c2", TSDB_DATA_TYPE_BINARY, 20)
|
.addColumn("c2", TSDB_DATA_TYPE_BINARY, 20)
|
||||||
.addTag("jtag", TSDB_DATA_TYPE_JSON);
|
.addTag("jtag", TSDB_DATA_TYPE_JSON);
|
||||||
builder.done();
|
builder.done();
|
||||||
mcs->createSubTable(db, "st2", "st2s1", 1);
|
mcs->createSubTable(db, "st2", "st2s1", 2);
|
||||||
mcs->createSubTable(db, "st2", "st2s2", 2);
|
mcs->createSubTable(db, "st2", "st2s2", 3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,15 +20,19 @@
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
|
#include "systable.h"
|
||||||
|
#include "tdatablock.h"
|
||||||
|
#include "tmisce.h"
|
||||||
#include "tname.h"
|
#include "tname.h"
|
||||||
#include "ttypes.h"
|
#include "ttypes.h"
|
||||||
#include "tmisce.h"
|
|
||||||
|
using std::string;
|
||||||
|
|
||||||
std::unique_ptr<MockCatalogService> g_mockCatalogService;
|
std::unique_ptr<MockCatalogService> g_mockCatalogService;
|
||||||
|
|
||||||
class TableBuilder : public ITableBuilder {
|
class TableBuilder : public ITableBuilder {
|
||||||
public:
|
public:
|
||||||
virtual TableBuilder& addColumn(const std::string& name, int8_t type, int32_t bytes) {
|
virtual TableBuilder& addColumn(const string& name, int8_t type, int32_t bytes) {
|
||||||
assert(colId_ <= schema()->tableInfo.numOfTags + schema()->tableInfo.numOfColumns);
|
assert(colId_ <= schema()->tableInfo.numOfTags + schema()->tableInfo.numOfColumns);
|
||||||
SSchema* col = schema()->schema + (colId_ - 1);
|
SSchema* col = schema()->schema + (colId_ - 1);
|
||||||
col->type = type;
|
col->type = type;
|
||||||
|
@ -142,27 +146,16 @@ class MockCatalogServiceImpl {
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t catalogGetDBVgList(const char* pDbFName, SArray** pVgList) const {
|
int32_t catalogGetDBVgList(const char* pDbFName, SArray** pVgList) const {
|
||||||
std::string dbFName(pDbFName);
|
string dbName(string(pDbFName).substr(string(pDbFName).find_last_of('.') + 1));
|
||||||
DbMetaCache::const_iterator it = meta_.find(dbFName.substr(std::string(pDbFName).find_last_of('.') + 1));
|
if (0 == dbName.compare(TSDB_INFORMATION_SCHEMA_DB) || 0 == dbName.compare(TSDB_PERFORMANCE_SCHEMA_DB)) {
|
||||||
if (meta_.end() == it) {
|
return catalogGetAllDBVgList(pVgList);
|
||||||
return TSDB_CODE_FAILED;
|
|
||||||
}
|
}
|
||||||
std::set<int32_t> vgSet;
|
return catalogGetDBVgListImpl(dbName, pVgList);
|
||||||
*pVgList = taosArrayInit(it->second.size(), sizeof(SVgroupInfo));
|
|
||||||
for (const auto& vgs : it->second) {
|
|
||||||
for (const auto& vg : vgs.second->vgs) {
|
|
||||||
if (0 == vgSet.count(vg.vgId)) {
|
|
||||||
taosArrayPush(*pVgList, &vg);
|
|
||||||
vgSet.insert(vg.vgId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return TSDB_CODE_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t catalogGetDBCfg(const char* pDbFName, SDbCfgInfo* pDbCfg) const {
|
int32_t catalogGetDBCfg(const char* pDbFName, SDbCfgInfo* pDbCfg) const {
|
||||||
std::string dbFName(pDbFName);
|
string dbFName(pDbFName);
|
||||||
DbCfgCache::const_iterator it = dbCfg_.find(dbFName.substr(std::string(pDbFName).find_last_of('.') + 1));
|
DbCfgCache::const_iterator it = dbCfg_.find(dbFName.substr(string(pDbFName).find_last_of('.') + 1));
|
||||||
if (dbCfg_.end() == it) {
|
if (dbCfg_.end() == it) {
|
||||||
return TSDB_CODE_FAILED;
|
return TSDB_CODE_FAILED;
|
||||||
}
|
}
|
||||||
|
@ -171,7 +164,7 @@ class MockCatalogServiceImpl {
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t catalogGetUdfInfo(const std::string& funcName, SFuncInfo* pInfo) const {
|
int32_t catalogGetUdfInfo(const string& funcName, SFuncInfo* pInfo) const {
|
||||||
auto it = udf_.find(funcName);
|
auto it = udf_.find(funcName);
|
||||||
if (udf_.end() == it) {
|
if (udf_.end() == it) {
|
||||||
return TSDB_CODE_FAILED;
|
return TSDB_CODE_FAILED;
|
||||||
|
@ -236,15 +229,15 @@ class MockCatalogServiceImpl {
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
TableBuilder& createTableBuilder(const std::string& db, const std::string& tbname, int8_t tableType,
|
TableBuilder& createTableBuilder(const string& db, const string& tbname, int8_t tableType, int32_t numOfColumns,
|
||||||
int32_t numOfColumns, int32_t numOfTags) {
|
int32_t numOfTags) {
|
||||||
builder_ = TableBuilder::createTableBuilder(tableType, numOfColumns, numOfTags);
|
builder_ = TableBuilder::createTableBuilder(tableType, numOfColumns, numOfTags);
|
||||||
meta_[db][tbname] = builder_->table();
|
meta_[db][tbname] = builder_->table();
|
||||||
meta_[db][tbname]->schema->uid = getNextId();
|
meta_[db][tbname]->schema->uid = getNextId();
|
||||||
return *(builder_.get());
|
return *(builder_.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
void createSubTable(const std::string& db, const std::string& stbname, const std::string& tbname, int16_t vgid) {
|
void createSubTable(const string& db, const string& stbname, const string& tbname, int16_t vgid) {
|
||||||
std::unique_ptr<STableMeta> table;
|
std::unique_ptr<STableMeta> table;
|
||||||
if (TSDB_CODE_SUCCESS != copyTableSchemaMeta(db, stbname, &table)) {
|
if (TSDB_CODE_SUCCESS != copyTableSchemaMeta(db, stbname, &table)) {
|
||||||
throw std::runtime_error("copyTableSchemaMeta failed");
|
throw std::runtime_error("copyTableSchemaMeta failed");
|
||||||
|
@ -274,13 +267,13 @@ class MockCatalogServiceImpl {
|
||||||
// string field length
|
// string field length
|
||||||
#define SFL 20
|
#define SFL 20
|
||||||
// string field header
|
// string field header
|
||||||
#define SH(h) CA(SFL, std::string(h))
|
#define SH(h) CA(SFL, string(h))
|
||||||
// string field
|
// string field
|
||||||
#define SF(n) CA(SFL, n)
|
#define SF(n) CA(SFL, n)
|
||||||
// integer field length
|
// integer field length
|
||||||
#define IFL 10
|
#define IFL 10
|
||||||
// integer field header
|
// integer field header
|
||||||
#define IH(i) CA(IFL, std::string(i))
|
#define IH(i) CA(IFL, string(i))
|
||||||
// integer field
|
// integer field
|
||||||
#define IF(i) CA(IFL, std::to_string(i))
|
#define IF(i) CA(IFL, std::to_string(i))
|
||||||
// split line
|
// split line
|
||||||
|
@ -308,7 +301,7 @@ class MockCatalogServiceImpl {
|
||||||
int16_t numOfFields = numOfColumns + schema->tableInfo.numOfTags;
|
int16_t numOfFields = numOfColumns + schema->tableInfo.numOfTags;
|
||||||
for (int16_t i = 0; i < numOfFields; ++i) {
|
for (int16_t i = 0; i < numOfFields; ++i) {
|
||||||
const SSchema* col = schema->schema + i;
|
const SSchema* col = schema->schema + i;
|
||||||
std::cout << SF(std::string(col->name)) << SH(ftToString(i, numOfColumns)) << SH(dtToString(col->type))
|
std::cout << SF(string(col->name)) << SH(ftToString(i, numOfColumns)) << SH(dtToString(col->type))
|
||||||
<< IF(col->bytes) << std::endl;
|
<< IF(col->bytes) << std::endl;
|
||||||
}
|
}
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
|
@ -316,7 +309,7 @@ class MockCatalogServiceImpl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void createFunction(const std::string& func, int8_t funcType, int8_t outputType, int32_t outputLen, int32_t bufSize) {
|
void createFunction(const string& func, int8_t funcType, int8_t outputType, int32_t outputLen, int32_t bufSize) {
|
||||||
std::shared_ptr<SFuncInfo> info(new SFuncInfo);
|
std::shared_ptr<SFuncInfo> info(new SFuncInfo);
|
||||||
strcpy(info->name, func.c_str());
|
strcpy(info->name, func.c_str());
|
||||||
info->funcType = funcType;
|
info->funcType = funcType;
|
||||||
|
@ -342,19 +335,19 @@ class MockCatalogServiceImpl {
|
||||||
info.expr = strdup(pReq->expr);
|
info.expr = strdup(pReq->expr);
|
||||||
auto it = index_.find(pReq->stb);
|
auto it = index_.find(pReq->stb);
|
||||||
if (index_.end() == it) {
|
if (index_.end() == it) {
|
||||||
index_.insert(std::make_pair(std::string(pReq->stb), std::vector<STableIndexInfo>{info}));
|
index_.insert(std::make_pair(string(pReq->stb), std::vector<STableIndexInfo>{info}));
|
||||||
} else {
|
} else {
|
||||||
it->second.push_back(info);
|
it->second.push_back(info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void createDnode(int32_t dnodeId, const std::string& host, int16_t port) {
|
void createDnode(int32_t dnodeId, const string& host, int16_t port) {
|
||||||
SEpSet epSet = {0};
|
SEpSet epSet = {0};
|
||||||
addEpIntoEpSet(&epSet, host.c_str(), port);
|
addEpIntoEpSet(&epSet, host.c_str(), port);
|
||||||
dnode_.insert(std::make_pair(dnodeId, epSet));
|
dnode_.insert(std::make_pair(dnodeId, epSet));
|
||||||
}
|
}
|
||||||
|
|
||||||
void createDatabase(const std::string& db, bool rollup, int8_t cacheLast) {
|
void createDatabase(const string& db, bool rollup, int8_t cacheLast) {
|
||||||
SDbCfgInfo cfg = {0};
|
SDbCfgInfo cfg = {0};
|
||||||
if (rollup) {
|
if (rollup) {
|
||||||
cfg.pRetensions = taosArrayInit(TARRAY_MIN_SIZE, sizeof(SRetention));
|
cfg.pRetensions = taosArrayInit(TARRAY_MIN_SIZE, sizeof(SRetention));
|
||||||
|
@ -364,12 +357,12 @@ class MockCatalogServiceImpl {
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef std::map<std::string, std::shared_ptr<MockTableMeta>> TableMetaCache;
|
typedef std::map<string, std::shared_ptr<MockTableMeta>> TableMetaCache;
|
||||||
typedef std::map<std::string, TableMetaCache> DbMetaCache;
|
typedef std::map<string, TableMetaCache> DbMetaCache;
|
||||||
typedef std::map<std::string, std::shared_ptr<SFuncInfo>> UdfMetaCache;
|
typedef std::map<string, std::shared_ptr<SFuncInfo>> UdfMetaCache;
|
||||||
typedef std::map<std::string, std::vector<STableIndexInfo>> IndexMetaCache;
|
typedef std::map<string, std::vector<STableIndexInfo>> IndexMetaCache;
|
||||||
typedef std::map<int32_t, SEpSet> DnodeCache;
|
typedef std::map<int32_t, SEpSet> DnodeCache;
|
||||||
typedef std::map<std::string, SDbCfgInfo> DbCfgCache;
|
typedef std::map<string, SDbCfgInfo> DbCfgCache;
|
||||||
|
|
||||||
uint64_t getNextId() { return id_++; }
|
uint64_t getNextId() { return id_++; }
|
||||||
|
|
||||||
|
@ -386,15 +379,15 @@ class MockCatalogServiceImpl {
|
||||||
return pDst;
|
return pDst;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string toDbname(const std::string& dbFullName) const {
|
string toDbname(const string& dbFullName) const {
|
||||||
std::string::size_type n = dbFullName.find(".");
|
string::size_type n = dbFullName.find(".");
|
||||||
if (n == std::string::npos) {
|
if (n == string::npos) {
|
||||||
return dbFullName;
|
return dbFullName;
|
||||||
}
|
}
|
||||||
return dbFullName.substr(n + 1);
|
return dbFullName.substr(n + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ttToString(int8_t tableType) const {
|
string ttToString(int8_t tableType) const {
|
||||||
switch (tableType) {
|
switch (tableType) {
|
||||||
case TSDB_SUPER_TABLE:
|
case TSDB_SUPER_TABLE:
|
||||||
return "super table";
|
return "super table";
|
||||||
|
@ -407,7 +400,7 @@ class MockCatalogServiceImpl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string pToString(uint8_t precision) const {
|
string pToString(uint8_t precision) const {
|
||||||
switch (precision) {
|
switch (precision) {
|
||||||
case TSDB_TIME_PRECISION_MILLI:
|
case TSDB_TIME_PRECISION_MILLI:
|
||||||
return "millisecond";
|
return "millisecond";
|
||||||
|
@ -420,19 +413,18 @@ class MockCatalogServiceImpl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string dtToString(int8_t type) const { return tDataTypes[type].name; }
|
string dtToString(int8_t type) const { return tDataTypes[type].name; }
|
||||||
|
|
||||||
std::string ftToString(int16_t colid, int16_t numOfColumns) const {
|
string ftToString(int16_t colid, int16_t numOfColumns) const {
|
||||||
return (0 == colid ? "column" : (colid < numOfColumns ? "column" : "tag"));
|
return (0 == colid ? "column" : (colid < numOfColumns ? "column" : "tag"));
|
||||||
}
|
}
|
||||||
|
|
||||||
STableMeta* getTableSchemaMeta(const std::string& db, const std::string& tbname) const {
|
STableMeta* getTableSchemaMeta(const string& db, const string& tbname) const {
|
||||||
std::shared_ptr<MockTableMeta> table = getTableMeta(db, tbname);
|
std::shared_ptr<MockTableMeta> table = getTableMeta(db, tbname);
|
||||||
return table ? table->schema : nullptr;
|
return table ? table->schema : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t copyTableSchemaMeta(const std::string& db, const std::string& tbname,
|
int32_t copyTableSchemaMeta(const string& db, const string& tbname, std::unique_ptr<STableMeta>* dst) const {
|
||||||
std::unique_ptr<STableMeta>* dst) const {
|
|
||||||
STableMeta* src = getTableSchemaMeta(db, tbname);
|
STableMeta* src = getTableSchemaMeta(db, tbname);
|
||||||
if (nullptr == src) {
|
if (nullptr == src) {
|
||||||
return TSDB_CODE_TSC_INVALID_TABLE_NAME;
|
return TSDB_CODE_TSC_INVALID_TABLE_NAME;
|
||||||
|
@ -446,7 +438,7 @@ class MockCatalogServiceImpl {
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t copyTableVgroup(const std::string& db, const std::string& tbname, SVgroupInfo* vg) const {
|
int32_t copyTableVgroup(const string& db, const string& tbname, SVgroupInfo* vg) const {
|
||||||
std::shared_ptr<MockTableMeta> table = getTableMeta(db, tbname);
|
std::shared_ptr<MockTableMeta> table = getTableMeta(db, tbname);
|
||||||
if (table->vgs.empty()) {
|
if (table->vgs.empty()) {
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
|
@ -455,7 +447,7 @@ class MockCatalogServiceImpl {
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t copyTableVgroup(const std::string& db, const std::string& tbname, SArray** vgList) const {
|
int32_t copyTableVgroup(const string& db, const string& tbname, SArray** vgList) const {
|
||||||
std::shared_ptr<MockTableMeta> table = getTableMeta(db, tbname);
|
std::shared_ptr<MockTableMeta> table = getTableMeta(db, tbname);
|
||||||
if (table->vgs.empty()) {
|
if (table->vgs.empty()) {
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
|
@ -467,7 +459,7 @@ class MockCatalogServiceImpl {
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<MockTableMeta> getTableMeta(const std::string& db, const std::string& tbname) const {
|
std::shared_ptr<MockTableMeta> getTableMeta(const string& db, const string& tbname) const {
|
||||||
DbMetaCache::const_iterator it = meta_.find(db);
|
DbMetaCache::const_iterator it = meta_.find(db);
|
||||||
if (meta_.end() == it) {
|
if (meta_.end() == it) {
|
||||||
return std::shared_ptr<MockTableMeta>();
|
return std::shared_ptr<MockTableMeta>();
|
||||||
|
@ -527,6 +519,40 @@ class MockCatalogServiceImpl {
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32_t catalogGetDBVgListImpl(const string& dbName, SArray** pVgList) const {
|
||||||
|
DbMetaCache::const_iterator it = meta_.find(dbName);
|
||||||
|
if (meta_.end() == it) {
|
||||||
|
return TSDB_CODE_FAILED;
|
||||||
|
}
|
||||||
|
std::set<int32_t> vgSet;
|
||||||
|
*pVgList = taosArrayInit(it->second.size(), sizeof(SVgroupInfo));
|
||||||
|
for (const auto& vgs : it->second) {
|
||||||
|
for (const auto& vg : vgs.second->vgs) {
|
||||||
|
if (0 == vgSet.count(vg.vgId)) {
|
||||||
|
taosArrayPush(*pVgList, &vg);
|
||||||
|
vgSet.insert(vg.vgId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t catalogGetAllDBVgList(SArray** pVgList) const {
|
||||||
|
std::set<int32_t> vgSet;
|
||||||
|
*pVgList = taosArrayInit(TARRAY_MIN_SIZE, sizeof(SVgroupInfo));
|
||||||
|
for (const auto& db : meta_) {
|
||||||
|
for (const auto& vgs : db.second) {
|
||||||
|
for (const auto& vg : vgs.second->vgs) {
|
||||||
|
if (0 == vgSet.count(vg.vgId)) {
|
||||||
|
taosArrayPush(*pVgList, &vg);
|
||||||
|
vgSet.insert(vg.vgId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
int32_t getAllDbCfg(SArray* pDbCfgReq, SArray** pDbCfgData) const {
|
int32_t getAllDbCfg(SArray* pDbCfgReq, SArray** pDbCfgData) const {
|
||||||
int32_t code = TSDB_CODE_SUCCESS;
|
int32_t code = TSDB_CODE_SUCCESS;
|
||||||
if (NULL != pDbCfgReq) {
|
if (NULL != pDbCfgReq) {
|
||||||
|
@ -634,30 +660,29 @@ MockCatalogService::MockCatalogService() : impl_(new MockCatalogServiceImpl()) {
|
||||||
|
|
||||||
MockCatalogService::~MockCatalogService() {}
|
MockCatalogService::~MockCatalogService() {}
|
||||||
|
|
||||||
ITableBuilder& MockCatalogService::createTableBuilder(const std::string& db, const std::string& tbname,
|
ITableBuilder& MockCatalogService::createTableBuilder(const string& db, const string& tbname, int8_t tableType,
|
||||||
int8_t tableType, int32_t numOfColumns, int32_t numOfTags) {
|
int32_t numOfColumns, int32_t numOfTags) {
|
||||||
return impl_->createTableBuilder(db, tbname, tableType, numOfColumns, numOfTags);
|
return impl_->createTableBuilder(db, tbname, tableType, numOfColumns, numOfTags);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MockCatalogService::createSubTable(const std::string& db, const std::string& stbname, const std::string& tbname,
|
void MockCatalogService::createSubTable(const string& db, const string& stbname, const string& tbname, int16_t vgid) {
|
||||||
int16_t vgid) {
|
|
||||||
impl_->createSubTable(db, stbname, tbname, vgid);
|
impl_->createSubTable(db, stbname, tbname, vgid);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MockCatalogService::showTables() const { impl_->showTables(); }
|
void MockCatalogService::showTables() const { impl_->showTables(); }
|
||||||
|
|
||||||
void MockCatalogService::createFunction(const std::string& func, int8_t funcType, int8_t outputType, int32_t outputLen,
|
void MockCatalogService::createFunction(const string& func, int8_t funcType, int8_t outputType, int32_t outputLen,
|
||||||
int32_t bufSize) {
|
int32_t bufSize) {
|
||||||
impl_->createFunction(func, funcType, outputType, outputLen, bufSize);
|
impl_->createFunction(func, funcType, outputType, outputLen, bufSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MockCatalogService::createSmaIndex(const SMCreateSmaReq* pReq) { impl_->createSmaIndex(pReq); }
|
void MockCatalogService::createSmaIndex(const SMCreateSmaReq* pReq) { impl_->createSmaIndex(pReq); }
|
||||||
|
|
||||||
void MockCatalogService::createDnode(int32_t dnodeId, const std::string& host, int16_t port) {
|
void MockCatalogService::createDnode(int32_t dnodeId, const string& host, int16_t port) {
|
||||||
impl_->createDnode(dnodeId, host, port);
|
impl_->createDnode(dnodeId, host, port);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MockCatalogService::createDatabase(const std::string& db, bool rollup, int8_t cacheLast) {
|
void MockCatalogService::createDatabase(const string& db, bool rollup, int8_t cacheLast) {
|
||||||
impl_->createDatabase(db, rollup, cacheLast);
|
impl_->createDatabase(db, rollup, cacheLast);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -683,7 +708,7 @@ int32_t MockCatalogService::catalogGetDBCfg(const char* pDbFName, SDbCfgInfo* pD
|
||||||
return impl_->catalogGetDBCfg(pDbFName, pDbCfg);
|
return impl_->catalogGetDBCfg(pDbFName, pDbCfg);
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t MockCatalogService::catalogGetUdfInfo(const std::string& funcName, SFuncInfo* pInfo) const {
|
int32_t MockCatalogService::catalogGetUdfInfo(const string& funcName, SFuncInfo* pInfo) const {
|
||||||
return impl_->catalogGetUdfInfo(funcName, pInfo);
|
return impl_->catalogGetUdfInfo(funcName, pInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -250,11 +250,12 @@ static EScanType getScanType(SLogicPlanContext* pCxt, SNodeList* pScanPseudoCols
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NULL == pScanCols) {
|
if (NULL == pScanCols) {
|
||||||
return NULL == pScanPseudoCols
|
if (NULL == pScanPseudoCols) {
|
||||||
? SCAN_TYPE_TABLE
|
return SCAN_TYPE_TABLE;
|
||||||
: ((FUNCTION_TYPE_BLOCK_DIST_INFO == ((SFunctionNode*)nodesListGetNode(pScanPseudoCols, 0))->funcType)
|
}
|
||||||
? SCAN_TYPE_BLOCK_INFO
|
return FUNCTION_TYPE_BLOCK_DIST_INFO == ((SFunctionNode*)nodesListGetNode(pScanPseudoCols, 0))->funcType
|
||||||
: SCAN_TYPE_TABLE);
|
? SCAN_TYPE_BLOCK_INFO
|
||||||
|
: SCAN_TYPE_TABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return SCAN_TYPE_TABLE;
|
return SCAN_TYPE_TABLE;
|
||||||
|
@ -333,6 +334,8 @@ static int32_t makeScanLogicNode(SLogicPlanContext* pCxt, SRealTableNode* pRealT
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool needScanDefaultCol(EScanType scanType) { return SCAN_TYPE_TABLE_COUNT != scanType; }
|
||||||
|
|
||||||
static int32_t createScanLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SRealTableNode* pRealTable,
|
static int32_t createScanLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SRealTableNode* pRealTable,
|
||||||
SLogicNode** pLogicNode) {
|
SLogicNode** pLogicNode) {
|
||||||
SScanLogicNode* pScan = NULL;
|
SScanLogicNode* pScan = NULL;
|
||||||
|
@ -367,7 +370,7 @@ static int32_t createScanLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect
|
||||||
pScan->hasNormalCols = true;
|
pScan->hasNormalCols = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TSDB_CODE_SUCCESS == code) {
|
if (TSDB_CODE_SUCCESS == code && needScanDefaultCol(pScan->scanType)) {
|
||||||
code = addDefaultScanCol(pRealTable->pMeta, &pScan->pScanCols);
|
code = addDefaultScanCol(pRealTable->pMeta, &pScan->pScanCols);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include "filter.h"
|
#include "filter.h"
|
||||||
#include "functionMgt.h"
|
#include "functionMgt.h"
|
||||||
#include "planInt.h"
|
#include "planInt.h"
|
||||||
|
#include "systable.h"
|
||||||
#include "tglobal.h"
|
#include "tglobal.h"
|
||||||
#include "ttime.h"
|
#include "ttime.h"
|
||||||
|
|
||||||
|
@ -64,6 +65,7 @@ typedef enum ECondAction {
|
||||||
} ECondAction;
|
} ECondAction;
|
||||||
|
|
||||||
typedef bool (*FMayBeOptimized)(SLogicNode* pNode);
|
typedef bool (*FMayBeOptimized)(SLogicNode* pNode);
|
||||||
|
typedef bool (*FShouldBeOptimized)(SLogicNode* pNode, void* pInfo);
|
||||||
|
|
||||||
static SLogicNode* optFindPossibleNode(SLogicNode* pNode, FMayBeOptimized func) {
|
static SLogicNode* optFindPossibleNode(SLogicNode* pNode, FMayBeOptimized func) {
|
||||||
if (func(pNode)) {
|
if (func(pNode)) {
|
||||||
|
@ -79,6 +81,19 @@ static SLogicNode* optFindPossibleNode(SLogicNode* pNode, FMayBeOptimized func)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool optFindEligibleNode(SLogicNode* pNode, FShouldBeOptimized func, void* pInfo) {
|
||||||
|
if (func(pNode, pInfo)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
SNode* pChild;
|
||||||
|
FOREACH(pChild, pNode->pChildren) {
|
||||||
|
if (optFindEligibleNode((SLogicNode*)pChild, func, pInfo)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static void optResetParent(SLogicNode* pNode) {
|
static void optResetParent(SLogicNode* pNode) {
|
||||||
SNode* pChild = NULL;
|
SNode* pChild = NULL;
|
||||||
FOREACH(pChild, pNode->pChildren) { ((SLogicNode*)pChild)->pParent = pNode; }
|
FOREACH(pChild, pNode->pChildren) { ((SLogicNode*)pChild)->pParent = pNode; }
|
||||||
|
@ -2454,6 +2469,243 @@ static int32_t pushDownLimitOptimize(SOptimizeContext* pCxt, SLogicSubplan* pLog
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct STbCntScanOptInfo {
|
||||||
|
SAggLogicNode* pAgg;
|
||||||
|
SScanLogicNode* pScan;
|
||||||
|
SName table;
|
||||||
|
} STbCntScanOptInfo;
|
||||||
|
|
||||||
|
static bool tbCntScanOptIsEligibleGroupKeys(SNodeList* pGroupKeys) {
|
||||||
|
if (NULL == pGroupKeys) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
SNode* pGroupKey = NULL;
|
||||||
|
FOREACH(pGroupKey, pGroupKeys) {
|
||||||
|
SNode* pKey = nodesListGetNode(((SGroupingSetNode*)pGroupKey)->pParameterList, 0);
|
||||||
|
if (QUERY_NODE_COLUMN != nodeType(pKey)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
SColumnNode* pCol = (SColumnNode*)pKey;
|
||||||
|
if (0 != strcmp(pCol->colName, "db_name") && 0 != strcmp(pCol->colName, "stable_name")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool tbCntScanOptNotNullableExpr(SNode* pNode) {
|
||||||
|
if (QUERY_NODE_COLUMN != nodeType(pNode)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const char* pColName = ((SColumnNode*)pNode)->colName;
|
||||||
|
return 0 == strcmp(pColName, "*") || 0 == strcmp(pColName, "db_name") || 0 == strcmp(pColName, "stable_name") ||
|
||||||
|
0 == strcmp(pColName, "table_name");
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool tbCntScanOptIsEligibleAggFuncs(SNodeList* pAggFuncs) {
|
||||||
|
SNode* pNode = NULL;
|
||||||
|
FOREACH(pNode, pAggFuncs) {
|
||||||
|
SFunctionNode* pFunc = (SFunctionNode*)nodesListGetNode(pAggFuncs, 0);
|
||||||
|
if (FUNCTION_TYPE_COUNT != pFunc->funcType ||
|
||||||
|
!tbCntScanOptNotNullableExpr(nodesListGetNode(pFunc->pParameterList, 0))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool tbCntScanOptIsEligibleAgg(SAggLogicNode* pAgg) {
|
||||||
|
return tbCntScanOptIsEligibleGroupKeys(pAgg->pGroupKeys) && tbCntScanOptIsEligibleAggFuncs(pAgg->pAggFuncs);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool tbCntScanOptGetColValFromCond(SOperatorNode* pOper, SColumnNode** pCol, SValueNode** pVal) {
|
||||||
|
if (OP_TYPE_EQUAL != pOper->opType) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
*pCol = NULL;
|
||||||
|
*pVal = NULL;
|
||||||
|
if (QUERY_NODE_COLUMN == nodeType(pOper->pLeft)) {
|
||||||
|
*pCol = (SColumnNode*)pOper->pLeft;
|
||||||
|
} else if (QUERY_NODE_VALUE == nodeType(pOper->pLeft)) {
|
||||||
|
*pVal = (SValueNode*)pOper->pLeft;
|
||||||
|
}
|
||||||
|
if (QUERY_NODE_COLUMN == nodeType(pOper->pRight)) {
|
||||||
|
*pCol = (SColumnNode*)pOper->pRight;
|
||||||
|
} else if (QUERY_NODE_VALUE == nodeType(pOper->pRight)) {
|
||||||
|
*pVal = (SValueNode*)pOper->pRight;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL != *pCol && NULL != *pVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool tbCntScanOptIsEligibleLogicCond(STbCntScanOptInfo* pInfo, SLogicConditionNode* pCond) {
|
||||||
|
if (LOGIC_COND_TYPE_AND != pCond->condType) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hasDbCond = false;
|
||||||
|
bool hasStbCond = false;
|
||||||
|
SColumnNode* pCol = NULL;
|
||||||
|
SValueNode* pVal = NULL;
|
||||||
|
SNode* pNode = NULL;
|
||||||
|
FOREACH(pNode, pCond->pParameterList) {
|
||||||
|
if (QUERY_NODE_OPERATOR != nodeType(pNode) || !tbCntScanOptGetColValFromCond((SOperatorNode*)pNode, &pCol, &pVal)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!hasDbCond && 0 == strcmp(pCol->colName, "db_name")) {
|
||||||
|
hasDbCond = true;
|
||||||
|
strcpy(pInfo->table.dbname, pVal->literal);
|
||||||
|
} else if (!hasStbCond && 0 == strcmp(pCol->colName, "stable_name")) {
|
||||||
|
hasStbCond = true;
|
||||||
|
strcpy(pInfo->table.tname, pVal->literal);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hasDbCond;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool tbCntScanOptIsEligibleOpCond(SOperatorNode* pCond) {
|
||||||
|
SColumnNode* pCol = NULL;
|
||||||
|
SValueNode* pVal = NULL;
|
||||||
|
if (!tbCntScanOptGetColValFromCond(pCond, &pCol, &pVal)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return 0 == strcmp(pCol->colName, "db_name");
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool tbCntScanOptIsEligibleConds(STbCntScanOptInfo* pInfo, SNode* pConditions) {
|
||||||
|
if (NULL == pConditions) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (QUERY_NODE_LOGIC_CONDITION == nodeType(pConditions)) {
|
||||||
|
return tbCntScanOptIsEligibleLogicCond(pInfo, (SLogicConditionNode*)pConditions);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (QUERY_NODE_OPERATOR == nodeType(pConditions)) {
|
||||||
|
return tbCntScanOptIsEligibleOpCond((SOperatorNode*)pConditions);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool tbCntScanOptIsEligibleScan(STbCntScanOptInfo* pInfo) {
|
||||||
|
if (0 != strcmp(pInfo->pScan->tableName.dbname, TSDB_INFORMATION_SCHEMA_DB) ||
|
||||||
|
0 != strcmp(pInfo->pScan->tableName.tname, TSDB_INS_TABLE_TABLES) || NULL != pInfo->pScan->pGroupTags) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (1 == pInfo->pScan->pVgroupList->numOfVgroups && MNODE_HANDLE == pInfo->pScan->pVgroupList->vgroups[0].vgId) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return tbCntScanOptIsEligibleConds(pInfo, pInfo->pScan->node.pConditions);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool tbCntScanOptShouldBeOptimized(SLogicNode* pNode, STbCntScanOptInfo* pInfo) {
|
||||||
|
if (QUERY_NODE_LOGIC_PLAN_AGG != nodeType(pNode) || 1 != LIST_LENGTH(pNode->pChildren) ||
|
||||||
|
QUERY_NODE_LOGIC_PLAN_SCAN != nodeType(nodesListGetNode(pNode->pChildren, 0))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
pInfo->pAgg = (SAggLogicNode*)pNode;
|
||||||
|
pInfo->pScan = (SScanLogicNode*)nodesListGetNode(pNode->pChildren, 0);
|
||||||
|
return tbCntScanOptIsEligibleAgg(pInfo->pAgg) && tbCntScanOptIsEligibleScan(pInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
static SNode* tbCntScanOptCreateTableCountFunc() {
|
||||||
|
SFunctionNode* pFunc = (SFunctionNode*)nodesMakeNode(QUERY_NODE_FUNCTION);
|
||||||
|
if (NULL == pFunc) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
strcpy(pFunc->functionName, "_table_count");
|
||||||
|
strcpy(pFunc->node.aliasName, "_table_count");
|
||||||
|
if (TSDB_CODE_SUCCESS != fmGetFuncInfo(pFunc, NULL, 0)) {
|
||||||
|
nodesDestroyNode((SNode*)pFunc);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return (SNode*)pFunc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t tbCntScanOptRewriteScan(STbCntScanOptInfo* pInfo) {
|
||||||
|
pInfo->pScan->scanType = SCAN_TYPE_TABLE_COUNT;
|
||||||
|
strcpy(pInfo->pScan->tableName.dbname, pInfo->table.dbname);
|
||||||
|
strcpy(pInfo->pScan->tableName.tname, pInfo->table.tname);
|
||||||
|
NODES_DESTORY_LIST(pInfo->pScan->node.pTargets);
|
||||||
|
NODES_DESTORY_LIST(pInfo->pScan->pScanCols);
|
||||||
|
NODES_DESTORY_NODE(pInfo->pScan->node.pConditions);
|
||||||
|
NODES_DESTORY_LIST(pInfo->pScan->pScanPseudoCols);
|
||||||
|
int32_t code = nodesListMakeStrictAppend(&pInfo->pScan->pScanPseudoCols, tbCntScanOptCreateTableCountFunc());
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = createColumnByRewriteExpr(nodesListGetNode(pInfo->pScan->pScanPseudoCols, 0), &pInfo->pScan->node.pTargets);
|
||||||
|
}
|
||||||
|
SNode* pGroupKey = NULL;
|
||||||
|
FOREACH(pGroupKey, pInfo->pAgg->pGroupKeys) {
|
||||||
|
SNode* pGroupCol = nodesListGetNode(((SGroupingSetNode*)pGroupKey)->pParameterList, 0);
|
||||||
|
code = nodesListMakeStrictAppend(&pInfo->pScan->pGroupTags, nodesCloneNode(pGroupCol));
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = nodesListMakeStrictAppend(&pInfo->pScan->pScanCols, nodesCloneNode(pGroupCol));
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = nodesListMakeStrictAppend(&pInfo->pScan->node.pTargets, nodesCloneNode(pGroupCol));
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS != code) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t tbCntScanOptCreateSumFunc(SFunctionNode* pCntFunc, SNode* pParam, SNode** pOutput) {
|
||||||
|
SFunctionNode* pFunc = (SFunctionNode*)nodesMakeNode(QUERY_NODE_FUNCTION);
|
||||||
|
if (NULL == pFunc) {
|
||||||
|
return TSDB_CODE_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
strcpy(pFunc->functionName, "sum");
|
||||||
|
strcpy(pFunc->node.aliasName, pCntFunc->node.aliasName);
|
||||||
|
int32_t code = createColumnByRewriteExpr(pParam, &pFunc->pParameterList);
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = fmGetFuncInfo(pFunc, NULL, 0);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
*pOutput = (SNode*)pFunc;
|
||||||
|
} else {
|
||||||
|
nodesDestroyNode((SNode*)pFunc);
|
||||||
|
}
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t tbCntScanOptRewriteAgg(SAggLogicNode* pAgg) {
|
||||||
|
SScanLogicNode* pScan = (SScanLogicNode*)nodesListGetNode(pAgg->node.pChildren, 0);
|
||||||
|
SNode* pSum = NULL;
|
||||||
|
int32_t code = tbCntScanOptCreateSumFunc((SFunctionNode*)nodesListGetNode(pAgg->pAggFuncs, 0),
|
||||||
|
nodesListGetNode(pScan->pScanPseudoCols, 0), &pSum);
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
NODES_DESTORY_LIST(pAgg->pAggFuncs);
|
||||||
|
code = nodesListMakeStrictAppend(&pAgg->pAggFuncs, pSum);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = partTagsRewriteGroupTagsToFuncs(pScan->pGroupTags, 0, pAgg);
|
||||||
|
}
|
||||||
|
NODES_DESTORY_LIST(pAgg->pGroupKeys);
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t tableCountScanOptimize(SOptimizeContext* pCxt, SLogicSubplan* pLogicSubplan) {
|
||||||
|
STbCntScanOptInfo info = {0};
|
||||||
|
if (!optFindEligibleNode(pLogicSubplan->pNode, (FShouldBeOptimized)tbCntScanOptShouldBeOptimized, &info)) {
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t code = tbCntScanOptRewriteScan(&info);
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = tbCntScanOptRewriteAgg(info.pAgg);
|
||||||
|
}
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static const SOptimizeRule optimizeRuleSet[] = {
|
static const SOptimizeRule optimizeRuleSet[] = {
|
||||||
{.pName = "ScanPath", .optimizeFunc = scanPathOptimize},
|
{.pName = "ScanPath", .optimizeFunc = scanPathOptimize},
|
||||||
|
@ -2468,7 +2720,8 @@ static const SOptimizeRule optimizeRuleSet[] = {
|
||||||
{.pName = "RewriteUnique", .optimizeFunc = rewriteUniqueOptimize},
|
{.pName = "RewriteUnique", .optimizeFunc = rewriteUniqueOptimize},
|
||||||
{.pName = "LastRowScan", .optimizeFunc = lastRowScanOptimize},
|
{.pName = "LastRowScan", .optimizeFunc = lastRowScanOptimize},
|
||||||
{.pName = "TagScan", .optimizeFunc = tagScanOptimize},
|
{.pName = "TagScan", .optimizeFunc = tagScanOptimize},
|
||||||
{.pName = "PushDownLimit", .optimizeFunc = pushDownLimitOptimize}
|
{.pName = "PushDownLimit", .optimizeFunc = pushDownLimitOptimize},
|
||||||
|
{.pName = "TableCountScan", .optimizeFunc = tableCountScanOptimize},
|
||||||
};
|
};
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
|
|
|
@ -489,6 +489,8 @@ static ENodeType getScanOperatorType(EScanType scanType) {
|
||||||
return QUERY_NODE_PHYSICAL_PLAN_TABLE_MERGE_SCAN;
|
return QUERY_NODE_PHYSICAL_PLAN_TABLE_MERGE_SCAN;
|
||||||
case SCAN_TYPE_BLOCK_INFO:
|
case SCAN_TYPE_BLOCK_INFO:
|
||||||
return QUERY_NODE_PHYSICAL_PLAN_BLOCK_DIST_SCAN;
|
return QUERY_NODE_PHYSICAL_PLAN_BLOCK_DIST_SCAN;
|
||||||
|
case SCAN_TYPE_TABLE_COUNT:
|
||||||
|
return QUERY_NODE_PHYSICAL_PLAN_TABLE_COUNT_SCAN;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -524,6 +526,24 @@ static int32_t createLastRowScanPhysiNode(SPhysiPlanContext* pCxt, SSubplan* pSu
|
||||||
pScan->ignoreNull = pScanLogicNode->igLastNull;
|
pScan->ignoreNull = pScanLogicNode->igLastNull;
|
||||||
vgroupInfoToNodeAddr(pScanLogicNode->pVgroupList->vgroups, &pSubplan->execNode);
|
vgroupInfoToNodeAddr(pScanLogicNode->pVgroupList->vgroups, &pSubplan->execNode);
|
||||||
|
|
||||||
|
return createScanPhysiNodeFinalize(pCxt, pSubplan, pScanLogicNode, (SScanPhysiNode*)pScan, pPhyNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t createTableCountScanPhysiNode(SPhysiPlanContext* pCxt, SSubplan* pSubplan,
|
||||||
|
SScanLogicNode* pScanLogicNode, SPhysiNode** pPhyNode) {
|
||||||
|
STableCountScanPhysiNode* pScan = (STableCountScanPhysiNode*)makePhysiNode(pCxt, (SLogicNode*)pScanLogicNode,
|
||||||
|
QUERY_NODE_PHYSICAL_PLAN_TABLE_COUNT_SCAN);
|
||||||
|
if (NULL == pScan) {
|
||||||
|
return TSDB_CODE_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
pScan->pGroupTags = nodesCloneList(pScanLogicNode->pGroupTags);
|
||||||
|
if (NULL != pScanLogicNode->pGroupTags && NULL == pScan->pGroupTags) {
|
||||||
|
nodesDestroyNode((SNode*)pScan);
|
||||||
|
return TSDB_CODE_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
pScan->groupSort = pScanLogicNode->groupSort;
|
||||||
vgroupInfoToNodeAddr(pScanLogicNode->pVgroupList->vgroups, &pSubplan->execNode);
|
vgroupInfoToNodeAddr(pScanLogicNode->pVgroupList->vgroups, &pSubplan->execNode);
|
||||||
|
|
||||||
return createScanPhysiNodeFinalize(pCxt, pSubplan, pScanLogicNode, (SScanPhysiNode*)pScan, pPhyNode);
|
return createScanPhysiNodeFinalize(pCxt, pSubplan, pScanLogicNode, (SScanPhysiNode*)pScan, pPhyNode);
|
||||||
|
@ -589,7 +609,6 @@ static int32_t createSystemTableScanPhysiNode(SPhysiPlanContext* pCxt, SSubplan*
|
||||||
pScan->accountId = pCxt->pPlanCxt->acctId;
|
pScan->accountId = pCxt->pPlanCxt->acctId;
|
||||||
pScan->sysInfo = pCxt->pPlanCxt->sysInfo;
|
pScan->sysInfo = pCxt->pPlanCxt->sysInfo;
|
||||||
if (0 == strcmp(pScanLogicNode->tableName.tname, TSDB_INS_TABLE_TABLES) ||
|
if (0 == strcmp(pScanLogicNode->tableName.tname, TSDB_INS_TABLE_TABLES) ||
|
||||||
0 == strcmp(pScanLogicNode->tableName.tname, TSDB_INS_TABLE_TABLE_DISTRIBUTED) ||
|
|
||||||
0 == strcmp(pScanLogicNode->tableName.tname, TSDB_INS_TABLE_TAGS)) {
|
0 == strcmp(pScanLogicNode->tableName.tname, TSDB_INS_TABLE_TAGS)) {
|
||||||
vgroupInfoToNodeAddr(pScanLogicNode->pVgroupList->vgroups, &pSubplan->execNode);
|
vgroupInfoToNodeAddr(pScanLogicNode->pVgroupList->vgroups, &pSubplan->execNode);
|
||||||
} else {
|
} else {
|
||||||
|
@ -624,6 +643,8 @@ static int32_t createScanPhysiNode(SPhysiPlanContext* pCxt, SSubplan* pSubplan,
|
||||||
case SCAN_TYPE_TAG:
|
case SCAN_TYPE_TAG:
|
||||||
case SCAN_TYPE_BLOCK_INFO:
|
case SCAN_TYPE_BLOCK_INFO:
|
||||||
return createSimpleScanPhysiNode(pCxt, pSubplan, pScanLogicNode, pPhyNode);
|
return createSimpleScanPhysiNode(pCxt, pSubplan, pScanLogicNode, pPhyNode);
|
||||||
|
case SCAN_TYPE_TABLE_COUNT:
|
||||||
|
return createTableCountScanPhysiNode(pCxt, pSubplan, pScanLogicNode, pPhyNode);
|
||||||
case SCAN_TYPE_LAST_ROW:
|
case SCAN_TYPE_LAST_ROW:
|
||||||
return createLastRowScanPhysiNode(pCxt, pSubplan, pScanLogicNode, pPhyNode);
|
return createLastRowScanPhysiNode(pCxt, pSubplan, pScanLogicNode, pPhyNode);
|
||||||
case SCAN_TYPE_TABLE:
|
case SCAN_TYPE_TABLE:
|
||||||
|
|
|
@ -292,6 +292,20 @@ static bool stbSplNeedSplitJoin(bool streamQuery, SJoinLogicNode* pJoin) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool stbSplIsTableCountQuery(SLogicNode* pNode) {
|
||||||
|
if (1 != LIST_LENGTH(pNode->pChildren)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
SNode* pChild = nodesListGetNode(pNode->pChildren, 0);
|
||||||
|
if (QUERY_NODE_LOGIC_PLAN_PARTITION == nodeType(pChild)) {
|
||||||
|
if (1 != LIST_LENGTH(((SLogicNode*)pChild)->pChildren)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
pChild = nodesListGetNode(((SLogicNode*)pChild)->pChildren, 0);
|
||||||
|
}
|
||||||
|
return QUERY_NODE_LOGIC_PLAN_SCAN == nodeType(pChild) && SCAN_TYPE_TABLE_COUNT == ((SScanLogicNode*)pChild)->scanType;
|
||||||
|
}
|
||||||
|
|
||||||
static SNodeList* stbSplGetPartKeys(SLogicNode* pNode) {
|
static SNodeList* stbSplGetPartKeys(SLogicNode* pNode) {
|
||||||
if (QUERY_NODE_LOGIC_PLAN_SCAN == nodeType(pNode)) {
|
if (QUERY_NODE_LOGIC_PLAN_SCAN == nodeType(pNode)) {
|
||||||
return ((SScanLogicNode*)pNode)->pGroupTags;
|
return ((SScanLogicNode*)pNode)->pGroupTags;
|
||||||
|
@ -340,7 +354,7 @@ static bool stbSplNeedSplit(bool streamQuery, SLogicNode* pNode) {
|
||||||
case QUERY_NODE_LOGIC_PLAN_AGG:
|
case QUERY_NODE_LOGIC_PLAN_AGG:
|
||||||
return (!stbSplHasGatherExecFunc(((SAggLogicNode*)pNode)->pAggFuncs) ||
|
return (!stbSplHasGatherExecFunc(((SAggLogicNode*)pNode)->pAggFuncs) ||
|
||||||
stbSplIsPartTableAgg((SAggLogicNode*)pNode)) &&
|
stbSplIsPartTableAgg((SAggLogicNode*)pNode)) &&
|
||||||
stbSplHasMultiTbScan(streamQuery, pNode);
|
stbSplHasMultiTbScan(streamQuery, pNode) && !stbSplIsTableCountQuery(pNode);
|
||||||
case QUERY_NODE_LOGIC_PLAN_WINDOW:
|
case QUERY_NODE_LOGIC_PLAN_WINDOW:
|
||||||
return stbSplNeedSplitWindow(streamQuery, pNode);
|
return stbSplNeedSplitWindow(streamQuery, pNode);
|
||||||
case QUERY_NODE_LOGIC_PLAN_SORT:
|
case QUERY_NODE_LOGIC_PLAN_SORT:
|
||||||
|
|
|
@ -20,13 +20,6 @@ using namespace std;
|
||||||
|
|
||||||
class PlanSysTableTest : public PlannerTestBase {};
|
class PlanSysTableTest : public PlannerTestBase {};
|
||||||
|
|
||||||
TEST_F(PlanSysTableTest, show) {
|
|
||||||
useDb("root", "test");
|
|
||||||
|
|
||||||
run("show tables");
|
|
||||||
run("show stables");
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(PlanSysTableTest, informationSchema) {
|
TEST_F(PlanSysTableTest, informationSchema) {
|
||||||
useDb("root", "information_schema");
|
useDb("root", "information_schema");
|
||||||
|
|
||||||
|
@ -38,3 +31,17 @@ TEST_F(PlanSysTableTest, withAgg) {
|
||||||
|
|
||||||
run("SELECT COUNT(1) FROM ins_users");
|
run("SELECT COUNT(1) FROM ins_users");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(PlanSysTableTest, tableCount) {
|
||||||
|
useDb("root", "information_schema");
|
||||||
|
|
||||||
|
run("SELECT COUNT(*) FROM ins_tables");
|
||||||
|
|
||||||
|
run("SELECT COUNT(*) FROM ins_tables WHERE db_name = 'test'");
|
||||||
|
|
||||||
|
run("SELECT COUNT(*) FROM ins_tables WHERE db_name = 'test' AND stable_name = 'st1'");
|
||||||
|
|
||||||
|
run("SELECT db_name, COUNT(*) FROM ins_tables GROUP BY db_name");
|
||||||
|
|
||||||
|
run("SELECT db_name, stable_name, COUNT(*) FROM ins_tables GROUP BY db_name, stable_name");
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue