fix(stmt2):stmt2 get fields return wrong when tag is value (#30283)
* ci: add 3.3.6 branch * fix: delete taos-tools repo in Jenkinsfile2 * ci:add 3.3.6 branch to taosd-ci.yml * fix: [TD-34074] compile error (#30220) * fix: add case * fix: stmt2 get fields return wrong when tag is value * enh: replace preCtb bool to flag,handle more situation * fix: some unit test error * diff: add case and fix some problem * fix: remove async test, handle in TD-34077 * fix: [TD-34074] Forbid virtual table in tq and stmt and forbid supertable query's origin table from different databases. fix: [TD-34074] Forbid virtual table in tq and stmt and forbid supertable query's origin table from different databases. * fix(sml): process space in the end if writing raw data in sml & change some log level #30306 fix(sml): process space in the end if writing raw data in sml & change some log level * fix: taosadapter version 3.3.6 (#30324) * docs(stream): document streaming computation support for virtual tables in user manual (#30319) * docs(stream): document streaming computation support for virtual tables in user manual - Added section to user manual describing streaming computation support for virtual tables - Listed known limitations and behavior when using virtual tables in streaming mode * Update 14-stream.md --------- Co-authored-by: Pan Wei <72057773+dapan1121@users.noreply.github.com> * fix: review * ci: add tdgpt .c file into TDengine and TDgpt workflow * ci: add tdgpt .c file into TDengine and TDgpt workflow --------- Signed-off-by: WANG Xu <feici02@outlook.com> Co-authored-by: WANG Xu <feici02@outlook.com> Co-authored-by: haoranchen <haoran920c@163.com> Co-authored-by: Simon Guan <slguan@taosdata.com> Co-authored-by: Feng Chao <flyingangel_2008@163.com> Co-authored-by: facetosea <285808407@qq.com> Co-authored-by: Jing Sima <simondominic9997@outlook.com> Co-authored-by: Jinqing Kuang <kuangjinqingcn@gmail.com> Co-authored-by: dapan1121 <wpan@taosdata.com> Co-authored-by: Pan Wei <72057773+dapan1121@users.noreply.github.com> Co-authored-by: Haojun Liao <hjxilinx@users.noreply.github.com> Co-authored-by: huohong <346479823@qq.com> Co-authored-by: Minglei Jin <mljin@taosdata.com> Co-authored-by: freemine <freemine@yeah.net> Co-authored-by: Yihao Deng <luomoxyz@126.com> Co-authored-by: 54liuyao <54liuyao@163.com> Co-authored-by: Bomin Zhang <localvar@hotmail.com> Co-authored-by: 蟑螂·魂 <cockroach888@outlook.com> Co-authored-by: wangjiaming <wangjiaming0909@sina.com> Co-authored-by: Haojun Liao <hjliao@taosdata.com> Co-authored-by: dongming chen <cademfly@hotmail.com> Co-authored-by: Zhiyu Yang <69311263+zyyang90@users.noreply.github.com> Co-authored-by: Nie Minhui <143420805+minhuinie@users.noreply.github.com> Co-authored-by: Zhixiao Bao <62235797+xiao-77@users.noreply.github.com> Co-authored-by: Kaili Xu <klxu@taosdata.com> Co-authored-by: Linhe Huo <linhehuo@gmail.com> Co-authored-by: tjuzyp <ypzhang@taosdata.com> Co-authored-by: yanyuxing <yuxing.bitcapybara@gmail.com> Co-authored-by: WANG MINGMING <wangmm0220@gmail.com> Co-authored-by: yihaoDeng <yhdeng@taosdata.com> Co-authored-by: facetosea <25808407@qq.com> Co-authored-by: Minglei Jin <49711132+stephenkgu@users.noreply.github.com> Co-authored-by: She Yanjie <57549981+sheyanjie-qq@users.noreply.github.com> Co-authored-by: jiajingbin <39030567+jiajingbin@users.noreply.github.com> Co-authored-by: Alex Duan <51781608+DuanKuanJun@users.noreply.github.com> Co-authored-by: kevin men <men_shi_bin@163.com> Co-authored-by: Hongze Cheng <hzcheng@taosdata.com> Co-authored-by: Yaming Pei <sanwenyuv@sina.com> Co-authored-by: Xuefeng Tan <1172915550@qq.com>
This commit is contained in:
parent
d00f5e332d
commit
c625106609
|
@ -6,6 +6,7 @@ on:
|
|||
- 'main'
|
||||
- '3.0'
|
||||
- '3.1'
|
||||
- '3.3.6'
|
||||
paths-ignore:
|
||||
- 'packaging/**'
|
||||
- 'docs/**'
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
# taosadapter
|
||||
ExternalProject_Add(taosadapter
|
||||
GIT_REPOSITORY https://github.com/taosdata/taosadapter.git
|
||||
GIT_TAG 3.0
|
||||
GIT_TAG 3.3.6
|
||||
SOURCE_DIR "${TD_SOURCE_DIR}/tools/taosadapter"
|
||||
BINARY_DIR ""
|
||||
#BUILD_IN_SOURCE TRUE
|
||||
|
|
|
@ -532,6 +532,24 @@ These fields are present only when "windowType" is "Count".
|
|||
#### Fields for Window Invalidation
|
||||
|
||||
Due to scenarios such as data disorder, updates, or deletions during stream computing, windows that have already been generated might be removed or their results need to be recalculated. In such cases, a notification with the eventType "WINDOW_INVALIDATION" is sent to inform which windows have been invalidated.
|
||||
|
||||
For events with "eventType" as "WINDOW_INVALIDATION", the following fields are included:
|
||||
1. "windowStart": A long integer timestamp representing the start time of the window.
|
||||
1. "windowEnd": A long integer timestamp representing the end time of the window.
|
||||
|
||||
## Support for Virtual Tables in Stream Computing
|
||||
|
||||
Starting with v3.3.6.0, stream computing can use virtual tables—including virtual regular tables, virtual sub-tables, and virtual super tables—as data sources for computation. The syntax is identical to that for non‑virtual tables.
|
||||
|
||||
However, because the behavior of virtual tables differs from that of non‑virtual tables, the following restrictions apply when using stream computing:
|
||||
|
||||
1. The schema of virtual regular tables/virtual sub-tables involved in stream computing cannot be modified.
|
||||
1. During stream computing, if the data source corresponding to a column in a virtual table is changed, the stream computation will not pick up the change; it will still read from the old data source.
|
||||
1. During stream computing, if the original table corresponding to a column in a virtual table is deleted and later a new table with the same name and a column with the same name is created, the stream computation will not read data from the new table.
|
||||
1. The watermark for stream computing must be 0; otherwise, an error will occur during creation.
|
||||
1. If the data source for stream computing is a virtual super table, sub-tables that are added after the stream computing task starts will not participate in the computation.
|
||||
1. The timestamps of different underlying tables in a virtual table may not be completely consistent; merging the data might produce null values, and interpolation is currently not supported.
|
||||
1. Out-of-order data, updates, or deletions are not handled. In other words, when creating a stream, you cannot specify `ignore update 0` or `ignore expired 0`; otherwise, an error will be reported.
|
||||
1. Historical data computation is not supported. That is, when creating a stream, you cannot specify `fill_history 1`; otherwise, an error will be reported.
|
||||
1. The trigger modes MAX_DELAY, CONTINUOUS_WINDOW_CLOSE and FORCE_WINDOW_CLOSE are not supported.
|
||||
1. The COUNT_WINDOW type is not supported.
|
||||
|
|
|
@ -527,6 +527,24 @@ CREATE STREAM avg_current_stream FILL_HISTORY 1
|
|||
#### 窗口失效相关字段
|
||||
|
||||
因为流计算过程中会遇到数据乱序、更新、删除等情况,可能造成已生成的窗口被删除,或者结果需要重新计算。此时会向通知地址发送一条 WINDOW_INVALIDATION 的通知,说明哪些窗口已经被删除。
|
||||
|
||||
这部分是 eventType 为 WINDOW_INVALIDATION 时,event 对象才有的字段。
|
||||
1. windowStart:长整型时间戳,表示窗口的开始时间,精度与结果表的时间精度一致。
|
||||
1. windowEnd: 长整型时间戳,表示窗口的结束时间,精度与结果表的时间精度一致。
|
||||
|
||||
## 流式计算对虚拟表的支持
|
||||
|
||||
从 v3.3.6.0 开始,流计算能够使用虚拟表(包括虚拟普通表、虚拟子表、虚拟超级表)作为数据源进行计算,语法和非虚拟表完全一致。
|
||||
|
||||
但是虚拟表的行为与非虚拟表存在差异,所以目前在使用流计算对虚拟表进行计算时存在以下限制:
|
||||
|
||||
1. 流计算中涉及的虚拟普通表/虚拟子表的 schema 不允许更改。
|
||||
1. 流计算过程中,如果修改虚拟表某一列对应的数据源,对流计算来说不生效。即:流计算仍只读取老的数据源。
|
||||
1. 流计算过程中,如果虚拟表某一列对应的原始表被删除,之后新建了同名的表和同名的列,流计算不会读取新表的数据。
|
||||
1. 流计算的 watermark 只能是 0,否则创建时就报错。
|
||||
1. 如果流计算的数据源是虚拟超级表,流计算任务启动后新增的子表不参与计算。
|
||||
1. 虚拟表的不同原始表的时间戳不完全一致,数据合并后可能会产生空值,暂不支持插值处理。
|
||||
1. 不处理数据的乱序、更新或删除。即:流创建时不能指定 `ignore update 0` 或者 `ignore expired 0`,否则报错。
|
||||
1. 不支持历史数据计算,即:流创建时不能指定 `fill_history 1`,否则报错。
|
||||
1. 不支持触发模式:MAX_DELAY, FORCE_WINDOW_CLOSE, CONTINUOUS_WINDOW_CLOSE。
|
||||
1. 不支持窗口类型:COUNT_WINDOW。
|
||||
|
|
|
@ -49,10 +49,16 @@ extern "C" {
|
|||
} \
|
||||
} while (0)
|
||||
|
||||
#define HAS_BIND_VALUE ((uint8_t)0x1)
|
||||
#define IS_FIXED_VALUE ((uint8_t)0x2)
|
||||
#define USING_CLAUSE ((uint8_t)0x4)
|
||||
#define IS_FIXED_TAG ((uint8_t)0x8)
|
||||
#define NO_DATA_USING_CLAUSE ((uint8_t)0x7)
|
||||
|
||||
typedef struct SStmtCallback {
|
||||
TAOS_STMT* pStmt;
|
||||
int32_t (*getTbNameFn)(TAOS_STMT*, char**);
|
||||
int32_t (*setInfoFn)(TAOS_STMT*, STableMeta*, void*, SName*, bool, SHashObj*, SHashObj*, const char*, bool);
|
||||
int32_t (*setInfoFn)(TAOS_STMT*, STableMeta*, void*, SName*, bool, SHashObj*, SHashObj*, const char*, uint8_t);
|
||||
int32_t (*getExecInfoFn)(TAOS_STMT*, SHashObj**, SHashObj**);
|
||||
} SStmtCallback;
|
||||
|
||||
|
@ -175,7 +181,7 @@ int32_t qBindStmtColsValue(void* pBlock, SArray* pCols, TAOS_MULTI_BIND* bind, c
|
|||
int32_t qBindStmtSingleColValue(void* pBlock, SArray* pCols, TAOS_MULTI_BIND* bind, char* msgBuf, int32_t msgBufLen,
|
||||
int32_t colIdx, int32_t rowNum, void* charsetCxt);
|
||||
int32_t qBuildStmtColFields(void* pDataBlock, int32_t* fieldNum, TAOS_FIELD_E** fields);
|
||||
int32_t qBuildStmtStbColFields(void* pBlock, void* boundTags, bool hasCtbName, int32_t* fieldNum,
|
||||
int32_t qBuildStmtStbColFields(void* pBlock, void* boundTags, uint8_t tbNameFlag, int32_t* fieldNum,
|
||||
TAOS_FIELD_ALL** fields);
|
||||
int32_t qBuildStmtTagFields(void* pBlock, void* boundTags, int32_t* fieldNum, TAOS_FIELD_E** fields);
|
||||
int32_t qBindStmtTagsValue(void* pBlock, void* boundTags, int64_t suid, const char* sTableName, char* tName,
|
||||
|
|
|
@ -64,7 +64,7 @@ typedef struct SStmtBindInfo {
|
|||
int32_t sBindLastIdx;
|
||||
int8_t tbType;
|
||||
bool tagsCached;
|
||||
bool preCtbname;
|
||||
uint8_t tbNameFlag;
|
||||
void *boundTags;
|
||||
char tbName[TSDB_TABLE_FNAME_LEN];
|
||||
char tbFName[TSDB_TABLE_FNAME_LEN];
|
||||
|
|
|
@ -75,7 +75,7 @@ static int32_t smlProcessTagTelnet(SSmlHandle *info, char *data, char *sqlEnd){
|
|||
const char *sql = data;
|
||||
while (sql < sqlEnd) {
|
||||
JUMP_SPACE(sql, sqlEnd)
|
||||
if (unlikely(*sql == '\0')) break;
|
||||
if (unlikely(*sql == '\0' || *sql == '\n')) break;
|
||||
|
||||
const char *key = sql;
|
||||
size_t keyLen = 0;
|
||||
|
|
|
@ -238,7 +238,7 @@ int32_t stmtRestoreQueryFields(STscStmt* pStmt) {
|
|||
}
|
||||
*/
|
||||
int32_t stmtUpdateBindInfo(TAOS_STMT* stmt, STableMeta* pTableMeta, void* tags, SName* tbName, const char* sTableName,
|
||||
bool autoCreateTbl) {
|
||||
bool autoCreateTbl, uint8_t tbNameFlag) {
|
||||
STscStmt* pStmt = (STscStmt*)stmt;
|
||||
char tbFName[TSDB_TABLE_FNAME_LEN];
|
||||
int32_t code = tNameExtractFullName(tbName, tbFName);
|
||||
|
@ -256,6 +256,7 @@ int32_t stmtUpdateBindInfo(TAOS_STMT* stmt, STableMeta* pTableMeta, void* tags,
|
|||
pStmt->bInfo.tbType = pTableMeta->tableType;
|
||||
pStmt->bInfo.boundTags = tags;
|
||||
pStmt->bInfo.tagsCached = false;
|
||||
pStmt->bInfo.tbNameFlag = tbNameFlag;
|
||||
tstrncpy(pStmt->bInfo.stbFName, sTableName, sizeof(pStmt->bInfo.stbFName));
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
|
@ -271,10 +272,10 @@ int32_t stmtUpdateExecInfo(TAOS_STMT* stmt, SHashObj* pVgHash, SHashObj* pBlockH
|
|||
}
|
||||
|
||||
int32_t stmtUpdateInfo(TAOS_STMT* stmt, STableMeta* pTableMeta, void* tags, SName* tbName, bool autoCreateTbl,
|
||||
SHashObj* pVgHash, SHashObj* pBlockHash, const char* sTableName, bool preCtbname) {
|
||||
SHashObj* pVgHash, SHashObj* pBlockHash, const char* sTableName, uint8_t tbNameFlag) {
|
||||
STscStmt* pStmt = (STscStmt*)stmt;
|
||||
|
||||
STMT_ERR_RET(stmtUpdateBindInfo(stmt, pTableMeta, tags, tbName, sTableName, autoCreateTbl));
|
||||
STMT_ERR_RET(stmtUpdateBindInfo(stmt, pTableMeta, tags, tbName, sTableName, autoCreateTbl, tbNameFlag));
|
||||
STMT_ERR_RET(stmtUpdateExecInfo(stmt, pVgHash, pBlockHash));
|
||||
|
||||
pStmt->sql.autoCreateTbl = autoCreateTbl;
|
||||
|
@ -1729,7 +1730,10 @@ int stmtGetTagFields(TAOS_STMT* stmt, int* nums, TAOS_FIELD_E** fields) {
|
|||
STMT_ERRI_JRET(stmtFetchTagFields(stmt, nums, fields));
|
||||
|
||||
_return:
|
||||
|
||||
// compatible with previous versions
|
||||
if (code == TSDB_CODE_PAR_TABLE_NOT_EXIST && (pStmt->bInfo.tbNameFlag & NO_DATA_USING_CLAUSE) == 0x0) {
|
||||
code = TSDB_CODE_TSC_STMT_TBNAME_ERROR;
|
||||
}
|
||||
pStmt->errCode = preCode;
|
||||
|
||||
return code;
|
||||
|
|
|
@ -193,7 +193,7 @@ static int32_t stmtGetTbName(TAOS_STMT2* stmt, char** tbName) {
|
|||
}
|
||||
|
||||
static int32_t stmtUpdateBindInfo(TAOS_STMT2* stmt, STableMeta* pTableMeta, void* tags, SName* tbName,
|
||||
const char* sTableName, bool autoCreateTbl, bool preCtbname) {
|
||||
const char* sTableName, bool autoCreateTbl, int8_t tbNameFlag) {
|
||||
STscStmt2* pStmt = (STscStmt2*)stmt;
|
||||
char tbFName[TSDB_TABLE_FNAME_LEN];
|
||||
int32_t code = tNameExtractFullName(tbName, tbFName);
|
||||
|
@ -217,7 +217,7 @@ static int32_t stmtUpdateBindInfo(TAOS_STMT2* stmt, STableMeta* pTableMeta, void
|
|||
|
||||
pStmt->bInfo.boundTags = tags;
|
||||
pStmt->bInfo.tagsCached = false;
|
||||
pStmt->bInfo.preCtbname = preCtbname;
|
||||
pStmt->bInfo.tbNameFlag = tbNameFlag;
|
||||
tstrncpy(pStmt->bInfo.stbFName, sTableName, sizeof(pStmt->bInfo.stbFName));
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
|
@ -233,10 +233,10 @@ static int32_t stmtUpdateExecInfo(TAOS_STMT2* stmt, SHashObj* pVgHash, SHashObj*
|
|||
}
|
||||
|
||||
static int32_t stmtUpdateInfo(TAOS_STMT2* stmt, STableMeta* pTableMeta, void* tags, SName* tbName, bool autoCreateTbl,
|
||||
SHashObj* pVgHash, SHashObj* pBlockHash, const char* sTableName, bool preCtbname) {
|
||||
SHashObj* pVgHash, SHashObj* pBlockHash, const char* sTableName, uint8_t tbNameFlag) {
|
||||
STscStmt2* pStmt = (STscStmt2*)stmt;
|
||||
|
||||
STMT_ERR_RET(stmtUpdateBindInfo(stmt, pTableMeta, tags, tbName, sTableName, autoCreateTbl, preCtbname));
|
||||
STMT_ERR_RET(stmtUpdateBindInfo(stmt, pTableMeta, tags, tbName, sTableName, autoCreateTbl, tbNameFlag));
|
||||
STMT_ERR_RET(stmtUpdateExecInfo(stmt, pVgHash, pBlockHash));
|
||||
|
||||
pStmt->sql.autoCreateTbl = autoCreateTbl;
|
||||
|
@ -1233,7 +1233,8 @@ static int stmtFetchStbColFields2(STscStmt2* pStmt, int32_t* fieldNum, TAOS_FIEL
|
|||
}
|
||||
|
||||
STMT_ERRI_JRET(
|
||||
qBuildStmtStbColFields(*pDataBlock, pStmt->bInfo.boundTags, pStmt->bInfo.preCtbname, fieldNum, fields));
|
||||
qBuildStmtStbColFields(*pDataBlock, pStmt->bInfo.boundTags, pStmt->bInfo.tbNameFlag, fieldNum, fields));
|
||||
|
||||
if (pStmt->bInfo.tbType == TSDB_SUPER_TABLE && cleanStb) {
|
||||
pStmt->bInfo.needParse = true;
|
||||
qDestroyStmtDataBlock(*pDataBlock);
|
||||
|
@ -2022,7 +2023,9 @@ int stmtParseColFields2(TAOS_STMT2* stmt) {
|
|||
STMT_TYPE_MULTI_INSERT != pStmt->sql.type) {
|
||||
pStmt->bInfo.needParse = false;
|
||||
}
|
||||
|
||||
if (pStmt->sql.stbInterlaceMode && pStmt->sql.siInfo.pDataCtx != NULL) {
|
||||
pStmt->bInfo.needParse = false;
|
||||
}
|
||||
if (pStmt->exec.pRequest && STMT_TYPE_QUERY == pStmt->sql.type && pStmt->sql.runTimes) {
|
||||
taos_free_result(pStmt->exec.pRequest);
|
||||
pStmt->exec.pRequest = NULL;
|
||||
|
@ -2036,6 +2039,10 @@ int stmtParseColFields2(TAOS_STMT2* stmt) {
|
|||
}
|
||||
|
||||
_return:
|
||||
// compatible with previous versions
|
||||
if (code == TSDB_CODE_PAR_TABLE_NOT_EXIST && (pStmt->bInfo.tbNameFlag & NO_DATA_USING_CLAUSE) == 0x0) {
|
||||
code = TSDB_CODE_TSC_STMT_TBNAME_ERROR;
|
||||
}
|
||||
|
||||
pStmt->errCode = preCode;
|
||||
|
||||
|
|
|
@ -534,7 +534,7 @@ TEST(stmt2Case, insert_ctb_using_get_fields_Test) {
|
|||
printf("support case \n");
|
||||
// case 1 : test child table already exist
|
||||
{
|
||||
const char* sql = "INSERT INTO stmt2_testdb_3.t0(ts,b)using stmt2_testdb_3.stb (t1,t2) TAGS(?,?) VALUES (?,?)";
|
||||
const char* sql = "INSERT INTO stmt2_testdb_3.t0(ts,b)using stmt2_testdb_3.stb (t1,t2) TAGS(?,?) VALUES(?,?)";
|
||||
TAOS_FIELD_ALL expectedFields[4] = {{"t1", TSDB_DATA_TYPE_INT, 0, 0, 4, TAOS_FIELD_TAG},
|
||||
{"t2", TSDB_DATA_TYPE_BINARY, 0, 0, 12, TAOS_FIELD_TAG},
|
||||
{"ts", TSDB_DATA_TYPE_TIMESTAMP, 2, 0, 8, TAOS_FIELD_COL},
|
||||
|
@ -612,7 +612,7 @@ TEST(stmt2Case, insert_ctb_using_get_fields_Test) {
|
|||
|
||||
// case 8 : 'db' 'stb'
|
||||
{
|
||||
const char* sql = "INSERT INTO 'stmt2_testdb_3'.? using 'stmt2_testdb_3'.'stb' (t1,t2) TAGS(?,?) (ts,b)VALUES(?,?)";
|
||||
const char* sql = "INSERT INTO 'stmt2_testdb_3'.? using 'stmt2_testdb_3'.'stb' (t1,t2) TAGS(?,?)(ts,b)VALUES(?,?)";
|
||||
TAOS_FIELD_ALL expectedFields[5] = {{"tbname", TSDB_DATA_TYPE_BINARY, 0, 0, 271, TAOS_FIELD_TBNAME},
|
||||
{"t1", TSDB_DATA_TYPE_INT, 0, 0, 4, TAOS_FIELD_TAG},
|
||||
{"t2", TSDB_DATA_TYPE_BINARY, 0, 0, 12, TAOS_FIELD_TAG},
|
||||
|
@ -634,9 +634,20 @@ TEST(stmt2Case, insert_ctb_using_get_fields_Test) {
|
|||
printf("case 9 : %s\n", sql);
|
||||
getFieldsSuccess(taos, sql, expectedFields, 5);
|
||||
}
|
||||
// case 11: TD-34097
|
||||
{
|
||||
do_query(taos, "use stmt2_testdb_3");
|
||||
const char* sql = "INSERT INTO ? using stb (t1,t2) TAGS(1,'abc') (ts,b)VALUES(?,?)";
|
||||
TAOS_FIELD_ALL expectedFields[3] = {{"tbname", TSDB_DATA_TYPE_BINARY, 0, 0, 271, TAOS_FIELD_TBNAME},
|
||||
{"ts", TSDB_DATA_TYPE_TIMESTAMP, 2, 0, 8, TAOS_FIELD_COL},
|
||||
{"b", TSDB_DATA_TYPE_BINARY, 0, 0, 12, TAOS_FIELD_COL}};
|
||||
printf("case 11 : %s\n", sql);
|
||||
getFieldsSuccess(taos, sql, expectedFields, 3);
|
||||
}
|
||||
|
||||
// case 10 : test all types
|
||||
{
|
||||
do_query(taos, "use stmt2_testdb_3");
|
||||
const char* sql =
|
||||
"insert into ? using all_stb tags(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
|
||||
TAOS_FIELD_ALL expectedFields[33] = {{"tbname", TSDB_DATA_TYPE_BINARY, 0, 0, 271, TAOS_FIELD_TBNAME},
|
||||
|
@ -711,7 +722,27 @@ TEST(stmt2Case, insert_ctb_using_get_fields_Test) {
|
|||
printf("case 5 : %s\n", sql);
|
||||
getFieldsError(taos, sql, TSDB_CODE_TSC_SQL_SYNTAX_ERROR);
|
||||
}
|
||||
|
||||
// case 6 : mix value and ?
|
||||
{
|
||||
do_query(taos, "use stmt2_testdb_3");
|
||||
const char* sql = "INSERT INTO ? using stb (t1,t2) TAGS(1,?) (ts,b)VALUES(?,?)";
|
||||
printf("case 6 : %s\n", sql);
|
||||
getFieldsError(taos, sql, TSDB_CODE_TSC_SQL_SYNTAX_ERROR);
|
||||
}
|
||||
// case 7 : mix value and ?
|
||||
{
|
||||
do_query(taos, "use stmt2_testdb_3");
|
||||
const char* sql = "INSERT INTO ? using stb (t1,t2) TAGS(?,?) (ts,b)VALUES(15910606280001,?)";
|
||||
printf("case 7 : %s\n", sql);
|
||||
getFieldsError(taos, sql, TSDB_CODE_TSC_INVALID_OPERATION);
|
||||
}
|
||||
// case 8 : mix value and ?
|
||||
{
|
||||
do_query(taos, "use stmt2_testdb_3");
|
||||
const char* sql = "INSERT INTO ? using stb (t1,t2) TAGS(?,?) (ts,b)VALUES(15910606280001,'abc')";
|
||||
printf("case 8 : %s\n", sql);
|
||||
getFieldsError(taos, sql, TSDB_CODE_TSC_INVALID_OPERATION);
|
||||
}
|
||||
do_query(taos, "drop database if exists stmt2_testdb_3");
|
||||
taos_close(taos);
|
||||
}
|
||||
|
@ -1002,6 +1033,15 @@ TEST(stmt2Case, stmt2_insert_non_statndard) {
|
|||
printf("stmt2 [%s] : %s\n", "less params", sql);
|
||||
int code = taos_stmt2_prepare(stmt, sql, 0);
|
||||
checkError(stmt, code);
|
||||
// test get fields
|
||||
int fieldNum = 0;
|
||||
TAOS_FIELD_ALL* pFields = NULL;
|
||||
code = taos_stmt2_get_fields(stmt, &fieldNum, &pFields);
|
||||
checkError(stmt, code);
|
||||
ASSERT_EQ(fieldNum, 2);
|
||||
ASSERT_STREQ(pFields[0].name, "tbname");
|
||||
ASSERT_STREQ(pFields[1].name, "ts");
|
||||
|
||||
int total_affect_rows = 0;
|
||||
|
||||
int t64_len[2] = {sizeof(int64_t), sizeof(int64_t)};
|
||||
|
@ -1024,11 +1064,22 @@ TEST(stmt2Case, stmt2_insert_non_statndard) {
|
|||
code = taos_stmt2_bind_param(stmt, &bindv, -1);
|
||||
checkError(stmt, code);
|
||||
|
||||
code = taos_stmt2_get_fields(stmt, &fieldNum, &pFields);
|
||||
checkError(stmt, code);
|
||||
ASSERT_EQ(fieldNum, 2);
|
||||
ASSERT_STREQ(pFields[0].name, "tbname");
|
||||
ASSERT_STREQ(pFields[1].name, "ts");
|
||||
|
||||
int affected_rows;
|
||||
taos_stmt2_exec(stmt, &affected_rows);
|
||||
total_affect_rows += affected_rows;
|
||||
|
||||
checkError(stmt, code);
|
||||
|
||||
code = taos_stmt2_get_fields(stmt, &fieldNum, &pFields);
|
||||
checkError(stmt, code);
|
||||
ASSERT_EQ(fieldNum, 2);
|
||||
ASSERT_STREQ(pFields[0].name, "tbname");
|
||||
ASSERT_STREQ(pFields[1].name, "ts");
|
||||
}
|
||||
|
||||
ASSERT_EQ(total_affect_rows, 12);
|
||||
|
@ -1959,27 +2010,27 @@ void stmt2_async_test(std::atomic<bool>& stop_task) {
|
|||
stop_task = true;
|
||||
}
|
||||
|
||||
TEST(stmt2Case, async_order) {
|
||||
std::atomic<bool> stop_task(false);
|
||||
std::thread t(stmt2_async_test, std::ref(stop_task));
|
||||
// TEST(stmt2Case, async_order) {
|
||||
// std::atomic<bool> stop_task(false);
|
||||
// std::thread t(stmt2_async_test, std::ref(stop_task));
|
||||
|
||||
// 等待 60 秒钟
|
||||
auto start_time = std::chrono::steady_clock::now();
|
||||
while (!stop_task) {
|
||||
auto elapsed_time = std::chrono::steady_clock::now() - start_time;
|
||||
if (std::chrono::duration_cast<std::chrono::seconds>(elapsed_time).count() > 100) {
|
||||
if (t.joinable()) {
|
||||
t.detach();
|
||||
}
|
||||
FAIL() << "Test[stmt2_async_test] timed out";
|
||||
break;
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1)); // 每 1s 检查一次
|
||||
}
|
||||
if (t.joinable()) {
|
||||
t.join();
|
||||
}
|
||||
}
|
||||
// // 等待 60 秒钟
|
||||
// auto start_time = std::chrono::steady_clock::now();
|
||||
// while (!stop_task) {
|
||||
// auto elapsed_time = std::chrono::steady_clock::now() - start_time;
|
||||
// if (std::chrono::duration_cast<std::chrono::seconds>(elapsed_time).count() > 100) {
|
||||
// if (t.joinable()) {
|
||||
// t.detach();
|
||||
// }
|
||||
// FAIL() << "Test[stmt2_async_test] timed out";
|
||||
// break;
|
||||
// }
|
||||
// std::this_thread::sleep_for(std::chrono::seconds(1)); // 每 1s 检查一次
|
||||
// }
|
||||
// if (t.joinable()) {
|
||||
// t.join();
|
||||
// }
|
||||
// }
|
||||
|
||||
TEST(stmt2Case, rowformat_bind) {
|
||||
TAOS* taos = taos_connect("localhost", "root", "taosdata", "", 0);
|
||||
|
|
|
@ -32,7 +32,7 @@ typedef struct SInsertParseContext {
|
|||
bool needTableTagVal;
|
||||
bool needRequest; // whether or not request server
|
||||
bool isStmtBind; // whether is stmt bind
|
||||
bool preCtbname;
|
||||
uint8_t stmtTbNameFlag;
|
||||
} SInsertParseContext;
|
||||
|
||||
typedef int32_t (*_row_append_fn_t)(SMsgBuf* pMsgBuf, const void* value, int32_t len, void* param);
|
||||
|
@ -993,6 +993,10 @@ static int32_t parseTagsClauseImpl(SInsertParseContext* pCxt, SVnodeModifyOpStmt
|
|||
code = buildSyntaxErrMsg(&pCxt->msg, "? only used in stmt", token.z);
|
||||
break;
|
||||
}
|
||||
if (pTagVals->size != 0) {
|
||||
code = buildSyntaxErrMsg(&pCxt->msg, "no mix usage for ? and tag values", token.z);
|
||||
break;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
@ -1026,6 +1030,10 @@ static int32_t parseTagsClauseImpl(SInsertParseContext* pCxt, SVnodeModifyOpStmt
|
|||
pTag = NULL;
|
||||
}
|
||||
|
||||
if (code == TSDB_CODE_SUCCESS && !isParseBindParam) {
|
||||
pCxt->stmtTbNameFlag |= IS_FIXED_TAG;
|
||||
}
|
||||
|
||||
_exit:
|
||||
for (int32_t i = 0; i < taosArrayGetSize(pTagVals); ++i) {
|
||||
STagVal* p = (STagVal*)TARRAY_GET_ELEM(pTagVals, i);
|
||||
|
@ -1416,6 +1424,7 @@ static int32_t parseUsingTableName(SInsertParseContext* pCxt, SVnodeModifyOpStmt
|
|||
return getTargetTableSchema(pCxt, pStmt);
|
||||
}
|
||||
pStmt->usingTableProcessing = true;
|
||||
pCxt->stmtTbNameFlag |= USING_CLAUSE;
|
||||
// pStmt->pSql -> stb_name [(tag1_name, ...)
|
||||
pStmt->pSql += index;
|
||||
int32_t code = parseDuplicateUsingClause(pCxt, pStmt, &pCxt->usingDuplicateTable);
|
||||
|
@ -1465,7 +1474,7 @@ static int32_t getTableDataCxt(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pS
|
|||
|
||||
char tbFName[TSDB_TABLE_FNAME_LEN];
|
||||
int32_t code = 0;
|
||||
if (pCxt->preCtbname) {
|
||||
if ((pCxt->stmtTbNameFlag & NO_DATA_USING_CLAUSE) == USING_CLAUSE) {
|
||||
tstrncpy(pStmt->targetTableName.tname, pStmt->usingTableName.tname, sizeof(pStmt->targetTableName.tname));
|
||||
tstrncpy(pStmt->targetTableName.dbname, pStmt->usingTableName.dbname, sizeof(pStmt->targetTableName.dbname));
|
||||
pStmt->targetTableName.type = TSDB_SUPER_TABLE;
|
||||
|
@ -2764,6 +2773,7 @@ static int32_t checkTableClauseFirstToken(SInsertParseContext* pCxt, SVnodeModif
|
|||
}
|
||||
|
||||
if (TK_NK_QUESTION == pTbName->type) {
|
||||
pCxt->stmtTbNameFlag &= ~IS_FIXED_VALUE;
|
||||
pCxt->isStmtBind = true;
|
||||
if (NULL == pCxt->pComCxt->pStmtCb) {
|
||||
return buildSyntaxErrMsg(&pCxt->msg, "? only used in stmt", pTbName->z);
|
||||
|
@ -2772,14 +2782,15 @@ static int32_t checkTableClauseFirstToken(SInsertParseContext* pCxt, SVnodeModif
|
|||
char* tbName = NULL;
|
||||
int32_t code = (*pCxt->pComCxt->pStmtCb->getTbNameFn)(pCxt->pComCxt->pStmtCb->pStmt, &tbName);
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
pCxt->stmtTbNameFlag |= HAS_BIND_VALUE;
|
||||
pTbName->z = tbName;
|
||||
pTbName->n = strlen(tbName);
|
||||
} else if (code == TSDB_CODE_TSC_STMT_TBNAME_ERROR) {
|
||||
pCxt->preCtbname = true;
|
||||
code = TSDB_CODE_SUCCESS;
|
||||
} else {
|
||||
return code;
|
||||
}
|
||||
if (code == TSDB_CODE_TSC_STMT_TBNAME_ERROR) {
|
||||
pCxt->stmtTbNameFlag &= ~HAS_BIND_VALUE;
|
||||
code = TSDB_CODE_SUCCESS;
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
if (TK_NK_ID != pTbName->type && TK_NK_STRING != pTbName->type && TK_NK_QUESTION != pTbName->type) {
|
||||
|
@ -2788,26 +2799,34 @@ static int32_t checkTableClauseFirstToken(SInsertParseContext* pCxt, SVnodeModif
|
|||
|
||||
// db.? situation,ensure that the only thing following the '.' mark is '?'
|
||||
char* tbNameAfterDbName = strnchr(pTbName->z, '.', pTbName->n, true);
|
||||
if ((tbNameAfterDbName != NULL) && (*(tbNameAfterDbName + 1) == '?')) {
|
||||
char* tbName = NULL;
|
||||
if (NULL == pCxt->pComCxt->pStmtCb) {
|
||||
return buildSyntaxErrMsg(&pCxt->msg, "? only used in stmt", pTbName->z);
|
||||
}
|
||||
int32_t code = (*pCxt->pComCxt->pStmtCb->getTbNameFn)(pCxt->pComCxt->pStmtCb->pStmt, &tbName);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
pCxt->preCtbname = true;
|
||||
if (tbNameAfterDbName != NULL) {
|
||||
if (*(tbNameAfterDbName + 1) == '?') {
|
||||
pCxt->stmtTbNameFlag &= ~IS_FIXED_VALUE;
|
||||
char* tbName = NULL;
|
||||
if (NULL == pCxt->pComCxt->pStmtCb) {
|
||||
return buildSyntaxErrMsg(&pCxt->msg, "? only used in stmt", pTbName->z);
|
||||
}
|
||||
int32_t code = (*pCxt->pComCxt->pStmtCb->getTbNameFn)(pCxt->pComCxt->pStmtCb->pStmt, &tbName);
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
pCxt->stmtTbNameFlag |= HAS_BIND_VALUE;
|
||||
pTbName->z = tbName;
|
||||
pTbName->n = strlen(tbName);
|
||||
}
|
||||
if (code == TSDB_CODE_TSC_STMT_TBNAME_ERROR) {
|
||||
pCxt->stmtTbNameFlag &= ~HAS_BIND_VALUE;
|
||||
code = TSDB_CODE_SUCCESS;
|
||||
}
|
||||
} else {
|
||||
pTbName->z = tbName;
|
||||
pTbName->n = strlen(tbName);
|
||||
}
|
||||
}
|
||||
|
||||
if (pCxt->isStmtBind) {
|
||||
if (TK_NK_ID == pTbName->type || (tbNameAfterDbName != NULL && *(tbNameAfterDbName + 1) != '?')) {
|
||||
// In SQL statements, the table name has already been specified.
|
||||
pCxt->stmtTbNameFlag |= IS_FIXED_VALUE;
|
||||
parserWarn("QID:0x%" PRIx64 ", table name is specified in sql, ignore the table name in bind param",
|
||||
pCxt->pComCxt->requestId);
|
||||
*pHasData = true;
|
||||
}
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
if (TK_NK_ID == pTbName->type) {
|
||||
pCxt->stmtTbNameFlag |= IS_FIXED_VALUE;
|
||||
}
|
||||
|
||||
*pHasData = true;
|
||||
|
@ -2824,7 +2843,7 @@ static int32_t setStmtInfo(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt)
|
|||
SStmtCallback* pStmtCb = pCxt->pComCxt->pStmtCb;
|
||||
int32_t code = (*pStmtCb->setInfoFn)(pStmtCb->pStmt, pStmt->pTableMeta, tags, &pStmt->targetTableName,
|
||||
pStmt->usingTableProcessing, pStmt->pVgroupsHashObj, pStmt->pTableBlockHashObj,
|
||||
pStmt->usingTableName.tname, pCxt->preCtbname);
|
||||
pStmt->usingTableName.tname, pCxt->stmtTbNameFlag);
|
||||
|
||||
memset(&pCxt->tags, 0, sizeof(pCxt->tags));
|
||||
pStmt->pVgroupsHashObj = NULL;
|
||||
|
@ -2880,9 +2899,6 @@ static int32_t parseInsertBody(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pS
|
|||
if (TSDB_CODE_SUCCESS == code && hasData) {
|
||||
code = parseInsertTableClause(pCxt, pStmt, &token);
|
||||
}
|
||||
if (TSDB_CODE_PAR_TABLE_NOT_EXIST == code && pCxt->preCtbname) {
|
||||
code = TSDB_CODE_TSC_STMT_TBNAME_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (TSDB_CODE_SUCCESS == code && !pCxt->missCache) {
|
||||
|
|
|
@ -1070,10 +1070,11 @@ int32_t buildBoundFields(int32_t numOfBound, int16_t* boundColumns, SSchema* pSc
|
|||
}
|
||||
|
||||
int32_t buildStbBoundFields(SBoundColInfo boundColsInfo, SSchema* pSchema, int32_t* fieldNum, TAOS_FIELD_ALL** fields,
|
||||
STableMeta* pMeta, void* boundTags, bool preCtbname) {
|
||||
STableMeta* pMeta, void* boundTags, uint8_t tbNameFlag) {
|
||||
SBoundColInfo* tags = (SBoundColInfo*)boundTags;
|
||||
bool hastag = tags != NULL;
|
||||
int32_t numOfBound = boundColsInfo.numOfBound + (preCtbname ? 1 : 0);
|
||||
bool hastag = (tags != NULL) && !(tbNameFlag & IS_FIXED_TAG);
|
||||
int32_t numOfBound =
|
||||
boundColsInfo.numOfBound + ((tbNameFlag & IS_FIXED_VALUE) == 0 && (tbNameFlag & USING_CLAUSE) != 0 ? 1 : 0);
|
||||
if (hastag) {
|
||||
numOfBound += tags->mixTagsCols ? 0 : tags->numOfBound;
|
||||
}
|
||||
|
@ -1084,7 +1085,7 @@ int32_t buildStbBoundFields(SBoundColInfo boundColsInfo, SSchema* pSchema, int32
|
|||
return terrno;
|
||||
}
|
||||
|
||||
if (preCtbname && numOfBound != boundColsInfo.numOfBound) {
|
||||
if ((tbNameFlag & IS_FIXED_VALUE) == 0 && (tbNameFlag & USING_CLAUSE) != 0) {
|
||||
(*fields)[idx].field_type = TAOS_FIELD_TBNAME;
|
||||
tstrncpy((*fields)[idx].name, "tbname", sizeof((*fields)[idx].name));
|
||||
(*fields)[idx].type = TSDB_DATA_TYPE_BINARY;
|
||||
|
@ -1188,7 +1189,7 @@ int32_t qBuildStmtColFields(void* pBlock, int32_t* fieldNum, TAOS_FIELD_E** fiel
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t qBuildStmtStbColFields(void* pBlock, void* boundTags, bool preCtbname, int32_t* fieldNum,
|
||||
int32_t qBuildStmtStbColFields(void* pBlock, void* boundTags, uint8_t tbNameFlag, int32_t* fieldNum,
|
||||
TAOS_FIELD_ALL** fields) {
|
||||
STableDataCxt* pDataBlock = (STableDataCxt*)pBlock;
|
||||
SSchema* pSchema = getTableColumnSchema(pDataBlock->pMeta);
|
||||
|
@ -1202,7 +1203,7 @@ int32_t qBuildStmtStbColFields(void* pBlock, void* boundTags, bool preCtbname, i
|
|||
}
|
||||
|
||||
CHECK_CODE(buildStbBoundFields(pDataBlock->boundColsInfo, pSchema, fieldNum, fields, pDataBlock->pMeta, boundTags,
|
||||
preCtbname));
|
||||
tbNameFlag));
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -1029,7 +1029,7 @@ void mpUpdateSystemAvailableMemorySize() {
|
|||
|
||||
atomic_store_64(&tsCurrentAvailMemorySize, sysAvailSize);
|
||||
|
||||
uDebug("system available memory size: %" PRId64, sysAvailSize);
|
||||
uTrace("system available memory size: %" PRId64, sysAvailSize);
|
||||
}
|
||||
|
||||
void mpSchedTrim(int64_t* loopTimes) {
|
||||
|
|
|
@ -729,7 +729,7 @@ int32_t mptGetMemPoolMaxMemSize(void* pHandle, int64_t* maxSize) {
|
|||
}
|
||||
|
||||
if (TSDB_CODE_SUCCESS != code) {
|
||||
uError("get system avaiable memory size failed, error: 0x%x", code);
|
||||
uError("get system available memory size failed, error: 0x%x", code);
|
||||
return code;
|
||||
}
|
||||
|
||||
|
|
|
@ -87,7 +87,8 @@ int smlProcess_telnet_Test() {
|
|||
const char *sql1[] = {"sys.if.bytes.out 1479496100 1.3E0 host=web01 interface=eth0",
|
||||
"sys.if.bytes.out 1479496101 1.3E1 interface=eth0 host=web01 ",
|
||||
"sys.if.bytes.out 1479496102 1.3E3 network=tcp",
|
||||
" sys.procs.running 1479496100 42 host=web01 "};
|
||||
" sys.procs.running 1479496100 42 host=web01 ",
|
||||
" newline 1479496100 42 host=web\n01 t=fsb\n "};
|
||||
|
||||
// for(int i = 0; i < 4; i++){
|
||||
// strncpy(sql[i], sql1[i], 128);
|
||||
|
@ -2355,12 +2356,35 @@ int sml_td17324_Test() {
|
|||
return code;
|
||||
}
|
||||
|
||||
int smlProcess_34114_Test() {
|
||||
TAOS *taos = taos_connect("localhost", "root", "taosdata", NULL, 0);
|
||||
|
||||
TAOS_RES *pRes = taos_query(taos, "create database if not exists sml_34114_db schemaless 1");
|
||||
taos_free_result(pRes);
|
||||
|
||||
pRes = taos_query(taos, "use sml_34114_db");
|
||||
taos_free_result(pRes);
|
||||
|
||||
char *sql = {"sys.if.bytes.out 1479496100 1.3E0 host=web01 interface=eth0 \nsys.if.bytes.out 1479496101 1.3E1 interface=eth0 host=web01 "};
|
||||
int32_t totalRows = 0;
|
||||
pRes = taos_schemaless_insert_raw(taos, sql, strlen(sql), &totalRows, TSDB_SML_TELNET_PROTOCOL,
|
||||
TSDB_SML_TIMESTAMP_NANO_SECONDS);
|
||||
printf("%s result:%s\n", __FUNCTION__, taos_errstr(pRes));
|
||||
int code = taos_errno(pRes);
|
||||
taos_free_result(pRes);
|
||||
taos_close(taos);
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if (argc == 2) {
|
||||
taos_options(TSDB_OPTION_CONFIGDIR, argv[1]);
|
||||
}
|
||||
|
||||
int ret = smlProcess_json0_Test();
|
||||
int ret = smlProcess_34114_Test();
|
||||
ASSERT(!ret);
|
||||
ret = smlProcess_json0_Test();
|
||||
ASSERT(!ret);
|
||||
ret = sml_ts5528_test();
|
||||
ASSERT(!ret);
|
||||
|
|
Loading…
Reference in New Issue