提交 2fd013dd 编写于 作者: W wenzhouwww

Merge branch 'develop' of github.com:taosdata/TDengine into develop

......@@ -476,6 +476,9 @@ pipeline {
'''
sh '''
cd ${WKC}/src/connector/nodejs
npm install
npm run test
cd ${WKC}/tests/examples/nodejs
npm install td2.0-connector > /dev/null 2>&1
node nodejsChecker.js host=localhost
......@@ -486,6 +489,15 @@ pipeline {
'''
catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') {
sh '''
cd ${WKC}/src/connector/C#
dotnet test
dotnet run --project src/test/Cases/Cases.csproj
cd ${WKC}/tests/examples/C#
dotnet run --project C#checker/C#checker.csproj
dotnet run --project TDengineTest/TDengineTest.csproj
dotnet run --project schemaless/schemaless.csproj
cd ${WKC}/tests/examples/C#/taosdemo
dotnet build -c Release
tree | true
......
......@@ -364,7 +364,7 @@ taosdemo 不仅仅可以进行数据写入,也可以执行查询和订阅功
}
```
以下为 JSON 文件中和查询相关的特有参数含义:
```
"query_times": 每种查询类型的查询次数
"query_mode": 查询数据接口,"taosc":调用TDengine的c接口;“resetful”:使用restfule接口。可选项。缺省是“taosc”。
"specified_table_query": { 指定表的查询
......@@ -379,7 +379,7 @@ taosdemo 不仅仅可以进行数据写入,也可以执行查询和订阅功
"threads": 并发执行sqls的线程数,可选项,缺省是1。每个线程负责一部分子表,执行所有的sqls。
"sql": "select count(*) from xxxx"。查询超级表内所有子表的查询语句,其中表名必须写成 “xxxx”,实例会自动替换成子表名。
"result": 查询结果写入的文件名。可选项,缺省是空,表示查询结果不写入文件。
```
以下为一个典型订阅 JSON 示例文件内容:
```
......@@ -422,13 +422,13 @@ taosdemo 不仅仅可以进行数据写入,也可以执行查询和订阅功
}
```
以下为订阅功能相关的特有参数含义:
```
"interval": 执行订阅的间隔,单位是秒。可选项,缺省是0。
"restart": 订阅重启。"yes":如果订阅已经存在,重新开始,"no": 继续之前的订阅。(请注意执行用户需要对 dataDir 目录有读写权限)
"keepProgress": 保留订阅信息进度。yes表示保留订阅信息,no表示不保留。该值为yes,restart为no时,才能继续之前的订阅。
"resubAfterConsume": 配合 keepProgress 使用,在订阅消费了相应次数后调用 unsubscribe 取消订阅并再次订阅。
"result": 查询结果写入的文件名。可选项,缺省是空,表示查询结果不写入文件。 注意:每条sql语句后的保存结果的文件不能重名,且生成结果文件时,文件名会附加线程号。
```
结语
--
TDengine是涛思数据专为物联网、车联网、工业互联网、IT运维等设计和优化的大数据平台。TDengine 由于数据库内核中创新的数据存储和查询引擎设计,展现出远超同类产品的高效性能。并且由于支持 SQL 语法和多种编程语言的连接器(目前支持 Java, Python, Go, C#, NodeJS, Rust 等),易用性极强,学习成本为零。为了便于运维需求,我们还提供数据迁移和监控功能等相关生态工具软件。
......@@ -440,6 +440,7 @@ TDengine是涛思数据专为物联网、车联网、工业互联网、IT运维
附录 - 完整 taosdemo 参数介绍
--
taosdemo支持两种配置参数的模式,一种是命令行参数,一种是使用 JSON 格式的配置文件。
一、命令行参数
-f:指定taosdemo所需参数的meta文件。当使用该参数时,其他所有命令行参数都失效。可选项,缺省是NULL。目前仅支持不含 BOM(byte-order mark)的标准 UTF-8 编码文件。
......@@ -508,8 +509,9 @@ taosdemo支持两种配置参数的模式,一种是命令行参数,一种是
二、JSON 格式的配置文件中所有参数说明
taosdemo支持3种功能的测试,包括插入、查询、订阅。但一个taosdemo实例不能同时支持三种功能,一个 taosdemo 实例只能支持其中的一种功能,通过配置文件来指定进行哪种功能的测试。
1、插入功能测试的 JSON 配置文件
1、插入功能测试的 JSON 配置文件
```
{
"filetype": "insert",
"cfgdir": "/etc/taos",
......@@ -571,6 +573,7 @@ taosdemo支持3种功能的测试,包括插入、查询、订阅。但一个ta
}]
}]
}
```
"filetype": 本taosdemo实例进行哪种功能测试。"insert"表示数据插入功能。必选项。
......@@ -600,7 +603,7 @@ taosdemo支持3种功能的测试,包括插入、查询、订阅。但一个ta
"databases": [{
"dbinfo": {"name": 数据库名称。必选项。
"dbinfo": {"name": 数据库名称。必选项。
"drop": 如果数据库已经存在,”yes“:删除后重建;”no“:不删除,直接使用。可选项,缺省是”no“。drop = yes 会使其他子表创建相关条目无效。
......@@ -695,8 +698,9 @@ taosdemo支持3种功能的测试,包括插入、查询、订阅。但一个ta
"count":该类型的连续列个数,可选项,缺省是1。
}]
2、查询功能测试的 JSON 配置文件
2、查询功能测试的 JSON 配置文件
```
{
"filetype": "query",
"cfgdir": "/etc/taos",
......@@ -734,7 +738,7 @@ taosdemo支持3种功能的测试,包括插入、查询、订阅。但一个ta
]
}
}
```
"filetype": 本taosdemo实例进行哪种功能测试。"query"表示数据查询功能。必选项。
......@@ -784,8 +788,9 @@ taosdemo支持3种功能的测试,包括插入、查询、订阅。但一个ta
注意:每条sql语句后的保存结果的文件不能重名,且生成结果文件时,文件名会附加线程号。
查询结果显示:如果查询线程结束一次查询距开始执行时间超过30秒打印一次查询次数、用时和QPS。所有查询结束时,汇总打印总的查询次数和QPS。
3、订阅功能测试的 JSON 配置文件
3、订阅功能测试的 JSON 配置文件
```
{
"filetype":"subscribe",
"cfgdir": "/etc/taos",
......@@ -822,7 +827,8 @@ taosdemo支持3种功能的测试,包括插入、查询、订阅。但一个ta
"result": "./subscribe_res1.txt"
}]
}
}
}
```
"filetype": 本taosdemo实例进行哪种功能测试。"subscribe"表示数据查询功能。必选项。**
......@@ -878,4 +884,4 @@ taosdemo支持3种功能的测试,包括插入、查询、订阅。但一个ta
"sql": " select count(*) from xxxx "。查询语句,其中表名必须写成 “xxxx”,实例会自动替换成子表名。
"result": 查询结果写入的文件名。可选项,缺省是空,表示查询结果不写入文件。 注意:每条sql语句后的保存结果的文件不能重名,且生成结果文件时,文件名会附加线程号。
"result": 查询结果写入的文件名。可选项,缺省是空,表示查询结果不写入文件。 注意:每条sql语句后的保存结果的文件不能重名,且生成结果文件时,文件名会附加线程号。
......@@ -208,6 +208,8 @@ C/C++的API类似于MySQL的C API。应用程序使用时,需要包含TDengine
返回值为空表示失败。应用程序需要保存返回的参数,以便后续API调用。
**提示:** 同一进程可以根据不同的host/port 连接多个taosd 集群
- `char *taos_get_server_info(TAOS *taos)`
获取服务端版本信息。
......
......@@ -223,7 +223,6 @@ taosd -C
| 105 | compressColData | | **S** | bytes | 客户端与服务器之间进行消息通讯过程中,对服务器端查询结果进行列压缩的阈值。 | 0: 对所有查询结果均进行压缩 >0: 查询结果中任意列大小超过该值的消息才进行压缩 -1: 不压缩 | -1 | 2.3.0.0 版本新增。 |
| 106 | tsdbMetaCompactRatio | | **C** | | tsdb meta文件中冗余数据超过多少阈值,开启meta文件的压缩功能 | 0:不开启,[1-100]:冗余数据比例 | 0 | |
| 107 | rpcForceTcp | | **SC**| | 强制使用TCP传输 | 0: 不开启 1: 开启 | 0 | 在网络比较差的环境中,建议开启。2.0版本新增。|
| 107 | rpcForceTcp | | **SC** | | 强制使用TCP传输。 | 0: 不开启 1: 开启 | 0 | 在网络比较差的环境中,建议开启。2.0 版本新增。 |
**注意:**对于端口,TDengine会使用从serverPort起13个连续的TCP和UDP端口号,请务必在防火墙打开。因此如果是缺省配置,需要打开从6030到6042共13个端口,而且必须TCP和UDP都打开。(详细的端口情况请参见 [TDengine 2.0 端口说明](https://www.taosdata.com/cn/documentation/faq#port)
......
......@@ -374,7 +374,7 @@ The following is the content of a typical query JSON example file.
}
```
The following parameters are specific to the query in the JSON file.
```
"query_times": the number of queries per query type
"query_mode": query data interface, "tosc": call TDengine's c interface; "resetful": use restfule interface. Options are available. Default is "taosc".
"specified_table_query": { query for the specified table
......@@ -389,7 +389,7 @@ The following parameters are specific to the query in the JSON file.
"threads": the number of threads to execute sqls concurrently, optional, default is 1. Each thread is responsible for a part of sub-tables and executes all sqls.
"sql": "select count(*) from xxxx". Query statement for all sub-tables in the super table, where the table name must be written as "xxxx" and the instance will be replaced with the sub-table name automatically.
"result": the name of the file to which the query result is written. Optional, the default is null, which means the query results are not written to a file.
```
The following is a typical subscription JSON example file content.
```
......@@ -432,13 +432,13 @@ The following is a typical subscription JSON example file content.
}
```
The following are the meanings of the parameters specific to the subscription function.
```
"interval": interval for executing subscriptions, in seconds. Optional, default is 0.
"restart": subscription restart." yes": restart the subscription if it already exists, "no": continue the previous subscription. (Please note that the executing user needs to have read/write access to the dataDir directory)
"keepProgress": keep the progress of the subscription information. yes means keep the subscription information, no means don't keep it. The value is yes and restart is no to continue the previous subscriptions.
"resubAfterConsume": Used in conjunction with keepProgress to call unsubscribe after the subscription has been consumed the appropriate number of times and to subscribe again.
"result": the name of the file to which the query result is written. Optional, default is null, means the query result will not be written to the file. Note: The file to save the result after each sql statement cannot be renamed, and the file name will be appended with the thread number when generating the result file.
```
Conclusion
--
TDengine is a big data platform designed and optimized for IoT, Telematics, Industrial Internet, DevOps, etc. TDengine shows a high performance that far exceeds similar products due to the innovative data storage and query engine design in the database kernel. And withSQL syntax support and connectors for multiple programming languages (currently Java, Python, Go, C#, NodeJS, Rust, etc. are supported), it is extremely easy to use and has zero learning cost. To facilitate the operation and maintenance needs, we also provide data migration and monitoring functions and other related ecological tools and software.
......
......@@ -200,6 +200,8 @@ Create a database connection and initialize the connection context. The paramete
* port: Port number
A null return value indicates a failure. The application needs to save the returned parameters for subsequent API calls.
Note: The same process can connect to multiple taosd processes based on ip/port
- `char *taos_get_server_info(TAOS *taos)`
......
......@@ -115,8 +115,9 @@ typedef struct SParsedDataColInfo {
int16_t numOfCols;
int16_t numOfBound;
uint16_t flen; // TODO: get from STSchema
uint16_t allNullLen; // TODO: get from STSchema
uint16_t allNullLen; // TODO: get from STSchema(base on SDataRow)
uint16_t extendedVarLen;
uint16_t boundNullLen; // bound column len with all NULL value(without VarDataOffsetT/SColIdx part)
int32_t * boundedColumns; // bound column idx according to schema
SBoundColumn * cols;
SBoundIdxInfo *colIdxInfo;
......@@ -132,7 +133,7 @@ typedef struct {
typedef struct {
uint8_t memRowType; // default is 0, that is SDataRow
uint8_t compareStat; // 0 no need, 1 need compare
TDRowTLenT kvRowInitLen;
int32_t rowSize;
SMemRowInfo *rowInfo;
} SMemRowBuilder;
......@@ -150,8 +151,7 @@ typedef struct {
int tsParseTime(SStrToken *pToken, int64_t *time, char **next, char *error, int16_t timePrec);
int initMemRowBuilder(SMemRowBuilder *pBuilder, uint32_t nRows, uint32_t nCols, uint32_t nBoundCols,
int32_t allNullLen);
int initMemRowBuilder(SMemRowBuilder *pBuilder, uint32_t nRows, SParsedDataColInfo *pColInfo);
void destroyMemRowBuilder(SMemRowBuilder *pBuilder);
/**
......@@ -533,16 +533,6 @@ static FORCE_INLINE int32_t getExtendedRowSize(STableDataBlocks *pBlock) {
return pBlock->rowSize + TD_MEM_ROW_DATA_HEAD_SIZE + pBlock->boundColumnInfo.extendedVarLen;
}
static FORCE_INLINE void checkAndConvertMemRow(SMemRow row, int32_t dataLen, int32_t kvLen) {
if (isDataRow(row)) {
if (kvLen < (dataLen * KVRatioConvert)) {
memRowSetConvert(row);
}
} else if (kvLen > dataLen) {
memRowSetConvert(row);
}
}
static FORCE_INLINE void initSMemRow(SMemRow row, uint8_t memRowType, STableDataBlocks *pBlock, int16_t nBoundCols) {
memRowSetType(row, memRowType);
if (isDataRowT(memRowType)) {
......@@ -642,8 +632,7 @@ static uint8_t TRUE_VALUE = (uint8_t)TSDB_TRUE;
static uint8_t FALSE_VALUE = (uint8_t)TSDB_FALSE;
static FORCE_INLINE int32_t tsParseOneColumnKV(SSchema *pSchema, SStrToken *pToken, SMemRow row, char *msg, char **str,
bool primaryKey, int16_t timePrec, int32_t toffset, int16_t colId,
int32_t *dataLen, int32_t *kvLen, uint8_t compareStat) {
bool primaryKey, int16_t timePrec, int32_t toffset, int16_t colId) {
int64_t iv;
int32_t ret;
char * endptr = NULL;
......@@ -655,26 +644,22 @@ static FORCE_INLINE int32_t tsParseOneColumnKV(SSchema *pSchema, SStrToken *pTok
switch (pSchema->type) {
case TSDB_DATA_TYPE_BOOL: { // bool
if (isNullStr(pToken)) {
tscAppendMemRowColValEx(row, getNullValue(pSchema->type), true, colId, pSchema->type, toffset, dataLen, kvLen,
compareStat);
tdAppendMemRowColVal(row, getNullValue(pSchema->type), true, colId, pSchema->type, toffset);
} else {
if ((pToken->type == TK_BOOL || pToken->type == TK_STRING) && (pToken->n != 0)) {
if (strncmp(pToken->z, "true", pToken->n) == 0) {
tscAppendMemRowColValEx(row, &TRUE_VALUE, true, colId, pSchema->type, toffset, dataLen, kvLen, compareStat);
tdAppendMemRowColVal(row, &TRUE_VALUE, true, colId, pSchema->type, toffset);
} else if (strncmp(pToken->z, "false", pToken->n) == 0) {
tscAppendMemRowColValEx(row, &FALSE_VALUE, true, colId, pSchema->type, toffset, dataLen, kvLen,
compareStat);
tdAppendMemRowColVal(row, &FALSE_VALUE, true, colId, pSchema->type, toffset);
} else {
return tscSQLSyntaxErrMsg(msg, "invalid bool data", pToken->z);
}
} else if (pToken->type == TK_INTEGER) {
iv = strtoll(pToken->z, NULL, 10);
tscAppendMemRowColValEx(row, ((iv == 0) ? &FALSE_VALUE : &TRUE_VALUE), true, colId, pSchema->type, toffset,
dataLen, kvLen, compareStat);
tdAppendMemRowColVal(row, ((iv == 0) ? &FALSE_VALUE : &TRUE_VALUE), true, colId, pSchema->type, toffset);
} else if (pToken->type == TK_FLOAT) {
double dv = strtod(pToken->z, NULL);
tscAppendMemRowColValEx(row, ((dv == 0) ? &FALSE_VALUE : &TRUE_VALUE), true, colId, pSchema->type, toffset,
dataLen, kvLen, compareStat);
tdAppendMemRowColVal(row, ((dv == 0) ? &FALSE_VALUE : &TRUE_VALUE), true, colId, pSchema->type, toffset);
} else {
return tscInvalidOperationMsg(msg, "invalid bool data", pToken->z);
}
......@@ -684,8 +669,7 @@ static FORCE_INLINE int32_t tsParseOneColumnKV(SSchema *pSchema, SStrToken *pTok
case TSDB_DATA_TYPE_TINYINT:
if (isNullStr(pToken)) {
tscAppendMemRowColValEx(row, getNullValue(pSchema->type), true, colId, pSchema->type, toffset, dataLen, kvLen,
compareStat);
tdAppendMemRowColVal(row, getNullValue(pSchema->type), true, colId, pSchema->type, toffset);
} else {
ret = tStrToInteger(pToken->z, pToken->type, pToken->n, &iv, true);
if (ret != TSDB_CODE_SUCCESS) {
......@@ -695,15 +679,14 @@ static FORCE_INLINE int32_t tsParseOneColumnKV(SSchema *pSchema, SStrToken *pTok
}
uint8_t tmpVal = (uint8_t)iv;
tscAppendMemRowColValEx(row, &tmpVal, true, colId, pSchema->type, toffset, dataLen, kvLen, compareStat);
tdAppendMemRowColVal(row, &tmpVal, true, colId, pSchema->type, toffset);
}
break;
case TSDB_DATA_TYPE_UTINYINT:
if (isNullStr(pToken)) {
tscAppendMemRowColValEx(row, getNullValue(pSchema->type), true, colId, pSchema->type, toffset, dataLen, kvLen,
compareStat);
tdAppendMemRowColVal(row, getNullValue(pSchema->type), true, colId, pSchema->type, toffset);
} else {
ret = tStrToInteger(pToken->z, pToken->type, pToken->n, &iv, false);
if (ret != TSDB_CODE_SUCCESS) {
......@@ -713,15 +696,14 @@ static FORCE_INLINE int32_t tsParseOneColumnKV(SSchema *pSchema, SStrToken *pTok
}
uint8_t tmpVal = (uint8_t)iv;
tscAppendMemRowColValEx(row, &tmpVal, true, colId, pSchema->type, toffset, dataLen, kvLen, compareStat);
tdAppendMemRowColVal(row, &tmpVal, true, colId, pSchema->type, toffset);
}
break;
case TSDB_DATA_TYPE_SMALLINT:
if (isNullStr(pToken)) {
tscAppendMemRowColValEx(row, getNullValue(pSchema->type), true, colId, pSchema->type, toffset, dataLen, kvLen,
compareStat);
tdAppendMemRowColVal(row, getNullValue(pSchema->type), true, colId, pSchema->type, toffset);
} else {
ret = tStrToInteger(pToken->z, pToken->type, pToken->n, &iv, true);
if (ret != TSDB_CODE_SUCCESS) {
......@@ -731,15 +713,14 @@ static FORCE_INLINE int32_t tsParseOneColumnKV(SSchema *pSchema, SStrToken *pTok
}
int16_t tmpVal = (int16_t)iv;
tscAppendMemRowColValEx(row, &tmpVal, true, colId, pSchema->type, toffset, dataLen, kvLen, compareStat);
tdAppendMemRowColVal(row, &tmpVal, true, colId, pSchema->type, toffset);
}
break;
case TSDB_DATA_TYPE_USMALLINT:
if (isNullStr(pToken)) {
tscAppendMemRowColValEx(row, getNullValue(pSchema->type), true, colId, pSchema->type, toffset, dataLen, kvLen,
compareStat);
tdAppendMemRowColVal(row, getNullValue(pSchema->type), true, colId, pSchema->type, toffset);
} else {
ret = tStrToInteger(pToken->z, pToken->type, pToken->n, &iv, false);
if (ret != TSDB_CODE_SUCCESS) {
......@@ -749,15 +730,14 @@ static FORCE_INLINE int32_t tsParseOneColumnKV(SSchema *pSchema, SStrToken *pTok
}
uint16_t tmpVal = (uint16_t)iv;
tscAppendMemRowColValEx(row, &tmpVal, true, colId, pSchema->type, toffset, dataLen, kvLen, compareStat);
tdAppendMemRowColVal(row, &tmpVal, true, colId, pSchema->type, toffset);
}
break;
case TSDB_DATA_TYPE_INT:
if (isNullStr(pToken)) {
tscAppendMemRowColValEx(row, getNullValue(pSchema->type), true, colId, pSchema->type, toffset, dataLen, kvLen,
compareStat);
tdAppendMemRowColVal(row, getNullValue(pSchema->type), true, colId, pSchema->type, toffset);
} else {
ret = tStrToInteger(pToken->z, pToken->type, pToken->n, &iv, true);
if (ret != TSDB_CODE_SUCCESS) {
......@@ -767,15 +747,14 @@ static FORCE_INLINE int32_t tsParseOneColumnKV(SSchema *pSchema, SStrToken *pTok
}
int32_t tmpVal = (int32_t)iv;
tscAppendMemRowColValEx(row, &tmpVal, true, colId, pSchema->type, toffset, dataLen, kvLen, compareStat);
tdAppendMemRowColVal(row, &tmpVal, true, colId, pSchema->type, toffset);
}
break;
case TSDB_DATA_TYPE_UINT:
if (isNullStr(pToken)) {
tscAppendMemRowColValEx(row, getNullValue(pSchema->type), true, colId, pSchema->type, toffset, dataLen, kvLen,
compareStat);
tdAppendMemRowColVal(row, getNullValue(pSchema->type), true, colId, pSchema->type, toffset);
} else {
ret = tStrToInteger(pToken->z, pToken->type, pToken->n, &iv, false);
if (ret != TSDB_CODE_SUCCESS) {
......@@ -785,15 +764,14 @@ static FORCE_INLINE int32_t tsParseOneColumnKV(SSchema *pSchema, SStrToken *pTok
}
uint32_t tmpVal = (uint32_t)iv;
tscAppendMemRowColValEx(row, &tmpVal, true, colId, pSchema->type, toffset, dataLen, kvLen, compareStat);
tdAppendMemRowColVal(row, &tmpVal, true, colId, pSchema->type, toffset);
}
break;
case TSDB_DATA_TYPE_BIGINT:
if (isNullStr(pToken)) {
tscAppendMemRowColValEx(row, getNullValue(pSchema->type), true, colId, pSchema->type, toffset, dataLen, kvLen,
compareStat);
tdAppendMemRowColVal(row, getNullValue(pSchema->type), true, colId, pSchema->type, toffset);
} else {
ret = tStrToInteger(pToken->z, pToken->type, pToken->n, &iv, true);
if (ret != TSDB_CODE_SUCCESS) {
......@@ -802,14 +780,13 @@ static FORCE_INLINE int32_t tsParseOneColumnKV(SSchema *pSchema, SStrToken *pTok
return tscInvalidOperationMsg(msg, "bigint data overflow", pToken->z);
}
tscAppendMemRowColValEx(row, &iv, true, colId, pSchema->type, toffset, dataLen, kvLen, compareStat);
tdAppendMemRowColVal(row, &iv, true, colId, pSchema->type, toffset);
}
break;
case TSDB_DATA_TYPE_UBIGINT:
if (isNullStr(pToken)) {
tscAppendMemRowColValEx(row, getNullValue(pSchema->type), true, colId, pSchema->type, toffset, dataLen, kvLen,
compareStat);
tdAppendMemRowColVal(row, getNullValue(pSchema->type), true, colId, pSchema->type, toffset);
} else {
ret = tStrToInteger(pToken->z, pToken->type, pToken->n, &iv, false);
if (ret != TSDB_CODE_SUCCESS) {
......@@ -819,14 +796,13 @@ static FORCE_INLINE int32_t tsParseOneColumnKV(SSchema *pSchema, SStrToken *pTok
}
uint64_t tmpVal = (uint64_t)iv;
tscAppendMemRowColValEx(row, &tmpVal, true, colId, pSchema->type, toffset, dataLen, kvLen, compareStat);
tdAppendMemRowColVal(row, &tmpVal, true, colId, pSchema->type, toffset);
}
break;
case TSDB_DATA_TYPE_FLOAT:
if (isNullStr(pToken)) {
tscAppendMemRowColValEx(row, getNullValue(pSchema->type), true, colId, pSchema->type, toffset, dataLen, kvLen,
compareStat);
tdAppendMemRowColVal(row, getNullValue(pSchema->type), true, colId, pSchema->type, toffset);
} else {
double dv;
if (TK_ILLEGAL == tscToDouble(pToken, &dv, &endptr)) {
......@@ -839,14 +815,13 @@ static FORCE_INLINE int32_t tsParseOneColumnKV(SSchema *pSchema, SStrToken *pTok
}
float tmpVal = (float)dv;
tscAppendMemRowColValEx(row, &tmpVal, true, colId, pSchema->type, toffset, dataLen, kvLen, compareStat);
tdAppendMemRowColVal(row, &tmpVal, true, colId, pSchema->type, toffset);
}
break;
case TSDB_DATA_TYPE_DOUBLE:
if (isNullStr(pToken)) {
tscAppendMemRowColValEx(row, getNullValue(pSchema->type), true, colId, pSchema->type, toffset, dataLen, kvLen,
compareStat);
tdAppendMemRowColVal(row, getNullValue(pSchema->type), true, colId, pSchema->type, toffset);
} else {
double dv;
if (TK_ILLEGAL == tscToDouble(pToken, &dv, &endptr)) {
......@@ -857,15 +832,14 @@ static FORCE_INLINE int32_t tsParseOneColumnKV(SSchema *pSchema, SStrToken *pTok
return tscInvalidOperationMsg(msg, "illegal double data", pToken->z);
}
tscAppendMemRowColValEx(row, &dv, true, colId, pSchema->type, toffset, dataLen, kvLen, compareStat);
tdAppendMemRowColVal(row, &dv, true, colId, pSchema->type, toffset);
}
break;
case TSDB_DATA_TYPE_BINARY:
// binary data cannot be null-terminated char string, otherwise the last char of the string is lost
if (pToken->type == TK_NULL) {
tscAppendMemRowColValEx(row, getNullValue(pSchema->type), true, colId, pSchema->type, toffset, dataLen, kvLen,
compareStat);
tdAppendMemRowColVal(row, getNullValue(pSchema->type), true, colId, pSchema->type, toffset);
} else { // too long values will return invalid sql, not be truncated automatically
if (pToken->n + VARSTR_HEADER_SIZE > pSchema->bytes) { // todo refactor
return tscInvalidOperationMsg(msg, "string data overflow", pToken->z);
......@@ -873,14 +847,13 @@ static FORCE_INLINE int32_t tsParseOneColumnKV(SSchema *pSchema, SStrToken *pTok
// STR_WITH_SIZE_TO_VARSTR(payload, pToken->z, pToken->n);
char *rowEnd = memRowEnd(row);
STR_WITH_SIZE_TO_VARSTR(rowEnd, pToken->z, pToken->n);
tscAppendMemRowColValEx(row, rowEnd, false, colId, pSchema->type, toffset, dataLen, kvLen, compareStat);
tdAppendMemRowColVal(row, rowEnd, false, colId, pSchema->type, toffset);
}
break;
case TSDB_DATA_TYPE_NCHAR:
if (pToken->type == TK_NULL) {
tscAppendMemRowColValEx(row, getNullValue(pSchema->type), true, colId, pSchema->type, toffset, dataLen, kvLen,
compareStat);
tdAppendMemRowColVal(row, getNullValue(pSchema->type), true, colId, pSchema->type, toffset);
} else {
// if the converted output len is over than pColumnModel->bytes, return error: 'Argument list too long'
int32_t output = 0;
......@@ -892,7 +865,7 @@ static FORCE_INLINE int32_t tsParseOneColumnKV(SSchema *pSchema, SStrToken *pTok
return tscInvalidOperationMsg(msg, buf, pToken->z);
}
varDataSetLen(rowEnd, output);
tscAppendMemRowColValEx(row, rowEnd, false, colId, pSchema->type, toffset, dataLen, kvLen, compareStat);
tdAppendMemRowColVal(row, rowEnd, false, colId, pSchema->type, toffset);
}
break;
......@@ -901,17 +874,16 @@ static FORCE_INLINE int32_t tsParseOneColumnKV(SSchema *pSchema, SStrToken *pTok
if (primaryKey) {
// When building SKVRow primaryKey, we should not skip even with NULL value.
int64_t tmpVal = 0;
tscAppendMemRowColValEx(row, &tmpVal, true, colId, pSchema->type, toffset, dataLen, kvLen, compareStat);
tdAppendMemRowColVal(row, &tmpVal, true, colId, pSchema->type, toffset);
} else {
tscAppendMemRowColValEx(row, getNullValue(pSchema->type), true, colId, pSchema->type, toffset, dataLen, kvLen,
compareStat);
tdAppendMemRowColVal(row, getNullValue(pSchema->type), true, colId, pSchema->type, toffset);
}
} else {
int64_t tmpVal;
if (tsParseTime(pToken, &tmpVal, str, msg, timePrec) != TSDB_CODE_SUCCESS) {
return tscInvalidOperationMsg(msg, "invalid timestamp", pToken->z);
}
tscAppendMemRowColValEx(row, &tmpVal, true, colId, pSchema->type, toffset, dataLen, kvLen, compareStat);
tdAppendMemRowColVal(row, &tmpVal, true, colId, pSchema->type, toffset);
}
break;
......
......@@ -41,9 +41,8 @@ enum {
static int32_t tscAllocateMemIfNeed(STableDataBlocks *pDataBlock, int32_t rowSize, int32_t *numOfRows);
static int32_t parseBoundColumns(SInsertStatementParam *pInsertParam, SParsedDataColInfo *pColInfo, SSchema *pSchema,
char *str, char **end);
int initMemRowBuilder(SMemRowBuilder *pBuilder, uint32_t nRows, uint32_t nCols, uint32_t nBoundCols,
int32_t allNullLen) {
ASSERT(nRows >= 0 && nCols > 0 && (nBoundCols <= nCols));
int initMemRowBuilder(SMemRowBuilder *pBuilder, uint32_t nRows, SParsedDataColInfo *pColInfo) {
ASSERT(nRows >= 0 && pColInfo->numOfCols > 0 && (pColInfo->numOfBound <= pColInfo->numOfCols));
if (nRows > 0) {
// already init(bind multiple rows by single column)
if (pBuilder->compareStat == ROW_COMPARE_NEED && (pBuilder->rowInfo != NULL)) {
......@@ -51,41 +50,12 @@ int initMemRowBuilder(SMemRowBuilder *pBuilder, uint32_t nRows, uint3
}
}
// default compareStat is ROW_COMPARE_NO_NEED
if (nBoundCols == 0) { // file input
pBuilder->memRowType = SMEM_ROW_DATA;
return TSDB_CODE_SUCCESS;
uint32_t dataLen = TD_MEM_ROW_DATA_HEAD_SIZE + pColInfo->allNullLen;
uint32_t kvLen = TD_MEM_ROW_KV_HEAD_SIZE + pColInfo->numOfBound * sizeof(SColIdx) + pColInfo->boundNullLen;
if (isUtilizeKVRow(kvLen, dataLen)) {
pBuilder->memRowType = SMEM_ROW_KV;
} else {
float boundRatio = ((float)nBoundCols / (float)nCols);
if (boundRatio < KVRatioKV) {
pBuilder->memRowType = SMEM_ROW_KV;
return TSDB_CODE_SUCCESS;
} else if (boundRatio > KVRatioData) {
pBuilder->memRowType = SMEM_ROW_DATA;
return TSDB_CODE_SUCCESS;
}
pBuilder->compareStat = ROW_COMPARE_NEED;
if (boundRatio < KVRatioPredict) {
pBuilder->memRowType = SMEM_ROW_KV;
} else {
pBuilder->memRowType = SMEM_ROW_DATA;
}
}
pBuilder->kvRowInitLen = TD_MEM_ROW_KV_HEAD_SIZE + nBoundCols * sizeof(SColIdx);
if (nRows > 0) {
pBuilder->rowInfo = tcalloc(nRows, sizeof(SMemRowInfo));
if (pBuilder->rowInfo == NULL) {
return TSDB_CODE_TSC_OUT_OF_MEMORY;
}
for (int i = 0; i < nRows; ++i) {
(pBuilder->rowInfo + i)->dataLen = TD_MEM_ROW_DATA_HEAD_SIZE + allNullLen;
(pBuilder->rowInfo + i)->kvLen = pBuilder->kvRowInitLen;
}
pBuilder->memRowType = SMEM_ROW_DATA;
}
return TSDB_CODE_SUCCESS;
......@@ -468,8 +438,6 @@ int tsParseOneRow(char **str, STableDataBlocks *pDataBlocks, int16_t timePrec, i
STableMeta * pTableMeta = pDataBlocks->pTableMeta;
SSchema * schema = tscGetTableSchema(pTableMeta);
SMemRowBuilder * pBuilder = &pDataBlocks->rowBuilder;
int32_t dataLen = spd->allNullLen + TD_MEM_ROW_DATA_HEAD_SIZE;
int32_t kvLen = pBuilder->kvRowInitLen;
bool isParseBindParam = false;
initSMemRow(row, pBuilder->memRowType, pDataBlocks, spd->numOfBound);
......@@ -546,8 +514,8 @@ int tsParseOneRow(char **str, STableDataBlocks *pDataBlocks, int16_t timePrec, i
int16_t colId = -1;
tscGetMemRowAppendInfo(schema, pBuilder->memRowType, spd, i, &toffset, &colId);
int32_t ret = tsParseOneColumnKV(pSchema, &sToken, row, pInsertParam->msg, str, isPrimaryKey, timePrec, toffset,
colId, &dataLen, &kvLen, pBuilder->compareStat);
int32_t ret =
tsParseOneColumnKV(pSchema, &sToken, row, pInsertParam->msg, str, isPrimaryKey, timePrec, toffset, colId);
if (ret != TSDB_CODE_SUCCESS) {
return ret;
}
......@@ -562,13 +530,8 @@ int tsParseOneRow(char **str, STableDataBlocks *pDataBlocks, int16_t timePrec, i
}
if (!isParseBindParam) {
// 2. check and set convert flag
if (pBuilder->compareStat == ROW_COMPARE_NEED) {
checkAndConvertMemRow(row, dataLen, kvLen);
}
// 3. set the null value for the columns that do not assign values
if ((spd->numOfBound < spd->numOfCols) && isDataRow(row) && !isNeedConvertRow(row)) {
// set the null value for the columns that do not assign values
if ((spd->numOfBound < spd->numOfCols) && isDataRow(row)) {
SDataRow dataRow = memRowDataBody(row);
for (int32_t i = 0; i < spd->numOfCols; ++i) {
if (spd->cols[i].valStat == VAL_STAT_NONE) {
......@@ -578,7 +541,7 @@ int tsParseOneRow(char **str, STableDataBlocks *pDataBlocks, int16_t timePrec, i
}
}
*len = getExtendedRowSize(pDataBlocks);
*len = pBuilder->rowSize;
return TSDB_CODE_SUCCESS;
}
......@@ -631,11 +594,11 @@ int32_t tsParseValues(char **str, STableDataBlocks *pDataBlock, int maxRows, SIn
int32_t extendedRowSize = getExtendedRowSize(pDataBlock);
if (TSDB_CODE_SUCCESS !=
(code = initMemRowBuilder(&pDataBlock->rowBuilder, 0, tinfo.numOfColumns, pDataBlock->boundColumnInfo.numOfBound,
pDataBlock->boundColumnInfo.allNullLen))) {
if (TSDB_CODE_SUCCESS != (code = initMemRowBuilder(&pDataBlock->rowBuilder, 0, &pDataBlock->boundColumnInfo))) {
return code;
}
pDataBlock->rowBuilder.rowSize = extendedRowSize;
while (1) {
index = 0;
sToken = tStrGetToken(*str, &index, false);
......@@ -714,6 +677,7 @@ void tscSetBoundColumnInfo(SParsedDataColInfo *pColInfo, SSchema *pSchema, int32
pColInfo->boundedColumns[i] = i;
}
pColInfo->allNullLen += pColInfo->flen;
pColInfo->boundNullLen = pColInfo->allNullLen; // default set allNullLen
pColInfo->extendedVarLen = (uint16_t)(nVar * sizeof(VarDataOffsetT));
}
......@@ -1254,6 +1218,7 @@ static int32_t parseBoundColumns(SInsertStatementParam *pInsertParam, SParsedDat
int32_t nCols = pColInfo->numOfCols;
pColInfo->numOfBound = 0;
pColInfo->boundNullLen = 0;
memset(pColInfo->boundedColumns, 0, sizeof(int32_t) * nCols);
for (int32_t i = 0; i < nCols; ++i) {
pColInfo->cols[i].valStat = VAL_STAT_NONE;
......@@ -1311,6 +1276,17 @@ static int32_t parseBoundColumns(SInsertStatementParam *pInsertParam, SParsedDat
pColInfo->cols[t].valStat = VAL_STAT_HAS;
pColInfo->boundedColumns[pColInfo->numOfBound] = t;
++pColInfo->numOfBound;
switch (pSchema[t].type) {
case TSDB_DATA_TYPE_BINARY:
pColInfo->boundNullLen += (VARSTR_HEADER_SIZE + CHAR_BYTES);
break;
case TSDB_DATA_TYPE_NCHAR:
pColInfo->boundNullLen += (VARSTR_HEADER_SIZE + TSDB_NCHAR_SIZE);
break;
default:
pColInfo->boundNullLen += TYPE_BYTES[pSchema[t].type];
break;
}
findColumnIndex = true;
if (isOrdered && (lastColIdx > t)) {
isOrdered = false;
......@@ -1334,6 +1310,17 @@ static int32_t parseBoundColumns(SInsertStatementParam *pInsertParam, SParsedDat
pColInfo->cols[t].valStat = VAL_STAT_HAS;
pColInfo->boundedColumns[pColInfo->numOfBound] = t;
++pColInfo->numOfBound;
switch (pSchema[t].type) {
case TSDB_DATA_TYPE_BINARY:
pColInfo->boundNullLen += (VARSTR_HEADER_SIZE + CHAR_BYTES);
break;
case TSDB_DATA_TYPE_NCHAR:
pColInfo->boundNullLen += (VARSTR_HEADER_SIZE + TSDB_NCHAR_SIZE);
break;
default:
pColInfo->boundNullLen += TYPE_BYTES[pSchema[t].type];
break;
}
findColumnIndex = true;
if (isOrdered && (lastColIdx > t)) {
isOrdered = false;
......@@ -1784,13 +1771,18 @@ static void parseFileSendDataBlock(void *param, TAOS_RES *tres, int32_t numOfRow
goto _error;
}
tscAllocateMemIfNeed(pTableDataBlock, getExtendedRowSize(pTableDataBlock), &maxRows);
int32_t extendedRowSize = getExtendedRowSize(pTableDataBlock);
tscAllocateMemIfNeed(pTableDataBlock, extendedRowSize, &maxRows);
tokenBuf = calloc(1, TSDB_MAX_BYTES_PER_ROW);
if (tokenBuf == NULL) {
code = TSDB_CODE_TSC_OUT_OF_MEMORY;
goto _error;
}
// insert from .csv means full and ordered columns, thus use SDataRow all the time
ASSERT(SMEM_ROW_DATA == pTableDataBlock->rowBuilder.memRowType);
pTableDataBlock->rowBuilder.rowSize = extendedRowSize;
while ((readLen = tgetline(&line, &n, fp)) != -1) {
if (('\r' == line[readLen - 1]) || ('\n' == line[readLen - 1])) {
line[--readLen] = 0;
......
......@@ -100,7 +100,7 @@ static int32_t validateStateWindowNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SS
static int32_t addProjectionExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExprItem* pItem, bool outerQuery);
static int32_t validateWhereNode(SQueryInfo* pQueryInfo, tSqlExpr** pExpr, SSqlObj* pSql);
static int32_t validateWhereNode(SQueryInfo* pQueryInfo, tSqlExpr** pExpr, SSqlObj* pSql, bool joinQuery);
static int32_t validateFillNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSqlNode);
static int32_t validateRangeNode(SSqlObj* pSql, SQueryInfo* pQueryInfo, SSqlNode* pSqlNode);
static int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSqlNode, SSchema* pSchema);
......@@ -472,7 +472,7 @@ int32_t handleUserDefinedFunc(SSqlObj* pSql, struct SSqlInfo* pInfo) {
}
createInfo->name.z[createInfo->name.n] = 0;
// funcname's naming rule is same to column
// funcname's naming rule is same to column
if (validateColumnName(createInfo->name.z) != TSDB_CODE_SUCCESS) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg1);
}
......@@ -5036,11 +5036,13 @@ int32_t handleNeOptr(tSqlExpr** rexpr, tSqlExpr* expr) {
static int32_t handleExprInQueryCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr** pExpr, SCondExpr* pCondExpr,
int32_t* type, int32_t* tbIdx, int32_t parentOptr, tSqlExpr** columnExpr, tSqlExpr** tsExpr) {
int32_t* type, int32_t* tbIdx, int32_t parentOptr, tSqlExpr** columnExpr,
tSqlExpr** tsExpr, bool joinQuery) {
const char* msg1 = "table query cannot use tags filter";
const char* msg2 = "illegal column name";
const char* msg4 = "too many join tables";
const char* msg5 = "not support ordinary column join";
const char* msg6 = "illegal condition expression";
tSqlExpr* pLeft = (*pExpr)->pLeft;
tSqlExpr* pRight = (*pExpr)->pRight;
......@@ -5157,7 +5159,7 @@ static int32_t handleExprInQueryCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSql
} else {
rexpr = *pExpr;
}
ret = setNormalExprToCond(tsExpr, rexpr, parentOptr);
if (type) {
*type |= TSQL_EXPR_TS;
......@@ -5189,7 +5191,7 @@ static int32_t handleExprInQueryCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSql
*pExpr = NULL;
if (type) {
*type |= TSQL_EXPR_JOIN;
}
}
} else {
// do nothing
// ret = setExprToCond(pCmd, &pCondExpr->pTagCond,
......@@ -5202,7 +5204,7 @@ static int32_t handleExprInQueryCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSql
handleNeOptr(&rexpr, *pExpr);
*pExpr = rexpr;
}
if (type) {
*type |= TSQL_EXPR_TAG;
}
......@@ -5211,9 +5213,13 @@ static int32_t handleExprInQueryCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSql
if (type) {
*type |= TSQL_EXPR_COLUMN;
}
if (pRight->tokenId == TK_ID) { // other column cannot be served as the join column
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg5);
if (pRight->tokenId == TK_ID) {
if (joinQuery) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg5); // other column cannot be served as the join column
} else {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg6);
}
}
tSqlExpr *rexpr = NULL;
......@@ -5231,7 +5237,8 @@ static int32_t handleExprInQueryCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSql
}
int32_t getQueryCondExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr** pExpr, SCondExpr* pCondExpr,
int32_t* type, int32_t* tbIdx, int32_t parentOptr, tSqlExpr** columnExpr, tSqlExpr** tsExpr) {
int32_t* type, int32_t* tbIdx, int32_t parentOptr, tSqlExpr** columnExpr,
tSqlExpr** tsExpr, bool joinQuery) {
if (pExpr == NULL) {
return TSDB_CODE_SUCCESS;
}
......@@ -5263,12 +5270,12 @@ int32_t getQueryCondExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr** pExpr
int32_t rightTbIdx = 0;
if (!tSqlExprIsParentOfLeaf(*pExpr)) {
ret = getQueryCondExpr(pCmd, pQueryInfo, &(*pExpr)->pLeft, pCondExpr, type ? &leftType : NULL, &leftTbIdx, (*pExpr)->tokenId, &columnLeft, &tsLeft);
ret = getQueryCondExpr(pCmd, pQueryInfo, &(*pExpr)->pLeft, pCondExpr, type ? &leftType : NULL, &leftTbIdx, (*pExpr)->tokenId, &columnLeft, &tsLeft, joinQuery);
if (ret != TSDB_CODE_SUCCESS) {
goto err_ret;
}
ret = getQueryCondExpr(pCmd, pQueryInfo, &(*pExpr)->pRight, pCondExpr, type ? &rightType : NULL, &rightTbIdx, (*pExpr)->tokenId, &columnRight, &tsRight);
ret = getQueryCondExpr(pCmd, pQueryInfo, &(*pExpr)->pRight, pCondExpr, type ? &rightType : NULL, &rightTbIdx, (*pExpr)->tokenId, &columnRight, &tsRight, joinQuery);
if (ret != TSDB_CODE_SUCCESS) {
goto err_ret;
}
......@@ -5323,7 +5330,7 @@ int32_t getQueryCondExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr** pExpr
goto err_ret;
}
ret = handleExprInQueryCond(pCmd, pQueryInfo, pExpr, pCondExpr, type, tbIdx, parentOptr, columnExpr, tsExpr);
ret = handleExprInQueryCond(pCmd, pQueryInfo, pExpr, pCondExpr, type, tbIdx, parentOptr, columnExpr, tsExpr, joinQuery);
if (ret) {
goto err_ret;
}
......@@ -5863,12 +5870,11 @@ _ret:
int32_t
validateWhereNode(SQueryInfo* pQueryInfo, tSqlExpr** pExpr, SSqlObj* pSql) {
int32_t validateWhereNode(SQueryInfo* pQueryInfo, tSqlExpr** pExpr, SSqlObj* pSql, bool joinQuery) {
if (pExpr == NULL) {
return TSDB_CODE_SUCCESS;
}
const char* msg1 = "invalid expression";
// const char* msg2 = "invalid filter expression";
......@@ -5892,7 +5898,7 @@ validateWhereNode(SQueryInfo* pQueryInfo, tSqlExpr** pExpr, SSqlObj* pSql) {
}
#endif
if ((ret = getQueryCondExpr(&pSql->cmd, pQueryInfo, pExpr, &condExpr, etype, &tbIdx, (*pExpr)->tokenId, &condExpr.pColumnCond, &condExpr.pTimewindow)) != TSDB_CODE_SUCCESS) {
if ((ret = getQueryCondExpr(&pSql->cmd, pQueryInfo, pExpr, &condExpr, etype, &tbIdx, (*pExpr)->tokenId, &condExpr.pColumnCond, &condExpr.pTimewindow, joinQuery)) != TSDB_CODE_SUCCESS) {
goto PARSE_WHERE_EXIT;
}
......@@ -8742,7 +8748,7 @@ int32_t doCheckForStream(SSqlObj* pSql, SSqlInfo* pInfo) {
if (tscValidateName(pName, true, &dbIncluded1) != TSDB_CODE_SUCCESS) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg1);
}
SRelationInfo* pFromInfo = pInfo->pCreateTableInfo->pSelect->from;
if (pFromInfo == NULL || taosArrayGetSize(pFromInfo->list) == 0) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg6);
......@@ -8759,7 +8765,7 @@ int32_t doCheckForStream(SSqlObj* pSql, SSqlInfo* pInfo) {
char buf[TSDB_TABLE_FNAME_LEN];
SStrToken sTblToken;
sTblToken.z = buf;
int32_t code = validateTableName(srcToken.z, srcToken.n, &sTblToken, &dbIncluded2);
if (code != TSDB_CODE_SUCCESS) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg1);
......@@ -8779,8 +8785,10 @@ int32_t doCheckForStream(SSqlObj* pSql, SSqlInfo* pInfo) {
return TSDB_CODE_TSC_INVALID_OPERATION;
}
int32_t joinQuery = (pSqlNode->from != NULL && taosArrayGetSize(pSqlNode->from->list) > 1);
if (pSqlNode->pWhere != NULL) { // query condition in stream computing
if (validateWhereNode(pQueryInfo, &pSqlNode->pWhere, pSql) != TSDB_CODE_SUCCESS) {
if (validateWhereNode(pQueryInfo, &pSqlNode->pWhere, pSql, joinQuery) != TSDB_CODE_SUCCESS) {
return TSDB_CODE_TSC_INVALID_OPERATION;
}
}
......@@ -9721,11 +9729,13 @@ int32_t validateSqlNode(SSqlObj* pSql, SSqlNode* pSqlNode, SQueryInfo* pQueryInf
(TPARSER_HAS_TOKEN(pSqlNode->interval.interval) || TPARSER_HAS_TOKEN(pSqlNode->sessionVal.gap));
TSDB_QUERY_SET_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_TABLE_QUERY);
int32_t joinQuery = (pSqlNode->from != NULL && taosArrayGetSize(pSqlNode->from->list) > 1);
// parse the group by clause in the first place
if (validateGroupbyNode(pQueryInfo, pSqlNode->pGroupby, pCmd) != TSDB_CODE_SUCCESS) {
return TSDB_CODE_TSC_INVALID_OPERATION;
}
if (validateSelectNodeList(pCmd, pQueryInfo, pSqlNode->pSelNodeList, false, timeWindowQuery, true) !=
TSDB_CODE_SUCCESS) {
......@@ -9757,7 +9767,7 @@ int32_t validateSqlNode(SSqlObj* pSql, SSqlNode* pSqlNode, SQueryInfo* pQueryInf
SExprInfo* pExpr = tscExprGet(pQueryInfo, i);
int32_t f = pExpr->base.functionId;
if (f == TSDB_FUNC_DERIVATIVE || f == TSDB_FUNC_TWA || f == TSDB_FUNC_IRATE ||
if (f == TSDB_FUNC_DERIVATIVE || f == TSDB_FUNC_TWA || f == TSDB_FUNC_IRATE ||
f == TSDB_FUNC_RATE || f == TSDB_FUNC_DIFF) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg7);
}
......@@ -9766,7 +9776,7 @@ int32_t validateSqlNode(SSqlObj* pSql, SSqlNode* pSqlNode, SQueryInfo* pQueryInf
// validate the query filter condition info
if (pSqlNode->pWhere != NULL) {
if (validateWhereNode(pQueryInfo, &pSqlNode->pWhere, pSql) != TSDB_CODE_SUCCESS) {
if (validateWhereNode(pQueryInfo, &pSqlNode->pWhere, pSql, joinQuery) != TSDB_CODE_SUCCESS) {
return TSDB_CODE_TSC_INVALID_OPERATION;
}
} else {
......@@ -9811,7 +9821,6 @@ int32_t validateSqlNode(SSqlObj* pSql, SSqlNode* pSqlNode, SQueryInfo* pQueryInf
}
// parse the having clause in the first place
int32_t joinQuery = (pSqlNode->from != NULL && taosArrayGetSize(pSqlNode->from->list) > 1);
if (validateHavingClause(pQueryInfo, pSqlNode->pHaving, pCmd, pSqlNode->pSelNodeList, joinQuery, timeWindowQuery) !=
TSDB_CODE_SUCCESS) {
return TSDB_CODE_TSC_INVALID_OPERATION;
......@@ -9863,6 +9872,8 @@ int32_t validateSqlNode(SSqlObj* pSql, SSqlNode* pSqlNode, SQueryInfo* pQueryInf
int32_t type = isSTable? TSDB_QUERY_TYPE_STABLE_QUERY:TSDB_QUERY_TYPE_TABLE_QUERY;
TSDB_QUERY_SET_TYPE(pQueryInfo->type, type);
int32_t joinQuery = (pSqlNode->from != NULL && taosArrayGetSize(pSqlNode->from->list) > 1);
// parse the group by clause in the first place
if (validateGroupbyNode(pQueryInfo, pSqlNode->pGroupby, pCmd) != TSDB_CODE_SUCCESS) {
return TSDB_CODE_TSC_INVALID_OPERATION;
......@@ -9870,7 +9881,7 @@ int32_t validateSqlNode(SSqlObj* pSql, SSqlNode* pSqlNode, SQueryInfo* pQueryInf
pQueryInfo->onlyHasTagCond = true;
// set where info
if (pSqlNode->pWhere != NULL) {
if (validateWhereNode(pQueryInfo, &pSqlNode->pWhere, pSql) != TSDB_CODE_SUCCESS) {
if (validateWhereNode(pQueryInfo, &pSqlNode->pWhere, pSql, joinQuery) != TSDB_CODE_SUCCESS) {
return TSDB_CODE_TSC_INVALID_OPERATION;
}
......@@ -9881,7 +9892,6 @@ int32_t validateSqlNode(SSqlObj* pSql, SSqlNode* pSqlNode, SQueryInfo* pQueryInf
}
}
int32_t joinQuery = (pSqlNode->from != NULL && taosArrayGetSize(pSqlNode->from->list) > 1);
int32_t timeWindowQuery =
(TPARSER_HAS_TOKEN(pSqlNode->interval.interval) || TPARSER_HAS_TOKEN(pSqlNode->sessionVal.gap));
......@@ -9891,7 +9901,7 @@ int32_t validateSqlNode(SSqlObj* pSql, SSqlNode* pSqlNode, SQueryInfo* pQueryInf
}
if (isSTable && tscQueryTags(pQueryInfo) && pQueryInfo->distinct && !pQueryInfo->onlyHasTagCond) {
return TSDB_CODE_TSC_INVALID_OPERATION;
return TSDB_CODE_TSC_INVALID_OPERATION;
}
// parse the window_state
......
......@@ -2066,18 +2066,11 @@ static int trimDataBlock(void* pDataBlock, STableDataBlocks* pTableDataBlock, SI
}
} else {
for (int32_t i = 0; i < numOfRows; ++i) {
char* payload = (blkKeyTuple + i)->payloadAddr;
if (isNeedConvertRow(payload)) {
convertSMemRow(pDataBlock, payload, pTableDataBlock);
TDRowTLenT rowTLen = memRowTLen(pDataBlock);
pDataBlock = POINTER_SHIFT(pDataBlock, rowTLen);
pBlock->dataLen += rowTLen;
} else {
TDRowTLenT rowTLen = memRowTLen(payload);
memcpy(pDataBlock, payload, rowTLen);
pDataBlock = POINTER_SHIFT(pDataBlock, rowTLen);
pBlock->dataLen += rowTLen;
}
char* payload = (blkKeyTuple + i)->payloadAddr;
TDRowTLenT rowTLen = memRowTLen(payload);
memcpy(pDataBlock, payload, rowTLen);
pDataBlock = POINTER_SHIFT(pDataBlock, rowTLen);
pBlock->dataLen += rowTLen;
}
}
......
......@@ -614,22 +614,17 @@ typedef void *SMemRow;
#define SMEM_ROW_DATA 0x0U // SDataRow
#define SMEM_ROW_KV 0x01U // SKVRow
#define SMEM_ROW_CONVERT 0x80U // SMemRow convert flag
#define KVRatioKV (0.2f) // all bool
#define KVRatioPredict (0.4f)
#define KVRatioData (0.75f) // all bigint
#define KVRatioConvert (0.9f)
#define memRowType(r) ((*(uint8_t *)(r)) & 0x01)
#define memRowSetType(r, t) ((*(uint8_t *)(r)) = (t)) // set the total byte in case of dirty memory
#define memRowSetConvert(r) ((*(uint8_t *)(r)) = (((*(uint8_t *)(r)) & 0x7F) | SMEM_ROW_CONVERT)) // highest bit
#define isDataRowT(t) (SMEM_ROW_DATA == (((uint8_t)(t)) & 0x01))
#define isDataRow(r) (SMEM_ROW_DATA == memRowType(r))
#define isKvRowT(t) (SMEM_ROW_KV == (((uint8_t)(t)) & 0x01))
#define isKvRow(r) (SMEM_ROW_KV == memRowType(r))
#define isNeedConvertRow(r) (((*(uint8_t *)(r)) & 0x80) == SMEM_ROW_CONVERT)
#define isUtilizeKVRow(k, d) ((k) < ((d)*KVRatioConvert))
#define memRowDataBody(r) POINTER_SHIFT(r, TD_MEM_ROW_TYPE_SIZE) // section after flag
#define memRowKvBody(r) \
......
......@@ -42,6 +42,7 @@ extern int8_t tsArbOnline;
extern int64_t tsArbOnlineTimestamp;
extern int32_t tsDnodeId;
extern int64_t tsDnodeStartTime;
extern int8_t tsDnodeNopLoop;
// common
extern int tsRpcTimer;
......
......@@ -47,6 +47,7 @@ int64_t tsArbOnlineTimestamp = TSDB_ARB_DUMMY_TIME;
char tsEmail[TSDB_FQDN_LEN] = {0};
int32_t tsDnodeId = 0;
int64_t tsDnodeStartTime = 0;
int8_t tsDnodeNopLoop = 0;
// common
int32_t tsRpcTimer = 300;
......@@ -622,6 +623,16 @@ static void doInitGlobalConfig(void) {
cfg.unitType = TAOS_CFG_UTYPE_NONE;
taosInitConfigOption(cfg);
cfg.option = "dnodeNopLoop";
cfg.ptr = &tsDnodeNopLoop;
cfg.valType = TAOS_CFG_VTYPE_INT8;
cfg.cfgType = TSDB_CFG_CTYPE_B_CONFIG;
cfg.minValue = 0;
cfg.maxValue = 1;
cfg.ptrLength = 0;
cfg.unitType = TAOS_CFG_UTYPE_NONE;
taosInitConfigOption(cfg);
cfg.option = "balance";
cfg.ptr = &tsEnableBalance;
cfg.valType = TAOS_CFG_VTYPE_INT8;
......
......@@ -3,6 +3,7 @@ using TDengineDriver;
using System.Runtime.InteropServices;
using System.Text;
using System.Collections.Generic;
namespace Test.UtilsTools
{
public class UtilsTools
......@@ -163,4 +164,4 @@ namespace Test.UtilsTools
System.Environment.Exit(0);
}
}
}
\ No newline at end of file
}
package com.taosdata.jdbc;
import java.sql.*;
public class AbstractStatementWrapper extends AbstractStatement{
protected Statement statement;
public AbstractStatementWrapper(Statement statement) {
this.statement = statement;
}
@Override
public ResultSet executeQuery(String sql) throws SQLException {
return statement.executeQuery(sql);
}
@Override
public int executeUpdate(String sql) throws SQLException {
return statement.executeUpdate(sql);
}
@Override
public void close() throws SQLException {
statement.close();
}
@Override
public boolean execute(String sql) throws SQLException {
return statement.execute(sql);
}
@Override
public ResultSet getResultSet() throws SQLException {
return statement.getResultSet();
}
@Override
public int getUpdateCount() throws SQLException {
return statement.getUpdateCount();
}
@Override
public Connection getConnection() throws SQLException {
return statement.getConnection();
}
@Override
public boolean isClosed() throws SQLException {
return statement.isClosed();
}
}
......@@ -6,30 +6,30 @@ import com.taosdata.jdbc.rs.RestfulConnection;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;
/**
* this class is an extension of {@link Statement}. e.g.:
* Statement statement = conn.createStatement();
* SchemalessStatement schemalessStatement = new SchemalessStatement(statement);
* schemalessStatement.execute(sql);
* schemalessStatement.insert(lines, SchemalessProtocolType, SchemalessTimestampType);
* This class is for schemaless lines(line/telnet/json) write to tdengine.
* e.g.:
* SchemalessWriter writer = new SchemalessWriter(connection);
* writer.write(lines, SchemalessProtocolType, SchemalessTimestampType);
*/
public class SchemalessStatement extends AbstractStatementWrapper {
public SchemalessStatement(Statement statement) {
super(statement);
public class SchemalessWriter {
protected Connection connection;
public SchemalessWriter(Connection connection) {
this.connection = connection;
}
/**
* batch insert schemaless lines
* batch schemaless lines write to db
*
* @param lines schemaless lines
* @param protocolType schemaless type {@link SchemalessProtocolType}
* @param timestampType Time precision {@link SchemalessTimestampType}
* @throws SQLException execute insert exception
* @throws SQLException execute exception
*/
public void insert(String[] lines, SchemalessProtocolType protocolType, SchemalessTimestampType timestampType) throws SQLException {
Connection connection = this.getConnection();
public void write(String[] lines, SchemalessProtocolType protocolType, SchemalessTimestampType timestampType) throws SQLException {
if (connection instanceof TSDBConnection) {
TSDBConnection tsdbConnection = (TSDBConnection) connection;
tsdbConnection.getConnector().insertLines(lines, protocolType, timestampType);
......@@ -41,14 +41,27 @@ public class SchemalessStatement extends AbstractStatementWrapper {
}
/**
* only one insert
* only one line writes to db
*
* @param line schemaless line
* @param protocolType schemaless type {@link SchemalessProtocolType}
* @param timestampType Time precision {@link SchemalessTimestampType}
* @throws SQLException execute insert exception
* @throws SQLException execute exception
*/
public void write(String line, SchemalessProtocolType protocolType, SchemalessTimestampType timestampType) throws SQLException {
write(new String[]{line}, protocolType, timestampType);
}
/**
* batch schemaless lines write to db with list
*
* @param lines schemaless list
* @param protocolType schemaless type {@link SchemalessProtocolType}
* @param timestampType Time precision {@link SchemalessTimestampType}
* @throws SQLException execute exception
*/
public void insert(String line, SchemalessProtocolType protocolType, SchemalessTimestampType timestampType) throws SQLException {
insert(new String[]{line}, protocolType, timestampType);
public void write(List<String> lines, SchemalessProtocolType protocolType, SchemalessTimestampType timestampType) throws SQLException {
String[] strings = lines.toArray(new String[0]);
write(strings, protocolType, timestampType);
}
}
......@@ -10,6 +10,8 @@ import org.junit.Before;
import org.junit.Test;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
public class SchemalessInsertTest {
private final String dbname = "test_schemaless_insert";
......@@ -27,10 +29,8 @@ public class SchemalessInsertTest {
"st,t1=3i64,t2=4f64,t3=\"t3\" c1=3i64,c3=L\"passit\",c2=false,c4=4f64 1626006833639000000",
"st,t1=4i64,t3=\"t4\",t2=5f64,t4=5f64 c1=3i64,c3=L\"passitagin\",c2=true,c4=5f64,c5=5f64 1626006833640000000"};
// when
try (Statement statement = conn.createStatement();
SchemalessStatement schemalessStatement = new SchemalessStatement(statement)) {
schemalessStatement.insert(lines, SchemalessProtocolType.LINE, SchemalessTimestampType.NANO_SECONDS);
}
SchemalessWriter writer = new SchemalessWriter(conn);
writer.write(lines, SchemalessProtocolType.LINE, SchemalessTimestampType.NANO_SECONDS);
// then
Statement statement = conn.createStatement();
......@@ -62,10 +62,9 @@ public class SchemalessInsertTest {
};
// when
try (Statement statement = conn.createStatement();
SchemalessStatement schemalessStatement = new SchemalessStatement(statement)) {
schemalessStatement.insert(lines, SchemalessProtocolType.TELNET, SchemalessTimestampType.NOT_CONFIGURED);
}
SchemalessWriter writer = new SchemalessWriter(conn);
writer.write(lines, SchemalessProtocolType.TELNET, SchemalessTimestampType.NOT_CONFIGURED);
// then
Statement statement = conn.createStatement();
......@@ -114,10 +113,8 @@ public class SchemalessInsertTest {
"]";
// when
try (Statement statement = conn.createStatement();
SchemalessStatement schemalessStatement = new SchemalessStatement(statement)) {
schemalessStatement.insert(json, SchemalessProtocolType.JSON, SchemalessTimestampType.NOT_CONFIGURED);
}
SchemalessWriter writer = new SchemalessWriter(conn);
writer.write(json, SchemalessProtocolType.JSON, SchemalessTimestampType.NOT_CONFIGURED);
// then
Statement statement = conn.createStatement();
......@@ -135,6 +132,33 @@ public class SchemalessInsertTest {
statement.close();
}
@Test
public void telnetListInsert() throws SQLException {
// given
List<String> list = new ArrayList<>();
list.add("stb0_0 1626006833 4 host=host0 interface=eth0");
list.add("stb0_1 1626006833 4 host=host0 interface=eth0");
list.add("stb0_2 1626006833 4 host=host0 interface=eth0 id=\"special_name\"");
// when
SchemalessWriter writer = new SchemalessWriter(conn);
writer.write(list, SchemalessProtocolType.TELNET, SchemalessTimestampType.NOT_CONFIGURED);
// then
Statement statement = conn.createStatement();
ResultSet rs = statement.executeQuery("show tables");
Assert.assertNotNull(rs);
ResultSetMetaData metaData = rs.getMetaData();
Assert.assertTrue(metaData.getColumnCount() > 0);
int rowCnt = 0;
while (rs.next()) {
rowCnt++;
}
Assert.assertEquals(list.size(), rowCnt);
rs.close();
statement.close();
}
@Before
public void before() {
String host = "127.0.0.1";
......
......@@ -3,7 +3,6 @@ var conn = taos.connect();
var c1 = conn.cursor();
let stime = new Date();
let interval = 1000;
function convertDateToTS(date) {
let tsArr = date.toISOString().split("T")
return "\"" + tsArr[0] + " " + tsArr[1].substring(0, tsArr[1].length - 1) + "\"";
......
const taos = require('../tdengine');
var conn = taos.connect({ host: "127.0.0.1", user: "root", password: "taosdata", config: "/etc/taos", port: 10 });
var c1 = conn.cursor();
executeUpdate("create database nodedb;");
executeUpdate("create database if not exists nodedb;");
executeUpdate("use nodedb;");
executeUpdate("create table unsigntest(ts timestamp,ut tinyint unsigned,us smallint unsigned,ui int unsigned,ub bigint unsigned,bi bigint);");
executeUpdate("create table if not exists unsigntest(ts timestamp,ut tinyint unsigned,us smallint unsigned,ui int unsigned,ub bigint unsigned,bi bigint);");
executeUpdate("insert into unsigntest values (now, 254,65534,4294967294,18446744073709551614,9223372036854775807);");
executeUpdate("insert into unsigntest values (now, 0,0,0,0,-9223372036854775807);");
executeQuery("select * from unsigntest;");
executeUpdate("drop database nodedb;");
executeUpdate("drop database if exists nodedb;");
function executeUpdate(sql) {
console.log(sql);
......
......@@ -19,6 +19,7 @@
#include "tconfig.h"
#include "dnodeMain.h"
bool dnodeExit = false;
static tsem_t exitSem;
static void siguser1Handler(int32_t signum, void *sigInfo, void *context);
static void siguser2Handler(int32_t signum, void *sigInfo, void *context);
......@@ -182,6 +183,8 @@ static void sigintHandler(int32_t signum, void *sigInfo, void *context) {
syslog(LOG_INFO, "Shut down signal is %d", signum);
syslog(LOG_INFO, "Shutting down TDengine service...");
dnodeExit = true;
// inform main thread to exit
tsem_post(&exitSem);
#ifdef WINDOWS
......
......@@ -30,6 +30,7 @@ typedef struct {
int32_t * vnodeList;
} SOpenVnodeThread;
extern bool dnodeExit;
extern void * tsDnodeTmr;
static void * tsStatusTimer = NULL;
static uint32_t tsRebootTime = 0;
......@@ -222,6 +223,22 @@ static void dnodeProcessStatusRsp(SRpcMsg *pMsg) {
if (clusterId[0] != '\0') {
dnodeSetDropped();
dError("exit zombie dropped dnode");
// warning: only for k8s!
while (tsDnodeNopLoop) {
if (dnodeExit) {
dInfo("Break loop");
return;
}
dInfo("Nop loop");
#ifdef WINDOWS
Sleep(100);
#else
usleep(100000);
#endif
}
exit(EXIT_FAILURE);
}
}
......
###################################################################
# 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
from util.log import *
from util.cases import *
from util.sql import *
from util.dnodes import *
class TDTestCase:
def caseDescription(self):
'''
case1<pxiao>: [TS-854] normal table batch insert with binding same table, different number of columns and timestamp in ascending order
case2<pxiao>: [TS-854] normal table batch insert with binding same table, different number of columns and timestamp in descending order
case3<pxiao>: [TS-854] normal table batch insert with binding same table, different number of columns and timestamp out of order
case4<pxiao>: [TS-854] normal table batch insert with binding same table, different number of columns and same timestamp
case5<pxiao>: [TS-854] normal table batch insert with binding different tables, different number of columns and timestamp in ascending order
case6<pxiao>: [TS-854] normal table batch insert with binding different tables, different number of columns and timestamp in descending order
case7<pxiao>: [TS-854] normal table batch insert with binding different tables, different number of columns and timestamp out of order
case8<pxiao>: [TS-854] normal table batch insert with binding different tables, different number of columns and same timestamp
case9<pxiao>: [TS-854] sub table batch insert with binding same table, different number of columns and timestamp in ascending order
case10<pxiao>: [TS-854] sub table batch insert with binding same table, different number of columns and timestamp in descending order
case11<pxiao>: [TS-854] sub table batch insert with binding same table, different number of columns and timestamp out of order
case12<pxiao>: [TS-854] sub table batch insert with binding same table, different number of columns and same timestamp
case13<pxiao>: [TS-854] sub table batch insert with binding different tables, different number of columns and timestamp in ascending order
case14<pxiao>: [TS-854] sub table batch insert with binding different tables, different number of columns and timestamp in descending order
case15<pxiao>: [TS-854] sub table batch insert with binding different tables, different number of columns and timestamp out of order
case16<pxiao>: [TS-854] sub table batch insert with binding different tables, different number of columns and same timestamp
case17<pxiao>: [TS-854] sub table batch insert with binding same table, different number of columns, different number of tags and timestamp in ascending order
case18<pxiao>: [TS-854] sub table batch insert with binding same table, different number of columns, different number of tags and timestamp in descending order
case19<pxiao>: [TS-854] sub table batch insert with binding same table, different number of columns, different number of tags and timestamp out of order
case20<pxiao>: [TS-854] sub table batch insert with binding same table, different number of columns, different number of tags and same timestamp
case21<pxiao>: [TS-854] sub table batch insert with binding different tables, different number of columns, different number of tags and timestamp in ascending order
case22<pxiao>: [TS-854] sub table batch insert with binding different tables, different number of columns, different number of tags and timestamp in descending order
case23<pxiao>: [TS-854] sub table batch insert with binding different tables, different number of columns, different number of tags and timestamp out of order
case24<pxiao>: [TS-854] sub table batch insert with binding different tables, different number of columns, different number of tags and same timestamp
'''
return
def init(self, conn, logSql):
tdLog.debug("start to execute %s" % __file__)
tdSql.init(conn.cursor(), logSql)
self.ts = 1607817000000
def run(self):
tdSql.prepare()
tdSql.execute("create table tb1(ts timestamp, c1 double, c2 double, c3 double, c4 double)")
args = [(self.ts + 1000, self.ts + 3000, self.ts + 5000, self.ts + 7000),
(self.ts + 8000, self.ts + 6000, self.ts + 4000, self.ts + 2000),
(self.ts - 1000 , self.ts - 5000, self.ts - 3000, self.ts - 8000),
(self.ts, self.ts, self.ts, self.ts)]
# case 1, 2, 3, 4
tdLog.info("test case for case 1, 2, 3, 4")
sql = "insert into tb1(ts, c1) values(%d, 0.0) tb1(ts, c1) values(%d, 0.0) tb1(ts, c1) values(%d, 0.0) tb1(ts, c1, c2, c3, c4) values(%d, 0.0, 0.0, 0.0, 0.0)"
i = 1
rows = 0
for arg in args:
tdLog.info("test case for case %d" % i)
tdLog.info(sql % arg)
tdSql.execute(sql % arg)
if i == 4:
rows = rows + 1
else:
rows = rows + 4
tdSql.query("select * from tb1")
tdSql.checkRows(rows)
i = i + 1
# restart taosd and check again
tdDnodes.stop(1)
tdDnodes.start(1)
tdSql.query("select * from tb1")
tdSql.checkRows(rows)
# case 5, 6, 7, 8
tdSql.execute("create table tb2(ts timestamp, c1 int, c2 int, c3 int, c4 int)")
tdSql.execute("create table tb3(ts timestamp, c1 double, c2 double, c3 double, c4 double)")
tdLog.info("test case for case 5, 6, 7, 8")
sql = "insert into tb2(ts, c1) values(%d, 0) tb2(ts, c1, c2, c3, c4) values(%d, 0, 0, 0, 0) tb3(ts, c2) values(%d, 0.0) tb3(ts, c1, c2, c3, c4) values(%d, 0.0, 0.0, 0.0, 0.0)"
rows = 0
for arg in args:
tdLog.info("test case for case %d" % i)
tdLog.info(sql % arg)
tdSql.execute(sql % arg)
tdSql.query("select * from tb2")
if i == 8:
rows = rows + 1
else:
rows = rows + 2
tdSql.query("select * from tb2")
tdSql.checkRows(rows)
tdSql.query("select * from tb3")
tdSql.checkRows(rows)
i = i + 1
# restart taosd and check again
tdDnodes.stop(1)
tdDnodes.start(1)
tdSql.query("select * from tb2")
tdSql.checkRows(rows)
tdSql.query("select * from tb3")
tdSql.checkRows(rows)
# case 9, 10, 11, 12
tdSql.execute("create table stb(ts timestamp, c1 double, c2 double, c3 double, c4 double) tags(t1 nchar(20))")
tdLog.info("test case for case 9, 10, 11, 12")
sql = "insert into t1(ts, c1) using stb tags('tag1') values(%d, 0.0) t1(ts, c1) using stb tags('tag1') values(%d, 0.0) t1(ts, c1) using stb tags('tag1') values(%d, 0.0) t1(ts, c1, c2, c3, c4) using stb tags('tag1') values(%d, 0.0, 0.0, 0.0, 0.0)"
rows = 0
for arg in args:
tdLog.info("test case for case %d" % i)
tdLog.info(sql % arg)
tdSql.execute(sql % arg)
if i == 12:
rows = rows + 1
else:
rows = rows + 4
tdSql.query("select * from stb")
tdSql.checkRows(rows)
i = i + 1
# restart taosd and check again
tdDnodes.stop(1)
tdDnodes.start(1)
tdSql.query("select * from stb")
tdSql.checkRows(rows)
# case 13, 14, 15, 16
tdSql.execute("create table stb2(ts timestamp, c1 int, c2 int, c3 int, c4 int) tags(t1 nchar(20))")
tdSql.execute("create table stb3(ts timestamp, c1 double, c2 double, c3 double, c4 double) tags(t1 binary(20))")
tdLog.info("test case for case 13, 14, 15, 16")
sql = "insert into t2(ts, c1) using stb2 tags('tag2') values(%d, 0) t2(ts, c1, c2, c3, c4) using stb2 tags('tag2') values(%d, 0, 0, 0, 0) t3(ts, c2) using stb3 tags('tag3') values(%d, 0.0) t3(ts, c1, c2, c3, c4) using stb3 tags('tag3') values(%d, 0.0, 0.0, 0.0, 0.0)"
rows = 0
for arg in args:
tdLog.info("test case for case %d" % i)
tdLog.info(sql % arg)
tdSql.execute(sql % arg)
if i == 16:
rows = rows + 1
else:
rows = rows + 2
tdSql.query("select * from stb2")
tdSql.checkRows(rows)
tdSql.query("select * from stb3")
tdSql.checkRows(rows)
i = i + 1
# restart taosd and check again
tdDnodes.stop(1)
tdDnodes.start(1)
tdSql.query("select * from stb2")
tdSql.checkRows(rows)
tdSql.query("select * from stb3")
tdSql.checkRows(rows)
# case 17, 18, 19, 20
tdSql.execute("drop table if exists stb")
tdSql.execute("create table stb(ts timestamp, c1 double, c2 double, c3 double, c4 double) tags(t1 nchar(20), t2 int, t3 binary(20))")
tdLog.info("test case for case 17, 18, 19, 20")
sql = "insert into t1(ts, c1) using stb(t1) tags('tag1') values(%d, 0.0) t1(ts, c1) using stb(t2) tags(1) values(%d, 0.0) t1(ts, c1) using stb(t1, t2) tags('tag1', 1) values(%d, 0.0) t1(ts, c1, c2, c3, c4) using stb(t1, t2, t3) tags('tag1', 1, 'tag3') values(%d, 0.0, 0.0, 0.0, 0.0)"
rows = 0
for arg in args:
tdLog.info("test case for case %d" % i)
tdLog.info(sql % arg)
tdSql.execute(sql % arg)
if i == 20:
rows = rows + 1
else:
rows = rows + 4
tdSql.query("select * from stb")
tdSql.checkRows(rows)
i = i + 1
# restart taosd and check again
tdDnodes.stop(1)
tdDnodes.start(1)
tdSql.query("select * from stb")
tdSql.checkRows(rows)
# case 21, 22, 23, 24
tdSql.execute("drop table if exists stb2")
tdSql.execute("drop table if exists stb3")
tdSql.execute("create table stb2(ts timestamp, c1 int, c2 int, c3 int, c4 int) tags(t1 nchar(20), t2 int)")
tdSql.execute("create table stb3(ts timestamp, c1 double, c2 double, c3 double, c4 double) tags(t1 binary(20), t2 double)")
tdLog.info("test case for case 21, 22, 23, 24")
sql = "insert into t2(ts, c1) using stb2(t1) tags('tag2') values(%d, 0) t2(ts, c1, c2, c3, c4) using stb2(t1, t2) tags('tag2', 1) values(%d, 0, 0, 0, 0) t3(ts, c2) using stb3(t1) tags('tag3') values(%d, 0.0) t3(ts, c1, c2, c3, c4) using stb3(t1, t2) tags('tag3', 0.0) values(%d, 0.0, 0.0, 0.0, 0.0)"
rows = 0
for arg in args:
tdLog.info("test case for case %d" % i)
tdLog.info(sql % arg)
tdSql.execute(sql % arg)
if i == 24:
rows = rows + 1
else:
rows = rows + 2
tdSql.query("select * from stb2")
tdSql.checkRows(rows)
tdSql.query("select * from stb3")
tdSql.checkRows(rows)
i = i + 1
# restart taosd and check again
tdDnodes.stop(1)
tdDnodes.start(1)
tdSql.query("select * from stb2")
tdSql.checkRows(rows)
tdSql.query("select * from stb3")
tdSql.checkRows(rows)
def stop(self):
tdSql.close()
tdLog.success("%s successfully executed" % __file__)
tdCases.addWindows(__file__, TDTestCase())
tdCases.addLinux(__file__, TDTestCase())
python3 test.py -f 0-management/3-tag/json_tag.py
python3 test.py -f 1-insert/0-sql/basic.py
python3 test.py -f 1-insert/0-sql/batchInsert.py
\ No newline at end of file
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace TDengineDriver
{
enum TDengineDataType
{
TSDB_DATA_TYPE_NULL = 0, // 1 bytes
TSDB_DATA_TYPE_BOOL = 1, // 1 bytes
TSDB_DATA_TYPE_TINYINT = 2, // 1 bytes
TSDB_DATA_TYPE_SMALLINT = 3, // 2 bytes
TSDB_DATA_TYPE_INT = 4, // 4 bytes
TSDB_DATA_TYPE_BIGINT = 5, // 8 bytes
TSDB_DATA_TYPE_FLOAT = 6, // 4 bytes
TSDB_DATA_TYPE_DOUBLE = 7, // 8 bytes
TSDB_DATA_TYPE_BINARY = 8, // string
TSDB_DATA_TYPE_TIMESTAMP = 9,// 8 bytes
TSDB_DATA_TYPE_NCHAR = 10, // unicode string
TSDB_DATA_TYPE_UTINYINT = 11,// 1 byte
TSDB_DATA_TYPE_USMALLINT= 12,// 2 bytes
TSDB_DATA_TYPE_UINT = 13, // 4 bytes
TSDB_DATA_TYPE_UBIGINT= 14 // 8 bytes
}
enum TDengineInitOption
{
TSDB_OPTION_LOCALE = 0,
TSDB_OPTION_CHARSET = 1,
TSDB_OPTION_TIMEZONE = 2,
TDDB_OPTION_CONFIGDIR = 3,
TDDB_OPTION_SHELL_ACTIVITY_TIMER = 4
}
class TDengineMeta
{
public string name;
public short size;
public byte type;
public string TypeName()
{
switch ((TDengineDataType)type)
{
case TDengineDataType.TSDB_DATA_TYPE_BOOL:
return "BOOL";
case TDengineDataType.TSDB_DATA_TYPE_TINYINT:
return "TINYINT";
case TDengineDataType.TSDB_DATA_TYPE_SMALLINT:
return "SMALLINT";
case TDengineDataType.TSDB_DATA_TYPE_INT:
return "INT";
case TDengineDataType.TSDB_DATA_TYPE_BIGINT:
return "BIGINT";
case TDengineDataType.TSDB_DATA_TYPE_UTINYINT:
return "TINYINT UNSIGNED";
case TDengineDataType.TSDB_DATA_TYPE_USMALLINT:
return "SMALLINT UNSIGNED";
case TDengineDataType.TSDB_DATA_TYPE_UINT:
return "INT UNSIGNED";
case TDengineDataType.TSDB_DATA_TYPE_UBIGINT:
return "BIGINT UNSIGNED";
case TDengineDataType.TSDB_DATA_TYPE_FLOAT:
return "FLOAT";
case TDengineDataType.TSDB_DATA_TYPE_DOUBLE:
return "DOUBLE";
case TDengineDataType.TSDB_DATA_TYPE_BINARY:
return "STRING";
case TDengineDataType.TSDB_DATA_TYPE_TIMESTAMP:
return "TIMESTAMP";
case TDengineDataType.TSDB_DATA_TYPE_NCHAR:
return "NCHAR";
default:
return "undefine";
}
}
}
class TDengine
{
public const int TSDB_CODE_SUCCESS = 0;
[DllImport("taos", EntryPoint = "taos_init", CallingConvention = CallingConvention.Cdecl)]
static extern public void Init();
[DllImport("taos", EntryPoint = "taos_cleanup", CallingConvention = CallingConvention.Cdecl)]
static extern public void Cleanup();
[DllImport("taos", EntryPoint = "taos_options", CallingConvention = CallingConvention.Cdecl)]
static extern public void Options(int option, string value);
[DllImport("taos", EntryPoint = "taos_connect", CallingConvention = CallingConvention.Cdecl)]
static extern public IntPtr Connect(string ip, string user, string password, string db, short port);
[DllImport("taos", EntryPoint = "taos_errstr", CallingConvention = CallingConvention.Cdecl)]
static extern private IntPtr taos_errstr(IntPtr res);
static public string Error(IntPtr res)
{
IntPtr errPtr = taos_errstr(res);
return Marshal.PtrToStringAnsi(errPtr);
}
[DllImport("taos", EntryPoint = "taos_errno", CallingConvention = CallingConvention.Cdecl)]
static extern public int ErrorNo(IntPtr res);
[DllImport("taos", EntryPoint = "taos_query", CallingConvention = CallingConvention.Cdecl)]
static extern public IntPtr Query(IntPtr conn, string sqlstr);
[DllImport("taos", EntryPoint = "taos_affected_rows", CallingConvention = CallingConvention.Cdecl)]
static extern public int AffectRows(IntPtr res);
[DllImport("taos", EntryPoint = "taos_field_count", CallingConvention = CallingConvention.Cdecl)]
static extern public int FieldCount(IntPtr res);
[DllImport("taos", EntryPoint = "taos_fetch_fields", CallingConvention = CallingConvention.Cdecl)]
static extern private IntPtr taos_fetch_fields(IntPtr res);
static public List<TDengineMeta> FetchFields(IntPtr res)
{
const int fieldSize = 68;
List<TDengineMeta> metas = new List<TDengineMeta>();
if (res == IntPtr.Zero)
{
return metas;
}
int fieldCount = FieldCount(res);
IntPtr fieldsPtr = taos_fetch_fields(res);
for (int i = 0; i < fieldCount; ++i)
{
int offset = i * fieldSize;
TDengineMeta meta = new TDengineMeta();
meta.name = Marshal.PtrToStringAnsi(fieldsPtr + offset);
meta.type = Marshal.ReadByte(fieldsPtr + offset + 65);
meta.size = Marshal.ReadInt16(fieldsPtr + offset + 66);
metas.Add(meta);
}
return metas;
}
[DllImport("taos", EntryPoint = "taos_fetch_row", CallingConvention = CallingConvention.Cdecl)]
static extern public IntPtr FetchRows(IntPtr res);
[DllImport("taos", EntryPoint = "taos_free_result", CallingConvention = CallingConvention.Cdecl)]
static extern public IntPtr FreeResult(IntPtr res);
[DllImport("taos", EntryPoint = "taos_close", CallingConvention = CallingConvention.Cdecl)]
static extern public int Close(IntPtr taos);
//get precision in restultset
[DllImport("taos", EntryPoint = "taos_result_precision", CallingConvention = CallingConvention.Cdecl)]
static extern public int ResultPrecision(IntPtr taos);
//schemaless API
[DllImport("taos",SetLastError = true, EntryPoint = "taos_schemaless_insert", CallingConvention = CallingConvention.Cdecl)]
static extern public IntPtr SchemalessInsert(IntPtr taos, string[] lines, int numLines, int protocol, int precision);
}
}
......@@ -168,7 +168,7 @@ namespace TDengineDriver
host = this.GetArgumentAsString(argv, "-h", "127.0.0.1");
user = this.GetArgumentAsString(argv, "-u", "root");
password = this.GetArgumentAsString(argv, "-p", "taosdata");
dbName = this.GetArgumentAsString(argv, "-d", "db");
dbName = this.GetArgumentAsString(argv, "-d", "tdengint_test_cs");
stableName = this.GetArgumentAsString(argv, "-s", "st");
tablePrefix = this.GetArgumentAsString(argv, "-t", "t");
isInsertData = this.GetArgumentAsLong(argv, "-w", 0, 1, 1) != 0;
......
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="TDengine.Connector" Version="1.0.2" />
</ItemGroup>
</Project>
......@@ -118,7 +118,7 @@ namespace TDengineDriver
port = (short)this.GetArgumentAsLong(argv, "-p", 0, 65535, 6030);
user = this.GetArgumentAsString(argv, "-u", "root");
password = this.GetArgumentAsString(argv, "-P", "taosdata");
dbName = this.GetArgumentAsString(argv, "-d", "db");
dbName = this.GetArgumentAsString(argv, "-d", "taosdemo_cs");
stablePrefix = this.GetArgumentAsString(argv, "-s", "st");
tablePrefix = this.GetArgumentAsString(argv, "-m", "t");
isInsertOnly = this.GetArgumentAsFlag(argv, "-x", true);
......
......@@ -53,7 +53,7 @@
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.14.1</version>
<version>2.15.0</version>
</dependency>
<!-- proxool -->
<dependency>
......
......@@ -88,7 +88,7 @@
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.14.1</version>
<version>2.15.0</version>
</dependency>
<!-- junit -->
<dependency>
......
......@@ -17,8 +17,11 @@ import sys
import getopt
import os
from fabric2 import Connection
sys.path.append("pytest")
import importlib
import re
class CatalogGen:
def __init__(self, CaseDirList, CatalogName, DirDepth):
......@@ -31,7 +34,7 @@ class CatalogGen:
for i in self.CaseDirList:
self.GetCatalog(i)
self.CollectLog(i)
print('Catalog Generation done')
print("Catalog Generation done")
def CollectLog(self, CaseDir):
DirorFiles = os.listdir(CaseDir)
......@@ -43,12 +46,14 @@ class CatalogGen:
else:
if i == self.CatalogName and fileName not in self.blacklist:
self.blacklist.append(fileName)
with open(fileName, "r") as f :
with open(fileName, "r") as f:
Catalog = f.read()
title = CaseDir.split("/")[-1]
TitleLevel = CaseDir.count("/")
with open(os.path.dirname(CaseDir) + '/' + self.CatalogName, "a") as f :
f.write("#" * TitleLevel + ' %s\n' % title)
with open(
os.path.dirname(CaseDir) + "/" + self.CatalogName, "a"
) as f:
f.write("#" * TitleLevel + " %s\n" % title)
f.write(Catalog)
def GetCatalog(self, CaseDir):
......@@ -58,16 +63,20 @@ class CatalogGen:
fileName = os.path.join(root, file)
moduleName = fileName.replace(".py", "").replace("/", ".")
uModule = importlib.import_module(moduleName)
title = file.split('.')[0]
TitleLevel = root.count('/') + 1
title = file.split(".")[0]
TitleLevel = root.count("/") + 1
try:
ucase = uModule.TDTestCase()
with open(root + '/' + self.CatalogName, 'a') as f:
f.write('#'*TitleLevel + ' %s\n' % title)
for i in ucase.caseDescription.__doc__.split('\n'):
if i.lstrip() == '':continue
f.write('* ' + i.strip()+'\n')
except :
with open(root + "/" + self.CatalogName, "a") as f:
f.write("#" * TitleLevel + " %s\n" % title)
for i in ucase.caseDescription.__doc__.split("\n"):
if i.lstrip() == "":
continue
if re.match("^case.*:", i.strip()):
f.write("* " + i.strip() + "\n")
else:
f.write(i.strip() + "\n")
except:
print(fileName)
def CleanCatalog(self):
......@@ -75,57 +84,61 @@ class CatalogGen:
for root, dirs, files in os.walk(i):
for file in files:
if file == self.CatalogName:
os.remove(root + '/' + self.CatalogName)
print('clean is done')
os.remove(root + "/" + self.CatalogName)
print("clean is done")
if __name__ == "__main__":
CaseDirList = []
CatalogName = ''
CatalogName = ""
DirDepth = 0
generate = True
delete = True
opts, args = getopt.gnu_getopt(sys.argv[1:], 'd:c:v:n:th')
opts, args = getopt.gnu_getopt(sys.argv[1:], "d:c:v:n:th")
for key, value in opts:
if key in ['-h', '--help']:
if key in ["-h", "--help"]:
print("A collection of test cases catalog written using Python")
print(
'A collection of test cases catalog written using Python')
print("-d root dir of test case files written by Python, default: system-test,develop-test")
print('-c catalog file name, default: catalog.md')
print('-v dir depth of test cases.default: 5')
print('-n <True:False> generate')
print('-r <True:False> delete')
"-d root dir of test case files written by Python, default: system-test,develop-test"
)
print("-c catalog file name, default: catalog.md")
print("-v dir depth of test cases.default: 5")
print("-n <True:False> generate")
print("-r <True:False> delete")
sys.exit(0)
if key in ['-d']:
CaseDirList = value.split(',')
if key in ["-d"]:
CaseDirList = value.split(",")
if key in ['-c']:
if key in ["-c"]:
CatalogName = value
if key in ['-v']:
if key in ["-v"]:
DirDepth = int(value)
if key in ['-n']:
if (value.upper() == "TRUE"):
if key in ["-n"]:
if value.upper() == "TRUE":
generate = True
elif (value.upper() == "FALSE"):
elif value.upper() == "FALSE":
generate = False
if key in ['-r']:
if (value.upper() == "TRUE"):
if key in ["-r"]:
if value.upper() == "TRUE":
delete = True
elif (value.upper() == "FALSE"):
elif value.upper() == "FALSE":
delete = False
print(CaseDirList, CatalogName)
if CaseDirList == [] :
CaseDirList = ['system-test', 'develop-test']
if CatalogName == '' :
CatalogName = 'catalog.md'
if CaseDirList == []:
CaseDirList = ["system-test", "develop-test"]
if CatalogName == "":
CatalogName = "catalog.md"
if DirDepth == 0:
DirDepth = 5
print('opt:\n\tcatalogname: %s\n\tcasedirlist: %s\n\tdepth: %d\n\tgenerate: %s\n\tdelete: %s'
% (CatalogName, ','.join(CaseDirList), DirDepth, generate, delete))
print(
"opt:\n\tcatalogname: %s\n\tcasedirlist: %s\n\tdepth: %d\n\tgenerate: %s\n\tdelete: %s"
% (CatalogName, ",".join(CaseDirList), DirDepth, generate, delete)
)
f = CatalogGen(CaseDirList, CatalogName, DirDepth)
if delete:
f.CleanCatalog()
......
......@@ -8360,6 +8360,45 @@ class TDTestCase:
sql += "where ts >= '%s' AND ts <= '%s' range('%s' , '%s') EVERY(1s) FILL(NULL);" % (self.ts , self.ts + 10000 , self.ts + 150000 , self.ts + 200000)
datacheck = tdSql.error(sql)
# TD-10736 Exception use case for coredump
tdSql.execute("create database db_except;")
tdSql.execute("use db_except;")
tdSql.execute("create table tb (ts timestamp, c1 int);")
tdSql.execute("insert into tb values ('2021-10-01 08:00:00.000' ,1);")
tdSql.execute("insert into tb values ('2021-10-01 08:00:01.000' ,2);")
tdSql.execute("insert into tb values ('2021-10-01 08:00:02.000' ,3);")
tdSql.execute("insert into tb values ('2021-10-01 08:00:03.000' ,4);")
tdSql.execute("create stable stb (ts timestamp, c1 int) tags (id int);")
tdSql.execute("insert into sub_1 using stb tags (1) values ('2021-10-01 08:00:00.000' ,1);")
tdSql.execute("insert into sub_1 using stb tags (1) values ('2021-10-01 08:00:01.000' ,2);")
tdSql.execute("insert into sub_2 using stb tags (1) values ('2021-10-01 08:00:00.000' ,3);")
tdSql.execute("insert into sub_2 using stb tags (1) values ('2021-10-01 08:00:01.000' ,4);")
tdSql.execute("insert into sub_3 using stb tags (1) values ('2021-10-01 08:00:01.000' ,1);")
tdSql.execute("insert into sub_3 using stb tags (1) values ('2021-10-01 08:00:02.000' ,2);")
tdSql.execute("insert into sub_3 using stb tags (1) values ('2021-10-01 08:00:03.000' ,3);")
tdSql.execute("insert into sub_3 using stb tags (1) values ('2021-10-01 08:00:04.000' ,4);")
tdSql.query("select interp(c1) from tb where ts = '2021-10-01 08:00:00.000' every(1s); ")
tdSql.checkData(0,1,1)
tdSql.query("select interp(c1) from tb where ts = '2021-10-01 08:00:98.000' every(1s); ")
tdSql.checkRows(0)
tdSql.query("select interp(c1) from sub_1 where ts = '2021-10-01 08:00:00.000' every(1s); ")
tdSql.checkData(0,1,1)
tdSql.query("select interp(c1) from sub_1 where ts = '2021-10-01 08:00:98.000' every(1s); ")
tdSql.checkRows(0)
tdSql.error("select interp(c1) from stb where ts = '2021-10-01 08:00:00.000' every(1s); ")
tdSql.error("select interp(c1) from stb where ts = '2021-10-01 08:00:98.000' every(1s); ")
tdSql.query("select interp(c1) from stb where ts = '2021-10-01 08:00:00.000' every(1s) group by tbname; ")
tdSql.checkRows(2)
tdSql.query("select interp(c1) from stb where ts = '2021-10-01 08:00:98.000' every(1s) group by tbname; ")
tdSql.checkRows(0)
# Nested Query + where + range + FILL(NULL) + EVERY( s)(3)
# sql = "select * from (select %s from stable_1 where ts BETWEEN '%s' AND '%s' range('%s' , '%s') EVERY(1s) FILL(NULL) group by tbname) z1," % (interp_select , self.ts , self.ts + 10000 , self.ts - 10000 , self.ts + 100000)
# sql += "(select %s from stable_2 where ts BETWEEN '%s' AND '%s' range('%s' , '%s') EVERY(1s) FILL(NULL) group by tbname) z2 where z1.ts=z2.ts ;" % (interp_select , self.ts , self.ts + 10000 , self.ts - 10000 , self.ts + 100000)
......
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册