Merge branch '3.0' of https://github.com/taosdata/TDengine into fix/TS-4331-3.0

This commit is contained in:
Hongze Cheng 2024-07-05 14:31:39 +08:00
commit 9c5dbab91e
16 changed files with 134 additions and 26 deletions

View File

@ -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.

View File

@ -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

View File

@ -459,7 +459,7 @@ SELECT ... FROM (SELECT ... FROM ...) ...;
:::info
- 内层查询的返回结果将作为“虚拟表”供外层查询使用,此虚拟表建议起别名,以便于外层查询中方便引用。
- 外层查询支持直接通过列名或`列名`的形式引用内层查询的列或伪列。
- 外层查询支持直接通过列名或\`列名\`的形式引用内层查询的列或伪列。
- 在内层和外层查询中,都支持普通的表间/超级表间 JOIN。内层查询的计算结果也可以再参与数据子表的 JOIN 操作。
- 内层查询支持的功能特性与非嵌套的查询语句能力是一致的。
- 内层查询的 ORDER BY 子句一般没有意义,建议避免这样的写法以免无谓的资源消耗。

View File

@ -20,7 +20,7 @@ description: TDengine 中使用转义字符的详细规则
## 转义字符使用规则
1. 标识符里有转义字符(数据库名、表名、列名)
1. 标识符里有转义字符(数据库名、表名、列名、别名
1. 普通标识符: 直接提示错误的标识符,因为标识符规定必须是数字、字母和下划线,并且不能以数字开头。
2. 反引号``标识符: 保持原样,不转义
2. 数据里有转义字符

View File

@ -1,7 +0,0 @@
## 3.3.2.0 版本说明
### 新特性
### 优化
### 修复问题

View File

@ -0,0 +1,11 @@
---
title: 3.3.2.0 版本说明
sidebar_label: 3.3.2.0
description: 3.3.2.0 版本说明
---
### 新特性
### 优化
### 修复问题

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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;

View File

@ -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) {

View File

@ -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;

View File

@ -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())

View File

@ -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

View File

@ -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__)