diff --git a/documentation20/cn/08.connector/01.java/docs.md b/documentation20/cn/08.connector/01.java/docs.md
index e6d214c74d3367d814e0022d4c6a147c4a44b326..fb47d79268fe0a4fa84b444187a5aa700a687027 100644
--- a/documentation20/cn/08.connector/01.java/docs.md
+++ b/documentation20/cn/08.connector/01.java/docs.md
@@ -49,6 +49,7 @@ TDengine 的 JDBC 驱动实现尽可能与关系型数据库驱动保持一致
+注意:与 JNI 方式不同,RESTful 接口是无状态的,因此 `USE db_name` 指令没有效果,RESTful 下所有对表名、超级表名的引用都需要指定数据库名前缀。
## 如何获取 taos-jdbcdriver
@@ -551,7 +552,7 @@ TDengine 目前支持时间戳、数字、字符、布尔类型,与 Java 对
| BIGINT | java.lang.Long |
| FLOAT | java.lang.Float |
| DOUBLE | java.lang.Double |
-| SMALLINT | java.lang.Short |
+| SMALLINT | java.lang.Short |
| TINYINT | java.lang.Byte |
| BOOL | java.lang.Boolean |
| BINARY | byte array |
diff --git a/documentation20/cn/08.connector/docs.md b/documentation20/cn/08.connector/docs.md
index c74d1ebc3e651ab4e8747d8d1117233392d0b4b4..f26928eec7a0780a937f2b618a543926a1794e8a 100644
--- a/documentation20/cn/08.connector/docs.md
+++ b/documentation20/cn/08.connector/docs.md
@@ -585,7 +585,9 @@ conn.close()
## RESTful Connector
-为支持各种不同类型平台的开发,TDengine提供符合REST设计标准的API,即RESTful API。为最大程度降低学习成本,不同于其他数据库RESTful API的设计方法,TDengine直接通过HTTP POST 请求BODY中包含的SQL语句来操作数据库,仅需要一个URL。RESTful连接器的使用参见[视频教程](https://www.taosdata.com/blog/2020/11/11/1965.html)。
+为支持各种不同类型平台的开发,TDengine 提供符合 REST 设计标准的 API,即 RESTful API。为最大程度降低学习成本,不同于其他数据库 RESTful API 的设计方法,TDengine 直接通过 HTTP POST 请求 BODY 中包含的 SQL 语句来操作数据库,仅需要一个 URL。RESTful 连接器的使用参见[视频教程](https://www.taosdata.com/blog/2020/11/11/1965.html)。
+
+注意:与标准连接器的一个区别是,RESTful 接口是无状态的,因此 `USE db_name` 指令没有效果,所有对表名、超级表名的引用都需要指定数据库名前缀。
### HTTP请求格式
diff --git a/documentation20/cn/12.taos-sql/docs.md b/documentation20/cn/12.taos-sql/docs.md
index abbe7d8a0a9345c4145c0b65f43e56d5d6039d53..b0268a9ed4497d7f6d8d5511fa85494399e361d2 100644
--- a/documentation20/cn/12.taos-sql/docs.md
+++ b/documentation20/cn/12.taos-sql/docs.md
@@ -144,7 +144,7 @@ TDengine 缺省的时间戳是毫秒精度,但通过在 CREATE DATABASE 时传
```
UPDATE 参数控制是否允许更新数据。缺省值为 0,取值范围为 [0, 1]。0 表示会直接丢弃后写入的相同时间戳的数据;1 表示会使用后写入的数据覆盖已有的相同时间戳的数据。
- **Tips**: 以上所有参数修改后都可以用show databases来确认是否修改成功。另外,从 2.1.1.0 版本开始,修改这些参数后无需重启服务器即可生效。
+ **Tips**: 以上所有参数修改后都可以用show databases来确认是否修改成功。另外,从 2.1.3.0 版本开始,修改这些参数后无需重启服务器即可生效。
- **显示系统所有数据库**
@@ -263,6 +263,14 @@ TDengine 缺省的时间戳是毫秒精度,但通过在 CREATE DATABASE 时传
```
如果表是通过超级表创建,更改表结构的操作只能对超级表进行。同时针对超级表的结构更改对所有通过该结构创建的表生效。对于不是通过超级表创建的表,可以直接修改表结构。
+- **表修改列宽**
+
+ ```mysql
+ ALTER TABLE tb_name MODIFY COLUMN field_name data_type(length);
+ ```
+ 如果数据列的类型是可变长格式(BINARY 或 NCHAR),那么可以使用此指令修改其宽度(只能改大,不能改小)。(2.1.3.0 版本新增)
+ 如果表是通过超级表创建,更改表结构的操作只能对超级表进行。同时针对超级表的结构更改对所有通过该结构创建的表生效。对于不是通过超级表创建的表,可以直接修改表结构。
+
## 超级表STable管理
注意:在 2.0.15.0 及以后的版本中,开始支持 STABLE 保留字。也即,在本节后文的指令说明中,CREATE、DROP、ALTER 三个指令在老版本中保留字需写作 TABLE 而不是 STABLE。
@@ -323,6 +331,13 @@ TDengine 缺省的时间戳是毫秒精度,但通过在 CREATE DATABASE 时传
ALTER STABLE stb_name DROP COLUMN field_name;
```
+- **超级表修改列宽**
+
+ ```mysql
+ ALTER STABLE stb_name MODIFY COLUMN field_name data_type(length);
+ ```
+ 如果数据列的类型是可变长格式(BINARY 或 NCHAR),那么可以使用此指令修改其宽度(只能改大,不能改小)。(2.1.3.0 版本新增)
+
## 超级表 STable 中 TAG 管理
- **添加标签**
@@ -346,6 +361,13 @@ TDengine 缺省的时间戳是毫秒精度,但通过在 CREATE DATABASE 时传
```
修改超级表的标签名,从超级表修改某个标签名后,该超级表下的所有子表也会自动更新该标签名。
+- **修改标签列宽度**
+
+ ```mysql
+ ALTER STABLE stb_name MODIFY TAG tag_name data_type(length);
+ ```
+ 如果标签的类型是可变长格式(BINARY 或 NCHAR),那么可以使用此指令修改其宽度(只能改大,不能改小)。(2.1.3.0 版本新增)
+
- **修改子表标签值**
```mysql
diff --git a/packaging/check_package.sh b/packaging/check_package.sh
new file mode 100755
index 0000000000000000000000000000000000000000..e4d783d2f917abff1cd2aaff3714ce6c7edd5039
--- /dev/null
+++ b/packaging/check_package.sh
@@ -0,0 +1,245 @@
+#!/bin/bash
+#
+# This file is used to install database on linux systems. The operating system
+# is required to use systemd to manage services at boot
+
+set -e
+#set -x
+
+verMode=edge
+pagMode=full
+
+iplist=""
+serverFqdn=""
+
+# -----------------------Variables definition---------------------
+script_dir="../release"
+# Dynamic directory
+data_dir="/var/lib/taos"
+log_dir="/var/log/taos"
+
+data_link_dir="/usr/local/taos/data"
+log_link_dir="/usr/local/taos/log"
+
+cfg_install_dir="/etc/taos"
+
+bin_link_dir="/usr/bin"
+lib_link_dir="/usr/lib"
+lib64_link_dir="/usr/lib64"
+inc_link_dir="/usr/include"
+
+#install main path
+install_main_dir="/usr/local/taos"
+
+# old bin dir
+sbin_dir="/usr/local/taos/bin"
+
+temp_version=""
+fin_result=""
+
+service_config_dir="/etc/systemd/system"
+nginx_port=6060
+nginx_dir="/usr/local/nginxd"
+
+# Color setting
+RED='\033[0;31m'
+GREEN='\033[1;32m'
+GREEN_DARK='\033[0;32m'
+GREEN_UNDERLINE='\033[4;32m'
+NC='\033[0m'
+
+csudo=""
+if command -v sudo > /dev/null; then
+ csudo="sudo"
+fi
+
+# ============================= get input parameters =================================================
+
+# install.sh -v [server | client] -e [yes | no] -i [systemd | service | ...]
+
+# set parameters by default value
+interactiveFqdn=yes # [yes | no]
+verType=server # [server | client]
+initType=systemd # [systemd | service | ...]
+
+while getopts "hv:d:" arg
+do
+ case $arg in
+ d)
+ #echo "interactiveFqdn=$OPTARG"
+ script_dir=$( echo $OPTARG )
+ ;;
+ h)
+ echo "Usage: `basename $0` -d scripy_path"
+ exit 0
+ ;;
+ ?) #unknow option
+ echo "unkonw argument"
+ exit 1
+ ;;
+ esac
+done
+
+#echo "verType=${verType} interactiveFqdn=${interactiveFqdn}"
+
+function kill_process() {
+ pid=$(ps -ef | grep "$1" | grep -v "grep" | awk '{print $2}')
+ if [ -n "$pid" ]; then
+ ${csudo} kill -9 $pid || :
+ fi
+}
+
+function check_file() {
+ #check file whether exists
+ if [ ! -e $1/$2 ];then
+ echo -e "$1/$2 \033[31mnot exists\033[0m!quit"
+ fin_result=$fin_result"\033[31m$temp_version\033[0m test failed!\n"
+ echo -e $fin_result
+ exit 8
+ fi
+}
+
+function get_package_name() {
+ var=$1
+ if [[ $1 =~ 'aarch' ]];then
+ echo ${var::-21}
+ else
+ echo ${var::-17}
+ fi
+}
+function check_link() {
+ #check Link whether exists or broken
+ if [ -L $1 ] ; then
+ if [ ! -e $1 ] ; then
+ echo -e "$1 \033[31Broken link\033[0m"
+ fin_result=$fin_result"\033[31m$temp_version\033[0m test failed!\n"
+ echo -e $fin_result
+ exit 8
+ fi
+ else
+ echo -e "$1 \033[31mnot exists\033[0m!quit"
+ fin_result=$fin_result"\033[31m$temp_version\033[0m test failed!\n"
+ echo -e $fin_result
+ exit 8
+ fi
+}
+
+function check_main_path() {
+ #check install main dir and all sub dir
+ main_dir=("" "cfg" "bin" "connector" "driver" "examples" "include" "init.d")
+ for i in ${main_dir[@]};do
+ check_file ${install_main_dir} $i
+ done
+ if [ "$verMode" == "cluster" ]; then
+ nginx_main_dir=("admin" "conf" "html" "sbin" "logs")
+ for i in ${nginx_main_dir[@]};do
+ check_file ${nginx_dir} $i
+ done
+ fi
+ echo -e "Check main path:\033[32mOK\033[0m!"
+}
+
+function check_bin_path() {
+ # check install bin dir and all sub dir
+ bin_dir=("taos" "taosd" "taosdemo" "taosdump" "remove.sh" "tarbitrator" "set_core.sh")
+ for i in ${bin_dir[@]};do
+ check_file ${sbin_dir} $i
+ done
+ lbin_dir=("taos" "taosd" "taosdemo" "taosdump" "rmtaos" "tarbitrator" "set_core")
+ for i in ${lbin_dir[@]};do
+ check_link ${bin_link_dir}/$i
+ done
+ if [ "$verMode" == "cluster" ]; then
+ check_file ${nginx_dir}/sbin nginx
+ fi
+ echo -e "Check bin path:\033[32mOK\033[0m!"
+}
+
+
+function check_lib_path() {
+ # check all links
+ check_link ${lib_link_dir}/libtaos.so
+ check_link ${lib_link_dir}/libtaos.so.1
+
+ if [[ -d ${lib64_link_dir} ]]; then
+ check_link ${lib64_link_dir}/libtaos.so
+ check_link ${lib64_link_dir}/libtaos.so.1
+ fi
+ echo -e "Check lib path:\033[32mOK\033[0m!"
+}
+
+
+function check_header_path() {
+ # check all header
+ header_dir=("taos.h" "taoserror.h")
+ for i in ${header_dir[@]};do
+ check_link ${inc_link_dir}/$i
+ done
+ echo -e "Check bin path:\033[32mOK\033[0m!"
+}
+
+
+function check_config_dir() {
+ # check all config
+ check_file ${cfg_install_dir} taos.cfg
+ check_file ${install_main_dir}/cfg taos.cfg.org
+ echo -e "Check conf path:\033[32mOK\033[0m!"
+}
+
+function check_log_path() {
+ # check log path
+ check_file ${log_dir}
+ echo -e "Check log path:\033[32mOK\033[0m!"
+}
+
+function check_data_path() {
+ # check data path
+ check_file ${data_dir}
+ echo -e "Check data path:\033[32mOK\033[0m!"
+}
+
+function install_TDengine() {
+ cd ${script_dir}
+ tar zxf $1
+ temp_version=$(get_package_name $1)
+ cd $(get_package_name $1)
+ echo -e "\033[32muninstall TDengine && install TDengine...\033[0m"
+ rmtaos >/dev/null 2>&1 || echo 'taosd not installed' && echo -e '\n\n' |./install.sh >/dev/null 2>&1
+ echo -e "\033[32mTDengine has been installed!\033[0m"
+ echo -e "\033[32mTDengine is starting...\033[0m"
+ kill_process taos && systemctl start taosd && sleep 10
+}
+
+function test_TDengine() {
+ check_main_path
+ check_bin_path
+ check_lib_path
+ check_header_path
+ check_config_dir
+ check_log_path
+ check_data_path
+ result=`taos -s 'create database test ;create table test.tt(ts timestamp ,i int);insert into test.tt values(now,11);select * from test.tt' 2>&1 ||:`
+ if [[ $result =~ "Unable to establish" ]];then
+ echo -e "\033[31mTDengine connect failed\033[0m"
+ fin_result=$fin_result"\033[31m$temp_version\033[0m test failed!\n"
+ echo -e $fin_result
+ exit 8
+ fi
+ echo -e "Check TDengine connect:\033[32mOK\033[0m!"
+ fin_result=$fin_result"\033[32m$temp_version\033[0m test OK!\n"
+}
+# ## ==============================Main program starts from here============================
+TD_package_name=`ls ${script_dir}/*server*gz |awk -F '/' '{print $NF}' `
+temp=`pwd`
+for i in $TD_package_name;do
+ if [[ $i =~ 'enterprise' ]];then
+ verMode="cluster"
+ else
+ verMode=""
+ fi
+ cd $temp
+ install_TDengine $i
+ test_TDengine
+done
+echo "============================================================"
+echo -e $fin_result
\ No newline at end of file
diff --git a/src/client/src/tscSQLParser.c b/src/client/src/tscSQLParser.c
index f2eaed9be879fd2ecb4f6c6e727c86a164f8f6c7..2b2805bc82839e17a7e600b894559e5b95ab6e51 100644
--- a/src/client/src/tscSQLParser.c
+++ b/src/client/src/tscSQLParser.c
@@ -953,8 +953,10 @@ int32_t validateIntervalNode(SSqlObj* pSql, SQueryInfo* pQueryInfo, SSqlNode* pS
static int32_t validateStateWindowNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSqlNode, bool isStable) {
const char* msg1 = "invalid column name";
+ const char* msg2 = "invalid column type";
const char* msg3 = "not support state_window with group by ";
const char* msg4 = "function not support for super table query";
+ const char* msg5 = "not support state_window on tag column";
SStrToken *col = &(pSqlNode->windowstateVal.col) ;
if (col->z == NULL || col->n <= 0) {
@@ -982,8 +984,10 @@ static int32_t validateStateWindowNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SS
STableMetaInfo *pTableMetaInfo = tscGetMetaInfo(pQueryInfo, index.tableIndex);
STableMeta* pTableMeta = pTableMetaInfo->pTableMeta;
int32_t numOfCols = tscGetNumOfColumns(pTableMeta);
- if (index.columnIndex == TSDB_TBNAME_COLUMN_INDEX || index.columnIndex >= numOfCols) {
+ if (index.columnIndex == TSDB_TBNAME_COLUMN_INDEX) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg3);
+ } else if (index.columnIndex >= numOfCols) {
+ return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg5);
}
SGroupbyExpr* pGroupExpr = &pQueryInfo->groupbyExpr;
@@ -992,8 +996,10 @@ static int32_t validateStateWindowNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SS
}
SSchema* pSchema = tscGetTableColumnSchema(pTableMeta, index.columnIndex);
- if (pSchema->type == TSDB_DATA_TYPE_TIMESTAMP || pSchema->type == TSDB_DATA_TYPE_FLOAT || pSchema->type == TSDB_DATA_TYPE_DOUBLE) {
- return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg1);
+ if (pSchema->type == TSDB_DATA_TYPE_TIMESTAMP || pSchema->type == TSDB_DATA_TYPE_FLOAT
+ || pSchema->type == TSDB_DATA_TYPE_DOUBLE || pSchema->type == TSDB_DATA_TYPE_NCHAR
+ || pSchema->type == TSDB_DATA_TYPE_BINARY) {
+ return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2);
}
tscColumnListInsert(pQueryInfo->colList, index.columnIndex, pTableMeta->id.uid, pSchema);
diff --git a/src/connector/python/taos/cinterface.py b/src/connector/python/taos/cinterface.py
index 61a2a0e9c70c3097a1376efb4bab6e250b4d4438..cc7c279458c779b924564cdb17c88989014e3193 100644
--- a/src/connector/python/taos/cinterface.py
+++ b/src/connector/python/taos/cinterface.py
@@ -15,7 +15,7 @@ def _convert_microsecond_to_datetime(micro):
def _convert_nanosecond_to_datetime(nanosec):
- return datetime.datetime.fromtimestamp(nanosec / 1000000000.0)
+ return nanosec
def _crow_timestamp_to_python(data, num_of_rows, nbytes=None, precision=FieldType.C_TIMESTAMP_UNKNOWN):
diff --git a/src/os/inc/osFile.h b/src/os/inc/osFile.h
index 262f19ad22c603f02c8e4277761a0ac038a31c7d..86c08c0a3aca1f2e8434aee84c819d0c17060494 100644
--- a/src/os/inc/osFile.h
+++ b/src/os/inc/osFile.h
@@ -53,8 +53,24 @@ int64_t taosFSendFile(FILE *outfile, FILE *infile, int64_t *offset, int64_t size
void taosGetTmpfilePath(const char *fileNamePrefix, char *dstPath);
void taosClose(FileFd fd);
+#ifdef TAOS_RANDOM_FILE_FAIL
+ void taosSetRandomFileFailFactor(int32_t factor);
+ void taosSetRandomFileFailOutput(const char *path);
+ #ifdef TAOS_RANDOM_FILE_FAIL_TEST
+ int64_t taosReadFileRandomFail(int32_t fd, void *buf, int32_t count, const char *file, uint32_t line);
+ int64_t taosWriteFileRandomFail(int32_t fd, void *buf, int32_t count, const char *file, uint32_t line);
+ int64_t taosLSeekRandomFail(int32_t fd, int64_t offset, int32_t whence, const char *file, uint32_t line);
+ #undef taosRead
+ #undef taosWrite
+ #undef taosLSeek
+ #define taosRead(fd, buf, count) taosReadFileRandomFail(fd, buf, count, __FILE__, __LINE__)
+ #define taosWrite(fd, buf, count) taosWriteFileRandomFail(fd, buf, count, __FILE__, __LINE__)
+ #define taosLSeek(fd, offset, whence) taosLSeekRandomFail(fd, offset, whence, __FILE__, __LINE__)
+ #endif
+#endif
+
#ifdef __cplusplus
}
#endif
-#endif
\ No newline at end of file
+#endif
diff --git a/src/os/src/detail/osFail.c b/src/os/src/detail/osFail.c
index a99bcd01dbccd0290de1fc38a1220b573ab74b22..6ddeefc521264ac23d2fdf2961e20bc8c85a43b1 100644
--- a/src/os/src/detail/osFail.c
+++ b/src/os/src/detail/osFail.c
@@ -113,7 +113,7 @@ int64_t taosReadFileRandomFail(int32_t fd, void *buf, int32_t count, const char
}
}
- return taosReadImp(fd, buf, count);
+ return taosRead(fd, buf, count);
}
int64_t taosWriteFileRandomFail(int32_t fd, void *buf, int32_t count, const char *file, uint32_t line) {
@@ -124,7 +124,7 @@ int64_t taosWriteFileRandomFail(int32_t fd, void *buf, int32_t count, const char
}
}
- return taosWriteImp(fd, buf, count);
+ return taosWrite(fd, buf, count);
}
int64_t taosLSeekRandomFail(int32_t fd, int64_t offset, int32_t whence, const char *file, uint32_t line) {
@@ -135,7 +135,7 @@ int64_t taosLSeekRandomFail(int32_t fd, int64_t offset, int32_t whence, const ch
}
}
- return taosLSeekImp(fd, offset, whence);
+ return taosLSeek(fd, offset, whence);
}
#endif //TAOS_RANDOM_FILE_FAIL
diff --git a/tests/pytest/crash_gen/valgrind_taos.supp b/tests/pytest/crash_gen/valgrind_taos.supp
index 5f6604ba776b03eb5a00280cdf8ea2e8cde36f99..b42015a05323b4082d7bfaebe403146fc15901df 100644
--- a/tests/pytest/crash_gen/valgrind_taos.supp
+++ b/tests/pytest/crash_gen/valgrind_taos.supp
@@ -17517,4 +17517,209 @@
fun:taosGetFqdn
fun:taosCheckGlobalCfg
fun:taos_init_imp
+}
+{
+
+ Memcheck:Leak
+ match-leak-kinds: definite
+ fun:malloc
+ obj:/usr/bin/python3.8
+ fun:PyTuple_Pack
+ fun:__pyx_pymod_exec_mtrand
+ fun:PyModule_ExecDef
+ obj:/usr/bin/python3.8
+ obj:/usr/bin/python3.8
+ fun:PyVectorcall_Call
+ fun:_PyEval_EvalFrameDefault
+ fun:_PyEval_EvalCodeWithName
+ fun:_PyFunction_Vectorcall
+ fun:_PyEval_EvalFrameDefault
+}
+{
+
+ Memcheck:Leak
+ match-leak-kinds: definite
+ fun:malloc
+ fun:PyCode_NewWithPosOnlyArgs
+ fun:PyCode_New
+ fun:__Pyx_InitCachedConstants
+ fun:__pyx_pymod_exec__generator
+ fun:PyModule_ExecDef
+ obj:/usr/bin/python3.8
+ obj:/usr/bin/python3.8
+ fun:PyVectorcall_Call
+ fun:_PyEval_EvalFrameDefault
+ fun:_PyEval_EvalCodeWithName
+ fun:_PyFunction_Vectorcall
+}
+{
+
+ Memcheck:Leak
+ match-leak-kinds: definite
+ fun:malloc
+ obj:/usr/bin/python3.8
+ fun:PyTuple_Pack
+ fun:__pyx_pymod_exec_bit_generator
+ fun:PyModule_ExecDef
+ obj:/usr/bin/python3.8
+ obj:/usr/bin/python3.8
+ fun:PyVectorcall_Call
+ fun:_PyEval_EvalFrameDefault
+ fun:_PyEval_EvalCodeWithName
+ fun:_PyFunction_Vectorcall
+ fun:_PyEval_EvalFrameDefault
+}
+{
+
+ Memcheck:Leak
+ match-leak-kinds: definite
+ fun:malloc
+ obj:/usr/bin/python3.8
+ fun:PyTuple_Pack
+ fun:__pyx_pymod_exec__common
+ fun:PyModule_ExecDef
+ obj:/usr/bin/python3.8
+ obj:/usr/bin/python3.8
+ fun:PyVectorcall_Call
+ fun:_PyEval_EvalFrameDefault
+ fun:_PyEval_EvalCodeWithName
+ fun:_PyFunction_Vectorcall
+ fun:_PyEval_EvalFrameDefault
+}
+{
+
+ Memcheck:Leak
+ match-leak-kinds: definite
+ fun:malloc
+ obj:/usr/bin/python3.8
+ fun:PyTuple_Pack
+ fun:__pyx_pymod_exec__bounded_integers
+ fun:PyModule_ExecDef
+ obj:/usr/bin/python3.8
+ obj:/usr/bin/python3.8
+ fun:PyVectorcall_Call
+ fun:_PyEval_EvalFrameDefault
+ fun:_PyEval_EvalCodeWithName
+ fun:_PyFunction_Vectorcall
+ fun:_PyEval_EvalFrameDefault
+}
+{
+
+ Memcheck:Leak
+ match-leak-kinds: definite
+ fun:malloc
+ obj:/usr/bin/python3.8
+ fun:PyTuple_Pack
+ fun:__pyx_pymod_exec__mt19937
+ fun:PyModule_ExecDef
+ obj:/usr/bin/python3.8
+ obj:/usr/bin/python3.8
+ fun:PyVectorcall_Call
+ fun:_PyEval_EvalFrameDefault
+ fun:_PyEval_EvalCodeWithName
+ fun:_PyFunction_Vectorcall
+ fun:_PyEval_EvalFrameDefault
+}
+{
+
+ Memcheck:Leak
+ match-leak-kinds: definite
+ fun:malloc
+ obj:/usr/bin/python3.8
+ fun:PyTuple_Pack
+ fun:__pyx_pymod_exec__philox
+ fun:PyModule_ExecDef
+ obj:/usr/bin/python3.8
+ obj:/usr/bin/python3.8
+ fun:PyVectorcall_Call
+ fun:_PyEval_EvalFrameDefault
+ fun:_PyEval_EvalCodeWithName
+ fun:_PyFunction_Vectorcall
+ fun:_PyEval_EvalFrameDefault
+}
+{
+
+ Memcheck:Leak
+ match-leak-kinds: definite
+ fun:malloc
+ obj:/usr/bin/python3.8
+ fun:PyTuple_Pack
+ fun:__pyx_pymod_exec__pcg64
+ fun:PyModule_ExecDef
+ obj:/usr/bin/python3.8
+ obj:/usr/bin/python3.8
+ fun:PyVectorcall_Call
+ fun:_PyEval_EvalFrameDefault
+ fun:_PyEval_EvalCodeWithName
+ fun:_PyFunction_Vectorcall
+ fun:_PyEval_EvalFrameDefault
+}
+{
+
+ Memcheck:Leak
+ match-leak-kinds: definite
+ fun:malloc
+ obj:/usr/bin/python3.8
+ fun:PyTuple_Pack
+ fun:__pyx_pymod_exec__sfc64
+ fun:PyModule_ExecDef
+ obj:/usr/bin/python3.8
+ obj:/usr/bin/python3.8
+ fun:PyVectorcall_Call
+ fun:_PyEval_EvalFrameDefault
+ fun:_PyEval_EvalCodeWithName
+ fun:_PyFunction_Vectorcall
+ fun:_PyEval_EvalFrameDefault
+}
+{
+
+ Memcheck:Leak
+ match-leak-kinds: definite
+ fun:malloc
+ obj:/usr/bin/python3.8
+ fun:PyTuple_Pack
+ fun:__Pyx_InitCachedConstants
+ fun:__pyx_pymod_exec__generator
+ fun:PyModule_ExecDef
+ obj:/usr/bin/python3.8
+ obj:/usr/bin/python3.8
+ fun:PyVectorcall_Call
+ fun:_PyEval_EvalFrameDefault
+ fun:_PyEval_EvalCodeWithName
+ fun:_PyFunction_Vectorcall
+ fun:_PyEval_EvalFrameDefault
+}
+{
+
+ Memcheck:Leak
+ match-leak-kinds: definite
+ fun:malloc
+ fun:PyCode_NewWithPosOnlyArgs
+ fun:PyCode_New
+ fun:__pyx_pymod_exec_mtrand
+ fun:PyModule_ExecDef
+ obj:/usr/bin/python3.8
+ obj:/usr/bin/python3.8
+ fun:PyVectorcall_Call
+ fun:_PyEval_EvalFrameDefault
+ fun:_PyEval_EvalCodeWithName
+ fun:_PyFunction_Vectorcall
+ fun:_PyEval_EvalFrameDefault
+}
+{
+
+ Memcheck:Leak
+ match-leak-kinds: definite
+ fun:malloc
+ fun:PyCode_NewWithPosOnlyArgs
+ fun:PyCode_New
+ fun:__pyx_pymod_exec_bit_generator
+ fun:PyModule_ExecDef
+ obj:/usr/bin/python3.8
+ obj:/usr/bin/python3.8
+ fun:PyVectorcall_Call
+ fun:_PyEval_EvalFrameDefault
+ fun:_PyEval_EvalCodeWithName
+ fun:_PyFunction_Vectorcall
+ fun:_PyEval_EvalFrameDefault
}
\ No newline at end of file
diff --git a/tests/pytest/dbmgmt/nanoSecondCheck.py b/tests/pytest/dbmgmt/nanoSecondCheck.py
new file mode 100644
index 0000000000000000000000000000000000000000..27050a2213f7e6bddeb5cc6135c7fe4760018f61
--- /dev/null
+++ b/tests/pytest/dbmgmt/nanoSecondCheck.py
@@ -0,0 +1,210 @@
+# #################################################################
+# 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 -*-
+
+# TODO: after TD-4518 and TD-4510 is resolved, add the exception test case for these situations
+
+import sys
+from util.log import *
+from util.cases import *
+from util.sql import *
+import time
+from datetime import datetime
+import os
+
+
+class TDTestCase:
+ def init(self, conn, logSql):
+ tdLog.debug("start to execute %s" % __file__)
+ tdSql.init(conn.cursor(), logSql)
+
+ def run(self):
+ tdSql.prepare()
+ tdSql.execute('reset query cache')
+ tdSql.execute('drop database if exists db')
+ tdSql.execute('create database db precision "ns";')
+ tdSql.query('show databases;')
+ tdSql.checkData(0,16,'ns')
+ tdSql.execute('use db')
+
+ tdLog.debug('testing nanosecond support in 1st timestamp')
+ tdSql.execute('create table tb (ts timestamp, speed int)')
+ tdSql.execute('insert into tb values(\'2021-06-10 0:00:00.100000001\', 1);')
+ tdSql.execute('insert into tb values(1623254400150000000, 2);')
+ tdSql.execute('import into tb values(1623254400300000000, 3);')
+ tdSql.execute('import into tb values(1623254400299999999, 4);')
+ tdSql.execute('insert into tb values(1623254400300000001, 5);')
+ tdSql.execute('insert into tb values(1623254400999999999, 7);')
+
+
+ tdSql.query('select * from tb;')
+ tdSql.checkData(0,0,'2021-06-10 0:00:00.100000001')
+ tdSql.checkData(1,0,'2021-06-10 0:00:00.150000000')
+ tdSql.checkData(2,0,'2021-06-10 0:00:00.299999999')
+ tdSql.checkData(3,1,3)
+ tdSql.checkData(4,1,5)
+ tdSql.checkData(5,1,7)
+ tdSql.checkRows(6)
+ tdSql.query('select count(*) from tb where ts > 1623254400100000000 and ts < 1623254400100000002;')
+ tdSql.checkData(0,0,1)
+ tdSql.query('select count(*) from tb where ts > \'2021-06-10 0:00:00.100000001\' and ts < \'2021-06-10 0:00:00.160000000\';')
+ tdSql.checkData(0,0,1)
+
+ tdSql.query('select count(*) from tb where ts > 1623254400100000000 and ts < 1623254400150000000;')
+ tdSql.checkData(0,0,1)
+ tdSql.query('select count(*) from tb where ts > \'2021-06-10 0:00:00.100000000\' and ts < \'2021-06-10 0:00:00.150000000\';')
+ tdSql.checkData(0,0,1)
+
+ tdSql.query('select count(*) from tb where ts > 1623254400400000000;')
+ tdSql.checkData(0,0,1)
+ tdSql.query('select count(*) from tb where ts < \'2021-06-10 00:00:00.400000000\';')
+ tdSql.checkData(0,0,5)
+
+ tdSql.query('select count(*) from tb where ts > now + 400000000b;')
+ tdSql.checkRows(0)
+
+ tdSql.query('select count(*) from tb where ts >= \'2021-06-10 0:00:00.100000001\';')
+ tdSql.checkData(0,0,6)
+
+ tdSql.query('select count(*) from tb where ts <= 1623254400300000000;')
+ tdSql.checkData(0,0,4)
+
+ tdSql.query('select count(*) from tb where ts = \'2021-06-10 0:00:00.000000000\';')
+ tdSql.checkRows(0)
+
+ tdSql.query('select count(*) from tb where ts = 1623254400150000000;')
+ tdSql.checkData(0,0,1)
+
+ tdSql.query('select count(*) from tb where ts = \'2021-06-10 0:00:00.100000001\';')
+ tdSql.checkData(0,0,1)
+
+ tdSql.query('select count(*) from tb where ts between 1623254400000000000 and 1623254400400000000;')
+ tdSql.checkData(0,0,5)
+
+ tdSql.query('select count(*) from tb where ts between \'2021-06-10 0:00:00.299999999\' and \'2021-06-10 0:00:00.300000001\';')
+ tdSql.checkData(0,0,3)
+
+ tdSql.query('select avg(speed) from tb interval(5000000000b);')
+ tdSql.checkRows(1)
+
+ tdSql.query('select avg(speed) from tb interval(100000000b)')
+ tdSql.checkRows(4)
+
+ tdSql.query('select avg(speed) from tb interval(100000000b) sliding (100000000b);')
+ tdSql.checkRows(4)
+
+ tdSql.query('select last(*) from tb')
+ tdSql.checkData(0,0, '2021-06-10 0:00:00.999999999')
+ tdSql.checkData(0,0, 1623254400999999999)
+
+ tdSql.query('select first(*) from tb')
+ tdSql.checkData(0,0, 1623254400100000001)
+ tdSql.checkData(0,0, '2021-06-10 0:00:00.100000001')
+
+ tdSql.execute('insert into tb values(now + 500000000b, 6);')
+ tdSql.query('select * from tb;')
+ tdSql.checkRows(7)
+
+ tdLog.debug('testing nanosecond support in other timestamps')
+ tdSql.execute('create table tb2 (ts timestamp, speed int, ts2 timestamp);')
+ tdSql.execute('insert into tb2 values(\'2021-06-10 0:00:00.100000001\', 1, \'2021-06-11 0:00:00.100000001\');')
+ tdSql.execute('insert into tb2 values(1623254400150000000, 2, 1623340800150000000);')
+ tdSql.execute('import into tb2 values(1623254400300000000, 3, 1623340800300000000);')
+ tdSql.execute('import into tb2 values(1623254400299999999, 4, 1623340800299999999);')
+ tdSql.execute('insert into tb2 values(1623254400300000001, 5, 1623340800300000001);')
+ tdSql.execute('insert into tb2 values(1623254400999999999, 7, 1623513600999999999);')
+
+ tdSql.query('select * from tb2;')
+ tdSql.checkData(0,0,'2021-06-10 0:00:00.100000001')
+ tdSql.checkData(1,0,'2021-06-10 0:00:00.150000000')
+ tdSql.checkData(2,1,4)
+ tdSql.checkData(3,1,3)
+ tdSql.checkData(4,2,'2021-06-11 00:00:00.300000001')
+ tdSql.checkData(5,2,'2021-06-13 00:00:00.999999999')
+ tdSql.checkRows(6)
+ tdSql.query('select count(*) from tb2 where ts2 > 1623340800000000000 and ts2 < 1623340800150000000;')
+ tdSql.checkData(0,0,1)
+ tdSql.query('select count(*) from tb2 where ts2 > \'2021-06-11 0:00:00.100000000\' and ts2 < \'2021-06-11 0:00:00.100000002\';')
+ tdSql.checkData(0,0,1)
+
+ tdSql.query('select count(*) from tb2 where ts2 > 1623340800500000000;')
+ tdSql.checkData(0,0,1)
+ tdSql.query('select count(*) from tb2 where ts2 < \'2021-06-11 0:00:00.400000000\';')
+ tdSql.checkData(0,0,5)
+
+ tdSql.query('select count(*) from tb2 where ts2 > now + 400000000b;')
+ tdSql.checkRows(0)
+
+ tdSql.query('select count(*) from tb2 where ts2 >= \'2021-06-11 0:00:00.100000001\';')
+ tdSql.checkData(0,0,6)
+
+ tdSql.query('select count(*) from tb2 where ts2 <= 1623340800400000000;')
+ tdSql.checkData(0,0,5)
+
+ tdSql.query('select count(*) from tb2 where ts2 = \'2021-06-11 0:00:00.000000000\';')
+ tdSql.checkRows(0)
+
+ tdSql.query('select count(*) from tb2 where ts2 = \'2021-06-11 0:00:00.300000001\';')
+ tdSql.checkData(0,0,1)
+
+ tdSql.query('select count(*) from tb2 where ts2 = 1623340800300000001;')
+ tdSql.checkData(0,0,1)
+
+ tdSql.query('select count(*) from tb2 where ts2 between 1623340800000000000 and 1623340800450000000;')
+ tdSql.checkData(0,0,5)
+
+ tdSql.query('select count(*) from tb2 where ts2 between \'2021-06-11 0:00:00.299999999\' and \'2021-06-11 0:00:00.300000001\';')
+ tdSql.checkData(0,0,3)
+
+ tdSql.query('select count(*) from tb2 where ts2 <> 1623513600999999999;')
+ tdSql.checkData(0,0,5)
+
+ tdSql.query('select count(*) from tb2 where ts2 <> \'2021-06-11 0:00:00.100000001\';')
+ tdSql.checkData(0,0,5)
+
+ tdSql.query('select count(*) from tb2 where ts2 <> \'2021-06-11 0:00:00.100000000\';')
+ tdSql.checkData(0,0,6)
+
+ tdSql.query('select count(*) from tb2 where ts2 != 1623513600999999999;')
+ tdSql.checkData(0,0,5)
+
+ tdSql.query('select count(*) from tb2 where ts2 != \'2021-06-11 0:00:00.100000001\';')
+ tdSql.checkData(0,0,5)
+
+ tdSql.query('select count(*) from tb2 where ts2 != \'2021-06-11 0:00:00.100000000\';')
+ tdSql.checkData(0,0,6)
+
+ tdSql.execute('insert into tb2 values(now + 500000000b, 6, now +2d);')
+ tdSql.query('select * from tb2;')
+ tdSql.checkRows(7)
+
+ tdLog.debug('testing ill nanosecond format handling')
+ tdSql.execute('create table tb3 (ts timestamp, speed int);')
+
+ tdSql.error('insert into tb3 values(16232544001500000, 2);')
+ tdSql.execute('insert into tb3 values(\'2021-06-10 0:00:00.123456\', 2);')
+ tdSql.query('select * from tb3 where ts = \'2021-06-10 0:00:00.123456000\';')
+ tdSql.checkRows(1)
+
+ tdSql.execute('insert into tb3 values(\'2021-06-10 0:00:00.123456789000\', 2);')
+ tdSql.query('select * from tb3 where ts = \'2021-06-10 0:00:00.123456789\';')
+ tdSql.checkRows(1)
+
+ os.system('sudo timedatectl set-ntp on')
+
+ def stop(self):
+ tdSql.close()
+ tdLog.success("%s successfully executed" % __file__)
+
+
+tdCases.addWindows(__file__, TDTestCase())
+tdCases.addLinux(__file__, TDTestCase())
\ No newline at end of file
diff --git a/tests/pytest/fulltest.sh b/tests/pytest/fulltest.sh
index b9b7bbcaf6bd056329ae04b0b2fb91ff56f3ce45..5b4a69af206d1f0018dd1d90936888c940ac8537 100755
--- a/tests/pytest/fulltest.sh
+++ b/tests/pytest/fulltest.sh
@@ -75,6 +75,7 @@ python3 ./test.py -f tag_lite/smallint.py
python3 ./test.py -f tag_lite/tinyint.py
#python3 ./test.py -f dbmgmt/database-name-boundary.py
+python3 test.py -f dbmgmt/nanoSecondCheck.py
python3 ./test.py -f import_merge/importBlock1HO.py
python3 ./test.py -f import_merge/importBlock1HPO.py
diff --git a/tests/pytest/functions/function_derivative.py b/tests/pytest/functions/function_derivative.py
index 4ddb9c309bfa37897bc1eb7870dc4fd1e9cd6293..9d60129672b5516d83e696f67b5c8d5a17630afd 100644
--- a/tests/pytest/functions/function_derivative.py
+++ b/tests/pytest/functions/function_derivative.py
@@ -128,7 +128,14 @@ class TDTestCase:
def run(self):
tdSql.prepare()
- self.insertAndCheckData()
+ self.insertAndCheckData()
+
+ tdSql.execute("create table st(ts timestamp, c1 int, c2 int) tags(id int)")
+ tdSql.execute("insert into dev1(ts, c1) using st tags(1) values(now, 1)")
+
+ tdSql.error("select derivative(c1, 10s, 0) from (select c1 from st)")
+ tdSql.query("select diff(c1) from (select derivative(c1, 1s, 0) c1 from dev1)")
+ tdSql.checkRows(0)
def stop(self):
tdSql.close()
diff --git a/tests/pytest/util/sql.py b/tests/pytest/util/sql.py
index 8f62c5932b71049e97375ef6c57ecb563d204844..913c158d05f38d0bf80ae5d672a0d039c2999f37 100644
--- a/tests/pytest/util/sql.py
+++ b/tests/pytest/util/sql.py
@@ -18,6 +18,7 @@ import datetime
import inspect
import psutil
import shutil
+import pandas as pd
from util.log import *
@@ -134,25 +135,32 @@ class TDSql:
return self.cursor.istype(col, dataType)
def checkData(self, row, col, data):
- self.checkRowCol(row, col)
- if self.queryResult[row][col] != data:
- if self.cursor.istype(col, "TIMESTAMP") and self.queryResult[row][col] == datetime.datetime.fromisoformat(data):
- tdLog.info("sql:%s, row:%d col:%d data:%s == expect:%s" %
+ self.checkRowCol(row, col)
+ if self.queryResult[row][col] != data:
+ if self.cursor.istype(col, "TIMESTAMP"):
+ # suppose user want to check nanosecond timestamp if a longer data passed
+ if (len(data) >= 28):
+ if pd.to_datetime(self.queryResult[row][col]) == pd.to_datetime(data):
+ tdLog.info("sql:%s, row:%d col:%d data:%d == expect:%s" %
+ (self.sql, row, col, self.queryResult[row][col], data))
+ else:
+ if self.queryResult[row][col] == datetime.datetime.fromisoformat(data):
+ tdLog.info("sql:%s, row:%d col:%d data:%s == expect:%s" %
(self.sql, row, col, self.queryResult[row][col], data))
return
if str(self.queryResult[row][col]) == str(data):
tdLog.info("sql:%s, row:%d col:%d data:%s == expect:%s" %
- (self.sql, row, col, self.queryResult[row][col], data))
+ (self.sql, row, col, self.queryResult[row][col], data))
return
- elif isinstance(data, float) and abs(self.queryResult[row][col] - data) <= 0.000001:
+ elif isinstance(data, float) and abs(self.queryResult[row][col] - data) <= 0.000001:
tdLog.info("sql:%s, row:%d col:%d data:%f == expect:%f" %
- (self.sql, row, col, self.queryResult[row][col], data))
+ (self.sql, row, col, self.queryResult[row][col], data))
return
else:
caller = inspect.getframeinfo(inspect.stack()[1][0])
args = (caller.filename, caller.lineno, self.sql, row, col, self.queryResult[row][col], data)
- tdLog.exit("%s(%d) failed: sql:%s row:%d col:%d data:%s != expect:%s" % args)
+ tdLog.exit("%s(%d) failed: sql:%s row:%d col:%d data:%s != expect:%s" % args)
if data is None:
tdLog.info("sql:%s, row:%d col:%d data:%s == expect:%s" %
@@ -162,11 +170,11 @@ class TDSql:
(self.sql, row, col, self.queryResult[row][col], data))
elif isinstance(data, datetime.date):
tdLog.info("sql:%s, row:%d col:%d data:%s == expect:%s" %
- (self.sql, row, col, self.queryResult[row][col], data))
+ (self.sql, row, col, self.queryResult[row][col], data))
elif isinstance(data, float):
tdLog.info("sql:%s, row:%d col:%d data:%s == expect:%s" %
(self.sql, row, col, self.queryResult[row][col], data))
- else:
+ else:
tdLog.info("sql:%s, row:%d col:%d data:%s == expect:%d" %
(self.sql, row, col, self.queryResult[row][col], data))
@@ -200,7 +208,7 @@ class TDSql:
tdLog.exit("%s(%d) failed: sql:%s, affectedRows:%d != expect:%d" % args)
tdLog.info("sql:%s, affectedRows:%d == expect:%d" % (self.sql, self.affectedRows, expectAffectedRows))
-
+
def taosdStatus(self, state):
tdLog.sleep(5)
pstate = 0
@@ -221,7 +229,7 @@ class TDSql:
continue
pstate = 0
break
-
+
args=(pstate,state)
if pstate == state:
tdLog.info("taosd state is %d == expect:%d" %args)
@@ -236,11 +244,11 @@ class TDSql:
tdLog.exit("dir: %s is empty, expect: not empty" %dir)
else:
tdLog.info("dir: %s is empty, expect: empty" %dir)
- else:
+ else:
if state :
tdLog.info("dir: %s is not empty, expect: not empty" %dir)
else:
- tdLog.exit("dir: %s is not empty, expect: empty" %dir)
+ tdLog.exit("dir: %s is not empty, expect: empty" %dir)
else:
tdLog.exit("dir: %s doesn't exist" %dir)
def createDir(self, dir):
@@ -250,5 +258,5 @@ class TDSql:
os.makedirs( dir, 755 )
tdLog.info("dir: %s is created" %dir)
pass
-
+
tdSql = TDSql()