diff --git a/docs/en/12-taos-sql/06-select.md b/docs/en/12-taos-sql/06-select.md index 2d6c1469b6..e30e476ba4 100755 --- a/docs/en/12-taos-sql/06-select.md +++ b/docs/en/12-taos-sql/06-select.md @@ -459,7 +459,7 @@ SELECT ... FROM (SELECT ... FROM ...) ...; :::info - The result of a nested query is returned as a virtual table used by the outer query. It's recommended to give an alias to this table for the convenience of using it in the outer query. -- Outer queries support directly referencing columns or pseudo-columns of inner queries in the form of column names or `column names`. +- Outer queries support directly referencing columns or pseudo-columns of inner queries in the form of column names or \`column names\`. - JOIN operation is allowed between tables/STables inside both inner and outer queries. Join operation can be performed on the result set of the inner query. - The features that can be used in the inner query are the same as those that can be used in a non-nested query. - `ORDER BY` inside the inner query is unnecessary and will slow down the query performance significantly. It is best to avoid the use of `ORDER BY` inside the inner query. diff --git a/docs/en/12-taos-sql/18-escape.md b/docs/en/12-taos-sql/18-escape.md index 2d067b2ad9..a14591b0da 100644 --- a/docs/en/12-taos-sql/18-escape.md +++ b/docs/en/12-taos-sql/18-escape.md @@ -18,7 +18,7 @@ description: This document describes the usage of escape characters in TDengine. ## Restrictions -1. If there are escape characters in identifiers (database name, table name, column name) +1. If there are escape characters in identifiers (database name, table name, column name, alias Name) - Identifier without ``: Error will be returned because identifier must be constituted of digits, ASCII characters or underscore and can't be started with digits - Identifier quoted with ``: Original content is kept, no escaping 2. If there are escape characters in values diff --git a/docs/zh/12-taos-sql/06-select.md b/docs/zh/12-taos-sql/06-select.md index acf42a3b8f..f10c5ebb69 100755 --- a/docs/zh/12-taos-sql/06-select.md +++ b/docs/zh/12-taos-sql/06-select.md @@ -459,7 +459,7 @@ SELECT ... FROM (SELECT ... FROM ...) ...; :::info - 内层查询的返回结果将作为“虚拟表”供外层查询使用,此虚拟表建议起别名,以便于外层查询中方便引用。 -- 外层查询支持直接通过列名或`列名`的形式引用内层查询的列或伪列。 +- 外层查询支持直接通过列名或\`列名\`的形式引用内层查询的列或伪列。 - 在内层和外层查询中,都支持普通的表间/超级表间 JOIN。内层查询的计算结果也可以再参与数据子表的 JOIN 操作。 - 内层查询支持的功能特性与非嵌套的查询语句能力是一致的。 - 内层查询的 ORDER BY 子句一般没有意义,建议避免这样的写法以免无谓的资源消耗。 diff --git a/docs/zh/12-taos-sql/18-escape.md b/docs/zh/12-taos-sql/18-escape.md index 81e4179042..6bd20abf36 100644 --- a/docs/zh/12-taos-sql/18-escape.md +++ b/docs/zh/12-taos-sql/18-escape.md @@ -20,7 +20,7 @@ description: TDengine 中使用转义字符的详细规则 ## 转义字符使用规则 -1. 标识符里有转义字符(数据库名、表名、列名) +1. 标识符里有转义字符(数据库名、表名、列名、别名) 1. 普通标识符: 直接提示错误的标识符,因为标识符规定必须是数字、字母和下划线,并且不能以数字开头。 2. 反引号``标识符: 保持原样,不转义 2. 数据里有转义字符 diff --git a/docs/zh/28-releases/03-notes/02-3.3.2.0.md b/docs/zh/28-releases/03-notes/02-3.3.2.0.md deleted file mode 100644 index f4ecf3cc2c..0000000000 --- a/docs/zh/28-releases/03-notes/02-3.3.2.0.md +++ /dev/null @@ -1,7 +0,0 @@ -## 3.3.2.0 版本说明 - -### 新特性 - -### 优化 - -### 修复问题 diff --git a/docs/zh/28-releases/03-notes/3.3.2.0.md b/docs/zh/28-releases/03-notes/3.3.2.0.md new file mode 100644 index 0000000000..41ba9d9896 --- /dev/null +++ b/docs/zh/28-releases/03-notes/3.3.2.0.md @@ -0,0 +1,11 @@ +--- +title: 3.3.2.0 版本说明 +sidebar_label: 3.3.2.0 +description: 3.3.2.0 版本说明 +--- + +### 新特性 + +### 优化 + +### 修复问题 diff --git a/docs/zh/28-releases/03-notes/01-index.md b/docs/zh/28-releases/03-notes/index.md similarity index 100% rename from docs/zh/28-releases/03-notes/01-index.md rename to docs/zh/28-releases/03-notes/index.md diff --git a/source/dnode/vnode/src/tsdb/tsdbRead2.c b/source/dnode/vnode/src/tsdb/tsdbRead2.c index 37da1a9d53..272c0762d8 100644 --- a/source/dnode/vnode/src/tsdb/tsdbRead2.c +++ b/source/dnode/vnode/src/tsdb/tsdbRead2.c @@ -1759,6 +1759,7 @@ static int32_t doMergeBufAndFileRows(STsdbReader* pReader, STableBlockScanInfo* if (ps == NULL) { return terrno; } + tsdbRowMergerInit(pMerger, ps); } SRowKey minKey = k; @@ -1842,6 +1843,7 @@ static int32_t mergeFileBlockAndSttBlock(STsdbReader* pReader, SSttBlockReader* if (ps == NULL) { return terrno; } + tsdbRowMergerInit(pMerger, ps); } bool dataInDataFile = hasDataInFileBlock(pBlockData, pDumpInfo); @@ -1963,6 +1965,7 @@ static int32_t doMergeMultiLevelRows(STsdbReader* pReader, STableBlockScanInfo* if (ps == NULL) { return terrno; } + tsdbRowMergerInit(pMerger, ps); } SRowKey minKey = k; @@ -2326,6 +2329,7 @@ int32_t mergeRowsInFileBlocks(SBlockData* pBlockData, STableBlockScanInfo* pBloc if (ps == NULL) { return terrno; } + tsdbRowMergerInit(pMerger, ps); } tRowKeyAssign(&pBlockScanInfo->lastProcKey, pKey); diff --git a/source/libs/executor/src/scanoperator.c b/source/libs/executor/src/scanoperator.c index 6c512d4859..490f6b86fa 100644 --- a/source/libs/executor/src/scanoperator.c +++ b/source/libs/executor/src/scanoperator.c @@ -3459,11 +3459,15 @@ static int32_t tagScanFilterByTagCond(SArray* aUidTags, SNode* pTagCond, SArray* SScalarParam output = {0}; code = tagScanCreateResultData(&type, numOfTables, &output); if (TSDB_CODE_SUCCESS != code) { + blockDataDestroy(pResBlock); + taosArrayDestroy(pBlockList); return code; } code = scalarCalculate(pTagCond, pBlockList, &output); if (TSDB_CODE_SUCCESS != code) { + blockDataDestroy(pResBlock); + taosArrayDestroy(pBlockList); return code; } diff --git a/source/libs/parser/inc/parAst.h b/source/libs/parser/inc/parAst.h index dc42245d93..579317a2fc 100644 --- a/source/libs/parser/inc/parAst.h +++ b/source/libs/parser/inc/parAst.h @@ -139,7 +139,7 @@ SNode* createCastFunctionNode(SAstCreateContext* pCxt, SNode* pExpr, SDataTy SNode* createNodeListNode(SAstCreateContext* pCxt, SNodeList* pList); SNode* createNodeListNodeEx(SAstCreateContext* pCxt, SNode* p1, SNode* p2); SNode* createRealTableNode(SAstCreateContext* pCxt, SToken* pDbName, SToken* pTableName, SToken* pTableAlias); -SNode* createTempTableNode(SAstCreateContext* pCxt, SNode* pSubquery, const SToken* pTableAlias); +SNode* createTempTableNode(SAstCreateContext* pCxt, SNode* pSubquery, SToken* pTableAlias); SNode* createJoinTableNode(SAstCreateContext* pCxt, EJoinType type, EJoinSubType stype, SNode* pLeft, SNode* pRight, SNode* pJoinCond); SNode* createViewNode(SAstCreateContext* pCxt, SToken* pDbName, SToken* pViewName); diff --git a/source/libs/parser/src/parAstCreater.c b/source/libs/parser/src/parAstCreater.c index 0497e7a0e2..7c2f504a4f 100644 --- a/source/libs/parser/src/parAstCreater.c +++ b/source/libs/parser/src/parAstCreater.c @@ -949,8 +949,11 @@ SNode* createRealTableNode(SAstCreateContext* pCxt, SToken* pDbName, SToken* pTa return (SNode*)realTable; } -SNode* createTempTableNode(SAstCreateContext* pCxt, SNode* pSubquery, const SToken* pTableAlias) { +SNode* createTempTableNode(SAstCreateContext* pCxt, SNode* pSubquery, SToken* pTableAlias) { CHECK_PARSER_STATUS(pCxt); + if (!checkTableName(pCxt, pTableAlias)) { + return NULL; + } STempTableNode* tempTable = (STempTableNode*)nodesMakeNode(QUERY_NODE_TEMP_TABLE); CHECK_OUT_OF_MEM(tempTable); tempTable->pSubquery = pSubquery; diff --git a/source/libs/stream/src/streamBackendRocksdb.c b/source/libs/stream/src/streamBackendRocksdb.c index cf7852cddb..f5c0ac57df 100644 --- a/source/libs/stream/src/streamBackendRocksdb.c +++ b/source/libs/stream/src/streamBackendRocksdb.c @@ -238,6 +238,9 @@ int32_t remoteChkp_readMetaData(char* path, SArray* list) { sprintf(metaPath, "%s%s%s", path, TD_DIRSEP, "META"); TdFilePtr pFile = taosOpenFile(path, TD_FILE_READ); + if (pFile == NULL) { + return -1; + } char buf[128] = {0}; if (taosReadFile(pFile, buf, sizeof(buf)) <= 0) { @@ -245,7 +248,8 @@ int32_t remoteChkp_readMetaData(char* path, SArray* list) { taosCloseFile(&pFile); return -1; } - int32_t len = strlen(buf); + + int32_t len = strnlen(buf, tListLen(buf)); for (int i = 0; i < len; i++) { if (buf[i] == '\n') { char* item = taosMemoryCalloc(1, i + 1); @@ -2117,9 +2121,7 @@ void taskDbDestroy(void* pDb, bool flush) { stDebug("succ to destroy stream backend:%p", wrapper); - int8_t nCf = sizeof(ginitDict) / sizeof(ginitDict[0]); - - if (wrapper == NULL) return; + int8_t nCf = tListLen(ginitDict); if (flush) { if (wrapper->db && wrapper->pCf) { @@ -4223,7 +4225,8 @@ int32_t dbChkpDumpTo(SDbChkp* p, char* dname, SArray* list) { static char* chkpMeta = "META"; memset(dstBuf, 0, len); - sprintf(dstDir, "%s%s%s", dstDir, TD_DIRSEP, chkpMeta); + sprintf(dstBuf, "%s%s%s", dstDir, TD_DIRSEP, chkpMeta); + memcpy(dstDir, dstBuf, strlen(dstBuf)); TdFilePtr pFile = taosOpenFile(dstDir, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_TRUNC); if (pFile == NULL) { diff --git a/source/libs/stream/src/streamSnapshot.c b/source/libs/stream/src/streamSnapshot.c index adefe97f1f..0871ff5eb7 100644 --- a/source/libs/stream/src/streamSnapshot.c +++ b/source/libs/stream/src/streamSnapshot.c @@ -312,17 +312,12 @@ int32_t streamSnapHandleInit(SStreamSnapHandle* pHandle, char* path, void* pMeta ASSERT(code == 0); taosArrayPush(pDbSnapSet, &snapFile); } + pHandle->pDbSnapSet = pDbSnapSet; pHandle->pSnapInfoSet = pSnapInfoSet; pHandle->currIdx = 0; pHandle->pMeta = pMeta; return 0; - -_err: - streamSnapHandleDestroy(pHandle); - - code = -1; - return code; } void streamSnapHandleDestroy(SStreamSnapHandle* handle) { @@ -444,6 +439,7 @@ _NEXT: pSnapFile = taosArrayGet(pHandle->pDbSnapSet, pHandle->currIdx); goto _NEXT; } else { + taosMemoryFree(buf); *ppData = NULL; *size = 0; return 0; @@ -465,7 +461,9 @@ _NEXT: pHdr->totalSize = item->size; pHdr->snapInfo = pSnapFile->snapInfo; - memcpy(pHdr->name, item->name, strlen(item->name)); + int32_t len = TMIN(strlen(item->name), tListLen(pHdr->name)); + memcpy(pHdr->name, item->name, len); + pSnapFile->seraial += nread; *ppData = buf; diff --git a/tests/army/query/queryBugs.py b/tests/army/query/queryBugs.py new file mode 100644 index 0000000000..ca28ff549c --- /dev/null +++ b/tests/army/query/queryBugs.py @@ -0,0 +1,67 @@ +################################################################### +# Copyright (c) 2016 by TAOS Technologies, Inc. +# All rights reserved. +# +# This file is proprietary and confidential to TAOS Technologies. +# No part of this file may be reproduced, stored, transmitted, +# disclosed or used in any form or by any means other than as +# expressly provided by the written permission from Jianhui Tao +# +################################################################### + +# -*- coding: utf-8 -*- + +import sys +import time +import random + +import taos +import frame +import frame.etool + + +from frame.log import * +from frame.cases import * +from frame.sql import * +from frame.caseBase import * +from frame import * + + +class TDTestCase(TBase): + + # fix + def FIX_TD_30686(self): + tdLog.info("check bug TD_30686 ...\n") + sqls = [ + "create database db", + "create table db.st(ts timestamp, age int) tags(area tinyint);", + "insert into db.t1 using db.st tags(100) values('2024-01-01 10:00:01', 1);", + "insert into db.t2 using db.st tags(110) values('2024-01-01 10:00:02', 2);", + "insert into db.t3 using db.st tags(3) values('2024-01-01 10:00:03', 3);" + ] + tdSql.executes(sqls) + + sql = "select * from db.st where area < 139 order by ts;" + results = [ + ["2024-01-01 10:00:01", 1, 100], + ["2024-01-01 10:00:02", 2, 110], + ["2024-01-01 10:00:03", 3, 3] + ] + tdSql.checkDataMem(sql, results) + + # run + def run(self): + tdLog.debug(f"start to excute {__file__}") + + # TD BUGS + self.FIX_TD_30686() + + # TS BUGS + + + tdLog.success(f"{__file__} successfully executed") + + + +tdCases.addLinux(__file__, TDTestCase()) +tdCases.addWindows(__file__, TDTestCase()) diff --git a/tests/parallel_test/cases.task b/tests/parallel_test/cases.task index b51df65a7d..aff5bedaf8 100644 --- a/tests/parallel_test/cases.task +++ b/tests/parallel_test/cases.task @@ -34,6 +34,7 @@ ,,y,army,./pytest.sh python3 ./test.py -f storage/oneStageComp.py -N 3 -L 3 -D 1 ,,y,army,./pytest.sh python3 ./test.py -f storage/compressBasic.py -N 3 ,,y,army,./pytest.sh python3 ./test.py -f grant/grantBugs.py -N 3 +,,y,army,./pytest.sh python3 ./test.py -f query/queryBugs.py -N 3 # # system test diff --git a/tests/system-test/0-others/backquote_check.py b/tests/system-test/0-others/backquote_check.py index 7c91fd9e8c..d5b5d2ef1a 100644 --- a/tests/system-test/0-others/backquote_check.py +++ b/tests/system-test/0-others/backquote_check.py @@ -26,6 +26,8 @@ class TDTestCase: self.dbname = 'db' self.setsql = TDSetSql() self.stbname = 'stb' + self.ntbname1 = 'ntb1' + self.ntbname2 = 'ntb2' self.streamname = 'stm' self.streamtb = 'stm_stb' def topic_name_check(self): @@ -74,11 +76,33 @@ class TDTestCase: tdSql.checkEqual(tdSql.queryResult[0][0],self.streamname) tdSql.execute(f'drop stream `{self.streamname}`') tdSql.execute(f'drop database {self.dbname}') - + + def table_name_check(self): + tdSql.execute(f'create database if not exists {self.dbname} wal_retention_period 3600') + tdSql.execute(f'use {self.dbname}') + tdSql.execute(f'create table {self.ntbname1} (ts timestamp,c0 int,c1 int)') + tdSql.execute(f'create table {self.ntbname2} (ts timestamp,c0 int,c1 int)') + tdSql.execute(f'insert into {self.ntbname1} values(now(),1,1)') + tdSql.execute(f'insert into {self.ntbname2} values(now(),2,2)') + tdSql.query(f'select `{self.ntbname1}`.`c0`, `{self.ntbname1}`.`c1` from `{self.ntbname1}`') + tdSql.checkEqual(tdSql.queryResult[0][0], 1) + tdSql.query(f'select `{self.ntbname1}`.`c0`, `{self.ntbname1}`.`c1` from `{self.dbname}`.`{self.ntbname1}`') + tdSql.checkEqual(tdSql.queryResult[0][0], 1) + tdSql.query(f'select `{self.ntbname1}`.`c0` from `{self.ntbname2}` `{self.ntbname1}`') + tdSql.checkEqual(tdSql.queryResult[0][0], 2) + tdSql.query(f'select `{self.ntbname1}`.`c0` from (select * from `{self.ntbname2}`) `{self.ntbname1}`') + tdSql.checkEqual(tdSql.queryResult[0][0], 2) + # select `t1`.`col1`, `col2`, `col3` from (select ts `col1`, 123 `col2`, c0 + c1 as `col3` from t2) `t1`; + tdSql.query(f'select `{self.ntbname1}`.`col1`, `col2`, `col3` from (select ts `col1`, 123 `col2`, c0 + c1 as `col3` from {self.ntbname2}) `{self.ntbname1}`') + tdSql.checkEqual(tdSql.queryResult[0][1], 123) + tdSql.checkEqual(tdSql.queryResult[0][2], 4) + + tdSql.execute(f'drop database {self.dbname}') def run(self): self.topic_name_check() self.db_name_check() self.stream_name_check() + self.table_name_check() def stop(self): tdSql.close() tdLog.success("%s successfully executed" % __file__)