diff --git a/README-CN.md b/README-CN.md index 4ace609b38022432643719d0a2f9ca8155646bb5..b86e2d83b5d1e45d3b07796418116ed8d4e6f33a 100644 --- a/README-CN.md +++ b/README-CN.md @@ -121,7 +121,7 @@ sudo dnf install -y maven 为了在 CentOS 上构建 [taosTools](https://github.com/taosdata/taos-tools) 需要安装如下依赖软件 ```bash -sudo yum install zlib-devel xz-devel snappy-devel jansson-devel pkgconfig libatomic libstdc++-static +sudo yum install zlib-devel xz-devel snappy-devel jansson jansson-devel pkgconfig libatomic libstdc++-static ``` 注意:由于 snappy 缺乏 pkg-config 支持 diff --git a/README.md b/README.md index 82702ae91f1637c9721f8b47cdc6f67d44a8dda3..204dc98725fbf37b96d1273036b8bb8dc3716fb4 100644 --- a/README.md +++ b/README.md @@ -126,7 +126,7 @@ sudo dnf install -y maven To build the [taosTools](https://github.com/taosdata/taos-tools) on CentOS, the following packages need to be installed. ```bash -sudo yum install zlib-devel xz-devel snappy-devel jansson-devel pkgconfig libatomic libstdc++-static +sudo yum install zlib-devel xz-devel snappy-devel jansson jansson-devel pkgconfig libatomic libstdc++-static ``` Note: Since snappy lacks pkg-config support (refer to [link](https://github.com/google/snappy/pull/86)), it lead a cmake prompt libsnappy not found. But snappy will works well. diff --git a/cmake/define.inc b/cmake/define.inc index 9e3d4a0dfa05d1bdbc783da68d470c3a57f57d7b..c1169b994804666c553b89300d140325341a14f0 100755 --- a/cmake/define.inc +++ b/cmake/define.inc @@ -17,10 +17,6 @@ IF (TD_USB_DONGLE) ADD_DEFINITIONS(-D_USB_DONGLE) ENDIF () -IF (TD_MQTT) - ADD_DEFINITIONS(-D_MQTT) -ENDIF () - IF (TD_TSDB_PLUGINS) ADD_DEFINITIONS(-D_TSDB_PLUGINS) ENDIF () @@ -291,7 +287,7 @@ MESSAGE(STATUS "CMAKE_CXX_COMPILER_ID: " ${CMAKE_CXX_COMPILER_ID}) IF ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") EXECUTE_PROCESS( COMMAND ${CMAKE_CXX_COMPILER} --version OUTPUT_VARIABLE clang_full_version_string ) string (REGEX REPLACE ".*clang version ([0-9]+\\.[0-9]+).*" "\\1" CLANG_VERSION_STRING ${clang_full_version_string}) - IF (CLANG_VERSION_STRING GREATER_EQUAL 13.0) + IF (CLANG_VERSION_STRING GREATER_EQUAL 13.1) SET(COMMON_FLAGS "${COMMON_FLAGS} -Wno-unused-but-set-variable") ENDIF () ENDIF () diff --git a/cmake/platform.inc b/cmake/platform.inc index b0e463026ef64d3ce662911001daa17488dfe321..c384a4bac49c7be5cb1019aa3ff732f6bd8ee278 100755 --- a/cmake/platform.inc +++ b/cmake/platform.inc @@ -64,7 +64,7 @@ IF (${CMAKE_SYSTEM_NAME} MATCHES "Linux") SET(TD_ARCHLINUX TRUE) MESSAGE(STATUS "The current OS is Arch Linux") ELSE () - MESSAGE(STATUS "Ths distro is " ${TD_OS_INFO}) + MESSAGE(STATUS "The distro is " ${TD_OS_INFO}) ENDIF() ELSEIF (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") SET(TD_DARWIN TRUE) diff --git a/deps/TSZ b/deps/TSZ index 11c1060d4f917dd799ae628b131db5d6a5ef6954..2ac3cf959ba1b3fc2afe3f617cc6ba023488eef6 160000 --- a/deps/TSZ +++ b/deps/TSZ @@ -1 +1 @@ -Subproject commit 11c1060d4f917dd799ae628b131db5d6a5ef6954 +Subproject commit 2ac3cf959ba1b3fc2afe3f617cc6ba023488eef6 diff --git a/docs-cn/01-intro/01-intro.md b/docs-cn/01-intro/01-intro.md index f1e70a1af72ff0c61cd5007cdd62205e369ffc58..7d807be15eefb5acb1350330d557f91805bd1898 100644 --- a/docs-cn/01-intro/01-intro.md +++ b/docs-cn/01-intro/01-intro.md @@ -6,7 +6,7 @@ toc_max_heading_level: 2 ## TDengine 简介 -TDengine 是一款高性能、分布式、支持 SQL 的时序数据库。而且除时序数据库功能外,它还提供缓存、数据订阅、流式计算等功能,最大程度减少研发和运维的复杂度,且核心代码,包括集群功能全部开源(开源协议,AGPL v3.0)。与其他时序数据数据库相比,TDengine 有以下特点: +TDengine 是一款高性能、分布式、支持 SQL 的时序数据库。而且除时序数据库功能外,它还提供[缓存](/develop/cache/)、数据订阅、流式计算等功能,最大程度减少研发和运维的复杂度,且核心代码,包括集群功能全部开源(开源协议,AGPL v3.0)。与其他时序数据数据库相比,TDengine 有以下特点: - **高性能**:通过创新的存储引擎设计,无论是数据写入还是查询,TDengine 的性能比通用数据库快 10 倍以上,也远超其他时序数据库,而且存储空间也大为节省。 diff --git a/docs-cn/03-get-started/03-get-started.md b/docs-cn/03-get-started/03-get-started.md index 11ed177bd0089ea3b5a959de9ad2293be8a11c1a..6776455c9dc3ab68d291488b7b3b0353967f0ac1 100644 --- a/docs-cn/03-get-started/03-get-started.md +++ b/docs-cn/03-get-started/03-get-started.md @@ -1,6 +1,6 @@ --- title: 立即开始 -description: "从 Docker,安装包或使用 apt-get 快速安装 TDengine, 通过命令行程序 taos shell 和工具 taosdemo 快速体验 TDengine 功能" +description: "从 Docker,安装包或使用 apt-get 快速安装 TDengine, 通过命令行程序TAOS CLI和工具 taosdemo 快速体验 TDengine 功能" --- import Tabs from "@theme/Tabs"; @@ -10,7 +10,7 @@ import AptGetInstall from "./\_apt_get_install.mdx"; ## 安装 -TDengine 完整的软件包包括服务端(taosd)、用于与第三方系统对接并提供RESTful接口的taosAdapter、应用驱动(taosc)、命令行程序 (CLI,taos) 和一些工具软件,目前 2.X 版服务端taosd、taosAdapter仅在 Linux 系统上安装和运行,后续将支持 Windows、macOS 等系统。应用驱动 taosc 与 TDengine CLI 可以在 Windows 或 Linux 上安装和运行。TDengine 除 RESTful接口外,还提供一些列编程语言的连接器。2.4 之前的版本中,无 taosAdapter,RESTfule 接口均由 taosd 内置的 http 服务提供。 +TDengine 完整的软件包包括服务端(taosd)、用于与第三方系统对接并提供RESTful接口的taosAdapter、应用驱动(taosc)、命令行程序 (CLI,taos) 和一些工具软件,目前 2.X 版服务端taosd、taosAdapter 仅在 Linux 系统上安装和运行,后续将支持 Windows、macOS 等系统。应用驱动 taosc 与 TDengine CLI 可以在 Windows 或 Linux 上安装和运行。TDengine 除 RESTful接口外,还提供一些列编程语言的连接器。2.4 之前的版本中,无 taosAdapter,RESTfule 接口均由 taosd 内置的 http 服务提供。 TDengine 支持 X64/ARM64/MIPS64/Alpha64 硬件平台,后续将支持 ARM32、RISC-V 等 CPU 架构。 @@ -43,10 +43,6 @@ docker exec -it bash ::: -:::note -暂时不建议生产环境采用 Docker 来部署 TDengine CLI 或服务端,但在开发环境下或初次尝试时,使用 Docker 方式部署是十分方便的。特别是,利用 Docker,可以方便地在 macOS 和 Windows 环境下尝试 TDengine。 - -::: @@ -65,7 +61,7 @@ docker exec -it bash ## 启动 -使用 `systemctl` 命令来启动 TDengine 的服务进程。 +安装后,请使用 `systemctl` 命令来启动 TDengine 的服务进程。 ```bash systemctl start taosd @@ -98,7 +94,7 @@ which systemctl ## TDengine 命令行 (CLI) -为便于检查 TDengine 的状态,执行各种即席(Ad Hoc)查询,TDengine 提供一命令行应用程序(以下简称为 TDengine CLI) taos. 要进入 TDengine 命令行,您只要在 Linux 终端执行 `taos` 即可。 +为便于检查 TDengine 的状态,执行各种即席(Ad Hoc)查询,TDengine 提供一命令行应用程序(以下简称为 TDengine CLI) taos。要进入 TDengine 命令行,您只要在安装有 TDengine 的 Linux 终端执行 `taos` 即可。 ```bash taos @@ -126,7 +122,7 @@ select * from t; Query OK, 2 row(s) in set (0.003128s) ``` -除执行 SQL 语句外,系统管理员还可以从 TDengine CLI 进行检查系统运行状态、添加删除用户账号等操作。更多细节请参考 [这里](../reference/taos-shell/) +除执行 SQL 语句外,系统管理员还可以从 TDengine CLI 进行检查系统运行状态、添加删除用户账号等操作。TAOS CLI 连同应用驱动也可以独立安装在 Linux 或 windows 机器上运行,更多细节请参考 [这里](../reference/taos-shell/) ## 使用 taosBenchmark 体验写入速度 @@ -144,7 +140,7 @@ taosBenchmark 命令本身带有很多选项,配置表的数目、记录条数 ## 使用 TDengine CLI 体验查询速度 -在 TDengine CLI 输入查询命令,体验查询速度。 +使用上述 taosBenchmark 插入数据后,可以在 TDengine CLI 输入查询命令,体验查询速度。 查询超级表下记录总条数: diff --git a/docs-cn/03-get-started/_pkg_install.mdx b/docs-cn/03-get-started/_pkg_install.mdx index 13047f99805172cf37958f18a0c94c5b3201745b..83c987af8bcf24a9593105b680d32a0421344d5f 100644 --- a/docs-cn/03-get-started/_pkg_install.mdx +++ b/docs-cn/03-get-started/_pkg_install.mdx @@ -1,3 +1,5 @@ +import PkgList from "/components/PkgList"; + TDengine 的安装非常简单,从下载到安装成功仅仅只要几秒钟。 为方便使用,从 2.4.0.10 开始,标准的服务端安装包包含了 taos、taosd、taosAdapter、taosdump、taosBenchmark、TDinsight 安装脚本和示例代码;如果您只需要用到服务端程序和客户端连接的 C/C++ 语言支持,也可以仅下载 lite 版本的安装包。 @@ -6,51 +8,10 @@ TDengine 的安装非常简单,从下载到安装成功仅仅只要几秒钟 发布版本包括稳定版和 Beta 版,Beta 版含有更多新功能。正式上线或测试建议安装稳定版。您可以根据需要选择下载: - + 具体的安装方法,请参见[安装包的安装和卸载](/operation/pkg-install)。 下载其他组件、最新 Beta 版及之前版本的安装包,请点击[这里](https://www.taosdata.com/all-downloads) -请点击[这里](https://github.com/taosdata/TDengine/releases) 查看 Release Notes。 +查看 Release Notes, 请点击[这里](https://github.com/taosdata/TDengine/releases) diff --git a/docs-cn/04-develop/01-connect/index.md b/docs-cn/04-develop/01-connect/index.md index 144b08433d511b06a95344e819a907a95779e0d2..07bcc8ea125a0e4bc8f40a1bd2fab3a568b3402d 100644 --- a/docs-cn/04-develop/01-connect/index.md +++ b/docs-cn/04-develop/01-connect/index.md @@ -136,18 +136,19 @@ Node.js 连接器通过不同的包提供不同的连接方式。 1. 安装 Node.js 原生连接器 -``` -npm i td2.0-connector -``` + ``` + npm i td2.0-connector + ``` :::note 推荐 Node 版本大于等于 `node-v12.8.0` 小于 `node-v13.0.0` +::: + +2. 安装 Node.js REST 连接器 -::: 2. 安装 Node.js REST 连接器 - -``` -npm i td2.0-rest-connector -``` + ``` + npm i td2.0-rest-connector + ``` diff --git a/docs-cn/04-develop/04-query-data/_c_async.mdx b/docs-cn/04-develop/04-query-data/_c_async.mdx index ffdd53306b1198fbd0332d0f403d20f6908d8e1b..09f3d3b3ff6d6644f837642ef41db459ba7c5753 100644 --- a/docs-cn/04-develop/04-query-data/_c_async.mdx +++ b/docs-cn/04-develop/04-query-data/_c_async.mdx @@ -1,3 +1,3 @@ ```c -{{#include docs-examples/c/async_query_example.c}} +{{#include docs-examples/c/async_query_example.c:demo}} ``` \ No newline at end of file diff --git a/docs-cn/04-develop/04-query-data/index.mdx b/docs-cn/04-develop/04-query-data/index.mdx index 02e20a7418fb341f0eb6326d576b1ec5487e38c3..829280fba5b1e5a956b79699df39f9bb2c1cb177 100644 --- a/docs-cn/04-develop/04-query-data/index.mdx +++ b/docs-cn/04-develop/04-query-data/index.mdx @@ -44,11 +44,11 @@ Query OK, 2 row(s) in set (0.001100s) 具体的查询语法请看 [TAOS SQL 的数据查询](/taos-sql/select) 章节。 -### 多表聚合查询 +## 多表聚合查询 物联网场景中,往往同一个类型的数据采集点有多个。TDengine 采用超级表(STable)的概念来描述某一个类型的数据采集点,一张普通的表来描述一个具体的数据采集点。同时 TDengine 使用标签来描述数据采集点的静态属性,一个具体的数据采集点有具体的标签值。通过指定标签的过滤条件,TDengine 提供了一高效的方法将超级表(某一类型的数据采集点)所属的子表进行聚合查询。对普通表的聚合函数以及绝大部分操作都适用于超级表,语法完全一样。 -#### 示例一 +### 示例一 在 TAOS Shell,查找北京所有智能电表采集的电压平均值,并按照 location 分组。 @@ -61,7 +61,7 @@ taos> SELECT AVG(voltage) FROM meters GROUP BY location; Query OK, 2 row(s) in set (0.002136s) ``` -#### 示例二 +### 示例二 在 TAOS shell, 查找 groupId 为 2 的所有智能电表过去 24 小时的记录条数,电流的最大值。 @@ -75,7 +75,7 @@ Query OK, 1 row(s) in set (0.002136s) TDengine 仅容许对属于同一个超级表的表之间进行聚合查询,不同超级表之间的聚合查询不支持。在 [TAOS SQL 的数据查询](/taos-sql/select) 一章,查询类操作都会注明是否支持超级表。 -### 降采样查询、插值 +## 降采样查询、插值 物联网场景里,经常需要通过降采样(down sampling)将采集的数据按时间段进行聚合。TDengine 提供了一个简便的关键词 interval 让按照时间窗口的查询操作变得极为简单。比如,将智能电表 d1001 采集的电流值每 10 秒钟求和 @@ -169,13 +169,10 @@ Query OK, 5 row(s) in set (0.001521s) - - - - {/* + - */} + diff --git a/docs-cn/04-develop/06-subscribe.mdx b/docs-cn/04-develop/06-subscribe.mdx index bf5b2c138e2182df8ed8baf9442a7b7ed6d62f2f..d471c114e827d7c4b40195c2c1b3c8f6a9d26ed4 100644 --- a/docs-cn/04-develop/06-subscribe.mdx +++ b/docs-cn/04-develop/06-subscribe.mdx @@ -160,7 +160,7 @@ make ./subscribe -sql='select * from meters where current > 10;' ``` -示例程序启动后,打开另一个终端窗口,启动 TDengine 的 shell 向 **D1001** 插入一条电流为 12A 的数据: +示例程序启动后,打开另一个终端窗口,启动 TDengine CLI 向 **D1001** 插入一条电流为 12A 的数据: ```sql $ taos @@ -172,24 +172,24 @@ $ taos ## 示例程序 -下面以一个示例程序介绍其具体使用方法。示例程序的目的是订阅数据库中所有电流超过 10A 的记录。 +下面的示例程序展示是如何使用连接器订阅所有电流超过 10A 的记录。 ### 准备数据 -```sql -# 创建 power 库 +``` +# create database "power" taos> create database power; -# 切换库 +# use "power" as the database in following operations taos> use power; -# 创建超级表 +# create super table "meters" taos> create table meters(ts timestamp, current float, voltage int, phase int) tags(location binary(64), groupId int); -# 创建表 +# create tabes using the schema defined by super table "meters" taos> create table d1001 using meters tags ("Beijing.Chaoyang", 2); taos> create table d1002 using meters tags ("Beijing.Haidian", 2); -# 插入测试数据 +# insert some rows taos> insert into d1001 values("2020-08-15 12:00:00.000", 12, 220, 1),("2020-08-15 12:10:00.000", 12.3, 220, 2),("2020-08-15 12:20:00.000", 12.2, 220, 1); taos> insert into d1002 values("2020-08-15 12:00:00.000", 9.9, 220, 1),("2020-08-15 12:10:00.000", 10.3, 220, 1),("2020-08-15 12:20:00.000", 11.2, 220, 1); -# 从超级表 meters 查询电流大于 10A 的记录 +# filter out the rows in which current is bigger than 10A taos> select * from meters where current > 10; ts | current | voltage | phase | location | groupid | =========================================================================================================== @@ -206,24 +206,24 @@ Query OK, 5 row(s) in set (0.004896s) - {/* + - + {/* - + */} - + {/* - + */} - */} + ### 运行示例程序 @@ -238,16 +238,16 @@ ts: 1597464600000 current: 10.3 voltage: 220 phase: 1 location: Beijing.Haidian ts: 1597465200000 current: 11.2 voltage: 220 phase: 1 location: Beijing.Haidian groupid : 2 ``` -接着,使用 taos 客户端向表中新增一条数据: +接着,使用 TDengine CLI 向表中新增一条数据: -```sql +``` # taos taos> use power; -taos> insert into d1001 values("2020-08-15 12:40:00.000", 12.4, 220, 1); +taos> insert into d1001 values(now, 12.4, 220, 1); ``` 因为这条数据的电流大于 10A,示例程序会将其消费: ``` -ts: 1597466400000 current: 12.4 voltage: 220 phase: 1 location: Beijing.Chaoyang groupid: 2 +ts: 1651146662805 current: 12.4 voltage: 220 phase: 1 location: Beijing.Chaoyang groupid: 2 ``` diff --git a/docs-cn/04-develop/_category_.yml b/docs-cn/04-develop/_category_.yml index 83687164926268d4ae4cbe897006dde89d2e2c7b..b17f078b9a42143b8eb42a04909d5c881dcaad9d 100644 --- a/docs-cn/04-develop/_category_.yml +++ b/docs-cn/04-develop/_category_.yml @@ -1,4 +1,5 @@ label: 开发指南 link: + type: generated-index slug: /develop - type: generated-index \ No newline at end of file + description: "开始指南是对开发者友好的使用教程,既包括数据建模、写入、查询等基础功能的使用,也包括数据订阅、连续查询等高级功能的使用。对于每个主题,都配有各编程语言的连接器的示例代码,方便开发者快速上手。如果想更深入地了解各连接器的使用,请阅读连接器参考指南。" diff --git a/docs-cn/12-taos-sql/01-data-type.md b/docs-cn/12-taos-sql/01-data-type.md index 7e63e1c9507f3b12f37fdb42a9c347bd92aafb75..be5c9a8cb4ed7f4ed9f9c7e11faf1b0f8f6e51b8 100644 --- a/docs-cn/12-taos-sql/01-data-type.md +++ b/docs-cn/12-taos-sql/01-data-type.md @@ -1,6 +1,7 @@ --- sidebar_label: 支持的数据类型 title: 支持的数据类型 +description: "TDengine 支持的数据类型: 时间戳、浮点型、JSON 类型等" --- 使用 TDengine,最重要的是时间戳。创建并插入记录、查询历史记录的时候,均需要指定时间戳。时间戳有如下规则: @@ -13,7 +14,7 @@ title: 支持的数据类型 TDengine 缺省的时间戳精度是毫秒,但通过在 `CREATE DATABASE` 时传递的 PRECISION 参数也可以支持微秒和纳秒。(从 2.1.5.0 版本开始支持纳秒精度) -``` +```sql CREATE DATABASE db_name PRECISION 'ns'; ``` @@ -31,9 +32,7 @@ CREATE DATABASE db_name PRECISION 'ns'; | 8 | TINYINT | 1 | 单字节整型,范围 [-127, 127], -128 用作 NULL | | 9 | BOOL | 1 | 布尔型,{true, false} | | 10 | NCHAR | 自定义 | 记录包含多字节字符在内的字符串,如中文字符。每个 nchar 字符占用 4 bytes 的存储空间。字符串两端使用单引号引用,字符串内的单引号需用转义字符 `\’`。nchar 使用时须指定字符串大小,类型为 nchar(10) 的列表示此列的字符串最多存储 10 个 nchar 字符,会固定占用 40 bytes 的空间。如果用户字符串长度超出声明长度,将会报错。 | -| 11 | JSON | | json 数据类型, 只有 tag 可以是 json 格式 | - - +| 11 | JSON | | json 数据类型, 只有 tag 可以是 json 格式 | :::tip TDengine 对 SQL 语句中的英文字符不区分大小写,自动转化为小写执行。因此用户大小写敏感的字符串及密码,需要使用单引号将字符串引起来。 diff --git a/docs-cn/12-taos-sql/02-database.md b/docs-cn/12-taos-sql/02-database.md index 5240efa26fc98aaa0ffe83abbb3e44a23dbf338c..5d358193f96b9c3258d1236f8d11341f8889b8e5 100644 --- a/docs-cn/12-taos-sql/02-database.md +++ b/docs-cn/12-taos-sql/02-database.md @@ -1,6 +1,7 @@ --- sidebar_label: 数据库管理 title: 数据库管理 +description: "创建、删除数据库,查看、修改数据库参数" --- ## 创建数据库 diff --git a/docs-cn/12-taos-sql/index.md b/docs-cn/12-taos-sql/index.md index bc5c2efd67b5dca554ba7e7a0012477af2e373ab..c34c1e5dc812ad589a0c4fdf89a8d02ff4fd18a4 100644 --- a/docs-cn/12-taos-sql/index.md +++ b/docs-cn/12-taos-sql/index.md @@ -1,5 +1,6 @@ --- title: TAOS SQL +description: "TAOS SQL 支持的语法规则、主要查询功能、支持的 SQL 查询函数,以及常用技巧等内容" --- 本文档说明 TAOS SQL 支持的语法规则、主要查询功能、支持的 SQL 查询函数,以及常用技巧等内容。阅读本文档需要读者具有基本的 SQL 语言的基础。 diff --git a/docs-cn/14-reference/02-rest-api/02-rest-api.mdx b/docs-cn/14-reference/02-rest-api/02-rest-api.mdx index 42f93fce0d325eb5c42392bcffb678b113612961..defa1e094c59622c437924af00ff80492ceda514 100644 --- a/docs-cn/14-reference/02-rest-api/02-rest-api.mdx +++ b/docs-cn/14-reference/02-rest-api/02-rest-api.mdx @@ -90,15 +90,15 @@ HTTP 请求的 Header 里需带有身份认证信息,TDengine 支持 Basic 认 - 自定义身份认证信息如下所示(token 稍后介绍) -``` -Authorization: Taosd -``` + ``` + Authorization: Taosd + ``` - Basic 身份认证信息如下所示 -``` -Authorization: Basic -``` + ``` + Authorization: Basic + ``` HTTP 请求的 BODY 里就是一个完整的 SQL 语句,SQL 语句中的数据表应提供数据库前缀,例如 \.\。如果表名不带数据库前缀,又没有在 url 中指定数据库名的话,系统会返回错误。因为 HTTP 模块只是一个简单的转发,没有当前 DB 的概念。 @@ -190,47 +190,47 @@ curl http://192.168.0.1:6041/rest/login/root/taosdata - 在 demo 库里查询表 d1001 的所有记录: -```bash -curl -H 'Authorization: Basic cm9vdDp0YW9zZGF0YQ==' -d 'select * from demo.d1001' 192.168.0.1:6041/rest/sql -``` + ```bash + curl -H 'Authorization: Basic cm9vdDp0YW9zZGF0YQ==' -d 'select * from demo.d1001' 192.168.0.1:6041/rest/sql + ``` -返回值: + 返回值: -```json -{ - "status": "succ", - "head": ["ts", "current", "voltage", "phase"], - "column_meta": [ - ["ts", 9, 8], - ["current", 6, 4], - ["voltage", 4, 4], - ["phase", 6, 4] - ], - "data": [ - ["2018-10-03 14:38:05.000", 10.3, 219, 0.31], - ["2018-10-03 14:38:15.000", 12.6, 218, 0.33] - ], - "rows": 2 -} -``` + ```json + { + "status": "succ", + "head": ["ts", "current", "voltage", "phase"], + "column_meta": [ + ["ts", 9, 8], + ["current", 6, 4], + ["voltage", 4, 4], + ["phase", 6, 4] + ], + "data": [ + ["2018-10-03 14:38:05.000", 10.3, 219, 0.31], + ["2018-10-03 14:38:15.000", 12.6, 218, 0.33] + ], + "rows": 2 + } + ``` - 创建库 demo: -```bash -curl -H 'Authorization: Basic cm9vdDp0YW9zZGF0YQ==' -d 'create database demo' 192.168.0.1:6041/rest/sql -``` + ```bash + curl -H 'Authorization: Basic cm9vdDp0YW9zZGF0YQ==' -d 'create database demo' 192.168.0.1:6041/rest/sql + ``` -返回值: + 返回值: -```json -{ - "status": "succ", - "head": ["affected_rows"], - "column_meta": [["affected_rows", 4, 4]], - "data": [[1]], - "rows": 1 -} -``` + ```json + { + "status": "succ", + "head": ["affected_rows"], + "column_meta": [["affected_rows", 4, 4]], + "data": [[1]], + "rows": 1 + } + ``` ## 其他用法 diff --git a/docs-cn/14-reference/03-connector/03-connector.mdx b/docs-cn/14-reference/03-connector/03-connector.mdx index 846d5fdab30de1079a340655f7cbb77e73685cf4..c0e714f148a7821e070be38a5484484fdd747e9a 100644 --- a/docs-cn/14-reference/03-connector/03-connector.mdx +++ b/docs-cn/14-reference/03-connector/03-connector.mdx @@ -11,7 +11,7 @@ TDengine 提供了丰富的应用程序开发接口,为了便于用户快速 目前 TDengine 的原生接口连接器可支持的平台包括:X64/X86/ARM64/ARM32/MIPS/Alpha 等硬件平台,以及 Linux/Win64/Win32 等开发环境。对照矩阵如下: | **CPU** | **OS** | **JDBC** | **Python** | **Go** | **Node.js** | **C#** | **Rust** | C/C++ | -| -------------- | --------- | -------- | ---------- | ------ | ----------- | ------ | -------- | ------| +| -------------- | --------- | -------- | ---------- | ------ | ----------- | ------ | -------- | ----- | | **X86 64bit** | **Linux** | ● | ● | ● | ● | ● | ● | ● | | **X86 64bit** | **Win64** | ● | ● | ● | ● | ● | ● | ● | | **X86 64bit** | **Win32** | ● | ● | ● | ● | ○ | ○ | ● | @@ -30,40 +30,46 @@ TDengine 提供了丰富的应用程序开发接口,为了便于用户快速 TDengine 版本更新往往会增加新的功能特性,列表中的连接器版本为连接器最佳适配版本。 -| **TDengine 版本** | **Java** | **Python** | **Go** | **C#** | **Node.js** | **Rust** | -| ---------------------- | -------- | ---------- | ------------ | ------------- | --------------- | -------- | -| **2.4.0.14 及以上** | 2.0.38 | 当前版本 | develop 分支 | 1.0.2 - 1.0.6 | 2.0.10 - 2.0.12 | 当前版本 | -| **2.4.0.6 及以上** | 2.0.37 | 当前版本 | develop 分支 | 1.0.2 - 1.0.6 | 2.0.10 - 2.0.12 | 当前版本 | -| **2.4.0.4 - 2.4.0.5** | 2.0.37 | 当前版本 | develop 分支 | 1.0.2 - 1.0.6 | 2.0.10 - 2.0.12 | 当前版本 | -| **2.2.x.x ** | 2.0.36 | 当前版本 | master 分支 | n/a | 2.0.7 - 2.0.9 | 当前版本 | -| **2.0.x.x ** | 2.0.34 | 当前版本 | master 分支 | n/a | 2.0.1 - 2.0.6 | 当前版本 | +| **TDengine 版本** | **Java** | **Python** | **Go** | **C#** | **Node.js** | **Rust** | +| --------------------- | -------- | ---------- | ------------ | ------------- | --------------- | -------- | +| **2.4.0.14 及以上** | 2.0.38 | 当前版本 | develop 分支 | 1.0.2 - 1.0.6 | 2.0.10 - 2.0.12 | 当前版本 | +| **2.4.0.6 及以上** | 2.0.37 | 当前版本 | develop 分支 | 1.0.2 - 1.0.6 | 2.0.10 - 2.0.12 | 当前版本 | +| **2.4.0.4 - 2.4.0.5** | 2.0.37 | 当前版本 | develop 分支 | 1.0.2 - 1.0.6 | 2.0.10 - 2.0.12 | 当前版本 | +| **2.2.x.x ** | 2.0.36 | 当前版本 | master 分支 | n/a | 2.0.7 - 2.0.9 | 当前版本 | +| **2.0.x.x ** | 2.0.34 | 当前版本 | master 分支 | n/a | 2.0.1 - 2.0.6 | 当前版本 | ## 功能特性 -连接器对 TDengine 功能特性的支持对照如下[^1]: +连接器对 TDengine 功能特性的支持对照如下: ### 使用原生接口(taosc) -| **功能特性** | **Java** | **Python** | **Go** | **C#** | **Node.js** | **Rust** | -| ------------------ | --------- | ---------- | -------- | -------- | ----------- | -------- | -| **连接管理** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | -| **普通查询** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | -| **连续查询** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | -| **参数绑定** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | -| **订阅功能** | 支持 | 支持 | 支持 | 支持 | 支持 | 暂不支持 | -| **Schemaless** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | +| **功能特性** | **Java** | **Python** | **Go** | **C#** | **Node.js** | **Rust** | +| -------------- | -------- | ---------- | ------ | ------ | ----------- | -------- | +| **连接管理** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | +| **普通查询** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | +| **连续查询** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | +| **参数绑定** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | +| **订阅功能** | 支持 | 支持 | 支持 | 支持 | 支持 | 暂不支持 | +| **Schemaless** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | +| **DataFrame** | 不支持 | 支持 | 不支持 | 不支持 | 不支持 | 不支持 | + +:::info +由于不同编程语言数据库框架规范不同,并不意味着所有 C/C++ 接口都需要对应封装支持。 +::: ### 使用 REST 接口 -| **功能特性** | **Java** | **Python(暂不支持)** | **Go** | **C#(暂不支持)** | **Node.js** | **Rust** | -| ----------------------------- | --------- | ---------------------- | -------- | -------------------- | ----------- | -------- | -| **连接管理** | 支持 | n/a | 支持 | n/a | 支持 | 支持 | -| **普通查询** | 支持 | n/a | 支持 | n/a | 支持 | 支持 | -| **连续查询** | 支持 | n/a | 支持 | n/a | 支持 | 支持 | -| **参数绑定** | 不支持 | n/a | 不支持 | n/a | 不支持 | 不支持 | -| **订阅功能** | 不支持 | n/a | 不支持 | n/a | 不支持 | 不支持 | -| **Schemaless** | 暂不支持 | n/a | 暂不支持 | n/a | 暂不支持 | 暂不支持 | -| **批量拉取(基于WebSocket)** | 支持 | n/a | 暂不支持 | n/a | 暂不支持 | 暂不支持 | +| **功能特性** | **Java** | **Python** | **Go** | **C#(暂不支持)** | **Node.js** | **Rust** | +| ------------------------------ | -------- | ---------- | -------- | ------------------ | ----------- | -------- | +| **连接管理** | 支持 | 支持 | 支持 | N/A | 支持 | 支持 | +| **普通查询** | 支持 | 支持 | 支持 | N/A | 支持 | 支持 | +| **连续查询** | 支持 | 支持 | 支持 | N/A | 支持 | 支持 | +| **参数绑定** | 不支持 | 不支持 | 不支持 | N/A | 不支持 | 不支持 | +| **订阅功能** | 不支持 | 不支持 | 不支持 | N/A | 不支持 | 不支持 | +| **Schemaless** | 暂不支持 | 暂不支持 | 暂不支持 | N/A | 暂不支持 | 暂不支持 | +| **批量拉取(基于 WebSocket)** | 支持 | 暂不支持 | 暂不支持 | N/A | 暂不支持 | 暂不支持 | +| **DataFrame** | 不支持 | 支持 | 不支持 | N/A | 不支持 | 不支持 | :::warning @@ -109,5 +115,3 @@ import VerifyLinux from "./_verify_linux.mdx"; -[^1]: 由于不同语言数据库框架规范不同,并不意味着所有 C/C++ 接口都需要对应封装支持。 - diff --git a/docs-cn/14-reference/03-connector/_linux_install.mdx b/docs-cn/14-reference/03-connector/_linux_install.mdx index be363395cb6340a00ea0e51a0facc57a0340b301..6437583b43d905272a9676703d318b9fdb74d941 100644 --- a/docs-cn/14-reference/03-connector/_linux_install.mdx +++ b/docs-cn/14-reference/03-connector/_linux_install.mdx @@ -1,7 +1,11 @@ -1. 从[涛思官网](https://www.taosdata.com/cn/all-downloads/)下载: - - X64 硬件环境:TDengine-client-2.x.x.x-Linux-x64.tar.gz - - ARM64 硬件环境:TDengine-client-2.x.x.x-Linux-aarch64.tar.gz - - ARM32 硬件环境:TDengine-client-2.x.x.x-Linux-aarch32.tar.gz +import PkgList from "/components/PkgList"; + +1. 下载客户端安装包 + + + + [所有下载](https://www.taosdata.com/cn/all-downloads/) + 2. 解压缩软件包 将软件包放置在当前用户可读写的任意目录下,然后执行下面的命令:`tar -xzvf TDengine-client-VERSION.tar.gz` diff --git a/docs-cn/14-reference/03-connector/_windows_install.mdx b/docs-cn/14-reference/03-connector/_windows_install.mdx index ac7d5bfc0a9bdcfba7fa66258a4fdf097f1629b5..755f96b2d728621de5752ce752e5d249cda0f6d9 100644 --- a/docs-cn/14-reference/03-connector/_windows_install.mdx +++ b/docs-cn/14-reference/03-connector/_windows_install.mdx @@ -1,6 +1,11 @@ -1. 从[涛思官网](https://www.taosdata.com/cn/all-downloads/)下载 - - X64 硬件环境:TDengine-client-2.X.X.X-Windows-x64.exe - - X86 硬件环境:TDengine-client-2.X.X.X-Windows-x86.exe +import PkgList from "/components/PkgList"; + +1. 下载客户端安装包 + + + + [所有下载](https://www.taosdata.com/cn/all-downloads/) + 2. 执行安装程序,按提示选择默认值,完成安装 3. 安装路径 diff --git a/docs-cn/14-reference/03-connector/cpp.mdx b/docs-cn/14-reference/03-connector/cpp.mdx index d0e030c560035210e30fcd93d8f2a4b7390565be..29aebaed3d8ca852950508ba751b8c86689724ca 100644 --- a/docs-cn/14-reference/03-connector/cpp.mdx +++ b/docs-cn/14-reference/03-connector/cpp.mdx @@ -45,7 +45,7 @@ TDengine 客户端驱动的安装请参考 [安装指南](/reference/connector# exit(1); } - /* 此处省略查询和写入 */ + /* put your code here for read and write */ taos_close(taos); taos_cleanup(); @@ -217,9 +217,9 @@ TDengine 客户端驱动的安装请参考 [安装指南](/reference/connector# ```c typedef struct taosField { - char name[65]; // 列名 - uint8_t type; // 数据类型 - int16_t bytes; // 长度,单位是字节 + char name[65]; // column name + uint8_t type; // data type + int16_t bytes; // length, in bytes } TAOS_FIELD; ``` @@ -307,11 +307,11 @@ TDengine 的异步 API 均采用非阻塞调用模式。应用程序可以用多 typedef struct TAOS_BIND { int buffer_type; void * buffer; - uintptr_t buffer_length; // 未实际使用 + uintptr_t buffer_length; // not in use uintptr_t * length; int * is_null; - int is_unsigned; // 未实际使用 - int * error; // 未实际使用 + int is_unsigned; // not in use + int * error; // not in use } TAOS_BIND; ``` @@ -337,7 +337,7 @@ TDengine 的异步 API 均采用非阻塞调用模式。应用程序可以用多 uintptr_t buffer_length; uintptr_t * length; char * is_null; - int num; // 列的个数,即 buffer 中的参数个数 + int num; // the number of columns } TAOS_MULTI_BIND; ``` diff --git a/docs-cn/14-reference/03-connector/csharp.mdx b/docs-cn/14-reference/03-connector/csharp.mdx index 3c5e30437d67034fbebabd5f780ca1b3236df446..bbefaacb459153ab5116d557fdf1940d487b4bd3 100644 --- a/docs-cn/14-reference/03-connector/csharp.mdx +++ b/docs-cn/14-reference/03-connector/csharp.mdx @@ -18,7 +18,7 @@ import CSAsyncQuery from "../../04-develop/04-query-data/_cs_async.mdx" `TDengine.Connector` 是 TDengine 提供的 C# 语言连接器。C# 开发人员可以通过它开发存取 TDengine 集群数据的 C# 应用软件。 -`TDengine.Connector` 连接器支持通过客户端驱动(taosc)建立本地连接 TDengine 集群,进行数据写入、查询、订阅、schemaless 数据写入、参数绑定接口数据写入等功能。`TDengine.Connector` 目前暂未提供 REST 连接方式,用户可以参考 [RESTful APIs](https://docs.taosdata.com//reference/restful-api/) 文档自行编写。 +`TDengine.Connector` 连接器支持通过 TDengine 客户端驱动(taosc)建立与 TDengine 运行实例的连接,提供数据写入、查询、订阅、schemaless 数据写入、参数绑定接口数据写入等功能 `TDengine.Connector` 目前暂未提供 REST 连接方式,用户可以参考 [RESTful APIs](https://docs.taosdata.com//reference/restful-api/) 文档自行编写。 本文介绍如何在 Linux 或 Windows 环境中安装 `TDengine.Connector`,并通过 `TDengine.Connector` 连接 TDengine 集群,进行数据写入、查询等基本操作。 @@ -26,7 +26,7 @@ import CSAsyncQuery from "../../04-develop/04-query-data/_cs_async.mdx" ## 支持的平台 -请参考[支持的平台列表](/reference/connector#支持的平台) +支持的平台和 TDengine 客户端驱动支持的平台一致。 ## 版本支持 @@ -46,9 +46,8 @@ import CSAsyncQuery from "../../04-develop/04-query-data/_cs_async.mdx" ### 安装前准备 * 安装 [.NET SDK](https://dotnet.microsoft.com/download) - - (可选安装)[Nuget 客户端](https://docs.microsoft.com/en-us/nuget/install-nuget-client-tools) - - +* [Nuget 客户端](https://docs.microsoft.com/en-us/nuget/install-nuget-client-tools) (可选安装) +* 安装 TDengine 客户端驱动,具体步骤请参考[安装客户端驱动](/reference/connector#安装客户端驱动) ### 使用 dotnet CLI 安装 @@ -160,11 +159,11 @@ namespace TDengineExample | TDengine.Connector | 说明 | |--------------------|--------------------------------| -| 1.0.2 | 新增连接管理、同步查询、错误信息等功能。 | -| 1.0.3 | 新增参数绑定、schemaless、 json tag等功能。 | -| 1.0.4 | 新增异步查询,订阅等功能。修复绑定参数 bug。 | -| 1.0.5 | 修复 Windows 同步查询中文报错 bug。 | | 1.0.6 | 修复 schemaless 在 1.0.4 和 1.0.5 中失效 bug。 | +| 1.0.5 | 修复 Windows 同步查询中文报错 bug。 | +| 1.0.4 | 新增异步查询,订阅等功能。修复绑定参数 bug。 | +| 1.0.3 | 新增参数绑定、schemaless、 json tag等功能。 | +| 1.0.2 | 新增连接管理、同步查询、错误信息等功能。 | ## 其他说明 @@ -177,13 +176,13 @@ namespace TDengineExample ## 常见问题 -* "Unable to establish connection","Unable to resolve FQDN" +1. "Unable to establish connection","Unable to resolve FQDN" -一般是因为 FQDN 配置不正确。可以参考[如何彻底搞懂 TDengine 的 FQDN](https://www.taosdata.com/blog/2021/07/29/2741.html)解决。 + 一般是因为 FQDN 配置不正确。可以参考[如何彻底搞懂 TDengine 的 FQDN](https://www.taosdata.com/blog/2021/07/29/2741.html)解决。 -* Unhandled exception. System.DllNotFoundException: Unable to load DLL 'taos' or one of its dependencies: 找不到指定的模块。 +2. Unhandled exception. System.DllNotFoundException: Unable to load DLL 'taos' or one of its dependencies: 找不到指定的模块。 -一般是因为程序没有找到依赖的客户端驱动。解决方法为:Windows 下可以将 `C:\TDengine\driver\taos.dll` 拷贝到 `C:\Windows\System32\ ` 目录下,Linux 下建立如下软链接 `ln -s /usr/local/taos/driver/libtaos.so.x.x.x.x /usr/lib/libtaos.so` 即可。 + 一般是因为程序没有找到依赖的客户端驱动。解决方法为:Windows 下可以将 `C:\TDengine\driver\taos.dll` 拷贝到 `C:\Windows\System32\ ` 目录下,Linux 下建立如下软链接 `ln -s /usr/local/taos/driver/libtaos.so.x.x.x.x /usr/lib/libtaos.so` 即可。 ## API 参考 diff --git a/docs-cn/14-reference/03-connector/go.mdx b/docs-cn/14-reference/03-connector/go.mdx index 469508733f679d194bafb82ffa8fb863377f5da6..c5f448916a39acdf7f0ffff01bf431d93f2143b4 100644 --- a/docs-cn/14-reference/03-connector/go.mdx +++ b/docs-cn/14-reference/03-connector/go.mdx @@ -2,7 +2,7 @@ toc_max_heading_level: 4 sidebar_position: 4 sidebar_label: Go -title: Go Connector +title: TDengine Go Connector --- import Tabs from '@theme/Tabs'; @@ -15,9 +15,9 @@ import GoOpenTSDBTelnet from "../../04-develop/03-insert-data/_go_opts_telnet.md import GoOpenTSDBJson from "../../04-develop/03-insert-data/_go_opts_json.mdx" import GoQuery from "../../04-develop/04-query-data/_go.mdx" -`driver-go` 是 TDengine 的官方 Go 语言连接器。Go 开发人员可以通过它开发存取 TDengine 集群数据的应用软件。 +`driver-go` 是 TDengine 的官方 Go 语言连接器,实现了 Go 语言[ database/sql ](https://golang.org/pkg/database/sql/) 包的接口。Go 开发人员可以通过它开发存取 TDengine 集群数据的应用软件。 -`driver-go` 实现了 Go 语言[ database/sql ](https://golang.org/pkg/database/sql/) 包的接口。`driver-go` 支持通过客户端驱动程序(taosc)原生连接 TDengine 集群,支持数据写入、查询、订阅、schemaless 接口和参数绑定接口等功能。也支持使用 REST 接口连接 TDengine 集群。REST 接口实现的功能特性集合和原生接口有少量不同。 +`driver-go` 提供两种建立连接的方式。一种是**原生连接**,它通过 TDengine 客户端驱动程序(taosc)原生连接 TDengine 运行实例,支持数据写入、查询、订阅、schemaless 接口和参数绑定接口等功能。另外一种是 **REST 连接**,它通过 taosAdapter 提供的 REST 接口连接 TDengine 运行实例。REST 连接实现的功能特性集合和原生连接有少量不同。 本文介绍如何安装 `driver-go`,并通过 `driver-go` 连接 TDengine 集群、进行数据查询、数据写入等基本操作。 @@ -25,7 +25,8 @@ import GoQuery from "../../04-develop/04-query-data/_go.mdx" ## 支持的平台 -请参考[支持的平台列表](/reference/connector#支持的平台) +原生连接支持的平台和 TDengine 客户端驱动支持的平台一致。 +REST 连接支持所有能运行 Go 的平台。 ## 版本支持 @@ -35,7 +36,7 @@ import GoQuery from "../../04-develop/04-query-data/_go.mdx" ### 原生连接 -“原生连接”指连接器通过客户端驱动(taosc)直接与 TDengine 集群建立连接。支持的功能特性有: +“原生连接”指连接器通过 TDengine 客户端驱动(taosc)直接与 TDengine 运行实例建立的连接。支持的功能特性有: * 普通查询 * 连续查询 @@ -45,7 +46,7 @@ import GoQuery from "../../04-develop/04-query-data/_go.mdx" ### REST 连接 -REST 连接指连接器通过 taosAdapter 组件提供的 REST API 建立与 taosd 的连接。支持的功能特性有: +"REST 连接"指连接器通过 taosAdapter 组件提供的 REST API 与 TDengine 运行实例建立的连接。支持的功能特性有: * 普通查询 * 连续查询 @@ -55,7 +56,7 @@ REST 连接指连接器通过 taosAdapter 组件提供的 REST API 建立与 tao ### 安装前准备 * 安装 Go 开发环境(Go 1.14 及以上,GCC 4.8.5 及以上) - +* 如果使用原生连接器,请安装 TDengine 客户端驱动,具体步骤请参考[安装客户端驱动](/reference/connector#安装客户端驱动) 配置好环境变量,检查命令: @@ -66,6 +67,36 @@ REST 连接指连接器通过 taosAdapter 组件提供的 REST API 建立与 tao `go get -u github.com/taosdata/driver-go/v2@develop` +### 使用 go mod 管理 + +1. 使用 `go mod` 命令初始化项目: + + ```text + go mod init taos-demo + ``` + +2. 引入 taosSql : + + ```go + import ( + "database/sql" + _ "github.com/taosdata/driver-go/v2/taosSql" + ) + ``` + +3. 使用 `go mod tidy` 更新依赖包: + + ```text + go mod tidy + ``` + +4. 使用 `go run taos-demo` 运行程序或使用 `go build` 命令编译出二进制文件。 + + ```text + go run taos-demo + go build + ``` + ## 建立连接 ### 数据源名称(DSN) @@ -81,9 +112,10 @@ REST 连接指连接器通过 taosAdapter 组件提供的 REST API 建立与 tao ```text username:password@protocol(address)/dbname?param=value ``` +### 使用连接器进行连接 - + _taosSql_ 通过 cgo 实现了 Go 的 `database/sql/driver` 接口。只需要引入驱动就可以使用 [`database/sql`](https://golang.org/pkg/database/sql/) 的接口。 @@ -114,7 +146,7 @@ func main() { ``` - + _taosRestful_ 通过 `http client` 实现了 Go 的 `database/sql/driver` 接口。只需要引入驱动就可以使用[`database/sql`](https://golang.org/pkg/database/sql/)的接口。 @@ -234,37 +266,37 @@ func main() { ## 常见问题 -* 无法找到包 `github.com/taosdata/driver-go/v2/taosRestful` +1. 无法找到包 `github.com/taosdata/driver-go/v2/taosRestful` -将 `go.mod` 中 require 块对`github.com/taosdata/driver-go/v2`的引用改为`github.com/taosdata/driver-go/v2 develop`,之后执行 `go mod tidy`。 + 将 `go.mod` 中 require 块对`github.com/taosdata/driver-go/v2`的引用改为`github.com/taosdata/driver-go/v2 develop`,之后执行 `go mod tidy`。 -* database/sql 中 stmt 相关接口崩溃 +2. database/sql 中 stmt(参数绑定)相关接口崩溃 -REST 不支持 stmt 相关接口,建议使用`db.Exec`和`db.Query`。 + REST 不支持参数绑定相关接口,建议使用`db.Exec`和`db.Query`。 -* 使用 `use db` 语句后执行其他语句报错 `[0x217] Database not specified or available` +3. 使用 `use db` 语句后执行其他语句报错 `[0x217] Database not specified or available` -在 REST 接口中 SQL 语句的执行无上下文关联,使用 `use db` 语句不会生效,解决办法见上方使用限制章节。 + 在 REST 接口中 SQL 语句的执行无上下文关联,使用 `use db` 语句不会生效,解决办法见上方使用限制章节。 -* 使用 taosSql 不报错使用 taosRestful 报错 `[0x217] Database not specified or available` +4. 使用 taosSql 不报错使用 taosRestful 报错 `[0x217] Database not specified or available` -因为 REST 接口无状态,使用 `use db` 语句不会生效,解决办法见上方使用限制章节。 + 因为 REST 接口无状态,使用 `use db` 语句不会生效,解决办法见上方使用限制章节。 -* 升级 `github.com/taosdata/driver-go/v2/taosRestful` +5. 升级 `github.com/taosdata/driver-go/v2/taosRestful` -将 `go.mod` 文件中对 `github.com/taosdata/driver-go/v2` 的引用改为 `github.com/taosdata/driver-go/v2 develop`,之后执行 `go mod tidy`。 + 将 `go.mod` 文件中对 `github.com/taosdata/driver-go/v2` 的引用改为 `github.com/taosdata/driver-go/v2 develop`,之后执行 `go mod tidy`。 -* `readBufferSize` 参数调大后无明显效果 +6. `readBufferSize` 参数调大后无明显效果 -`readBufferSize` 调大后会减少获取结果时 `syscall` 的调用。如果查询结果的数据量不大,修改该参数不会带来明显提升,如果该参数修改过大,瓶颈会在解析 JSON 数据。如果需要优化查询速度,需要根据实际情况调整该值来达到查询效果最优。 + `readBufferSize` 调大后会减少获取结果时 `syscall` 的调用。如果查询结果的数据量不大,修改该参数不会带来明显提升,如果该参数修改过大,瓶颈会在解析 JSON 数据。如果需要优化查询速度,需要根据实际情况调整该值来达到查询效果最优。 -* `disableCompression` 参数设置为 `false` 时查询效率降低 +7. `disableCompression` 参数设置为 `false` 时查询效率降低 -当 `disableCompression` 参数设置为 `false` 时查询结果会使用 `gzip` 压缩后传输,拿到数据后要先进行 `gzip` 解压。 + 当 `disableCompression` 参数设置为 `false` 时查询结果会使用 `gzip` 压缩后传输,拿到数据后要先进行 `gzip` 解压。 -* `go get` 命令无法获取包,或者获取包超时 +8. `go get` 命令无法获取包,或者获取包超时 -设置 Go 代理 `go env -w GOPROXY=https://goproxy.cn,direct`。 + 设置 Go 代理 `go env -w GOPROXY=https://goproxy.cn,direct`。 ## 常用 API @@ -272,103 +304,107 @@ REST 不支持 stmt 相关接口,建议使用`db.Exec`和`db.Query`。 * `sql.Open(DRIVER_NAME string, dataSourceName string) *DB` -该 API 用来打开 DB,返回一个类型为 \*DB 的对象。 + 该 API 用来打开 DB,返回一个类型为 \*DB 的对象。 -**注意**: 该 API 成功创建的时候,并没有做权限等检查,只有在真正执行 Query 或者 Exec 的时候才能真正的去创建连接,并同时检查 user/password/host/port 是不是合法。 +:::info +该 API 成功创建的时候,并没有做权限等检查,只有在真正执行 Query 或者 Exec 的时候才能真正的去创建连接,并同时检查 user/password/host/port 是不是合法。 +::: * `func (db *DB) Exec(query string, args ...interface{}) (Result, error)` -`sql.Open` 内置的方法,用来执行非查询相关 SQL。 + `sql.Open` 内置的方法,用来执行非查询相关 SQL。 * `func (db *DB) Query(query string, args ...interface{}) (*Rows, error)` -`sql.Open` 内置的方法,用来执行查询语句。 + `sql.Open` 内置的方法,用来执行查询语句。 + +### 高级功能(af)API -### 高级功能 API +`af` 包封装了连接管理、订阅、schemaless、参数绑定等 TDengine 高级功能。 -af 包封装了订阅、stmt 等 TDengine 高级功能。 +#### 连接管理 * `af.Open(host, user, pass, db string, port int) (*Connector, error)` -该 API 通过 cgo 创建与 taosd 的连接。 + 该 API 通过 cgo 创建与 taosd 的连接。 * `func (conn *Connector) Close() error` -关闭与 taosd 的连接。 + 关闭与 taosd 的连接。 -* `func (conn *Connector) StmtExecute(sql string, params *param.Param) (res driver.Result, err error)` - -stmt 单行插入。 - -* `func (conn *Connector) StmtQuery(sql string, params *param.Param) (rows driver.Rows, err error)` - -stmt 查询,返回 `database/sql/driver` 包的 `Rows` 结构。 - -订阅 +#### 订阅 * `func (conn *Connector) Subscribe(restart bool, topic string, sql string, interval time.Duration) (Subscriber, error)` -订阅数据。 + 订阅数据。 * `func (s *taosSubscriber) Consume() (driver.Rows, error)` -消费订阅数据,返回 `database/sql/driver` 包的 `Rows` 结构。 + 消费订阅数据,返回 `database/sql/driver` 包的 `Rows` 结构。 * `func (s *taosSubscriber) Unsubscribe(keepProgress bool)` -取消订阅数据。 + 取消订阅数据。 -schemaless 写入 +#### schemaless * `func (conn *Connector) InfluxDBInsertLines(lines []string, precision string) error` -写入 influxDB 行协议。 + 写入 influxDB 行协议。 * `func (conn *Connector) OpenTSDBInsertTelnetLines(lines []string) error` -写入 OpenTDSB telnet 协议。 + 写入 OpenTDSB telnet 协议数据。 * `func (conn *Connector) OpenTSDBInsertJsonPayload(payload string) error` -写入 OpenTSDB json 协议。 + 写入 OpenTSDB JSON 协议数据。 + +#### 参数绑定 + +* `func (conn *Connector) StmtExecute(sql string, params *param.Param) (res driver.Result, err error)` + + 参数绑定单行插入。 + +* `func (conn *Connector) StmtQuery(sql string, params *param.Param) (rows driver.Rows, err error)` -批量 stmt 插入 + 参数绑定查询,返回 `database/sql/driver` 包的 `Rows` 结构。 * `func (conn *Connector) InsertStmt() *insertstmt.InsertStmt` -初始化 stmt。 + 初始化参数。 * `func (stmt *InsertStmt) Prepare(sql string) error` -预处理 SQL 语句。 + 参数绑定预处理 SQL 语句。 * `func (stmt *InsertStmt) SetTableName(name string) error` -设置表名。 + 参数绑定设置表名。 * `func (stmt *InsertStmt) SetSubTableName(name string) error` -设置子表名。 + 参数绑定设置子表名。 * `func (stmt *InsertStmt) BindParam(params []*param.Param, bindType *param.ColumnType) error` -绑定多行数据。 + 参数绑定多行数据。 * `func (stmt *InsertStmt) AddBatch() error` -添加到批处理。 + 添加到参数绑定批处理。 * `func (stmt *InsertStmt) Execute() error` -执行 stmt。 + 执行参数绑定。 * `func (stmt *InsertStmt) GetAffectedRows() int` -获取受影响行数。 + 获取参数绑定插入受影响行数。 * `func (stmt *InsertStmt) Close() error` -结束 stmt。 + 结束参数绑定。 ## API 参考 diff --git a/docs-cn/14-reference/03-connector/java.mdx b/docs-cn/14-reference/03-connector/java.mdx index 8b6f792205ed170c456df6dd91475c0cdd9fcbe1..970f8aeb7f1095544361f07ef758eb35de709a19 100644 --- a/docs-cn/14-reference/03-connector/java.mdx +++ b/docs-cn/14-reference/03-connector/java.mdx @@ -18,7 +18,7 @@ import TabItem from '@theme/TabItem'; - JDBC 原生连接:Java 应用在物理节点 1(pnode1)上使用 TSDBDriver 直接调用客户端驱动(libtaos.so 或 taos.dll)的 API 将写入和查询请求发送到位于物理节点 2(pnode2)上的 taosd 实例。 - JDBC REST 连接:Java 应用通过 RestfulDriver 将 SQL 封装成一个 REST 请求,发送给物理节点 2 的 REST 服务器(taosAdapter),通过 REST 服务器请求 taosd 并返回结果。 -使用 REST 连接器,不依赖 TDengine 客户端驱动,可以跨平台,更加方便灵活,但性能比原生连接器低约 30%。 +使用 REST 连接,不依赖 TDengine 客户端驱动,可以跨平台,更加方便灵活,但性能比原生连接器低约 30%。 :::info TDengine 的 JDBC 驱动实现尽可能与关系型数据库驱动保持一致,但 TDengine 与关系对象型数据库的使用场景和技术特征存在差异,所以`taos-jdbcdriver` 与传统的 JDBC driver 也存在一定差异。在使用时需要注意以下几点: @@ -30,7 +30,8 @@ TDengine 的 JDBC 驱动实现尽可能与关系型数据库驱动保持一致 ## 支持的平台 -请参考[支持的平台列表](/reference/connector#支持的平台) +原生连接支持的平台和 TDengine 客户端驱动支持的平台一致。 +REST 连接支持所有能运行 Java 的平台。 ## 版本支持 @@ -107,10 +108,10 @@ mvn clean install -Dmaven.test.skip=true TDengine 的 JDBC URL 规范格式为: `jdbc:[TAOS|TAOS-RS]://[host_name]:[port]/[database_name]?[user={user}|&password={password}|&charset={charset}|&cfgdir={config_dir}|&locale={locale}|&timezone={timezone}]` -对于建立连接,原生连接器与 REST 连接器有细微不同。 +对于建立连接,原生连接与 REST 连接有细微不同。 - + ```java Class.forName("com.taosdata.jdbc.TSDBDriver"); @@ -177,7 +178,7 @@ TDengine 中,只要保证 firstEp 和 secondEp 中一个节点有效,就可 > **注意**:这里的配置文件指的是调用 JDBC Connector 的应用程序所在机器上的配置文件,Linux OS 上默认值 /etc/taos/taos.cfg ,Windows OS 上默认值 C://TDengine/cfg/taos.cfg。 - + ```java Class.forName("com.taosdata.jdbc.rs.RestfulDriver"); @@ -807,24 +808,31 @@ Query OK, 1 row(s) in set (0.000141s) | taos-jdbcdriver 版本 | 主要变化 | | :------------------: | :----------------------------: | -| 2.0.36 | 增加对 schemaless 写入支持 | -| 2.0.37 | 增加对 json tag 支持 | | 2.0.38 | JDBC REST 连接增加批量拉取功能 | +| 2.0.37 | 增加对 json tag 支持 | +| 2.0.36 | 增加对 schemaless 写入支持 | ## 常见问题 -- 使用 Statement 的 `addBatch` 和 `executeBatch` 来执行“批量写入/更行”,为什么没有带来性能上的提升? +1. 使用 Statement 的 `addBatch` 和 `executeBatch` 来执行“批量写入/更行”,为什么没有带来性能上的提升? + **原因**:TDengine 的 JDBC 实现中,通过 `addBatch` 方法提交的 SQL 语句,会按照添加的顺序,依次执行,这种方式没有减少与服务端的交互次数,不会带来性能上的提升。 + **解决方法**:1. 在一条 insert 语句中拼接多个 values 值;2. 使用多线程的方式并发插入;3. 使用参数绑定的写入方式 -- java.lang.UnsatisfiedLinkError: no taos in java.library.path + +2. java.lang.UnsatisfiedLinkError: no taos in java.library.path + **原因**:程序没有找到依赖的本地函数库 taos。 + **解决方法**:Windows 下可以将 C:\TDengine\driver\taos.dll 拷贝到 C:\Windows\System32\ 目录下,Linux 下将建立如下软链 `ln -s /usr/local/taos/driver/libtaos.so.x.x.x.x /usr/lib/libtaos.so` 即可。 -- java.lang.UnsatisfiedLinkError: taos.dll Can't load AMD 64 bit on a IA 32-bit platform +3. java.lang.UnsatisfiedLinkError: taos.dll Can't load AMD 64 bit on a IA 32-bit platform + **原因**:目前 TDengine 只支持 64 位 JDK。 + **解决方法**:重新安装 64 位 JDK。 -- 其它问题请参考 [FAQ](/train-faq/faq) +4. 其它问题请参考 [FAQ](/train-faq/faq) ## API 参考 diff --git a/docs-cn/14-reference/03-connector/node.mdx b/docs-cn/14-reference/03-connector/node.mdx index f00db14f84d873a147123d1868e317b4d6f4f67f..0afcf2457dfdb11c01657abd983601322899b8fb 100644 --- a/docs-cn/14-reference/03-connector/node.mdx +++ b/docs-cn/14-reference/03-connector/node.mdx @@ -2,29 +2,30 @@ toc_max_heading_level: 4 sidebar_position: 6 sidebar_label: Node.js -title: Node.js Connector +title: TDengine Node.js Connector --- -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; +import Tabs from "@theme/Tabs"; +import TabItem from "@theme/TabItem"; -import Preparition from "./_preparition.mdx" -import NodeInsert from "../../04-develop/03-insert-data/_js_sql.mdx" -import NodeInfluxLine from "../../04-develop/03-insert-data/_js_line.mdx" -import NodeOpenTSDBTelnet from "../../04-develop/03-insert-data/_js_opts_telnet.mdx" -import NodeOpenTSDBJson from "../../04-develop/03-insert-data/_js_opts_json.mdx" -import NodeQuery from "../../04-develop/04-query-data/_js.mdx" -import NodeAsyncQuery from "../../04-develop/04-query-data/_js_async.mdx" +import Preparition from "./_preparition.mdx"; +import NodeInsert from "../../04-develop/03-insert-data/_js_sql.mdx"; +import NodeInfluxLine from "../../04-develop/03-insert-data/_js_line.mdx"; +import NodeOpenTSDBTelnet from "../../04-develop/03-insert-data/_js_opts_telnet.mdx"; +import NodeOpenTSDBJson from "../../04-develop/03-insert-data/_js_opts_json.mdx"; +import NodeQuery from "../../04-develop/04-query-data/_js.mdx"; +import NodeAsyncQuery from "../../04-develop/04-query-data/_js_async.mdx"; -`td2.0-connector` 是 TDengine 的官方 Node.js 语言连接器。Node.js 开发人员可以通过它开发可以存取 TDengine 集群数据的应用软件。 +`td2.0-connector` 和 `td2.0-rest-connector` 是 TDengine 的官方 Node.js 语言连接器。Node.js 开发人员可以通过它开发可以存取 TDengine 集群数据的应用软件。 -`td2.0-connector` 支持通过客户端驱动程序(taosc)原生连接 TDengine 集群,支持数据写入、查询、订阅、schemaless 接口和参数绑定接口等功能。也支持使用 REST 接口连接 TDengine 集群。REST 接口实现的功能特性集合和原生接口有少量不同。 +`td2.0-connector` 是**原生连接器**,它通过 TDengine 客户端驱动程序(taosc)连接 TDengine 运行实例,支持数据写入、查询、订阅、schemaless 接口和参数绑定接口等功能。`td2.0-rest-connector` 是 **REST 连接器**,它通过 taosAdapter 提供的 REST 接口连接 TDengine 的运行实例。REST 连接器可以在任何平台运行,但性能略为下降,接口实现的功能特性集合和原生接口有少量不同。 -`td2.0-connector` 的源码托管在 [GitHub](https://github.com/taosdata/taos-connector-node)。 +Node.js 连接器源码托管在 [GitHub](https://github.com/taosdata/taos-connector-node)。 ## 支持的平台 -请参考[支持的平台列表](/reference/connector#支持的平台) +原生连接器支持的平台和 TDengine 客户端驱动支持的平台一致。 +REST 连接器支持所有能运行 Node.js 的平台。 ## 版本支持 @@ -32,11 +33,7 @@ import NodeAsyncQuery from "../../04-develop/04-query-data/_js_async.mdx" ## 支持的功能特性 -### 原生连接 - -“原生连接”指连接器通过客户端驱动程序 taosc 直接与 TDengine 集群建立连接 - -原生连接支持的功能特性如下: +### 原生连接器 1. 连接管理 2. 普通查询 @@ -45,7 +42,7 @@ import NodeAsyncQuery from "../../04-develop/04-query-data/_js_async.mdx" 5. 订阅功能 6. Schemaless -### REST 连接 +### REST 连接器 1. 连接管理 2. 普通查询 @@ -55,11 +52,8 @@ import NodeAsyncQuery from "../../04-develop/04-query-data/_js_async.mdx" ### 安装前准备 -* 安装 Node.js 开发环境 - - -- 应用驱动安装请参考[安装连接器驱动步骤](/reference/connector/#安装客户端驱动)。 -我们使用 [node-gyp](https://github.com/nodejs/node-gyp) 和 TDengine 集群进行交互。安装 Node.js 连接器之前,还需要根据具体操作系统来安装下文提到的一些依赖工具。如果要安装的是 REST 连接器则可以跳过以下步骤,直接只用 npm 安装。 +- 安装 Node.js 开发环境 +- 如果使用 REST 连接器,跳过此步。但如果使用原生连接器,请安装 TDengine 客户端驱动,具体步骤请参考[安装客户端驱动](/reference/connector#安装客户端驱动)。我们使用 [node-gyp](https://github.com/nodejs/node-gyp) 和 TDengine 实例进行交互,还需要根据具体操作系统来安装下文提到的一些依赖工具。 @@ -87,6 +81,7 @@ import NodeAsyncQuery from "../../04-develop/04-query-data/_js_async.mdx" 参考微软的 Node.js 用户手册[ Microsoft's Node.js Guidelines for Windows](https://github.com/Microsoft/nodejs-guidelines/blob/master/windows-environment.md#compiling-native-addon-modules)。 如果在 Windows 10 ARM 上使用 ARM64 Node.js,还需添加 "Visual C++ compilers and libraries for ARM64" 和 "Visual C++ ATL for ARM64"。 + @@ -95,7 +90,7 @@ import NodeAsyncQuery from "../../04-develop/04-query-data/_js_async.mdx" -``` bash +```bash npm install td2.0-connector ``` @@ -105,6 +100,7 @@ npm install td2.0-connector ```bash npm i td2.0-rest-connector ``` + @@ -128,6 +124,8 @@ node nodejsChecker.js host=localhost ## 建立连接 +请选择使用一种连接器。 + @@ -135,8 +133,14 @@ node nodejsChecker.js host=localhost ```javascript //A cursor also needs to be initialized in order to interact with TDengine from Node.js. -const taos = require('td2.0-connector'); -var conn = taos.connect({host:"127.0.0.1", user:"root", password:"taosdata", config:"/etc/taos",port:0}) +const taos = require("td2.0-connector"); +var conn = taos.connect({ + host: "127.0.0.1", + user: "root", + password: "taosdata", + config: "/etc/taos", + port: 0, +}); var cursor = conn.cursor(); // Initializing a new cursor //Close a connection @@ -148,18 +152,18 @@ conn.close(); 安装并引用 `td2.0-rest-connector` 包。 -``` javascript +```javascript //A cursor also needs to be initialized in order to interact with TDengine from Node.js. -import { options, connect } from 'td2.0-rest-connector' -options.path='/rest/sqlt'; +import { options, connect } from "td2.0-rest-connector"; +options.path = "/rest/sqlt"; // set host -options.host='localhost'; +options.host = "localhost"; // set other options like user/passwd let conn = connect(options); let cursor = conn.cursor(); - ``` + @@ -193,24 +197,26 @@ let cursor = conn.cursor(); -### 更多示例程序 | 示例程序描述 | -|-----------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------| -| [connection](https://github.com/taosdata/TDengine/blob/develop/src/connector/nodejs/examples/cursorClose.js) | 建立连接的示例。 | -| [stmtBindBatch](https://github.com/taosdata/TDengine/blob/develop/src/connector/nodejs/examples/stmtBindParamBatchSample.js) | 绑定多行参数插入的示例。 | -| [stmtBind](https://github.com/taosdata/TDengine/blob/develop/src/connector/nodejs/examples/stmtBindParamSample.js) | 一行一行绑定参数插入的示例。 | -| [stmtBindSingleParamBatch](https://github.com/taosdata/TDengine/blob/develop/src/connector/nodejs/examples/stmtBindSingleParamBatchSample.js) | 按列绑定参数插入的示例。 | -| [stmtUseResult](https://github.com/taosdata/TDengine/blob/develop/src/connector/nodejs/examples/stmtUseResultSample.js) | 绑定参数查询的示例。 | -| [json tag](https://github.com/taosdata/TDengine/blob/develop/src/connector/nodejs/examples/testJsonTag.js) | Json tag 的使用示例。 | -| [Nanosecond](https://github.com/taosdata/TDengine/blob/develop/src/connector/nodejs/examples/testNanoseconds.js) | 时间戳为纳秒精度的使用的示例。 | -| [Microsecond](https://github.com/taosdata/TDengine/blob/develop/src/connector/nodejs/examples/testMicroseconds.js) | 时间戳为微秒精度的使用的示例。 | -| [schemless insert](https://github.com/taosdata/TDengine/blob/develop/src/connector/nodejs/examples/testSchemalessInsert.js) | schemless 插入的示例。 | -| [subscribe](https://github.com/taosdata/TDengine/blob/develop/src/connector/nodejs/examples/testSubscribe.js) | 订阅的使用示例。 | -| [asyncQuery](https://github.com/taosdata/TDengine/blob/develop/src/connector/nodejs/examples/tset.js) | 异步查询的使用示例。 | -| [REST](https://github.com/taosdata/TDengine/tree/develop/src/connector/TypeScript-REST/example) | 使用 REST 连接的 TypeScript 使用示例。| +## 更多示例程序 + +| 示例程序 | 示例程序描述 | +| ------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------- | +| [connection](https://github.com/taosdata/taos-connector-node/tree/develop/nodejs/examples/cursorClose.js) | 建立连接的示例。 | +| [stmtBindBatch](https://github.com/taosdata/taos-connector-node/tree/develop/nodejs/examples/stmtBindParamBatchSample.js) | 绑定多行参数插入的示例。 | +| [stmtBind](https://github.com/taosdata/taos-connector-node/tree/develop/nodejs/examples/stmtBindParamSample.js) | 一行一行绑定参数插入的示例。 | +| [stmtBindSingleParamBatch](https://github.com/taosdata/taos-connector-node/tree/develop/nodejs/examples/stmtBindSingleParamBatchSample.js) | 按列绑定参数插入的示例。 | +| [stmtUseResult](https://github.com/taosdata/taos-connector-node/tree/develop/nodejs/examples/stmtUseResultSample.js) | 绑定参数查询的示例。 | +| [json tag](https://github.com/taosdata/taos-connector-node/tree/develop/nodejs/examples/testJsonTag.js) | Json tag 的使用示例。 | +| [Nanosecond](https://github.com/taosdata/taos-connector-node/tree/develop/nodejs/examples/testNanoseconds.js) | 时间戳为纳秒精度的使用的示例。 | +| [Microsecond](https://github.com/taosdata/taos-connector-node/tree/develop/nodejs/examples/testMicroseconds.js) | 时间戳为微秒精度的使用的示例。 | +| [schemless insert](https://github.com/taosdata/taos-connector-node/tree/develop/nodejs/examples/testSchemalessInsert.js) | schemless 插入的示例。 | +| [subscribe](https://github.com/taosdata/taos-connector-node/tree/develop/nodejs/examples/testSubscribe.js) | 订阅的使用示例。 | +| [asyncQuery](https://github.com/taosdata/taos-connector-node/tree/develop/nodejs/examples/tset.js) | 异步查询的使用示例。 | +| [REST](https://github.com/taosdata/taos-connector-node/blob/develop/typescript-rest/example/example.ts) | 使用 REST 连接的 TypeScript 使用示例。 | ## 使用限制 -Node.js 连接器 >= v2.0.6 目前支持 node 的版本为: 支持 >=v12.8.0 <= v12.9.1 || >=v10.20.0 <= v10.9.0 ;2.0.5 及更早版本支持 v10.x 版本,其他版本可能存在包兼容性的问题。 +Node.js 连接器 >= v2.0.6 目前支持 node 的版本为:支持 >=v12.8.0 <= v12.9.1 || >=v10.20.0 <= v10.9.0 ;2.0.5 及更早版本支持 v10.x 版本,其他版本可能存在包兼容性的问题。 ## 其他说明 @@ -220,29 +226,33 @@ Node.js 连接器的使用参见[视频教程](https://www.taosdata.com/blog/202 1. 使用 REST 连接需要启动 taosadapter。 - ``` bash + ```bash sudo systemctl start taosadapter ``` -2. 连接器 >v2.0.6 目前兼容的 Node.js 为:>=v10.20.0 <= v10.9.0 || >=v12.8.0 <= v12.9.1 +2. Node.js 版本 + + 连接器 >v2.0.6 目前兼容的 Node.js 版本为:>=v10.20.0 <= v10.9.0 || >=v12.8.0 <= v12.9.1 + +3. "Unable to establish connection","Unable to resolve FQDN" -3. "Unable to establish connection","Unable to resolve FQDN", 一般都是应为为配置 FQDN 可以参考[如何彻底搞懂 TDengine 的 FQDN](https://www.taosdata.com/blog/2021/07/29/2741.html) 。 + 一般都是因为配置 FQDN 不正确。 可以参考[如何彻底搞懂 TDengine 的 FQDN](https://www.taosdata.com/blog/2021/07/29/2741.html) 。 ## 重要更新记录 -### 原生接口连接器 +### 原生连接器 -| td2.0-connector 版本 | 说明 | -|--------------------|---------------------------------------------------------------------| -| 2.0.10 | 支持连接管理,同步查询、异步查询、获取系统信息、错误信息、订阅功能。| -| 2.0.11 | 支持绑定参数、json tag、schemaless insert。 | -| 2.0.12 | 修复 cursor.close() 报错的问题。 | +| td2.0-connector 版本 | 说明 | +| -------------------- | ---------------------------------------------------------------- | +| 2.0.12 | 修复 cursor.close() 报错的 bug。 | +| 2.0.11 | 支持绑定参数、json tag、schemaless 接口等功能。 | +| 2.0.10 | 支持连接管理,普通查询、连续查询、获取系统信息、订阅功能等功能。 | -### REST 接口连接器 +### REST 连接器 -| td2.0-rest-connector 版本 | 说明 | -|--------------------|---------------------------------------------------------------------| -| 1.0.3 | 支持连接管理、同步查询、获取系统信息、错误信息、schemeless。 | +| td2.0-rest-connector 版本 | 说明 | +| ------------------------- | ---------------------------------------------------------------- | +| 1.0.3 | 支持连接管理、普通查询、获取系统信息、错误信息、连续查询等功能。 | ## API 参考 diff --git a/docs-cn/14-reference/03-connector/python.mdx b/docs-cn/14-reference/03-connector/python.mdx index 6142b9a3ce3bdf0d4b8d2c6e6741ae042e89cce0..5e6cdfba4fc3ee7fd6073b0264b54705c444bead 100644 --- a/docs-cn/14-reference/03-connector/python.mdx +++ b/docs-cn/14-reference/03-connector/python.mdx @@ -1,31 +1,33 @@ --- sidebar_position: 3 sidebar_label: Python -title: Python Connector -description: "taospy 是 TDengine 的官方 Python 连接器。taospy 提供了丰富的 API, 使得 python 应用可以很方便地使用 TDengine。tasopy 对 TDengine 的原生接口和 REST 接口都进行了封装, 分别对应 tasopy 的两个子模块:tasos 和 taosrest。除了对原生接口和 REST 接口的封装,taospy 还提供了符合 Python 数据访问规范(PEP 249)的编程接口。这使得 taospy 和很多第三方工具集成变得简单,比如 SQLAlchemy 和 pandas" +title: TDengine Python Connector +description: "taospy 是 TDengine 的官方 Python 连接器。taospy 提供了丰富的 API, 使得 Python 应用可以很方便地使用 TDengine。tasopy 对 TDengine 的原生接口和 REST 接口都进行了封装, 分别对应 tasopy 的两个子模块:tasos 和 taosrest。除了对原生接口和 REST 接口的封装,taospy 还提供了符合 Python 数据访问规范(PEP 249)的编程接口。这使得 taospy 和很多第三方工具集成变得简单,比如 SQLAlchemy 和 pandas" --- import Tabs from "@theme/Tabs"; import TabItem from "@theme/TabItem"; -`taospy` 是 TDengine 的官方 Python 连接器。`taospy` 提供了丰富的 API, 使得 python 应用可以很方便地使用 TDengine。`tasopy` 对 TDengine 的[原生接口](/reference/connector/cpp)和 [REST 接口](/reference/rest-api)都进行了封装, 分别对应 `tasopy` 包的 `taos` 模块 和 `taosrest` 模块。 +`taospy` 是 TDengine 的官方 Python 连接器。`taospy` 提供了丰富的 API, 使得 Python 应用可以很方便地使用 TDengine。`taospy` 对 TDengine 的[原生接口](/reference/connector/cpp)和 [REST 接口](/reference/rest-api)都进行了封装, 分别对应 `taospy` 包的 `taos` 模块 和 `taosrest` 模块。 除了对原生接口和 REST 接口的封装,`taospy` 还提供了符合 [Python 数据访问规范(PEP 249)](https://peps.python.org/pep-0249/) 的编程接口。这使得 `taospy` 和很多第三方工具集成变得简单,比如 [SQLAlchemy](https://www.sqlalchemy.org/) 和 [pandas](https://pandas.pydata.org/)。 +使用客户端驱动提供的原生接口直接与服务端建立的连接的方式下文中称为“原生连接”;使用 taosAdapter 提供的 REST 接口与服务端建立的连接的方式下文中称为“REST 连接”。 + Python 连接器的源码托管在 [GitHub](https://github.com/taosdata/taos-connector-python)。 ## 支持的平台 -- 原生连接[^1][支持的平台](/reference/connector/#支持的平台)和 TDengine 客户端支持的平台一致。 -- REST 连接[^2]支持所有能运行 Python 的平台。 +- 原生连接[支持的平台](/reference/connector/#支持的平台)和 TDengine 客户端支持的平台一致。 +- REST 连接支持所有能运行 Python 的平台。 ## 版本选择 -建议使用 Python >= 3.6。无论使用什么版本的 TDengine 都建议使用最新版本的 `tasopy`。 +无论使用什么版本的 TDengine 都建议使用最新版本的 `taospy`。 ## 支持的功能 -- 原生连接[^1]支持 TDeingine 的所有核心功能, 包括: 连接管理、查询[^3]、参数绑定、订阅、无模式写入(Schemaless)。 -- REST 连接[^2]目前仅支持查询功能[^3]。 +- 原生连接支持 TDeingine 的所有核心功能, 包括: 连接管理、执行 SQL、参数绑定、订阅、无模式写入(schemaless)。 +- REST 连接支持的功能包括:连接管理、执行 SQL。 (通过执行 SQL 可以: 管理数据库、管理表和超级表、写入数据、查询数据、创建连续查询等)。 ## 安装 @@ -50,7 +52,7 @@ pip3 uninstall taos taospy ::: -#### 安装 `tasopy` +#### 安装 `taospy` @@ -61,10 +63,10 @@ pip3 uninstall taos taospy pip3 install taospy ``` -也可用指定某个特定版本安装。 +也可以指定某个特定版本安装。 ``` -pip3 install taospy==2.2.5 +pip3 install taospy==2.3.0 ``` @@ -82,7 +84,7 @@ pip3 install git+https://github.com/taosdata/taos-connector-python.git -对于本地连接,需要验证客户端驱动和 Python 连接器本身是否正确安装。如果导入 `taos` 模块成功,在说明已经正确安装了客户端驱动和 Python 连接器。可在 Python 交互式 Shell 中输入: +对于原生连接,需要验证客户端驱动和 Python 连接器本身是否都正确安装。如果能成功导入 `taos` 模块,则说明已经正确安装了客户端驱动和 Python 连接器。可在 Python 交互式 Shell 中输入: ```python import taos @@ -91,7 +93,7 @@ import taos -对于 REST 连接,只需验证 `taosrest` 模块是否能成功导入。可在 Python 交互式 Shell 中输入: +对于 REST 连接,只需验证是否能成功导入 `taosrest` 模块。可在 Python 交互式 Shell 中输入: ```python import taosrest @@ -101,12 +103,12 @@ import taosrest :::tip -如果系统上有多个版本的 Python,则可能有多个 `pip` 命令。要确保使用的 `pip` 命令路径是正确的。上面我们用 `pip3` 命令安装,排除了使用 Python 2.x 版本对应的 `pip` 的可能性。但是如果系统上有多个 Python 3.x 版本,仍需注意验证。最简单的验证方式是, 查看 `taospy` 最终的安装位置是否正确。在命令再次输入 `pip3 isntall taospy`, 就会打印出 `taospy` 的具体安装位置,比如在 Widnows 上: +如果系统上有多个版本的 Python,则可能有多个 `pip` 命令。要确保使用的 `pip` 命令路径是正确的。上面我们用 `pip3` 命令安装,排除了使用 Python 2.x 版本对应的 `pip` 的可能性。但是如果系统上有多个 Python 3.x 版本,仍需检查安装路径是否正确。最简单的验证方式是,在命令再次输入 `pip3 install taospy`, 就会打印出 `taospy` 的具体安装位置,比如在 Windows 上: ``` C:\> pip3 install taospy Looking in indexes: https://pypi.tuna.tsinghua.edu.cn/simple -Requirement already satisfied: taospy in c:\users\username\appdata\local\programs\python\python310\lib\site-packages (2.2.5) +Requirement already satisfied: taospy in c:\users\username\appdata\local\programs\python\python310\lib\site-packages (2.3.0) ``` ::: @@ -115,7 +117,7 @@ Requirement already satisfied: taospy in c:\users\username\appdata\local\program ### 连通性测试 -在用连接器建立连接之前,建议先做本地到 TDengine 集群的连通性测试。 +在用连接器建立连接之前,建议先测试本地 TDengine CLI 到 TDengine 集群的连通性。 @@ -170,20 +172,17 @@ curl -u root:taosdata http://:/rest/sql -d "select server_version()" {{#include docs-examples/python/connect_native_reference.py}} ``` -`connect` 函数的所有参数都是可选参数。下表是连接参数的具体说明: +`connect` 函数的所有参数都是可选的关键字参数。下面是连接参数的具体说明: -| 参数 | 含义 | 默认值 | 作用范围 | -| -------- | -------------------------------------------------------------------------------------------------- | ---------------------------------------------------------- | -------- | -| host | 要连接的节点的 FQDN
如果不同提供此参数,则会连接客户端配置文件中的 firstEP | 无 | 本次连接 | -| user | 用户名 | root | 本次连接 | -| passowrd | 密码 | taosdata | 本次连接 | -| database | 默认使用的数据库,
如果有值那么这个数据库必须存在 | 无 | 本次连接 | -| port | 要连接的数据节点的起始端口,即 serverPort 配置。
只有在提供了 host 参数的时候,这个参数才生效 | 6030 | 本次连接 | -| config | 客户端配置文件路径 | 1. Windows: `C:\TDengine\cfg`
2. Linux: `/etc/taos/` | 本进程 | -| timezone | 客户端时区 | 客户端配置文件中 timezone | 本进程 | +- `host` : 要连接的节点的 FQDN。 没有默认值。如果不同提供此参数,则会连接客户端配置文件中的 firstEP。 +- `user` :TDengine 用户名。 默认值是 root。 +- `password` : TDengine 用户密码。 默认值是 taosdata。 +- `port` : 要连接的数据节点的起始端口,即 serverPort 配置。默认值是 6030。只有在提供了 host 参数的时候,这个参数才生效。 +- `config` : 客户端配置文件路径。 在 Windows 系统上默认是 `C:\TDengine\cfg`。 在 Linux 系统上默认是 `/etc/taos/`。 +- `timezone` : 查询结果中 TIMESTAMP 类型的数据,转换为 python 的 datetime 对象时使用的时区。默认为本地时区。 :::warning -当参数的作为范围是进程级别时,只有建立第一个连接时提供的参数生效。也就是说: 同一个进程的两个连接,必须使用相同的客户端配置。但这并不妨碍同一进程连接两个不同的集群,因为 host 参数是连接级别的。 +`config` 和 `timezone` 都是进程级别的配置。建议一个进程建立的所有连接都使用相同的参数值。否则可能产生无法预知的错误。 ::: :::tip @@ -194,15 +193,116 @@ curl -u root:taosdata http://:/rest/sql -d "select server_version()"
+```python +{{#include docs-examples/python/connect_rest_examples.py:connect}} +``` + +`connect` 函数的所有参数都是可选的关键字参数。下面是连接参数的具体说明: + +- `host`: 要连接的主机。默认是 localhost。 +- `user`: TDenigne 用户名。默认是 root。 +- `password`: TDeingine 用户密码。默认是 taosdata。 +- `port`: taosAdapter REST 服务监听端口。默认是 6041. +- `timeout`: HTTP 请求超时时间。单位为秒。默认为 `socket._GLOBAL_DEFAULT_TIMEOUT`。 一般无需配置。 + +:::note + +::: +
-## 开发指南 +## 示例程序 ### 基本使用 + + + +##### TaosConnection 类的使用 + +`TaosConnection` 类既包含对 PEP249 Connection 接口的实现(如:`cursor`方法和 `close` 方法),也包含很多扩展功能(如: `execute`、 `query`、`schemaless_insert` 和 `subscribe` 方法。 + +```python title="execute 方法" +{{#include docs-examples/python/connection_usage_native_reference.py:insert}} +``` + +```python title="query 方法" +{{#include docs-examples/python/connection_usage_native_reference.py:query}} +``` + +:::tip +查询结果只能获取一次。比如上面的示例中 `featch_all` 和 `fetch_all_into_dict` 只能用一个。重复获取得到的结果为空列表。 +::: + +##### TaosResult 类的使用 + +上面 `TaosConnection` 类的使用示例中,我们已经展示了两种获取查询结果的方法: `featch_all` 和 `fetch_all_into_dict`。除此之外 `TaosResult` 还提供了按行迭代(`rows_iter`)或按数据块迭代(`blocks_iter`)结果集的方法。在查询数据量较大的场景,使用这两个方法会更高效。 + +```python title="blocks_iter 方法" +{{#include docs-examples/python/result_set_examples.py}} +``` +##### TaosCursor 类的使用 + +`TaosConnection` 类和 `TaosResult` 类已经实现了原生接口的所有功能。如果你对 PEP249 规范中的接口比较熟悉也可以使用 `TaosCursor` 类提供的方法。 + +```python title="TaosCursor 的使用" +{{#include docs-examples/python/cursor_usage_native_reference.py}} +``` + +:::note +TaosCursor 类使用原生连接进行写入、查询操作。在客户端多线程的场景下,这个游标实例必须保持线程独享,不能跨线程共享使用,否则会导致返回结果出现错误。 + +::: + + + + +##### TaosRestCursor 类的使用 + +`TaosRestCursor` 类是对 PEP249 Cursor 接口的实现。 + +```python title="TaosRestCursor 的使用" +{{#include docs-examples/python/connect_rest_examples.py:basic}} +``` +- `cursor.execute` : 用来执行任意 SQL 语句。 +- `cursor.rowcount`: 对于写入操作返回写入成功记录数。对于查询操作,返回结果集行数。 +- `cursor.description` : 返回字段的描述信息。关于描述信息的具体格式请参考[TaosRestCursor](https://docs.taosdata.com/api/taospy/taosrest/cursor.html)。 + +##### RestClient 类的使用 + +`RestClient` 类是对于 [REST API](/reference/rest-api) 的直接封装。它只包含一个 `sql()` 方法用于执行任意 SQL 语句, 并返回执行结果。 + +```python title="RestClient 的使用" +{{#include docs-examples/python/rest_client_example.py}} +``` + +对于 `sql()` 方法更详细的介绍, 请参考 [RestClient](https://docs.taosdata.com/api/taospy/taosrest/restclient.html)。 + + + + + + ### 与 pandas 一起使用 + + + +```python +{{#include docs-examples/python/conn_native_pandas.py}} +``` + + + + +```python +{{#include docs-examples/python/conn_rest_pandas.py}} +``` + + + + ### 其它示例程序 | 示例程序链接 | 示例程序内容 | @@ -214,41 +314,40 @@ curl -u root:taosdata http://:/rest/sql -d "select server_version()" | [subscribe-async.py](https://github.com/taosdata/taos-connector-python/blob/main/examples/subscribe-async.py) | 异步订阅 | | [subscribe-sync.py](https://github.com/taosdata/taos-connector-python/blob/main/examples/subscribe-sync.py) | 同步订阅 | -## 其它说明 +## 其它说明 + +### 异常处理 -### 关于纳秒 (nanosecond) 在 Python 连接器中的说明 +所有数据库操作如果出现异常,都会直接抛出来。由应用程序负责异常处理。比如: -由于目前 Python 对 nanosecond 支持的不完善(参见链接 1. 2. ),目前的实现方式是在 nanosecond 精度时返回整数,而不是 ms 和 us 返回的 datetime 类型,应用开发者需要自行处理,建议使用 pandas 的 to_datetime()。未来如果 Python 正式完整支持了纳秒,涛思数据可能会修改相关接口。 +```python +{{#include docs-examples/python/handle_exception.py}} +``` + +### 关于纳秒 (nanosecond) + +由于目前 Python 对 nanosecond 支持的不完善(见下面的链接),目前的实现方式是在 nanosecond 精度时返回整数,而不是 ms 和 us 返回的 datetime 类型,应用开发者需要自行处理,建议使用 pandas 的 to_datetime()。未来如果 Python 正式完整支持了纳秒,Python 连接器可能会修改相关接口。 1. https://stackoverflow.com/questions/10611328/parsing-datetime-strings-containing-nanoseconds 2. https://www.python.org/dev/peps/pep-0564/ -### 关于 TaosCursor 类的说明 - -这个类对应原生连接进行的写入、查询操作。在客户端多线程的场景下,这个游标实例必须保持线程独享,不能跨线程共享使用,否则会导致返回结果出现错误。 ## 常见问题 - 欢迎[提问或报告问题](https://github.com/taosdata/taos-connector-python/issues)。 - ## 重要更新 -| 连接器版本 | 主要更新 | 发布日期 | -| ---------- | -------- | -------- | -| 2.3.0 | | | -| 2.2.5 | | | -| 2.2.4 | | | -| 2.2.3 | | | +| 连接器版本 | 重要更新 | 发布日期 | +| ---------- | --------------------------------------------------------------------------------- | ---------- | +| 2.3.1 | 1. support TDengine REST API
2. remove support for Python version below 3.6 | 2022-04-28 | +| 2.2.5 | support timezone option when connect | 2022-04-13 | +| 2.2.2 | support sqlalchemy dialect plugin | 2022-03-28 | -要了解更多,请参考:[Release Notes](https://github.com/taosdata/taos-connector-python/releases) + +[**Release Notes**](https://github.com/taosdata/taos-connector-python/releases) ## API 参考 - [taos](https://docs.taosdata.com/api/taospy/taos/) - [taosrest](https://docs.taosdata.com/api/taospy/taosrest) - -[^1]: 原生连接指使用客户端驱动提供的原生 API 直接与服务端建立的连接。当使用 taos 模块时,cnnect 函数返回的连接就是原生连接。 -[^2]: REST 连接指使用 taosAdapter 提供的 REST API 与服务端建立的连接。当使用 taosrest 模块时, connect 函数返回的连接就是 REST 连接。 -[^3]: 查询功能指执行 SQL 功能,不仅指查询数据。 diff --git a/docs-cn/14-reference/03-connector/rust.mdx b/docs-cn/14-reference/03-connector/rust.mdx index afe253f8c3d74295477f274f58ebee2960d2f54d..b6aac45c6ab30405190ab3ced39de017033e760a 100644 --- a/docs-cn/14-reference/03-connector/rust.mdx +++ b/docs-cn/14-reference/03-connector/rust.mdx @@ -2,7 +2,7 @@ toc_max_heading_level: 4 sidebar_position: 5 sidebar_label: Rust -title: Rust Connector +title: TDengine Rust Connector --- import Tabs from '@theme/Tabs'; @@ -19,35 +19,33 @@ import RustQuery from "../../04-develop/04-query-data/_rust.mdx" `libtaos` 是 TDengine 的官方 Rust 语言连接器。Rust 开发人员可以通过它开发存取 TDengine 数据库的应用软件。 -`libtaos` 使用不同的 “特性(即 Cargo 关键字 features)” 提供对通过客户端驱动程序(taosc)原生连接和使用 REST 连接 TDengine 集群。 +`libtaos` 提供两种建立连接的方式。一种是**原生连接**,它通过 TDengine 客户端驱动程序(taosc)连接 TDengine 运行实例。另外一种是 **REST 连接**,它通过 taosAdapter 的 REST 接口连接 TDengine 运行实例。你可以通过不同的 “特性(即 Cargo 关键字 features)” 来指定使用哪种连接器。REST 连接支持任何平台,但原生连接支持所有 TDengine 客户端能运行的平台。 `libtaos` 的源码托管在 [GitHub](https://github.com/taosdata/libtaos-rs)。 ## 支持的平台 -请参考[支持的平台列表](/reference/connector#支持的平台) - -:::warning - -Rust 连接器仍然在快速开发中,1.0 之前无法保证其向后兼容,请使用时注意版本及对应的文档。* - -::: +原生连接支持的平台和 TDengine 客户端驱动支持的平台一致。 +REST 连接支持所有能运行 Rust 的平台。 ## 版本支持 请参考[版本支持列表](/reference/connector#版本支持) -建议使用 2.4 版本以上的 TDengine,以避免已知问题。 +Rust 连接器仍然在快速开发中,1.0 之前无法保证其向后兼容。建议使用 2.4 版本以上的 TDengine,以避免已知问题。 -## 安装前准备 +## 安装 +### 安装前准备 * 安装 Rust 开发工具链 - +* 如果使用原生连接,请安装 TDengine 客户端驱动,具体步骤请参考[安装客户端驱动](/reference/connector#安装客户端驱动) -之后可以按照如下说明在 [Rust](https://rust-lang.org) 项目中添加 [libtaos][libtaos] 依赖: +### 添加 libtaos 依赖 + +根据选择的连接方式,按照如下说明在 [Rust](https://rust-lang.org) 项目中添加 [libtaos][libtaos] 依赖: - + 在 `Cargo.toml` 文件中添加 [libtaos][libtaos]: @@ -58,7 +56,7 @@ libtaos = "*" ``` - + 在 `Cargo.toml` 文件中添加 [libtaos][libtaos],并启用 `rest` 特性。 @@ -69,10 +67,12 @@ libtaos = { version = "*", features = ["rest"]} ``` - + + + ### 使用连接池 -选择使用客户端驱动或 REST 接口,并在 `Cargo.toml` 中启用 `r2d2` 特性。 +请在 `Cargo.toml` 中启用 `r2d2` 特性。 ```toml [dependencies] @@ -81,8 +81,6 @@ libtaos = { version = "*", features = ["r2d2"] } # or rest libtaos = { version = "*", features = ["rest", "r2d2"] } ``` -
-
## 建立连接 @@ -117,7 +115,7 @@ let conn2 = cfg.connect()?; ```rust let pool = r2d2::Pool::builder() - .max_size(10000) // 最大连接数 + .max_size(10000) // max connections .build(cfg)?; // ... @@ -223,10 +221,10 @@ let pool = r2d2::Pool::new(cfg)?; ```rust use std::time::Duration; let pool = r2d2::Pool::builder() - .max_size(5000) // 最大连接数 - .max_lifetime(Some(Duration::from_minutes(100))) // 每个连接的最长存活时间 - .min_idle(Some(1000)) // 最小空闲连接数 - .connection_timeout(Duration::from_minutes(2)) // 连接超时时间 + .max_size(5000) // max connections + .max_lifetime(Some(Duration::from_minutes(100))) // lifetime of each connection + .min_idle(Some(1000)) // minimal idle connections + .connection_timeout(Duration::from_minutes(2)) .build(cfg); ``` @@ -303,7 +301,7 @@ let mut stmt: Stmt = taos.stmt("insert into ? values(?,?)")?; ```rust let mut stmt = taos.stmt("insert into ? using stb0 tags(?) values(?,?)")?; -// 可以创建任意类型的标签,以 JSON 类型为例。 +// tags can be created with any supported type, here is an example using JSON let v = Field::Json(serde_json::from_str("{\"tag1\":\"一二三四五六七八九十\"}").unwrap()); stmt.set_tbname_tags("tb0", [&tag])?; ``` diff --git a/docs-cn/14-reference/05-taosbenchmark.md b/docs-cn/14-reference/05-taosbenchmark.md index c8668dedc5527f667dedf5fee9b54872047f0a51..0ccd25cf3a93f0496458e061d095f58fe3eac4ca 100644 --- a/docs-cn/14-reference/05-taosbenchmark.md +++ b/docs-cn/14-reference/05-taosbenchmark.md @@ -2,6 +2,7 @@ title: taosBenchmark sidebar_label: taosBenchmark toc_max_heading_level: 4 +description: "taosBenchmark (曾用名 taosdemo ) 是一个用于测试 TDengine 产品性能的工具" --- ## 简介 @@ -338,6 +339,8 @@ taosBenchmark -A INT,DOUBLE,NCHAR,BINARY\(16\) - **thread_count** : 插入数据的线程数量,默认为 8。 +- **create_table_thread_count** : 建表的线程数量,默认为 8。 + - **connection_pool_size** : 预先建立的与 TDengine 服务端之间的连接的数量。若不配置,则与所指定的线程数相同。 - **result_file** : 结果输出文件的路径,默认值为 ./output.txt。 diff --git a/docs-cn/14-reference/06-taosdump.md b/docs-cn/14-reference/06-taosdump.md index ede5d236a975b8c892545105b5537c2eea84d081..7131493ec9439225d8047288ed86026c887f0aac 100644 --- a/docs-cn/14-reference/06-taosdump.md +++ b/docs-cn/14-reference/06-taosdump.md @@ -1,11 +1,11 @@ --- title: taosdump +description: "taosdump 是一个支持从运行中的 TDengine 集群备份数据并将备份的数据恢复到相同或另一个运行中的 TDengine 集群中的工具应用程序" --- ## 简介 -taosdump 是一个支持从运行中的 TDengine 集群备份数据并将备份的数据恢复 -到相同或另一个运行中的 TDengine 集群中的工具应用程序。 +taosdump 是一个支持从运行中的 TDengine 集群备份数据并将备份的数据恢复到相同或另一个运行中的 TDengine 集群中的工具应用程序。 taosdump 可以用数据库、超级表或普通表作为逻辑数据单元进行备份,也可以对数据库、超级 表和普通表中指定时间段内的数据记录进行备份。使用时可以指定数据备份的目录路径,如果 diff --git a/docs-cn/14-reference/09-support-platform/index.md b/docs-cn/14-reference/09-support-platform/index.md index 11374e4deb44de4a08ce5c239cd6166014e7ee1d..d396e4be1fed2e3ecdf202c6e57d509bc1941ecd 100644 --- a/docs-cn/14-reference/09-support-platform/index.md +++ b/docs-cn/14-reference/09-support-platform/index.md @@ -1,5 +1,6 @@ --- title: 支持平台列表 +description: "TDengine 服务端、客户端和连接器支持的平台列表" --- ## TDengine 服务端支持的平台列表 diff --git a/docs-cn/14-reference/11-docker/index.md b/docs-cn/14-reference/11-docker/index.md index 6960db08b271b628d5c3c451865e4a7187b1712f..daac309c2382d50f7afae68e5852cb0106ac7ff2 100644 --- a/docs-cn/14-reference/11-docker/index.md +++ b/docs-cn/14-reference/11-docker/index.md @@ -1,9 +1,9 @@ --- title: 用 Docker 部署 TDengine +description: "本章主要介绍如何在容器中启动 TDengine 服务并访问它" --- -本章主要介绍如何在容器中启动 TDengine 服务并访问它。 -注意:可以在 docker run 命令行中或者 docker-compose 文件中使用环境变量来控制容器中服务的行为。 +本章主要介绍如何在容器中启动 TDengine 服务并访问它。可以在 docker run 命令行中或者 docker-compose 文件中使用环境变量来控制容器中服务的行为。 ## 启动 TDengine diff --git a/docs-cn/14-reference/12-directory.md b/docs-cn/14-reference/12-directory.md index df2a6536ee1faf9ef9a041a453ecd3d3375483f6..f8c8cb4a082f691cf75db9bed3b42d0d6e1bc8a3 100644 --- a/docs-cn/14-reference/12-directory.md +++ b/docs-cn/14-reference/12-directory.md @@ -1,5 +1,6 @@ --- title: 文件目录结构 +description: "TDengine 安装目录说明" --- 安装 TDengine 后,默认会在操作系统中生成下列目录或文件: diff --git a/docs-cn/14-reference/13-schemaless/13-schemaless.md b/docs-cn/14-reference/13-schemaless/13-schemaless.md index 7b34b97ce06626bda91919f31e4691125df0defa..d5ec8ddc44bcc73b189089856959b31ea27e3caf 100644 --- a/docs-cn/14-reference/13-schemaless/13-schemaless.md +++ b/docs-cn/14-reference/13-schemaless/13-schemaless.md @@ -1,9 +1,8 @@ --- title: Schemaless 写入 +description: "Schemaless 写入方式,可以免于预先创建超级表/子表的步骤,随着数据写入接口能够自动创建与数据对应的存储结构" --- -## 前言 - 在物联网应用中,常会采集比较多的数据项,用于实现智能控制、业务分析、设备监控等。由于应用逻辑的版本升级,或者设备自身的硬件调整等原因,数据采集项就有可能比较频繁地出现变动。为了在这种情况下方便地完成数据记录工作,TDengine 从 2.2.0.0 版本开始,提供调用 Schemaless 写入方式,可以免于预先创建超级表/子表的步骤,随着数据写入接口能够自动创建与数据对应的存储结构。并且在必要时,Schemaless 将自动增加必要的数据列,保证用户写入的数据可以被正确存储。 diff --git a/docs-cn/14-reference/_category_.yml b/docs-cn/14-reference/_category_.yml index f8031c35755f5912110136e8fdf3b176ddf5d6b0..079c784e6512109661afe08c12b398e8c4fab720 100644 --- a/docs-cn/14-reference/_category_.yml +++ b/docs-cn/14-reference/_category_.yml @@ -1,4 +1,5 @@ label: 参考指南 link: slug: /reference/ - type: generated-index \ No newline at end of file + type: generated-index + description: "参考指南是对 TDengine 本身、 TDengine 各语言连接器及自带的工具最详细的介绍。" diff --git a/docs-cn/27-train-faq/01-faq.md b/docs-cn/27-train-faq/01-faq.md index e14564e04e4b09054e11fb619c855c2bd5f17b0e..fac12cb44eaff68ec74d3019e537aecb0291410f 100644 --- a/docs-cn/27-train-faq/01-faq.md +++ b/docs-cn/27-train-faq/01-faq.md @@ -14,7 +14,7 @@ title: 常见问题及反馈 为了保证有足够的 debug 信息,如果问题能够重复,请修改/etc/taos/taos.cfg 文件,最后面添加一行“debugFlag 135"(不带引号本身),然后重启 taosd, 重复问题,然后再递交。也可以通过如下 SQL 语句,临时设置 taosd 的日志级别。 ``` - alter dnode debugFlag 135; + alter dnode debugFlag 135; ``` 但系统正常运行时,请一定将 debugFlag 设置为 131,否则会产生大量的日志信息,降低系统效率。 @@ -23,176 +23,176 @@ title: 常见问题及反馈 **1. TDengine2.0 之前的版本升级到 2.0 及以上的版本应该注意什么?☆☆☆** -2.0 版在之前版本的基础上,进行了完全的重构,配置文件和数据文件是不兼容的。在升级之前务必进行如下操作: + 2.0 版在之前版本的基础上,进行了完全的重构,配置文件和数据文件是不兼容的。在升级之前务必进行如下操作: -1. 删除配置文件,执行 `sudo rm -rf /etc/taos/taos.cfg` -2. 删除日志文件,执行 `sudo rm -rf /var/log/taos/` -3. 确保数据已经不再需要的前提下,删除数据文件,执行 `sudo rm -rf /var/lib/taos/` -4. 安装最新稳定版本的 TDengine -5. 如果需要迁移数据或者数据文件损坏,请联系涛思数据官方技术支持团队,进行协助解决 + 1. 删除配置文件,执行 `sudo rm -rf /etc/taos/taos.cfg` + 2. 删除日志文件,执行 `sudo rm -rf /var/log/taos/` + 3. 确保数据已经不再需要的前提下,删除数据文件,执行 `sudo rm -rf /var/lib/taos/` + 4. 安装最新稳定版本的 TDengine + 5. 如果需要迁移数据或者数据文件损坏,请联系涛思数据官方技术支持团队,进行协助解决 **2. Windows 平台下 JDBCDriver 找不到动态链接库,怎么办?** -请看为此问题撰写的[技术博客](https://www.taosdata.com/blog/2019/12/03/950.html)。 + 请看为此问题撰写的[技术博客](https://www.taosdata.com/blog/2019/12/03/950.html)。 **3. 创建数据表时提示 more dnodes are needed** -请看为此问题撰写的[技术博客](https://www.taosdata.com/blog/2019/12/03/965.html)。 + 请看为此问题撰写的[技术博客](https://www.taosdata.com/blog/2019/12/03/965.html)。 **4. 如何让 TDengine crash 时生成 core 文件?** -请看为此问题撰写的[技术博客](https://www.taosdata.com/blog/2019/12/06/974.html)。 + 请看为此问题撰写的[技术博客](https://www.taosdata.com/blog/2019/12/06/974.html)。 **5. 遇到错误“Unable to establish connection”, 我怎么办?** -客户端遇到连接故障,请按照下面的步骤进行检查: + 客户端遇到连接故障,请按照下面的步骤进行检查: -1. 检查网络环境 + 1. 检查网络环境 - - 云服务器:检查云服务器的安全组是否打开 TCP/UDP 端口 6030-6042 的访问权限 - - 本地虚拟机:检查网络能否 ping 通,尽量避免使用`localhost` 作为 hostname - - 公司服务器:如果为 NAT 网络环境,请务必检查服务器能否将消息返回值客户端 + - 云服务器:检查云服务器的安全组是否打开 TCP/UDP 端口 6030-6042 的访问权限 + - 本地虚拟机:检查网络能否 ping 通,尽量避免使用`localhost` 作为 hostname + - 公司服务器:如果为 NAT 网络环境,请务必检查服务器能否将消息返回值客户端 -2. 确保客户端与服务端版本号是完全一致的,开源社区版和企业版也不能混用 + 2. 确保客户端与服务端版本号是完全一致的,开源社区版和企业版也不能混用 -3. 在服务器,执行 `systemctl status taosd` 检查*taosd*运行状态。如果没有运行,启动*taosd* + 3. 在服务器,执行 `systemctl status taosd` 检查*taosd*运行状态。如果没有运行,启动*taosd* -4. 确认客户端连接时指定了正确的服务器 FQDN (Fully Qualified Domain Name —— 可在服务器上执行 Linux 命令 hostname -f 获得),FQDN 配置参考:[一篇文章说清楚 TDengine 的 FQDN](https://www.taosdata.com/blog/2020/09/11/1824.html)。 + 4. 确认客户端连接时指定了正确的服务器 FQDN (Fully Qualified Domain Name —— 可在服务器上执行 Linux 命令 hostname -f 获得),FQDN 配置参考:[一篇文章说清楚 TDengine 的 FQDN](https://www.taosdata.com/blog/2020/09/11/1824.html)。 -5. ping 服务器 FQDN,如果没有反应,请检查你的网络,DNS 设置,或客户端所在计算机的系统 hosts 文件。如果部署的是 TDengine 集群,客户端需要能 ping 通所有集群节点的 FQDN。 + 5. ping 服务器 FQDN,如果没有反应,请检查你的网络,DNS 设置,或客户端所在计算机的系统 hosts 文件。如果部署的是 TDengine 集群,客户端需要能 ping 通所有集群节点的 FQDN。 -6. 检查防火墙设置(Ubuntu 使用 ufw status,CentOS 使用 firewall-cmd --list-port),确认 TCP/UDP 端口 6030-6042 是打开的 + 6. 检查防火墙设置(Ubuntu 使用 ufw status,CentOS 使用 firewall-cmd --list-port),确认 TCP/UDP 端口 6030-6042 是打开的 -7. 对于 Linux 上的 JDBC(ODBC, Python, Go 等接口类似)连接, 确保*libtaos.so*在目录*/usr/local/taos/driver*里, 并且*/usr/local/taos/driver*在系统库函数搜索路径*LD_LIBRARY_PATH*里 + 7. 对于 Linux 上的 JDBC(ODBC, Python, Go 等接口类似)连接, 确保*libtaos.so*在目录*/usr/local/taos/driver*里, 并且*/usr/local/taos/driver*在系统库函数搜索路径*LD_LIBRARY_PATH*里 -8. 对于 Windows 上的 JDBC, ODBC, Python, Go 等连接,确保*C:\TDengine\driver\taos.dll*在你的系统库函数搜索目录里 (建议*taos.dll*放在目录 _C:\Windows\System32_) + 8. 对于 Windows 上的 JDBC, ODBC, Python, Go 等连接,确保*C:\TDengine\driver\taos.dll*在你的系统库函数搜索目录里 (建议*taos.dll*放在目录 _C:\Windows\System32_) -9. 如果仍不能排除连接故障 + 9. 如果仍不能排除连接故障 - - Linux 系统请使用命令行工具 nc 来分别判断指定端口的 TCP 和 UDP 连接是否通畅 - 检查 UDP 端口连接是否工作:`nc -vuz {hostIP} {port} ` - 检查服务器侧 TCP 端口连接是否工作:`nc -l {port}` - 检查客户端侧 TCP 端口连接是否工作:`nc {hostIP} {port}` + - Linux 系统请使用命令行工具 nc 来分别判断指定端口的 TCP 和 UDP 连接是否通畅 + 检查 UDP 端口连接是否工作:`nc -vuz {hostIP} {port} ` + 检查服务器侧 TCP 端口连接是否工作:`nc -l {port}` + 检查客户端侧 TCP 端口连接是否工作:`nc {hostIP} {port}` - - Windows 系统请使用 PowerShell 命令 Net-TestConnection -ComputerName {fqdn} -Port {port} 检测服务段端口是否访问 + - Windows 系统请使用 PowerShell 命令 Net-TestConnection -ComputerName {fqdn} -Port {port} 检测服务段端口是否访问 -10. 也可以使用 taos 程序内嵌的网络连通检测功能,来验证服务器和客户端之间指定的端口连接是否通畅(包括 TCP 和 UDP):[TDengine 内嵌网络检测工具使用指南](https://www.taosdata.com/blog/2020/09/08/1816.html)。 + 10. 也可以使用 taos 程序内嵌的网络连通检测功能,来验证服务器和客户端之间指定的端口连接是否通畅(包括 TCP 和 UDP):[TDengine 内嵌网络检测工具使用指南](https://www.taosdata.com/blog/2020/09/08/1816.html)。 **6. 遇到错误“Unexpected generic error in RPC”或者“Unable to resolve FQDN”,我怎么办?** -产生这个错误,是由于客户端或数据节点无法解析 FQDN(Fully Qualified Domain Name)导致。对于 TAOS Shell 或客户端应用,请做如下检查: + 产生这个错误,是由于客户端或数据节点无法解析 FQDN(Fully Qualified Domain Name)导致。对于 TAOS Shell 或客户端应用,请做如下检查: -1. 请检查连接的服务器的 FQDN 是否正确,FQDN 配置参考:[一篇文章说清楚 TDengine 的 FQDN](https://www.taosdata.com/blog/2020/09/11/1824.html) -2. 如果网络配置有 DNS server,请检查是否正常工作 -3. 如果网络没有配置 DNS server,请检查客户端所在机器的 hosts 文件,查看该 FQDN 是否配置,并是否有正确的 IP 地址 -4. 如果网络配置 OK,从客户端所在机器,你需要能 Ping 该连接的 FQDN,否则客户端是无法连接服务器的 -5. 如果服务器曾经使用过 TDengine,且更改过 hostname,建议检查 data 目录的 dnodeEps.json 是否符合当前配置的 EP,路径默认为/var/lib/taos/dnode。正常情况下,建议更换新的数据目录或者备份后删除以前的数据目录,这样可以避免该问题。 -6. 检查/etc/hosts 和/etc/hostname 是否是预配置的 FQDN + 1. 请检查连接的服务器的 FQDN 是否正确,FQDN 配置参考:[一篇文章说清楚 TDengine 的 FQDN](https://www.taosdata.com/blog/2020/09/11/1824.html) + 2. 如果网络配置有 DNS server,请检查是否正常工作 + 3. 如果网络没有配置 DNS server,请检查客户端所在机器的 hosts 文件,查看该 FQDN 是否配置,并是否有正确的 IP 地址 + 4. 如果网络配置 OK,从客户端所在机器,你需要能 Ping 该连接的 FQDN,否则客户端是无法连接服务器的 + 5. 如果服务器曾经使用过 TDengine,且更改过 hostname,建议检查 data 目录的 dnodeEps.json 是否符合当前配置的 EP,路径默认为/var/lib/taos/dnode。正常情况下,建议更换新的数据目录或者备份后删除以前的数据目录,这样可以避免该问题。 + 6. 检查/etc/hosts 和/etc/hostname 是否是预配置的 FQDN **7. 虽然语法正确,为什么我还是得到 "Invalid SQL" 错误** -如果你确认语法正确,2.0 之前版本,请检查 SQL 语句长度是否超过 64K。如果超过,也会返回这个错误。 + 如果你确认语法正确,2.0 之前版本,请检查 SQL 语句长度是否超过 64K。如果超过,也会返回这个错误。 **8. 是否支持 validation queries?** -TDengine 还没有一组专用的 validation queries。然而建议你使用系统监测的数据库”log"来做。 + TDengine 还没有一组专用的 validation queries。然而建议你使用系统监测的数据库”log"来做。 **9. 我可以删除或更新一条记录吗?** -TDengine 目前尚不支持删除功能,未来根据用户需求可能会支持。 + TDengine 目前尚不支持删除功能,未来根据用户需求可能会支持。 -从 2.0.8.0 开始,TDengine 支持更新已经写入数据的功能。使用更新功能需要在创建数据库时使用 UPDATE 1 参数,之后可以使用 INSERT INTO 命令更新已经写入的相同时间戳数据。UPDATE 参数不支持 ALTER DATABASE 命令修改。没有使用 UPDATE 1 参数创建的数据库,写入相同时间戳的数据不会修改之前的数据,也不会报错。 + 从 2.0.8.0 开始,TDengine 支持更新已经写入数据的功能。使用更新功能需要在创建数据库时使用 UPDATE 1 参数,之后可以使用 INSERT INTO 命令更新已经写入的相同时间戳数据。UPDATE 参数不支持 ALTER DATABASE 命令修改。没有使用 UPDATE 1 参数创建的数据库,写入相同时间戳的数据不会修改之前的数据,也不会报错。 -另需注意,在 UPDATE 设置为 0 时,后发送的相同时间戳的数据会被直接丢弃,但并不会报错,而且仍然会被计入 affected rows (所以不能利用 INSERT 指令的返回信息进行时间戳查重)。这样设计的主要原因是,TDengine 把写入的数据看做一个数据流,无论时间戳是否出现冲突,TDengine 都认为产生数据的原始设备真实地产生了这样的数据。UPDATE 参数只是控制这样的流数据在进行持久化时要怎样处理——UPDATE 为 0 时,表示先写入的数据覆盖后写入的数据;而 UPDATE 为 1 时,表示后写入的数据覆盖先写入的数据。这种覆盖关系如何选择,取决于对数据的后续使用和统计中,希望以先还是后生成的数据为准。 + 另需注意,在 UPDATE 设置为 0 时,后发送的相同时间戳的数据会被直接丢弃,但并不会报错,而且仍然会被计入 affected rows (所以不能利用 INSERT 指令的返回信息进行时间戳查重)。这样设计的主要原因是,TDengine 把写入的数据看做一个数据流,无论时间戳是否出现冲突,TDengine 都认为产生数据的原始设备真实地产生了这样的数据。UPDATE 参数只是控制这样的流数据在进行持久化时要怎样处理——UPDATE 为 0 时,表示先写入的数据覆盖后写入的数据;而 UPDATE 为 1 时,表示后写入的数据覆盖先写入的数据。这种覆盖关系如何选择,取决于对数据的后续使用和统计中,希望以先还是后生成的数据为准。 -此外,从 2.1.7.0 版本开始,支持将 UPDATE 参数设为 2,表示“支持部分列更新”。也即,当 UPDATE 设为 1 时,如果更新一个数据行,其中某些列没有提供取值,那么这些列会被设为 NULL;而当 UPDATE 设为 2 时,如果更新一个数据行,其中某些列没有提供取值,那么这些列会保持原有数据行中的对应值。 + 此外,从 2.1.7.0 版本开始,支持将 UPDATE 参数设为 2,表示“支持部分列更新”。也即,当 UPDATE 设为 1 时,如果更新一个数据行,其中某些列没有提供取值,那么这些列会被设为 NULL;而当 UPDATE 设为 2 时,如果更新一个数据行,其中某些列没有提供取值,那么这些列会保持原有数据行中的对应值。 **10. 我怎么创建超过 1024 列的表?** -使用 2.0 及其以上版本,默认支持 1024 列;2.0 之前的版本,TDengine 最大允许创建 250 列的表。但是如果确实超过限值,建议按照数据特性,逻辑地将这个宽表分解成几个小表。(从 2.1.7.0 版本开始,表的最大列数增加到了 4096 列。) + 使用 2.0 及其以上版本,默认支持 1024 列;2.0 之前的版本,TDengine 最大允许创建 250 列的表。但是如果确实超过限值,建议按照数据特性,逻辑地将这个宽表分解成几个小表。(从 2.1.7.0 版本开始,表的最大列数增加到了 4096 列。) **11. 最有效的写入数据的方法是什么?** -批量插入。每条写入语句可以一张表同时插入多条记录,也可以同时插入多张表的多条记录。 + 批量插入。每条写入语句可以一张表同时插入多条记录,也可以同时插入多张表的多条记录。 **12. Windows 系统下插入的 nchar 类数据中的汉字被解析成了乱码如何解决?** -Windows 下插入 nchar 类的数据中如果有中文,请先确认系统的地区设置成了中国(在 Control Panel 里可以设置),这时 cmd 中的`taos`客户端应该已经可以正常工作了;如果是在 IDE 里开发 Java 应用,比如 Eclipse, Intellij,请确认 IDE 里的文件编码为 GBK(这是 Java 默认的编码类型),然后在生成 Connection 时,初始化客户端的配置,具体语句如下: + Windows 下插入 nchar 类的数据中如果有中文,请先确认系统的地区设置成了中国(在 Control Panel 里可以设置),这时 cmd 中的`taos`客户端应该已经可以正常工作了;如果是在 IDE 里开发 Java 应用,比如 Eclipse, Intellij,请确认 IDE 里的文件编码为 GBK(这是 Java 默认的编码类型),然后在生成 Connection 时,初始化客户端的配置,具体语句如下: -```JAVA -Class.forName("com.taosdata.jdbc.TSDBDriver"); -Properties properties = new Properties(); -properties.setProperty(TSDBDriver.LOCALE_KEY, "UTF-8"); -Connection = DriverManager.getConnection(url, properties); -``` + ```JAVA + Class.forName("com.taosdata.jdbc.TSDBDriver"); + Properties properties = new Properties(); + properties.setProperty(TSDBDriver.LOCALE_KEY, "UTF-8"); + Connection = DriverManager.getConnection(url, properties); + ``` **13.JDBC 报错: the excuted SQL is not a DML or a DDL?** -请更新至最新的 JDBC 驱动 + 请更新至最新的 JDBC 驱动 -```xml - - com.taosdata.jdbc - taos-jdbcdriver - 2.0.27 - -``` + ```xml + + com.taosdata.jdbc + taos-jdbcdriver + 2.0.27 + + ``` **14. taos connect failed, reason: invalid timestamp** -常见原因是服务器和客户端时间没有校准,可以通过和时间服务器同步的方式(Linux 下使用 ntpdate 命令,Windows 在系统时间设置中选择自动同步)校准。 + 常见原因是服务器和客户端时间没有校准,可以通过和时间服务器同步的方式(Linux 下使用 ntpdate 命令,Windows 在系统时间设置中选择自动同步)校准。 **15. 表名显示不全** -由于 taos shell 在终端中显示宽度有限,有可能比较长的表名显示不全,如果按照显示的不全的表名进行相关操作会发生 Table does not exist 错误。解决方法可以是通过修改 taos.cfg 文件中的设置项 maxBinaryDisplayWidth, 或者直接输入命令 set max_binary_display_width 100。或者在命令结尾使用 \G 参数来调整结果的显示方式。 + 由于 taos shell 在终端中显示宽度有限,有可能比较长的表名显示不全,如果按照显示的不全的表名进行相关操作会发生 Table does not exist 错误。解决方法可以是通过修改 taos.cfg 文件中的设置项 maxBinaryDisplayWidth, 或者直接输入命令 set max_binary_display_width 100。或者在命令结尾使用 \G 参数来调整结果的显示方式。 **16. 如何进行数据迁移?** -TDengine 是根据 hostname 唯一标志一台机器的,在数据文件从机器 A 移动机器 B 时,注意如下两件事: + TDengine 是根据 hostname 唯一标志一台机器的,在数据文件从机器 A 移动机器 B 时,注意如下两件事: -- 2.0.0.0 至 2.0.6.x 的版本,重新配置机器 B 的 hostname 为机器 A 的 hostname。 -- 2.0.7.0 及以后的版本,到/var/lib/taos/dnode 下,修复 dnodeEps.json 的 dnodeId 对应的 FQDN,重启。确保机器内所有机器的此文件是完全相同的。 -- 1.x 和 2.x 版本的存储结构不兼容,需要使用迁移工具或者自己开发应用导出导入数据。 + - 2.0.0.0 至 2.0.6.x 的版本,重新配置机器 B 的 hostname 为机器 A 的 hostname。 + - 2.0.7.0 及以后的版本,到/var/lib/taos/dnode 下,修复 dnodeEps.json 的 dnodeId 对应的 FQDN,重启。确保机器内所有机器的此文件是完全相同的。 + - 1.x 和 2.x 版本的存储结构不兼容,需要使用迁移工具或者自己开发应用导出导入数据。 **17. 如何在命令行程序 taos 中临时调整日志级别** -为了调试方便,从 2.0.16 版本开始,命令行程序 taos 新增了与日志记录相关的两条指令: + 为了调试方便,从 2.0.16 版本开始,命令行程序 taos 新增了与日志记录相关的两条指令: -```sql -ALTER LOCAL flag_name flag_value; -``` + ```sql + ALTER LOCAL flag_name flag_value; + ``` -其含义是,在当前的命令行程序下,修改一个特定模块的日志记录级别(只对当前命令行程序有效,如果 taos 命令行程序重启,则需要重新设置): + 其含义是,在当前的命令行程序下,修改一个特定模块的日志记录级别(只对当前命令行程序有效,如果 taos 命令行程序重启,则需要重新设置): -- flag_name 的取值可以是:debugFlag,cDebugFlag,tmrDebugFlag,uDebugFlag,rpcDebugFlag -- flag_value 的取值可以是:131(输出错误和警告日志),135( 输出错误、警告和调试日志),143( 输出错误、警告、调试和跟踪日志) + - flag_name 的取值可以是:debugFlag,cDebugFlag,tmrDebugFlag,uDebugFlag,rpcDebugFlag + - flag_value 的取值可以是:131(输出错误和警告日志),135( 输出错误、警告和调试日志),143( 输出错误、警告、调试和跟踪日志) -```sql -ALTER LOCAL RESETLOG; -``` + ```sql + ALTER LOCAL RESETLOG; + ``` -其含义是,清空本机所有由客户端生成的日志文件。 + 其含义是,清空本机所有由客户端生成的日志文件。 **18. 时间戳的时区信息是怎样处理的?** -TDengine 中时间戳的时区总是由客户端进行处理,而与服务端无关。具体来说,客户端会对 SQL 语句中的时间戳进行时区转换,转为 UTC 时区(即 Unix 时间戳——Unix Timestamp)再交由服务端进行写入和查询;在读取数据时,服务端也是采用 UTC 时区提供原始数据,客户端收到后再根据本地设置,把时间戳转换为本地系统所要求的时区进行显示。 + TDengine 中时间戳的时区总是由客户端进行处理,而与服务端无关。具体来说,客户端会对 SQL 语句中的时间戳进行时区转换,转为 UTC 时区(即 Unix 时间戳——Unix Timestamp)再交由服务端进行写入和查询;在读取数据时,服务端也是采用 UTC 时区提供原始数据,客户端收到后再根据本地设置,把时间戳转换为本地系统所要求的时区进行显示。 -客户端在处理时间戳字符串时,会采取如下逻辑: + 客户端在处理时间戳字符串时,会采取如下逻辑: -1. 在未做特殊设置的情况下,客户端默认使用所在操作系统的时区设置。 -2. 如果在 taos.cfg 中设置了 timezone 参数,则客户端会以这个配置文件中的设置为准。 -3. 如果在 C/C++/Java/Python 等各种编程语言的 Connector Driver 中,在建立数据库连接时显式指定了 timezone,那么会以这个指定的时区设置为准。例如 Java Connector 的 JDBC URL 中就有 timezone 参数。 -4. 在书写 SQL 语句时,也可以直接使用 Unix 时间戳(例如 `1554984068000`)或带有时区的时间戳字符串,也即以 RFC 3339 格式(例如 `2013-04-12T15:52:01.123+08:00`)或 ISO-8601 格式(例如 `2013-04-12T15:52:01.123+0800`)来书写时间戳,此时这些时间戳的取值将不再受其他时区设置的影响。 + 1. 在未做特殊设置的情况下,客户端默认使用所在操作系统的时区设置。 + 2. 如果在 taos.cfg 中设置了 timezone 参数,则客户端会以这个配置文件中的设置为准。 + 3. 如果在 C/C++/Java/Python 等各种编程语言的 Connector Driver 中,在建立数据库连接时显式指定了 timezone,那么会以这个指定的时区设置为准。例如 Java Connector 的 JDBC URL 中就有 timezone 参数。 + 4. 在书写 SQL 语句时,也可以直接使用 Unix 时间戳(例如 `1554984068000`)或带有时区的时间戳字符串,也即以 RFC 3339 格式(例如 `2013-04-12T15:52:01.123+08:00`)或 ISO-8601 格式(例如 `2013-04-12T15:52:01.123+0800`)来书写时间戳,此时这些时间戳的取值将不再受其他时区设置的影响。 **19. TDengine 都会用到哪些网络端口?** -在 TDengine 2.0 版本中,会用到以下这些网络端口(以默认端口 6030 为前提进行说明,如果修改了配置文件中的设置,那么这里列举的端口都会出现变化),管理员可以参考这里的信息调整防火墙设置: + 在 TDengine 2.0 版本中,会用到以下这些网络端口(以默认端口 6030 为前提进行说明,如果修改了配置文件中的设置,那么这里列举的端口都会出现变化),管理员可以参考这里的信息调整防火墙设置: | 协议 | 默认端口 | 用途说明 | 修改方法 | | :--- | :-------- | :---------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------- | @@ -210,15 +210,15 @@ TDengine 中时间戳的时区总是由客户端进行处理,而与服务端 **20. go 语言编写组件编译失败怎样解决?** -新版本 TDengine 2.3.0.0 包含一个使用 go 语言开发的 taosAdapter 独立组件,需要单独运行,取代之前 taosd 内置的 httpd ,提供包含原 httpd 功能以及支持多种其他软件(Prometheus、Telegraf、collectd、StatsD 等)的数据接入功能。 -使用最新 develop 分支代码编译需要先 `git submodule update --init --recursive` 下载 taosAdapter 仓库代码后再编译。 + 新版本 TDengine 2.3.0.0 包含一个使用 go 语言开发的 taosAdapter 独立组件,需要单独运行,取代之前 taosd 内置的 httpd ,提供包含原 httpd 功能以及支持多种其他软件(Prometheus、Telegraf、collectd、StatsD 等)的数据接入功能。 + 使用最新 develop 分支代码编译需要先 `git submodule update --init --recursive` 下载 taosAdapter 仓库代码后再编译。 -目前编译方式默认自动编译 taosAdapter。go 语言版本要求 1.14 以上,如果发生 go 编译错误,往往是国内访问 go mod 问题,可以通过设置 go 环境变量来解决: + 目前编译方式默认自动编译 taosAdapter。go 语言版本要求 1.14 以上,如果发生 go 编译错误,往往是国内访问 go mod 问题,可以通过设置 go 环境变量来解决: -```sh -go env -w GO111MODULE=on -go env -w GOPROXY=https://goproxy.cn,direct -``` + ```sh + go env -w GO111MODULE=on + go env -w GOPROXY=https://goproxy.cn,direct + ``` -如果希望继续使用之前的内置 httpd,可以关闭 taosAdapter 编译,使用 -`cmake .. -DBUILD_HTTP=true` 使用原来内置的 httpd。 + 如果希望继续使用之前的内置 httpd,可以关闭 taosAdapter 编译,使用 + `cmake .. -DBUILD_HTTP=true` 使用原来内置的 httpd。 diff --git a/docs-examples/c/async_query_example.c b/docs-examples/c/async_query_example.c index ec7bd61293a36f7be44c1255ddff9aa6da1795e2..77002891bb4c03f7c7e32b329678e8a124f12a99 100644 --- a/docs-examples/c/async_query_example.c +++ b/docs-examples/c/async_query_example.c @@ -1,4 +1,195 @@ -// compiple with: +// compile with: // gcc -o async_query_example async_query_example.c -ltaos -// writing... \ No newline at end of file +#include +#include +#include +#include +#include +#include + +typedef int16_t VarDataLenT; + +#define TSDB_NCHAR_SIZE sizeof(int32_t) +#define VARSTR_HEADER_SIZE sizeof(VarDataLenT) + +#define GET_FLOAT_VAL(x) (*(float *)(x)) +#define GET_DOUBLE_VAL(x) (*(double *)(x)) + +#define varDataLen(v) ((VarDataLenT *)(v))[0] + +int printRow(char *str, TAOS_ROW row, TAOS_FIELD *fields, int numFields) { + int len = 0; + char split = ' '; + + for (int i = 0; i < numFields; ++i) { + if (i > 0) { + str[len++] = split; + } + + if (row[i] == NULL) { + len += sprintf(str + len, "%s", "NULL"); + continue; + } + + switch (fields[i].type) { + case TSDB_DATA_TYPE_TINYINT: + len += sprintf(str + len, "%d", *((int8_t *)row[i])); + break; + + case TSDB_DATA_TYPE_UTINYINT: + len += sprintf(str + len, "%u", *((uint8_t *)row[i])); + break; + + case TSDB_DATA_TYPE_SMALLINT: + len += sprintf(str + len, "%d", *((int16_t *)row[i])); + break; + + case TSDB_DATA_TYPE_USMALLINT: + len += sprintf(str + len, "%u", *((uint16_t *)row[i])); + break; + + case TSDB_DATA_TYPE_INT: + len += sprintf(str + len, "%d", *((int32_t *)row[i])); + break; + + case TSDB_DATA_TYPE_UINT: + len += sprintf(str + len, "%u", *((uint32_t *)row[i])); + break; + + case TSDB_DATA_TYPE_BIGINT: + len += sprintf(str + len, "%" PRId64, *((int64_t *)row[i])); + break; + + case TSDB_DATA_TYPE_UBIGINT: + len += sprintf(str + len, "%" PRIu64, *((uint64_t *)row[i])); + break; + + case TSDB_DATA_TYPE_FLOAT: { + float fv = 0; + fv = GET_FLOAT_VAL(row[i]); + len += sprintf(str + len, "%f", fv); + } break; + + case TSDB_DATA_TYPE_DOUBLE: { + double dv = 0; + dv = GET_DOUBLE_VAL(row[i]); + len += sprintf(str + len, "%lf", dv); + } break; + + case TSDB_DATA_TYPE_BINARY: + case TSDB_DATA_TYPE_NCHAR: { + int32_t charLen = varDataLen((char *)row[i] - VARSTR_HEADER_SIZE); + memcpy(str + len, row[i], charLen); + len += charLen; + } break; + + case TSDB_DATA_TYPE_TIMESTAMP: + len += sprintf(str + len, "%" PRId64, *((int64_t *)row[i])); + break; + + case TSDB_DATA_TYPE_BOOL: + len += sprintf(str + len, "%d", *((int8_t *)row[i])); + default: + break; + } + } + + return len; +} + +void printHeader(TAOS_RES *res) { + int numFields = taos_num_fields(res); + TAOS_FIELD *fields = taos_fetch_fields(res); + char header[256] = {0}; + int len = 0; + for (int i = 0; i < numFields; ++i) { + len += sprintf(header + len, "%s ", fields[i].name); + } + puts(header); +} + +// ANCHOR: demo + +/** + * @brief call back function of taos_fetch_row_a + * + * @param param : the third parameter you passed to taos_fetch_row_a + * @param res : pointer of TAOS_RES + * @param numOfRow : number of rows fetched in this batch. will be 0 if there is no more data. + * @return void* + */ +void *fetch_row_callback(void *param, TAOS_RES *res, int numOfRow) { + printf("numOfRow = %d \n", numOfRow); + int numFields = taos_num_fields(res); + TAOS_FIELD *fields = taos_fetch_fields(res); + TAOS *_taos = (TAOS *)param; + if (numOfRow > 0) { + for (int i = 0; i < numOfRow; ++i) { + TAOS_ROW row = taos_fetch_row(res); + char temp[256] = {0}; + printRow(temp, row, fields, numFields); + puts(temp); + } + taos_fetch_rows_a(res, fetch_row_callback, _taos); + } else { + printf("no more data, close the connection.\n"); + taos_free_result(res); + taos_close(_taos); + taos_cleanup(); + } +} + +/** + * @brief callback function of taos_query_a + * + * @param param: the fourth parameter you passed to taos_query_a + * @param res : the result set + * @param code : status code + * @return void* + */ +void *select_callback(void *param, TAOS_RES *res, int code) { + printf("query callback ...\n"); + TAOS *_taos = (TAOS *)param; + if (code == 0 && res) { + printHeader(res); + taos_fetch_rows_a(res, fetch_row_callback, _taos); + } else { + printf("failed to exeuce taos_query. error: %s\n", taos_errstr(res)); + taos_free_result(res); + taos_close(_taos); + taos_cleanup(); + exit(EXIT_FAILURE); + } +} + +int main() { + TAOS *taos = taos_connect("localhost", "root", "taosdata", "power", 6030); + if (taos == NULL) { + puts("failed to connect to server"); + exit(EXIT_FAILURE); + } + // param one is the connection returned by taos_connect. + // param two is the SQL to execute. + // param three is the callback function. + // param four can be any pointer. It will be passed to your callback function as the first parameter. we use taos + // here, because we want to close it after getting data. + taos_query_a(taos, "SELECT * FROM meters", select_callback, taos); + sleep(1); +} + +// output: +// query callback ... +// ts current voltage phase location groupid +// numOfRow = 8 +// 1538548685000 10.300000 219 0.310000 beijing.chaoyang 2 +// 1538548695000 12.600000 218 0.330000 beijing.chaoyang 2 +// 1538548696800 12.300000 221 0.310000 beijing.chaoyang 2 +// 1538548696650 10.300000 218 0.250000 beijing.chaoyang 3 +// 1538548685500 11.800000 221 0.280000 beijing.haidian 2 +// 1538548696600 13.400000 223 0.290000 beijing.haidian 2 +// 1538548685000 10.800000 223 0.290000 beijing.haidian 3 +// 1538548686500 11.500000 221 0.350000 beijing.haidian 3 +// numOfRow = 0 +// no more data, close the connection. +// ANCHOR_END: demo \ No newline at end of file diff --git a/docs-examples/c/connect_example.c b/docs-examples/c/connect_example.c index 3b8937a28977d2b281d04903862a45e0485c262e..ff0891e08267840fd5141d1b4271109d832c1c51 100644 --- a/docs-examples/c/connect_example.c +++ b/docs-examples/c/connect_example.c @@ -13,7 +13,9 @@ int main() { uint16_t port = 0; // 0 means use the default port TAOS *taos = taos_connect(host, user, passwd, db, port); if (taos == NULL) { - printf("failed to connect to server\n"); + int errono = taos_errno(NULL); + char *msg = taos_errstr(NULL); + printf("%d, %s\n", errono, msg); } else { printf("connected\n"); taos_close(taos); diff --git a/docs-examples/c/error_handle_example.c b/docs-examples/c/error_handle_example.c new file mode 100644 index 0000000000000000000000000000000000000000..36bb7f12f77a46230add5af82b68e6fb86ddfe77 --- /dev/null +++ b/docs-examples/c/error_handle_example.c @@ -0,0 +1,24 @@ +// compile with +// gcc error_handle_example.c -o error_handle_example -ltaos +#include +#include +#include "taos.h" + +int main() { + const char *host = "localhost"; + const char *user = "root"; + const char *passwd = "taosdata"; + // if don't want to connect to a default db, set it to NULL or "" + const char *db = "notexist"; + uint16_t port = 0; // 0 means use the default port + TAOS *taos = taos_connect(host, user, passwd, db, port); + if (taos == NULL) { + int errono = taos_errno(NULL); + char *msg = taos_errstr(NULL); + printf("%d, %s\n", errono, msg); + } else { + printf("connected\n"); + taos_close(taos); + } + taos_cleanup(); +} diff --git a/docs-examples/c/subscribe_demo.c b/docs-examples/c/subscribe_demo.c index 0c4d1b65d989a3ca81649478d25bda14e84094d6..b523b4667e08ae8a02f4a470c939091f216d1dcb 100644 --- a/docs-examples/c/subscribe_demo.c +++ b/docs-examples/c/subscribe_demo.c @@ -1,3 +1,66 @@ +// A simple demo for asynchronous subscription. // compile with: // gcc -o subscribe_demo subscribe_demo.c -ltaos -// writing... + +#include +#include +#include +#include + +int nTotalRows; + +/** + * @brief callback function of subscription. + * + * @param tsub + * @param res + * @param param. the additional parameter passed to taos_subscribe + * @param code. error code + */ +void subscribe_callback(TAOS_SUB* tsub, TAOS_RES* res, void* param, int code) { + if (code != 0) { + printf("error: %d\n", code); + exit(EXIT_FAILURE); + } + + TAOS_ROW row = NULL; + int num_fields = taos_num_fields(res); + TAOS_FIELD* fields = taos_fetch_fields(res); + int nRows = 0; + + while ((row = taos_fetch_row(res))) { + char buf[4096] = {0}; + taos_print_row(buf, row, fields, num_fields); + puts(buf); + nRows++; + } + + nTotalRows += nRows; + printf("%d rows consumed.\n", nRows); +} + +int main() { + TAOS* taos = taos_connect("localhost", "root", "taosdata", NULL, 6030); + if (taos == NULL) { + printf("failed to connect to server\n"); + exit(EXIT_FAILURE); + } + + int restart = 1; // if the topic already exists, where to subscribe from the begine. + const char* topic = "topic-meter-current-bg-10"; + const char* sql = "select * from power.meters where current > 10"; + void* param = NULL; // additional parameter. + int interval = 2000; // consumption interval in microseconds. + TAOS_SUB* tsub = taos_subscribe(taos, restart, topic, sql, subscribe_callback, NULL, interval); + + // wait for insert from others process. you can open TDengine CLI to insert some records for test. + + getchar(); // press Enter to stop + + printf("total rows consumed: %d\n", nTotalRows); + int keep = 0; // weather to keep subscribe process + taos_unsubscribe(tsub, keep); + + taos_close(taos); + taos_cleanup(); +} diff --git a/docs-examples/java/src/main/java/com/taos/example/SubscribeDemo.java b/docs-examples/java/src/main/java/com/taos/example/SubscribeDemo.java index 410897847c41600fb30edbbcda3360c614a444ba..d82d03b9de561e3ea6a8e7d40a48ce9dd3f2a20d 100644 --- a/docs-examples/java/src/main/java/com/taos/example/SubscribeDemo.java +++ b/docs-examples/java/src/main/java/com/taos/example/SubscribeDemo.java @@ -27,11 +27,14 @@ public class SubscribeDemo { properties.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8"); String jdbcUrl = "jdbc:TAOS://127.0.0.1:6030/power?user=root&password=taosdata"; connection = DriverManager.getConnection(jdbcUrl, properties); - subscribe = ((TSDBConnection) connection).subscribe(topic, sql, true); // 创建订阅 + // create subscribe + subscribe = ((TSDBConnection) connection).subscribe(topic, sql, true); int count = 0; while (count < 10) { - TimeUnit.SECONDS.sleep(1); // 等待1秒,避免频繁调用 consume,给服务端造成压力 - TSDBResultSet resultSet = subscribe.consume(); // 消费数据 + // wait 1 second to avoid frequent calls to consume + TimeUnit.SECONDS.sleep(1); + // consume + TSDBResultSet resultSet = subscribe.consume(); if (resultSet == null) { continue; } @@ -50,7 +53,8 @@ public class SubscribeDemo { } finally { try { if (null != subscribe) - subscribe.close(true); // 关闭订阅 + // close subscribe + subscribe.close(true); if (connection != null) connection.close(); } catch (SQLException throwable) { diff --git a/docs-examples/python/conn_native_pandas.py b/docs-examples/python/conn_native_pandas.py new file mode 100644 index 0000000000000000000000000000000000000000..314759f7662c7bf4c9df2c8b3396ad3101c91cd4 --- /dev/null +++ b/docs-examples/python/conn_native_pandas.py @@ -0,0 +1,19 @@ +import pandas +from sqlalchemy import create_engine + +engine = create_engine("taos://root:taosdata@localhost:6030/power") +df = pandas.read_sql("SELECT * FROM meters", engine) + +# print index +print(df.index) +# print data type of element in ts column +print(type(df.ts[0])) +print(df.head(3)) + +# output: +# RangeIndex(start=0, stop=8, step=1) +# +# ts current voltage phase location groupid +# 0 2018-10-03 14:38:05.000 10.3 219 0.31 beijing.chaoyang 2 +# 1 2018-10-03 14:38:15.000 12.6 218 0.33 beijing.chaoyang 2 +# 2 2018-10-03 14:38:16.800 12.3 221 0.31 beijing.chaoyang 2 diff --git a/docs-examples/python/conn_rest_pandas.py b/docs-examples/python/conn_rest_pandas.py new file mode 100644 index 0000000000000000000000000000000000000000..143e4275fa4eda685766297e4b90cba3935a574d --- /dev/null +++ b/docs-examples/python/conn_rest_pandas.py @@ -0,0 +1,19 @@ +import pandas +from sqlalchemy import create_engine + +engine = create_engine("taosrest://root:taosdata@localhost:6041") +df: pandas.DataFrame = pandas.read_sql("SELECT * FROM power.meters", engine) + +# print index +print(df.index) +# print data type of element in ts column +print(type(df.ts[0])) +print(df.head(3)) + +# output: +# +# RangeIndex(start=0, stop=8, step=1) +# ts current ... location groupid +# 0 2018-10-03 14:38:05+08:00 10.3 ... beijing.chaoyang 2 +# 1 2018-10-03 14:38:15+08:00 12.6 ... beijing.chaoyang 2 +# 2 2018-10-03 14:38:16.800000+08:00 12.3 ... beijing.chaoyang 2 diff --git a/docs-examples/python/connect_native_reference.py b/docs-examples/python/connect_native_reference.py index d52b795c33d55e187a09b9395355ecaf935ad133..c17e9795b58724f6646b8d7c0f84047098a93d69 100644 --- a/docs-examples/python/connect_native_reference.py +++ b/docs-examples/python/connect_native_reference.py @@ -5,7 +5,16 @@ conn: taos.TaosConnection = taos.connect(host="localhost", password="taosdata", database="test", port=6030, - config="C:\TDengine\cfg", # for linux the default value is /etc/taos - timezone="Asia/Shanghai" # default your host's timezone - ) + config="/etc/taos", # for windows the default value is C:\TDengine\cfg + timezone="Asia/Shanghai") # default your host's timezone + +server_version = conn.server_info +print("server_version", server_version) +client_version = conn.client_info +print("client_version", client_version) # 2.4.0.16 + conn.close() + +# possible output: +# 2.4.0.16 +# 2.4.0.16 diff --git a/docs-examples/python/connect_rest_examples.py b/docs-examples/python/connect_rest_examples.py new file mode 100644 index 0000000000000000000000000000000000000000..a043d506b965bc31179dbb6f38749d196ab338ff --- /dev/null +++ b/docs-examples/python/connect_rest_examples.py @@ -0,0 +1,45 @@ +# ANCHOR: connect +from taosrest import connect, TaosRestConnection, TaosRestCursor + +conn: TaosRestConnection = connect(host="localhost", + user="root", + password="taosdata", + port=6041, + timeout=30) + +# ANCHOR_END: connect +# ANCHOR: basic +# create STable +cursor: TaosRestCursor = conn.cursor() +cursor.execute("DROP DATABASE IF EXISTS power") +cursor.execute("CREATE DATABASE power") +cursor.execute("CREATE STABLE power.meters (ts TIMESTAMP, current FLOAT, voltage INT, phase FLOAT) TAGS (location BINARY(64), groupId INT)") + +# insert data +cursor.execute("""INSERT INTO power.d1001 USING power.meters TAGS(Beijing.Chaoyang, 2) VALUES ('2018-10-03 14:38:05.000', 10.30000, 219, 0.31000) ('2018-10-03 14:38:15.000', 12.60000, 218, 0.33000) ('2018-10-03 14:38:16.800', 12.30000, 221, 0.31000) + power.d1002 USING power.meters TAGS(Beijing.Chaoyang, 3) VALUES ('2018-10-03 14:38:16.650', 10.30000, 218, 0.25000) + power.d1003 USING power.meters TAGS(Beijing.Haidian, 2) VALUES ('2018-10-03 14:38:05.500', 11.80000, 221, 0.28000) ('2018-10-03 14:38:16.600', 13.40000, 223, 0.29000) + power.d1004 USING power.meters TAGS(Beijing.Haidian, 3) VALUES ('2018-10-03 14:38:05.000', 10.80000, 223, 0.29000) ('2018-10-03 14:38:06.500', 11.50000, 221, 0.35000)""") +print("inserted row count:", cursor.rowcount) + +# query data +cursor.execute("SELECT * FROM power.meters LIMIT 3") +# get total rows +print("queried row count:", cursor.rowcount) +# get column names from cursor +column_names = [meta[0] for meta in cursor.description] +# get rows +data: list[tuple] = cursor.fetchall() +print(column_names) +for row in data: + print(row) + +# output: +# inserted row count: 8 +# queried row count: 3 +# ['ts', 'current', 'voltage', 'phase', 'location', 'groupid'] +# [datetime.datetime(2018, 10, 3, 14, 38, 5, tzinfo=datetime.timezone(datetime.timedelta(seconds=28800), '+08:00')), 10.3, 219, 0.31, 'beijing.chaoyang', 2] +# [datetime.datetime(2018, 10, 3, 14, 38, 15, tzinfo=datetime.timezone(datetime.timedelta(seconds=28800), '+08:00')), 12.6, 218, 0.33, 'beijing.chaoyang', 2] +# [datetime.datetime(2018, 10, 3, 14, 38, 16, 800000, tzinfo=datetime.timezone(datetime.timedelta(seconds=28800), '+08:00')), 12.3, 221, 0.31, 'beijing.chaoyang', 2] + +# ANCHOR_END: basic diff --git a/docs-examples/python/connection_usage_native_reference.py b/docs-examples/python/connection_usage_native_reference.py new file mode 100644 index 0000000000000000000000000000000000000000..4803511e427bf4d906fd3a14ff6faf5a000da96c --- /dev/null +++ b/docs-examples/python/connection_usage_native_reference.py @@ -0,0 +1,45 @@ +import taos + +# ANCHOR: insert +conn = taos.connect() +# Execute a sql, ignore the result set, just get affected rows. It's useful for DDL and DML statement. +conn.execute("DROP DATABASE IF EXISTS test") +conn.execute("CREATE DATABASE test") +# change database. same as execute "USE db" +conn.select_db("test") +conn.execute("CREATE STABLE weather(ts TIMESTAMP, temperature FLOAT) TAGS (location INT)") +affected_row: int = conn.execute("INSERT INTO t1 USING weather TAGS(1) VALUES (now, 23.5) (now+1m, 23.5) (now+2m 24.4)") +print("affected_row", affected_row) +# output: +# affected_row 3 +# ANCHOR_END: insert + +# ANCHOR: query +# Execute a sql and get its result set. It's useful for SELECT statement +result: taos.TaosResult = conn.query("SELECT * from weather") + +# Get fields from result +fields: taos.field.TaosFields = result.fields +for field in fields: + print(field) # {name: ts, type: 9, bytes: 8} + +# output: +# {name: ts, type: 9, bytes: 8} +# {name: temperature, type: 6, bytes: 4} +# {name: location, type: 4, bytes: 4} + +# Get data from result as list of tuple +data = result.fetch_all() +print(data) +# output: +# [(datetime.datetime(2022, 4, 27, 9, 4, 25, 367000), 23.5, 1), (datetime.datetime(2022, 4, 27, 9, 5, 25, 367000), 23.5, 1), (datetime.datetime(2022, 4, 27, 9, 6, 25, 367000), 24.399999618530273, 1)] + +# Or get data from result as a list of dict +# map_data = result.fetch_all_into_dict() +# print(map_data) +# output: +# [{'ts': datetime.datetime(2022, 4, 27, 9, 1, 15, 343000), 'temperature': 23.5, 'location': 1}, {'ts': datetime.datetime(2022, 4, 27, 9, 2, 15, 343000), 'temperature': 23.5, 'location': 1}, {'ts': datetime.datetime(2022, 4, 27, 9, 3, 15, 343000), 'temperature': 24.399999618530273, 'location': 1}] +# ANCHOR_END: query + + +conn.close() diff --git a/docs-examples/python/cursor_usage_native_reference.py b/docs-examples/python/cursor_usage_native_reference.py new file mode 100644 index 0000000000000000000000000000000000000000..a5103810f0199708f94b5c36e1dc080b7998e420 --- /dev/null +++ b/docs-examples/python/cursor_usage_native_reference.py @@ -0,0 +1,32 @@ +import taos + +conn = taos.connect() +cursor = conn.cursor() + +cursor.execute("DROP DATABASE IF EXISTS test") +cursor.execute("CREATE DATABASE test") +cursor.execute("USE test") +cursor.execute("CREATE STABLE weather(ts TIMESTAMP, temperature FLOAT) TAGS (location INT)") + +for i in range(1000): + location = str(i % 10) + tb = "t" + location + cursor.execute(f"INSERT INTO {tb} USING weather TAGS({location}) VALUES (now+{i}a, 23.5) (now+{i + 1}a, 23.5)") + +cursor.execute("SELECT count(*) FROM weather") +data = cursor.fetchall() +print("count:", data[0][0]) +cursor.execute("SELECT tbname, * FROM weather LIMIT 2") +col_names = [meta[0] for meta in cursor.description] +print(col_names) +rows = cursor.fetchall() +print(rows) + +cursor.close() +conn.close() + +# output: +# count: 2000 +# ['tbname', 'ts', 'temperature', 'location'] +# row_count: -1 +# [('t0', datetime.datetime(2022, 4, 27, 14, 54, 24, 392000), 23.5, 0), ('t0', datetime.datetime(2022, 4, 27, 14, 54, 24, 393000), 23.5, 0)] diff --git a/docs-examples/python/handle_exception.py b/docs-examples/python/handle_exception.py new file mode 100644 index 0000000000000000000000000000000000000000..59554465c0891c80f0507656fcc79538c3811fa7 --- /dev/null +++ b/docs-examples/python/handle_exception.py @@ -0,0 +1,19 @@ +import taos + +try: + conn = taos.connect() + conn.execute("CREATE TABLE 123") # wrong sql +except taos.Error as e: + print(e) + print("exception class: ", e.__class__.__name__) + print("error number:", e.errno) + print("error message:", e.msg) +except BaseException as other: + print("exception occur") + print(other) + +# output: +# [0x0216]: syntax error near 'Incomplete SQL statement' +# exception class: ProgrammingError +# error number: -2147483114 +# error message: syntax error near 'Incomplete SQL statement' diff --git a/docs-examples/python/rest_client_example.py b/docs-examples/python/rest_client_example.py new file mode 100644 index 0000000000000000000000000000000000000000..46d33a1d795f8c8dbb0b830061d43ed4510046ba --- /dev/null +++ b/docs-examples/python/rest_client_example.py @@ -0,0 +1,9 @@ +from taosrest import RestClient + +client = RestClient("localhost", 6041, "root", "taosdata") +res: dict = client.sql("SELECT ts, current FROM power.meters LIMIT 1") +print(res) + +# output: +# {'status': 'succ', 'head': ['ts', 'current'], 'column_meta': [['ts', 9, 8], ['current', 6, 4]], 'data': [[datetime.datetime(2018, 10, 3, 14, 38, 5, tzinfo=datetime.timezone(datetime.timedelta(seconds=28800), '+08:00')), 10.3]], 'rows': 1} + diff --git a/docs-examples/python/result_set_examples.py b/docs-examples/python/result_set_examples.py new file mode 100644 index 0000000000000000000000000000000000000000..6cba0d3f73cdaa408309de93652ed8f346c8f759 --- /dev/null +++ b/docs-examples/python/result_set_examples.py @@ -0,0 +1,33 @@ +import taos + +conn = taos.connect() +conn.execute("DROP DATABASE IF EXISTS test") +conn.execute("CREATE DATABASE test") +conn.select_db("test") +conn.execute("CREATE STABLE weather(ts TIMESTAMP, temperature FLOAT) TAGS (location INT)") +# prepare data +for i in range(2000): + location = str(i % 10) + tb = "t" + location + conn.execute(f"INSERT INTO {tb} USING weather TAGS({location}) VALUES (now+{i}a, 23.5) (now+{i + 1}a, 23.5)") + +result: taos.TaosResult = conn.query("SELECT * FROM weather") + +block_index = 0 +blocks: taos.TaosBlocks = result.blocks_iter() +for rows, length in blocks: + print("block ", block_index, " length", length) + print("first row in this block:", rows[0]) + block_index += 1 + +conn.close() + +# possible output: +# block 0 length 1200 +# first row in this block: (datetime.datetime(2022, 4, 27, 15, 14, 52, 46000), 23.5, 0) +# block 1 length 1200 +# first row in this block: (datetime.datetime(2022, 4, 27, 15, 14, 52, 76000), 23.5, 3) +# block 2 length 1200 +# first row in this block: (datetime.datetime(2022, 4, 27, 15, 14, 52, 99000), 23.5, 6) +# block 3 length 400 +# first row in this block: (datetime.datetime(2022, 4, 27, 15, 14, 52, 122000), 23.5, 9) diff --git a/docs-examples/python/subscribe_demo.py b/docs-examples/python/subscribe_demo.py index cc53e59d81a6bfd33d002f076a28016ece1a2b17..db9d49c3f4f8122634800c02a683d4cb022a7ba0 100644 --- a/docs-examples/python/subscribe_demo.py +++ b/docs-examples/python/subscribe_demo.py @@ -1 +1,38 @@ -import taos \ No newline at end of file +""" +Python asynchronous subscribe demo. +run on Linux system with: python3 subscribe_demo.py +""" + +from ctypes import c_void_p + +import taos +import time + + +def query_callback(p_sub, p_result, p_param, code): + """ + :param p_sub: pointer returned by native API -- taos_subscribe + :param p_result: pointer to native TAOS_RES + :param p_param: None + :param code: error code + :return: None + """ + print("in callback") + result = taos.TaosResult(c_void_p(p_result)) + # raise exception if error occur + result.check_error(code) + for row in result.rows_iter(): + print(row) + print(f"{result.row_count} rows consumed.") + + +if __name__ == '__main__': + conn = taos.connect() + restart = True + topic = "topic-meter-current-bg" + sql = "select * from power.meters where current > 10" # Error sql + interval = 2000 # consumption interval in microseconds. + _ = conn.subscribe(restart, topic, sql, interval, query_callback) + # Note: we received the return value as _ above, to avoid the TaosSubscription object to be deleted by gc. + while True: + time.sleep(10) # use Ctrl + C to interrupt diff --git a/src/client/src/tscSQLParser.c b/src/client/src/tscSQLParser.c index f5b887936814b4d0614c9cb2ded71235e5863904..26df02ca7ca471fe3a53b88fde35bee2ce60296f 100644 --- a/src/client/src/tscSQLParser.c +++ b/src/client/src/tscSQLParser.c @@ -1073,7 +1073,7 @@ static bool isTopBottomUniqueQuery(SQueryInfo* pQueryInfo) { for (int32_t i = 0; i < size; ++i) { int32_t functionId = tscExprGet(pQueryInfo, i)->base.functionId; - if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM + if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM || functionId == TSDB_FUNC_SAMPLE || functionId == TSDB_FUNC_UNIQUE || functionId == TSDB_FUNC_TAIL) { return true; } @@ -1286,6 +1286,17 @@ static int32_t validateStateWindowNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SS return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg6); } + size_t size = tscNumOfExprs(pQueryInfo); + for (int32_t i = 0; i < size; ++i) { + SExprInfo* pExpr = tscExprGet(pQueryInfo, i); + assert(pExpr != NULL); + + int32_t functionId = pExpr->base.functionId; + if (functionId == TSDB_FUNC_CSUM || functionId == TSDB_FUNC_MAVG) { + return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg6); + } + } + tscColumnListInsert(pQueryInfo->colList, index.columnIndex, pTableMeta->id.uid, pSchema); SColIndex colIndex = { .colIndex = index.columnIndex, .flag = TSDB_COL_NORMAL, .colId = pSchema->colId }; taosArrayPush(pGroupExpr->columnInfo, &colIndex); @@ -3362,13 +3373,7 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col tVariantDump(pVariant, val, TSDB_DATA_TYPE_BIGINT, true); if(functionId == TSDB_FUNC_UNIQUE){ // consider of memory size - if(pSchema->bytes < 10){ - GET_INT64_VAL(val) = MAX_UNIQUE_RESULT_ROWS * 100; - }else if(pSchema->bytes < 100){ - GET_INT64_VAL(val) = MAX_UNIQUE_RESULT_ROWS * 10; - }else{ - GET_INT64_VAL(val) = MAX_UNIQUE_RESULT_ROWS; - } + GET_INT64_VAL(val) = MAX_UNIQUE_RESULT_ROWS; } int64_t numRowsSelected = GET_INT64_VAL(val); @@ -4269,7 +4274,9 @@ bool hasUnsupportFunctionsForSTableQuery(SSqlCmd* pCmd, SQueryInfo* pQueryInfo) invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2); return true; } - } else if (tscIsSessionWindowQuery(pQueryInfo)) { + } + + if (tscIsSessionWindowQuery(pQueryInfo)) { invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg3); return true; } @@ -7095,6 +7102,10 @@ int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSq return invalidOperationMsg(pMsgBuf, msg1); } + if (index.columnIndex == TSDB_TBNAME_COLUMN_INDEX) { + return invalidOperationMsg(pMsgBuf, msg1); + } + if (udf) { return invalidOperationMsg(pMsgBuf, msg11); } @@ -7650,8 +7661,8 @@ int32_t validateFunctionsInIntervalOrGroupbyQuery(SSqlCmd* pCmd, SQueryInfo* pQu int32_t f = pExpr->base.functionId; if ((f == TSDB_FUNC_PRJ && pExpr->base.numOfParams == 0) || f == TSDB_FUNC_DIFF || f == TSDB_FUNC_SCALAR_EXPR || f == TSDB_FUNC_DERIVATIVE || - f == TSDB_FUNC_CSUM || f == TSDB_FUNC_MAVG || f == TSDB_FUNC_STATE_COUNT || - f == TSDB_FUNC_STATE_DURATION) + f == TSDB_FUNC_CSUM || f == TSDB_FUNC_MAVG || + f == TSDB_FUNC_STATE_COUNT || f == TSDB_FUNC_STATE_DURATION) { isProjectionFunction = true; break; @@ -8534,7 +8545,8 @@ int32_t doFunctionsCompatibleCheck(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, char* const char* msg4 = "retrieve tags not compatible with group by or interval query"; const char* msg5 = "functions can not be mixed up"; const char* msg6 = "TWA/Diff/Derivative/Irate/CSum/MAvg/Elapsed/stateCount/stateDuration only support group by tbname"; - const char* msg7 = "unique/state function does not supportted in state window query"; + const char* msg7 = "unique/state function not supported in state window query"; + const char* msg8 = "histogram function not supported in time window query"; // only retrieve tags, group by is not supportted if (tscQueryTags(pQueryInfo)) { @@ -8548,10 +8560,19 @@ int32_t doFunctionsCompatibleCheck(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, char* return TSDB_CODE_SUCCESS; } } + if (tscIsProjectionQuery(pQueryInfo) && tscIsSessionWindowQuery(pQueryInfo)) { return invalidOperationMsg(msg, msg3); } + size_t numOfExprs = tscNumOfExprs(pQueryInfo); + for (int32_t i = 0; i < numOfExprs; ++i) { + SExprInfo* pExpr = tscExprGet(pQueryInfo, i); + if ((isTimeWindowQuery(pQueryInfo) || pQueryInfo->stateWindow) && pExpr->base.functionId == TSDB_FUNC_HISTOGRAM) { + return invalidOperationMsg(msg, msg8); + } + } + if (pQueryInfo->groupbyExpr.numOfGroupCols > 0) { // check if all the tags prj columns belongs to the group by columns if (onlyTagPrjFunction(pQueryInfo) && allTagPrjInGroupby(pQueryInfo)) { @@ -8595,7 +8616,7 @@ int32_t doFunctionsCompatibleCheck(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, char* } } - if (pQueryInfo->stateWindow && (f == TSDB_FUNC_UNIQUE || f == TSDB_FUNC_STATE_COUNT || f == TSDB_FUNC_STATE_DURATION)){ + if (pQueryInfo->stateWindow && (f == TSDB_FUNC_UNIQUE || f == TSDB_FUNC_STATE_COUNT || f == TSDB_FUNC_STATE_DURATION)) { return invalidOperationMsg(msg, msg7); } @@ -8641,8 +8662,13 @@ int32_t validateFunctionFromUpstream(SQueryInfo* pQueryInfo, char* msg) { SExprInfo* pExpr = tscExprGet(pQueryInfo, i); int32_t f = pExpr->base.functionId; - if (f == TSDB_FUNC_DERIVATIVE || f == TSDB_FUNC_TWA || f == TSDB_FUNC_IRATE || f == TSDB_FUNC_DIFF || f == TSDB_FUNC_ELAPSED || - f == TSDB_FUNC_STATE_COUNT || f == TSDB_FUNC_STATE_DURATION) { + if (f == TSDB_FUNC_DERIVATIVE || + f == TSDB_FUNC_TWA || + f == TSDB_FUNC_IRATE || + f == TSDB_FUNC_DIFF || + f == TSDB_FUNC_ELAPSED || + f == TSDB_FUNC_STATE_COUNT || + f == TSDB_FUNC_STATE_DURATION) { for (int32_t j = 0; j < upNum; ++j) { SQueryInfo* pUp = taosArrayGetP(pQueryInfo->pUpstream, j); STableMetaInfo *pTableMetaInfo = tscGetMetaInfo(pUp, 0); diff --git a/src/client/src/tscUtil.c b/src/client/src/tscUtil.c index 099f01e9a708377b076895d3d472d653b977fc56..c23ba15d44928bb4023c5615edb792f81b1de3d5 100644 --- a/src/client/src/tscUtil.c +++ b/src/client/src/tscUtil.c @@ -1528,6 +1528,11 @@ void handleDownstreamOperator(SSqlObj** pSqlObjList, int32_t numOfUpstream, SQue tscDebug("0x%"PRIx64" create QInfo 0x%"PRIx64" to execute the main query while all nest queries are ready", pSql->self, pSql->self); px->pQInfo = createQInfoFromQueryNode(px, &tableGroupInfo, pSourceOperator, NULL, NULL, MASTER_SCAN, pSql->self); + if (px->pQInfo == NULL) { + tscAsyncResultOnError(pSql); + pOutput->code = TSDB_CODE_QRY_OUT_OF_MEMORY; + return; + } px->pQInfo->runtimeEnv.udfIsCopy = true; px->pQInfo->runtimeEnv.pUdfInfo = pUdfInfo; @@ -2696,8 +2701,11 @@ int32_t tscExprTopBottomIndex(SQueryInfo* pQueryInfo){ SExprInfo* pExpr = tscExprGet(pQueryInfo, i); if (pExpr == NULL) continue; - if (pExpr->base.functionId == TSDB_FUNC_TOP || pExpr->base.functionId == TSDB_FUNC_BOTTOM - || pExpr->base.functionId == TSDB_FUNC_UNIQUE || pExpr->base.functionId == TSDB_FUNC_TAIL) { + if (pExpr->base.functionId == TSDB_FUNC_TOP + || pExpr->base.functionId == TSDB_FUNC_BOTTOM + || pExpr->base.functionId == TSDB_FUNC_SAMPLE + || pExpr->base.functionId == TSDB_FUNC_UNIQUE + || pExpr->base.functionId == TSDB_FUNC_TAIL) { return i; } } diff --git a/src/client/tests/CMakeLists.txt b/src/client/tests/CMakeLists.txt index 6ba6d5f6a800f63989249afbaaf6973708963745..55edf5752fb1aa2e06f7c805fe48d017062cc813 100644 --- a/src/client/tests/CMakeLists.txt +++ b/src/client/tests/CMakeLists.txt @@ -1,9 +1,14 @@ CMAKE_MINIMUM_REQUIRED(VERSION 3.0...3.20) PROJECT(TDengine) -FIND_PATH(HEADER_GTEST_INCLUDE_DIR gtest.h /usr/include/gtest /usr/local/include/gtest) -FIND_LIBRARY(LIB_GTEST_STATIC_DIR libgtest.a /usr/lib/ /usr/local/lib /usr/lib64) -FIND_LIBRARY(LIB_GTEST_SHARED_DIR libgtest.so /usr/lib/ /usr/local/lib /usr/lib64) +IF (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + SET(HOMEBREW_LIB_PATH "/opt/homebrew/lib") + SET(HOMEBREW_INC_PATH "/opt/homebrew/include/gtest") +ENDIF () + +FIND_PATH(HEADER_GTEST_INCLUDE_DIR gtest.h /usr/include/gtest /usr/local/include/gtest ${HOMEBREW_INC_PATH}) +FIND_LIBRARY(LIB_GTEST_STATIC_DIR libgtest.a /usr/lib/ /usr/local/lib /usr/lib64 ${HOMEBREW_LIB_PATH}) +FIND_LIBRARY(LIB_GTEST_SHARED_DIR libgtest.so /usr/lib/ /usr/local/lib /usr/lib64 ${HOMEBREW_LIB_PATH}) IF (HEADER_GTEST_INCLUDE_DIR AND (LIB_GTEST_STATIC_DIR OR LIB_GTEST_SHARED_DIR)) MESSAGE(STATUS "gTest library found, build unit test") @@ -11,11 +16,16 @@ IF (HEADER_GTEST_INCLUDE_DIR AND (LIB_GTEST_STATIC_DIR OR LIB_GTEST_SHARED_DIR)) # GoogleTest requires at least C++11 SET(CMAKE_CXX_STANDARD 11) - INCLUDE_DIRECTORIES(/usr/include /usr/local/include) - LINK_DIRECTORIES(/usr/lib /usr/local/lib) + get_filename_component(HEADER_GTEST_PATH ${HEADER_GTEST_INCLUDE_DIR} PATH) + INCLUDE_DIRECTORIES(/usr/include /usr/local/include ${HEADER_GTEST_PATH}) AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} SOURCE_LIST) - ADD_EXECUTABLE(cliTest ${SOURCE_LIST}) - TARGET_LINK_LIBRARIES(cliTest taos cJson tutil common gtest pthread) + IF (LIB_GTEST_STATIC_DIR) + get_filename_component(GTEST_LIB_PATH ${LIB_GTEST_STATIC_DIR} PATH) + MESSAGE(STATUS "${Green} found libtest.a in ${GTEST_LIB_PATH}, will build cliTest ${ColourReset}") + LINK_DIRECTORIES(/usr/lib /usr/local/lib ${GTEST_LIB_PATH}) + ADD_EXECUTABLE(cliTest ${SOURCE_LIST}) + TARGET_LINK_LIBRARIES(cliTest taos cJson tutil common gtest pthread) + ENDIF() ENDIF() diff --git a/src/connector/TypeScript-REST/example/example.ts b/src/connector/TypeScript-REST/example/example.ts deleted file mode 100644 index 91a1c917be7f7174861fa6e6e873982ce3868efe..0000000000000000000000000000000000000000 --- a/src/connector/TypeScript-REST/example/example.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { options, connect } from '../tdengine_rest' -options.path = '/rest/sqlt' -options.host = 'localhost' - -const db = 'rest_ts_db'; -const table = 'rest' -const createDB = `create database if not exists ${db} keep 3650`; -const dropDB = `drop database if exists ${db}`; -const createTB = `create table if not exists ${db}.${table}(ts timestamp,i8 tinyint,i16 smallint,i32 int,i64 bigint,bnr binary(40),nchr nchar(40))`; -const addColumn = `alter table ${db}.${table} add column new_column nchar(40) `; -const dropColumn = `alter table ${db}.${table} drop column new_column`; -const insertSql = `insert into ${db}.${table} values('2022-03-30 18:30:51.567',1,2,3,4,'binary1','nchar1')` + - `('2022-03-30 18:30:51.568',5,6,7,8,'binary2','nchar2')` + - `('2022-03-30 18:30:51.569',9,0,1,2,'binary3','nchar3')`; -const querySql = `select * from ${db}.${table}`; -const errorSql = 'show database'; - -let conn = connect(options); -let cursor = conn.cursor(); - -async function execute(sql: string, pure = false) { - let result = await cursor.query(sql, pure); - // print query result as taos shell - result.toString(); - // Get Result object, return Result object. - console.log("result.getResult()",result.getResult()); - // Get status, return 'succ'|'error'. - console.log("result.getStatus()",result.getStatus()); - // Get head,return response head (Array|undefined,when execute failed this is undefined). - console.log("result.getHead()",result.getHead()); - // Get Meta data, return Meta[]|undefined(when execute failed this is undefined). - console.log("result.getMeta()",result.getMeta()); - // Get data,return Array>|undefined(when execute failed this is undefined). - console.log("result.getData()",result.getData()); - // Get affect rows,return number|undefined(when execute failed this is undefined). - console.log("result.getAffectRows()",result.getAffectRows()); - // Get command,return SQL send to server(need to `query(sql,false)`,set 'pure=false',default true). - console.log("result.getCommand()",result.getCommand()); - // Get error code ,return number|undefined(when execute failed this is undefined). - console.log("result.getErrCode()",result.getErrCode()); - // Get error string,return string|undefined(when execute failed this is undefined). - console.log("result.getErrStr()",result.getErrStr()); -} - -(async () => { - let start = new Date().getTime(); // 开始时间 - await execute(createDB); - await execute(createTB); - await execute(addColumn); - await execute(dropColumn); - await execute(insertSql); - await execute(querySql); - await execute(errorSql); - await execute(dropDB); - let end = new Date().getTime(); // 结束时间 - console.log("total spend time:%d ms",end - start); -})() - - - - - diff --git a/src/connector/TypeScript-REST/index.ts b/src/connector/TypeScript-REST/index.ts deleted file mode 100644 index 0d61cca21442311ccabed637ae89e38c620892bb..0000000000000000000000000000000000000000 --- a/src/connector/TypeScript-REST/index.ts +++ /dev/null @@ -1,14 +0,0 @@ - -import {TDConnect,Options} from './src/connect'; -let options:Options = { - host : '127.0.0.1', - port : 6041, - path : '/rest/sql', - user : 'root', - passwd : 'taosdata' -} -let connect = function connect(option:Options){ - return new TDConnect(option); -} - -export {options,connect} \ No newline at end of file diff --git a/src/connector/TypeScript-REST/package.json b/src/connector/TypeScript-REST/package.json deleted file mode 100644 index e2b76061ba80f55dedc101435c1a9617a417873f..0000000000000000000000000000000000000000 --- a/src/connector/TypeScript-REST/package.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "name": "td2.0-rest-connector", - "version": "1.0.3", - "description": "A REST connector for TDengine", - "source": "tdengine_rest.ts", - "main": "dist/main/rest.js", - "module": "dist/module/rest.mjs", - "types": "dist/types.d.ts", - "directories": { - "example": "example", - "test": "test" - }, - "scripts": { - "test": "parcel build --no-source-maps && node ./dist/test/test.main.js && node ./dist/test/test.module.mjs", - "example": "tsc && node ./tsc/example/example.js", - "build": "parcel build --no-source-maps", - "watch": "parcel watch" - }, - "repository": { - "type": "git", - "url": "https://github.com/taosdata/TDengine/tree/develop/src/connector/TypeScript-REST" - }, - - "keywords": [ - "REST", - "Node.js", - "Typescript", - "TDengine", - "taos", - "IOT", - "node-fetch" - ], - "author": "TaosData Inc.", - "license": "MIT", - "dependencies": { - "node-fetch": "^2.6.7", - "@types/node": "^17.0.23" - }, - "devDependencies": { - "@parcel/packager-ts": "^2.4.1", - "@parcel/transformer-typescript-types": "^2.4.1", - "@types/node-fetch": "^2.6.1", - "parcel": "^2.4.0", - "typescript": "^4.6.3" - }, - "bugs": { - "url": "https://github.com/taosdata/tdengine/issues" - }, - "homepage": "https://github.com/taosdata/tdengine#readme" -} diff --git a/src/connector/TypeScript-REST/src/connect.ts b/src/connector/TypeScript-REST/src/connect.ts deleted file mode 100644 index a8ae42dcc0f872fd2da5ce93129863b0af1ed325..0000000000000000000000000000000000000000 --- a/src/connector/TypeScript-REST/src/connect.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { TDengineCursor } from './cursor' -import { Uri, User } from './options' - -/** - * Options used to connect with REST(taosAdapter) - * Need to set options with 'host','path','port','user','passwd'. - * connWith is optional attribute for further use. - */ -export interface Options extends Uri, User { - connWith?: 'rest' | 'taosc' -} - -/** - * Create connect with TDengine,actually pass options - * to `Cursor` which send and receive HTTP request. - */ -export class TDConnect { - - _connOption: Options; - - constructor(connOption: Options) { - this._connOption = connOption - } - - cursor(): TDengineCursor { - return new TDengineCursor(this._connOption); - } - -} diff --git a/src/connector/TypeScript-REST/src/cursor.ts b/src/connector/TypeScript-REST/src/cursor.ts deleted file mode 100644 index 07af3f256a3e1b68c78010cd57264ee02e3318eb..0000000000000000000000000000000000000000 --- a/src/connector/TypeScript-REST/src/cursor.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { Uri, User } from './options' -import { TDResRequest } from './request' -import { Result } from './result' - - -export class TDengineCursor { - field: Array; - data: Array - _rowCount: number; - _uri: Uri; - _user: User; - - constructor(options: any) { - this._uri = { - host: options.host, - path: options.path, - port: options.port, - - } - this._user = { - user: options.user, - passwd: options.passwd, - } - this._rowCount = 0; - this.field = []; - this.data = []; - - } - - async query(sql: string, pure = true): Promise { - let req = new TDResRequest(this._uri, this._user); - let response = await req.request(sql); - let res_json = await response.json(); - - if (pure == false) { - return new Result(res_json, sql); - } else { - return new Result(res_json); - } - - } -} \ No newline at end of file diff --git a/src/connector/TypeScript-REST/src/options.ts b/src/connector/TypeScript-REST/src/options.ts deleted file mode 100644 index df90b515f530fb595f7819edf4ed23fa88ff2f31..0000000000000000000000000000000000000000 --- a/src/connector/TypeScript-REST/src/options.ts +++ /dev/null @@ -1,16 +0,0 @@ -export interface FetchOptions { - method: 'POST'; - body: string; - headers: Record -} - -export interface User { - user: string; - passwd: string; -} - -export interface Uri { - host: '127.0.0.1'|string; - path: "/rest/sqlt" | '/rest/sqlutc' | '/rest/sql'; - port: 6041; -} \ No newline at end of file diff --git a/src/connector/TypeScript-REST/src/request.ts b/src/connector/TypeScript-REST/src/request.ts deleted file mode 100644 index 259c34c32366dc2c9efc0d8121985c01baea8b52..0000000000000000000000000000000000000000 --- a/src/connector/TypeScript-REST/src/request.ts +++ /dev/null @@ -1,35 +0,0 @@ - -import { Uri,User,FetchOptions } from "./options"; -import fetch from 'node-fetch'; - -export class TDResRequest { - uri: Uri; - options: FetchOptions; - user:User; - - constructor(url: Uri, user:User) { - this.uri = url; - this.user = user; - this.options = { - method: 'POST', - body:'', - headers:{'Authorization':this._token()} - } - } - - _makeUrl(): string { - return `http://${this.uri.host}:${this.uri.port}${this.uri.path}`; - } - _token(): string { - return`Basic ${Buffer.from(`${this.user.user}:${this.user.passwd}`).toString('base64')}` - } - _body(command:string):void{ - this.options.body = command; - } - request(command:string): Promise { - this._body(command); - return fetch(this._makeUrl(), this.options); - } -} - - diff --git a/src/connector/TypeScript-REST/src/result.ts b/src/connector/TypeScript-REST/src/result.ts deleted file mode 100644 index ea2722e04d1bdcac3faccb7dae05433f2d4c243e..0000000000000000000000000000000000000000 --- a/src/connector/TypeScript-REST/src/result.ts +++ /dev/null @@ -1,219 +0,0 @@ -interface IResult { - status: string; - head?: Array; - column_meta?: Array>; - data?: Array>; - rows?: number; - command?: string; - //for error - code?: number; - desc?: string; -} - -interface meta { - columnName: string; - code: number; - size: number; - typeName?: string; -} - -export class Result { - private _status: string; - private _head?: string[]; - private _column_meta?: Array; - private _data?: Array>; - private _rows?: number; - private _command?: string; - //for error - private _code?: number; - private _desc?: string; - - constructor(res: IResult, commands?: string) { - let meta_list_length = res.column_meta == undefined ? 0 : res.column_meta.length - if (res.status === 'succ') { - this._status = res.status; - this._head = res.head; - this._column_meta = new Array(meta_list_length); - this._data = res.data; - this._rows = res.rows; - this._command = commands; - this._initMeta(res); - this._code = undefined; - this._desc = undefined; - } else { - this._status = res.status; - this._head = undefined; - this._column_meta = undefined; - this._data = undefined; - this._rows = undefined; - this._command = commands; - this._code = res.code; - this._desc = res.desc; - } - - } - private _initMeta(res: IResult): void { - if (res.column_meta != undefined) { - res.column_meta.forEach((item, index) => { - if (this._column_meta != undefined) - this._column_meta[index] = { - columnName: item[0], - code: item[1], - size: item[2], - typeName: typeNameMap[item[1]] - } - }) - } - } - - getResult(): Result { - return this; - } - - getStatus(): string { - return this._status; - } - - getHead(): Array | undefined { - return this._head; - } - - getMeta(): Array | undefined { - return this._column_meta; - } - - getData(): Array> | undefined { - return this._data; - } - - getAffectRows(): number | undefined { - return this._rows; - } - - getCommand(): string | undefined { - return this._command; - } - - getErrCode(): number | undefined { - return this._code; - } - - getErrStr(): string | undefined { - return this._desc; - } - - toString(): void { - let str = ''; - if(this._command != undefined){ - console.log(this._command); - } - if (this._status === 'succ' && this._column_meta != undefined && this._data != undefined) { - str = this._prettyStr(this._column_meta, this._data) - } else { - str = `Execute ${this._status},reason:${this._desc}. error_no:${this._code} `; - console.log(str) - } - } - - private _prettyStr(fields: Array, data: Array>): string { - let colName = new Array(); - let colType = new Array(); - let colSize = new Array(); - let colStr = ''; - - for (let i = 0; i < fields.length; i++) { - colName.push(fields[i].columnName) - colType.push(fields[i].typeName); - - if ((fields[i].code) == 8 || (fields[i].code) == 10) { - colSize.push(Math.max(fields[i].columnName.length, fields[i].size)); //max(column_name.length,column_type_precision) - } else { - colSize.push(Math.max(fields[i].columnName.length, suggestedMinWidths[fields[i].size]));// max(column_name.length,suggest_column_with_suggestion) - } - // console.log(colSize) - } - colName.forEach((name, i) => { - colStr += this._fillEmpty(Math.floor(colSize[i] / 2 - name.length / 2)) + name.toString() + this._fillEmpty(Math.ceil(colSize[i] / 2 - name.length / 2)) + " | " - }) - - let strSperator = "" - let sizeSum = colSize.reduce((a, b) => a += b, (0)) + colSize.length * 3 - strSperator = this._printN("=", sizeSum) - - console.log("\n" + colStr) - console.log(strSperator) - - data.forEach((row) => { - let rowStr = "" - row.forEach((cell, index) => { - rowStr += cell == null ? 'null' : cell.toString(); - rowStr += this._fillEmpty(colSize[index] - cell.toString().length) + " | " - }) - console.log(rowStr) - }) - - return colStr - } - - private _fillEmpty(n:number) { - let str = ""; - for (let i = 0; i < n; i++) { - str += " "; - } - return str; - } - - private _printN(s:string, n:number) { - let f = ""; - for (let i = 0; i < n; i++) { - f += s; - } - return f; - } -} - - - -interface indexableString { - [index: number]: string -} -/** - * this file record TDengine's data type and code. - */ -const typeNameMap: indexableString = { - 0: 'null', - 1: 'bool', - 2: 'tinyint', - 3: 'smallint', - 4: 'int', - 5: 'bigint', - 6: 'float', - 7: 'double', - 8: 'binary', - 9: 'timestamp', - 10: 'nchar', - 11: 'unsigned tinyint', - 12: 'unsigned smallint', - 13: 'unsigned int', - 14: 'unsigned bigint', - 15: 'json' -} - -interface indexableNumber { - [index: number]: number -} -const suggestedMinWidths: indexableNumber = { - 0: 4, - 1: 4, - 2: 4, - 3: 6, - 4: 11, - 5: 12, - 6: 24, - 7: 24, - 8: 10, - 9: 25, - 10: 10, -} - - diff --git a/src/connector/TypeScript-REST/tdengine_rest.ts b/src/connector/TypeScript-REST/tdengine_rest.ts deleted file mode 100644 index 0d61cca21442311ccabed637ae89e38c620892bb..0000000000000000000000000000000000000000 --- a/src/connector/TypeScript-REST/tdengine_rest.ts +++ /dev/null @@ -1,14 +0,0 @@ - -import {TDConnect,Options} from './src/connect'; -let options:Options = { - host : '127.0.0.1', - port : 6041, - path : '/rest/sql', - user : 'root', - passwd : 'taosdata' -} -let connect = function connect(option:Options){ - return new TDConnect(option); -} - -export {options,connect} \ No newline at end of file diff --git a/src/connector/TypeScript-REST/tsconfig.json b/src/connector/TypeScript-REST/tsconfig.json deleted file mode 100644 index 8e115328c6b74de8a1f2042f627dbbab1f98cff4..0000000000000000000000000000000000000000 --- a/src/connector/TypeScript-REST/tsconfig.json +++ /dev/null @@ -1,101 +0,0 @@ -{ - "compilerOptions": { - /* Visit https://aka.ms/tsconfig.json to read more about this file */ - - /* Projects */ - // "incremental": true, /* Enable incremental compilation */ - // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ - // "tsBuildInfoFile": "./", /* Specify the folder for .tsbuildinfo incremental compilation files. */ - // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects */ - // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ - // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ - - /* Language and Environment */ - "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ - // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ - // "jsx": "preserve", /* Specify what JSX code is generated. */ - // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ - // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ - // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */ - // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ - // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */ - // "reactNamespace": "", /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */ - // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ - // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ - - /* Modules */ - "module": "commonjs", /* Specify what module code is generated. */ - // "rootDir": "./", /* Specify the root folder within your source files. */ - // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ - // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ - // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ - // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ - // "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */ - // "types": [], /* Specify type package names to be included without being referenced in a source file. */ - // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ - // "resolveJsonModule": true, /* Enable importing .json files */ - // "noResolve": true, /* Disallow `import`s, `require`s or ``s from expanding the number of files TypeScript should add to a project. */ - - /* JavaScript Support */ - // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */ - // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ - // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */ - - /* Emit */ - // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ - // "declarationMap": true, /* Create sourcemaps for d.ts files. */ - // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ - // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ - // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */ - "outDir": "./tsc/", /* Specify an output folder for all emitted files. */ - // "removeComments": true, /* Disable emitting comments. */ - // "noEmit": true, /* Disable emitting files from a compilation. */ - // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ - // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types */ - // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ - // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ - // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ - // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ - // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ - // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ - // "newLine": "crlf", /* Set the newline character for emitting files. */ - // "stripInternal": true, /* Disable emitting declarations that have `@internal` in their JSDoc comments. */ - // "noEmitHelpers": true, /* Disable generating custom helper functions like `__extends` in compiled output. */ - // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ - // "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */ - // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ - // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ - - /* Interop Constraints */ - // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ - // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ - "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */ - // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ - "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ - - /* Type Checking */ - "strict": true, /* Enable all strict type-checking options. */ - // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied `any` type.. */ - // "strictNullChecks": true, /* When type checking, take into account `null` and `undefined`. */ - // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ - // "strictBindCallApply": true, /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */ - // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ - // "noImplicitThis": true, /* Enable error reporting when `this` is given the type `any`. */ - // "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */ - // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ - // "noUnusedLocals": true, /* Enable error reporting when a local variables aren't read. */ - // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read */ - // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ - // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ - // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ - // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ - // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ - // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type */ - // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ - // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ - - /* Completeness */ - // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ - "skipLibCheck": true /* Skip type checking all .d.ts files. */ - } -} diff --git a/src/connector/jdbc/pom.xml b/src/connector/jdbc/pom.xml index f196a6b4216f7b48c65b7475ebb488009b322eba..27d9c3b97c2d100b8997eccb94ba7935c2e1c72f 100644 --- a/src/connector/jdbc/pom.xml +++ b/src/connector/jdbc/pom.xml @@ -128,7 +128,7 @@ org.apache.maven.plugins maven-surefire-plugin - 2.12.4 + 3.0.0-M6 pertest ${maven.test.jvmargs} diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBDriver.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBDriver.java index 6e8296950075f17020dcf163b33035f90f1fd879..029e58bd61f3f29cedfac024182faaedd0e388f7 100755 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBDriver.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBDriver.java @@ -60,6 +60,12 @@ public class TSDBDriver extends AbstractDriver { * to the driver. */ public static final String PROPERTY_KEY_PASSWORD = "password"; + /** + * Key used to retrieve the token value from the properties instance passed to + * the driver. + * Just for Cloud Service + */ + public static final String PROPERTY_KEY_TOKEN = "token"; /** * Key for the configuration file directory of TSDB client in properties instance */ diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulDriver.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulDriver.java index 7af6bc607eeac7f2605cda9f9a55587b535d73cc..99b6c3bd3e659dc021741a9455d30ec4ef009fb4 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulDriver.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulDriver.java @@ -52,6 +52,7 @@ public class RestfulDriver extends AbstractDriver { String user; String password; + String cloudToken = null; try { if (!props.containsKey(TSDBDriver.PROPERTY_KEY_USER)) throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_USER_IS_REQUIRED); @@ -63,6 +64,10 @@ public class RestfulDriver extends AbstractDriver { } catch (UnsupportedEncodingException e) { throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_INVALID_VARIABLE, "unsupported UTF-8 concoding, user: " + props.getProperty(TSDBDriver.PROPERTY_KEY_USER) + ", password: " + props.getProperty(TSDBDriver.PROPERTY_KEY_PASSWORD)); } + if (props.containsKey(TSDBDriver.PROPERTY_KEY_TOKEN)) { + cloudToken = props.getProperty(TSDBDriver.PROPERTY_KEY_TOKEN); + } + String loginUrl; String batchLoad = info.getProperty(TSDBDriver.PROPERTY_KEY_BATCH_LOAD); if (Boolean.parseBoolean(batchLoad)) { @@ -102,6 +107,9 @@ public class RestfulDriver extends AbstractDriver { return new WSConnection(url, props, transport, database); } loginUrl = "http://" + props.getProperty(TSDBDriver.PROPERTY_KEY_HOST) + ":" + props.getProperty(TSDBDriver.PROPERTY_KEY_PORT) + "/rest/login/" + user + "/" + password + ""; + if (null != cloudToken) { + loginUrl += "?token=" + cloudToken; + } int poolSize = Integer.parseInt(props.getProperty("httpPoolSize", HttpClientPoolUtil.DEFAULT_MAX_PER_ROUTE)); boolean keepAlive = Boolean.parseBoolean(props.getProperty("httpKeepAlive", HttpClientPoolUtil.DEFAULT_HTTP_KEEP_ALIVE)); diff --git a/src/connector/nodejs/examples/cursorClose.js b/src/connector/nodejs/examples/cursorClose.js deleted file mode 100644 index 1c00f652ad7bf2d504c18195dde19d8f17ba3e73..0000000000000000000000000000000000000000 --- a/src/connector/nodejs/examples/cursorClose.js +++ /dev/null @@ -1,49 +0,0 @@ -const taos = require('../tdengine'); - -const conn = taos.connect({ - host: "localhost", -}); - -const cursor = conn.cursor(); - -function createDatabase() { - cursor.execute("CREATE DATABASE if not exists test_cursor_close"); - cursor.execute("USE test_cursor_close"); -} - -function insertData() { - const lines = [ - "meters,location=Beijing.Haidian,groupid=2 current=11.8,voltage=221,phase=0.28 1648432611249", - "meters,location=Beijing.Haidian,groupid=2 current=13.4,voltage=223,phase=0.29 1648432611250", - "meters,location=Beijing.Haidian,groupid=3 current=10.8,voltage=223,phase=0.29 1648432611249", - "meters,location=Beijing.Haidian,groupid=3 current=11.3,voltage=221,phase=0.35 1648432611250", - ]; - cursor.schemalessInsert( - lines, - taos.SCHEMALESS_PROTOCOL.TSDB_SML_LINE_PROTOCOL, - taos.SCHEMALESS_PRECISION.TSDB_SML_TIMESTAMP_MILLI_SECONDS - ); -} - -function query() { - let promise = cursor.query("select * from test_cursor_close.meters"); - promise.execute().then(result => result.pretty()).catch(err => console.log(e)); -} - -function destructData() { - cursor.execute("drop database if exists test_cursor_close"); -} - -function main() { - try { - createDatabase(); - insertData(); - query(); - destructData(); - } finally { - cursor.close(); - conn.close(); - } -} - -main(); \ No newline at end of file diff --git a/src/connector/nodejs/examples/performance.js b/src/connector/nodejs/examples/performance.js deleted file mode 100644 index ea197f034435e28edd67df8d5f4b141f410fed81..0000000000000000000000000000000000000000 --- a/src/connector/nodejs/examples/performance.js +++ /dev/null @@ -1,89 +0,0 @@ -function memoryUsageData() { - let s = process.memoryUsage() - for (key in s) { - s[key] = (s[key]/1000000).toFixed(3) + "MB"; - } - return s; -} -console.log("initial mem usage:", memoryUsageData()); - -const { PerformanceObserver, performance } = require('perf_hooks'); -const taos = require('../tdengine'); -var conn = taos.connect({host:"127.0.0.1", user:"root", password:"taosdata", config:"/etc/taos",port:0}); -var c1 = conn.cursor(); - -// Initialize env -c1.execute('create database if not exists td_connector_test;'); -c1.execute('use td_connector_test;') -c1.execute('create table if not exists all_types (ts timestamp, _int int, _bigint bigint, _float float, _double double, _binary binary(40), _smallint smallint, _tinyint tinyint, _bool bool, _nchar nchar(40));'); -c1.execute('create table if not exists stabletest (ts timestamp, v1 int, v2 int, v3 int, v4 double) tags (id int, location binary(20));') - - -// Insertion into single table Performance Test -var dataPrepTime = 0; -var insertTime = 0; -var insertTime5000 = 0; -var avgInsert5ktime = 0; -const obs = new PerformanceObserver((items) => { - let entry = items.getEntries()[0]; - - if (entry.name == 'Data Prep') { - dataPrepTime += entry.duration; - } - else if (entry.name == 'Insert'){ - insertTime += entry.duration - } - else { - console.log(entry.name + ': ' + (entry.duration/1000).toFixed(8) + 's'); - } - performance.clearMarks(); -}); -obs.observe({ entryTypes: ['measure'] }); - -function R(l,r) { - return Math.random() * (r - l) - r; -} -function randomBool() { - if (Math.random() < 0.5) { - return true; - } - return false; -} -function insertN(n) { - for (let i = 0; i < n; i++) { - performance.mark('A3'); - let insertData = ["now + " + i + "m", // Timestamp - parseInt( R(-Math.pow(2,31) + 1 , Math.pow(2,31) - 1) ), // Int - parseInt( R(-Math.pow(2,31) + 1 , Math.pow(2,31) - 1) ), // BigInt - parseFloat( R(-3.4E38, 3.4E38) ), // Float - parseFloat( R(-1.7E308, 1.7E308) ), // Double - "\"Long Binary\"", // Binary - parseInt( R(-32767, 32767) ), // Small Int - parseInt( R(-127, 127) ), // Tiny Int - randomBool(), - "\"Nchars 一些中文字幕\""]; // Bool - let query = 'insert into td_connector_test.all_types values(' + insertData.join(',') + ' );'; - performance.mark('B3'); - performance.measure('Data Prep', 'A3', 'B3'); - performance.mark('A2'); - c1.execute(query, {quiet:true}); - performance.mark('B2'); - performance.measure('Insert', 'A2', 'B2'); - if ( i % 5000 == 4999) { - console.log("Insert # " + (i+1)); - console.log('Insert 5k records: ' + ((insertTime - insertTime5000)/1000).toFixed(8) + 's'); - insertTime5000 = insertTime; - avgInsert5ktime = (avgInsert5ktime/1000 * Math.floor(i / 5000) + insertTime5000/1000) / Math.ceil( i / 5000); - console.log('DataPrepTime So Far: ' + (dataPrepTime/1000).toFixed(8) + 's | Inserting time So Far: ' + (insertTime/1000).toFixed(8) + 's | Avg. Insert 5k time: ' + avgInsert5ktime.toFixed(8)); - - - } - } -} -performance.mark('insert 1E5') -insertN(1E5); -performance.mark('insert 1E5 2') -performance.measure('Insert With Logs', 'insert 1E5', 'insert 1E5 2'); -console.log('DataPrepTime: ' + (dataPrepTime/1000).toFixed(8) + 's | Inserting time: ' + (insertTime/1000).toFixed(8) + 's'); -dataPrepTime = 0; insertTime = 0; -//'insert into td_connector_test.all_types values (now, null,null,null,null,null,null,null,null,null);' diff --git a/src/connector/nodejs/examples/stmtBindParamBatchSample.js b/src/connector/nodejs/examples/stmtBindParamBatchSample.js deleted file mode 100755 index c7748790875a5d7e99482dbf1266917fd2882231..0000000000000000000000000000000000000000 --- a/src/connector/nodejs/examples/stmtBindParamBatchSample.js +++ /dev/null @@ -1,111 +0,0 @@ -const taos = require('../tdengine'); -var conn = taos.connect({ host: "localhost" }); -var cursor = conn.cursor(); - -function executeUpdate(updateSql) { - console.log(updateSql); - cursor.execute(updateSql); -} -function executeQuery(querySql) { - - let query = cursor.query(querySql); - query.execute().then((result => { - console.log(querySql); - result.pretty(); - })); -} - -function stmtBindParamBatchSample() { - let db = 'node_test_db'; - let table = 'stmt_taos_bind_param_batch'; - - let createDB = `create database if not exists ${db} keep 3650;`; - let dropDB = `drop database if exists ${db};`; - let useDB = `use ${db}`; - let createTable = `create table if not exists ${table} ` + - `(ts timestamp,` + - `bl bool,` + - `i8 tinyint,` + - `i16 smallint,` + - `i32 int,` + - `i64 bigint,` + - `f32 float,` + - `d64 double,` + - `bnr binary(20),` + - `nchr nchar(20),` + - `u8 tinyint unsigned,` + - `u16 smallint unsigned,` + - `u32 int unsigned,` + - `u64 bigint unsigned` + - `)tags(` + - `t_bl bool,` + - `t_i8 tinyint,` + - `t_i16 smallint,` + - `t_i32 int,` + - `t_i64 bigint,` + - `t_f32 float,` + - `t_d64 double,` + - `t_bnr binary(20),` + - `t_nchr nchar(20),` + - `t_u8 tinyint unsigned,` + - `t_u16 smallint unsigned,` + - `t_u32 int unsigned,` + - `t_u64 bigint unsigned` + - `);`; - let querySql = `select * from ${table};`; - let insertSql = `insert into ? using ${table} tags(?,?,?,?,?,?,?,?,?,?,?,?,?) values (?,?,?,?,?,?,?,?,?,?,?,?,?,?);`; - - executeUpdate(dropDB); - executeUpdate(createDB); - executeUpdate(useDB); - executeUpdate(createTable); - - let mBinds = new taos.TaosMultiBindArr(14); - mBinds.multiBindTimestamp([1642435200000, 1642435300000, 1642435400000, 1642435500000, 1642435600000]); - mBinds.multiBindBool([true, false, true, undefined, null]); - mBinds.multiBindTinyInt([-127, 3, 127, null, undefined]); - mBinds.multiBindSmallInt([-256, 0, 256, null, undefined]); - mBinds.multiBindInt([-1299, 0, 1233, null, undefined]); - mBinds.multiBindBigInt([16424352000002222n, -16424354000001111n, 0, null, undefined]); - mBinds.multiBindFloat([12.33, 0, -3.1415, null, undefined]); - mBinds.multiBindDouble([3.141592653, 0, -3.141592653, null, undefined]); - mBinds.multiBindBinary(['TDengine_Binary', '', 'taosdata涛思数据', null, undefined]); - mBinds.multiBindNchar(['taos_data_nchar', 'taosdata涛思数据', '', null, undefined]); - mBinds.multiBindUTinyInt([0, 127, 254, null, undefined]); - mBinds.multiBindUSmallInt([0, 256, 512, null, undefined]); - mBinds.multiBindUInt([0, 1233, 4294967294, null, undefined]); - mBinds.multiBindUBigInt([16424352000002222n, 36424354000001111n, 0, null, undefined]); - - let tags = new taos.TaosBind(13); - - tags.bindBool(true); - tags.bindTinyInt(127); - tags.bindSmallInt(32767); - tags.bindInt(1234555); - tags.bindBigInt(-164243520000011111n); - tags.bindFloat(214.02); - tags.bindDouble(2.01); - tags.bindBinary('taosdata涛思数据'); - tags.bindNchar('TDengine数据'); - tags.bindUTinyInt(254); - tags.bindUSmallInt(65534); - tags.bindUInt(4294967290); - tags.bindUBigInt(164243520000011111n); - - cursor.stmtInit(); - cursor.stmtPrepare(insertSql); - cursor.stmtSetTbnameTags('s_01', tags.getBind()); - cursor.stmtBindParamBatch(mBinds.getMultiBindArr()); - cursor.stmtAddBatch(); - cursor.stmtExecute(); - cursor.stmtClose(); - - executeQuery(querySql); - executeUpdate(dropDB); - -} - -stmtBindParamBatchSample(); -setTimeout(() => { - conn.close(); -}, 2000); diff --git a/src/connector/nodejs/examples/stmtBindParamSample.js b/src/connector/nodejs/examples/stmtBindParamSample.js deleted file mode 100644 index 57c097d8cf1215b60a3ce386eb4b60f2005e7c87..0000000000000000000000000000000000000000 --- a/src/connector/nodejs/examples/stmtBindParamSample.js +++ /dev/null @@ -1,82 +0,0 @@ -// const TaosBind = require('../nodetaos/taosBind'); -const taos = require('../tdengine'); -var conn = taos.connect({ host: "localhost" }); -var cursor = conn.cursor(); - -function executeUpdate(updateSql) { - console.log(updateSql); - cursor.execute(updateSql); -} -function executeQuery(querySql) { - - let query = cursor.query(querySql); - query.execute().then((result => { - console.log(querySql); - result.pretty(); - })); -} - -function stmtBindParamSample() { - let db = 'node_test_db'; - let table = 'stmt_taos_bind_sample'; - - let createDB = `create database if not exists ${db} keep 3650;`; - let dropDB = `drop database if exists ${db};`; - let useDB = `use ${db}`; - let createTable = `create table if not exists ${table} ` + - `(ts timestamp,` + - `nil int,` + - `bl bool,` + - `i8 tinyint,` + - `i16 smallint,` + - `i32 int,` + - `i64 bigint,` + - `f32 float,` + - `d64 double,` + - `bnr binary(20),` + - `nchr nchar(20),` + - `u8 tinyint unsigned,` + - `u16 smallint unsigned,` + - `u32 int unsigned,` + - `u64 bigint unsigned);`; - let querySql = `select * from ${table};`; - let insertSql = `insert into ? values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?);` - - executeUpdate(dropDB); - executeUpdate(createDB); - executeUpdate(useDB); - executeUpdate(createTable); - - let binds = new taos.TaosBind(15); - binds.bindTimestamp(1642435200000); - binds.bindNil(); - binds.bindBool(true); - binds.bindTinyInt(127); - binds.bindSmallInt(32767); - binds.bindInt(1234555); - binds.bindBigInt(-164243520000011111n); - binds.bindFloat(214.02); - binds.bindDouble(2.01); - binds.bindBinary('taosdata涛思数据'); - binds.bindNchar('TDengine数据'); - binds.bindUTinyInt(254); - binds.bindUSmallInt(65534); - binds.bindUInt(4294967294); - binds.bindUBigInt(164243520000011111n); - - cursor.stmtInit(); - cursor.stmtPrepare(insertSql); - cursor.stmtSetTbname(table); - cursor.stmtBindParam(binds.getBind()); - cursor.stmtAddBatch(); - cursor.stmtExecute(); - cursor.stmtClose(); - - executeQuery(querySql); - executeUpdate(dropDB); -} - -stmtBindParamSample(); -setTimeout(() => { - conn.close(); -}, 2000); \ No newline at end of file diff --git a/src/connector/nodejs/examples/stmtBindSingleParamBatchSample.js b/src/connector/nodejs/examples/stmtBindSingleParamBatchSample.js deleted file mode 100755 index 938de75b7f3314ce3db32294de9d30b609e480b8..0000000000000000000000000000000000000000 --- a/src/connector/nodejs/examples/stmtBindSingleParamBatchSample.js +++ /dev/null @@ -1,101 +0,0 @@ -const taos = require('../tdengine'); -var conn = taos.connect({ host: "localhost" }); -var cursor = conn.cursor(); - -function executeUpdate(updateSql) { - console.log(updateSql); - cursor.execute(updateSql); -} -function executeQuery(querySql) { - - let query = cursor.query(querySql); - query.execute().then((result => { - console.log(querySql); - result.pretty(); - - })); -} - -function stmtSingleParaBatchSample() { - let db = 'node_test_db'; - let table = 'stmt_taos_bind_single_bind_batch'; - - let createDB = `create database if not exists ${db} keep 3650;`; - let dropDB = `drop database if exists ${db};`; - let useDB = `use ${db}`; - let createTable = `create table if not exists ${table} ` + - `(ts timestamp,` + - `bl bool,` + - `i8 tinyint,` + - `i16 smallint,` + - `i32 int,` + - `i64 bigint,` + - `f32 float,` + - `d64 double,` + - `bnr binary(20),` + - `nchr nchar(20),` + - `u8 tinyint unsigned,` + - `u16 smallint unsigned,` + - `u32 int unsigned,` + - `u64 bigint unsigned` + - `)tags(` + - `jsonTag json` + - `);`; - let querySql = `select * from ${table};`; - let insertSql = `insert into ? using ${table} tags(?) values(?,?,?,?,?,?,?,?,?,?,?,?,?,?);` - - executeUpdate(dropDB); - executeUpdate(createDB); - executeUpdate(useDB); - executeUpdate(createTable); - - // normal colum values. - let mbind = new taos.TaosMultiBind(); - let tsMBind = mbind.multiBindTimestamp([1642435200000, 1642435300000, 1642435400000, 1642435500000, 1642435600000]) - let boolMbind = mbind.multiBindBool([true, false, true, undefined, null]); - let tinyIntMbind = mbind.multiBindTinyInt([-127, 3, 127, null, undefined]); - let smallIntMbind = mbind.multiBindSmallInt([-256, 0, 256, null, undefined]); - let intMbind = mbind.multiBindInt([-1299, 0, 1233, null, undefined]); - let bigIntMbind = mbind.multiBindBigInt([16424352000002222n, -16424354000001111n, 0, null, undefined]); - let floatMbind = mbind.multiBindFloat([12.33, 0, -3.1415, null, undefined]); - let doubleMbind = mbind.multiBindDouble([3.141592653, 0, -3.141592653, null, undefined]); - let binaryMbind = mbind.multiBindBinary(['TDengine_Binary', '', 'taosdata涛思数据', null, undefined]); - let ncharMbind = mbind.multiBindNchar(['taos_data_nchar', 'taosdata涛思数据', '', null, undefined]); - let uTinyIntMbind = mbind.multiBindUTinyInt([0, 127, 254, null, undefined]); - let uSmallIntMbind = mbind.multiBindUSmallInt([0, 256, 512, null, undefined]); - let uIntMbind = mbind.multiBindUInt([0, 1233, 4294967294, null, undefined]); - let uBigIntMbind = mbind.multiBindUBigInt([16424352000002222n, 36424354000001111n, 0, null, undefined]); - - // tags value. - let tags = new taos.TaosBind(1); - tags.bindJson('{\"key1\":\"taosdata\",\"key2\":null,\"key3\":\"TDengine涛思数据\",\"key4\":3.2}'); - - cursor.stmtInit(); - cursor.stmtPrepare(insertSql); - cursor.stmtSetTbnameTags('s_01', tags.getBind()); - cursor.stmtBindSingleParamBatch(tsMBind, 0); - cursor.stmtBindSingleParamBatch(boolMbind, 1); - cursor.stmtBindSingleParamBatch(tinyIntMbind, 2); - cursor.stmtBindSingleParamBatch(smallIntMbind, 3); - cursor.stmtBindSingleParamBatch(intMbind, 4); - cursor.stmtBindSingleParamBatch(bigIntMbind, 5); - cursor.stmtBindSingleParamBatch(floatMbind, 6); - cursor.stmtBindSingleParamBatch(doubleMbind, 7); - cursor.stmtBindSingleParamBatch(binaryMbind, 8); - cursor.stmtBindSingleParamBatch(ncharMbind, 9); - cursor.stmtBindSingleParamBatch(uTinyIntMbind, 10); - cursor.stmtBindSingleParamBatch(uSmallIntMbind, 11); - cursor.stmtBindSingleParamBatch(uIntMbind, 12); - cursor.stmtBindSingleParamBatch(uBigIntMbind, 13); - - cursor.stmtAddBatch(); - cursor.stmtExecute(); - cursor.stmtClose(); - - executeQuery(querySql); - executeUpdate(dropDB); -} -stmtSingleParaBatchSample(); -setTimeout(() => { - conn.close(); -}, 2000); diff --git a/src/connector/nodejs/examples/stmtUseResultSample.js b/src/connector/nodejs/examples/stmtUseResultSample.js deleted file mode 100755 index 21e2fbf378e763c1e6f26692f31b1c85010c86fb..0000000000000000000000000000000000000000 --- a/src/connector/nodejs/examples/stmtUseResultSample.js +++ /dev/null @@ -1,100 +0,0 @@ -const taos = require('../tdengine'); -var conn = taos.connect({ host: "localhost" }); -var cursor = conn.cursor(); - -function executeUpdate(updateSql) { - console.log(updateSql); - cursor.execute(updateSql); -} -function executeQuery(querySql) { - let query = cursor.query(querySql); - query.execute().then((result => { - console.log(querySql); - result.pretty(); - })); -} - -function stmtUseResultSample() { - let db = 'node_test_db'; - let table = 'stmt_use_result'; - let subTable = 's1_0'; - - let createDB = `create database if not exists ${db} keep 3650;`; - let dropDB = `drop database if exists ${db};`; - let useDB = `use ${db}`; - let createTable = `create table if not exists ${table} ` + - `(ts timestamp,` + - `bl bool,` + - `i8 tinyint,` + - `i16 smallint,` + - `i32 int,` + - `i64 bigint,` + - `f32 float,` + - `d64 double,` + - `bnr binary(20),` + - `nchr nchar(20),` + - `u8 tinyint unsigned,` + - `u16 smallint unsigned,` + - `u32 int unsigned,` + - `u64 bigint unsigned` + - `)tags(` + - `jsonTag json` + - `);`; - let createSubTable = `create table if not exists ${subTable} using ${table} tags('{\"key1\":\"taosdata\",\"key2\":null,\"key3\":\"TDengine涛思数据\",\"key4\":3.2}')`; - let querySql = `select * from ${table} where i32>? and bnr = ? `; - let insertSql = `insert into ? values(?,?,?,?,?,?,?,?,?,?,?,?,?,?);`; - - let mBinds = new taos.TaosMultiBindArr(14); - mBinds.multiBindTimestamp([1642435200000,1642435300000,1642435400000,1642435500000,1642435600000]); - mBinds.multiBindBool([true,false,true,undefined,null]); - mBinds.multiBindTinyInt([-127,3,127,null,undefined]); - mBinds.multiBindSmallInt([-256,0,256,null,undefined]); - mBinds.multiBindInt([-1299,0,1233,null,undefined]); - mBinds.multiBindBigInt([16424352000002222n,-16424354000001111n,0,null,undefined]); - mBinds.multiBindFloat([12.33,0,-3.1415,null,undefined]); - mBinds.multiBindDouble([3.141592653,0,-3.141592653,null,undefined]); - mBinds.multiBindBinary(['TDengine_Binary','','taosdata涛思数据',null,undefined]); - mBinds.multiBindNchar(['taos_data_nchar','taosdata涛思数据','',null,undefined]); - mBinds.multiBindUTinyInt([0,127, 254,null,undefined]); - mBinds.multiBindUSmallInt([0,256,512,null,undefined]); - mBinds.multiBindUInt([0,1233,4294967294,null,undefined]); - mBinds.multiBindUBigInt([16424352000002222n,36424354000001111n,0,null,undefined]); - - // executeUpdate(dropDB); - executeUpdate(createDB); - executeUpdate(useDB); - executeUpdate(createTable); - executeUpdate(createSubTable); - - //stmt bind values - cursor.stmtInit(); - cursor.stmtPrepare(insertSql); - cursor.loadTableInfo([subTable]); - cursor.stmtSetTbname(subTable); - cursor.stmtBindParamBatch(mBinds.getMultiBindArr()); - cursor.stmtAddBatch(); - cursor.stmtExecute(); - cursor.stmtClose(); - - // stmt select with normal column. - let condition1 = new taos.TaosBind(2); - condition1.bindInt(0); - condition1.bindNchar('taosdata涛思数据'); - cursor.stmtInit(); - cursor.stmtPrepare(querySql); - cursor.stmtBindParam(condition1.getBind()); - cursor.stmtExecute(); - cursor.stmtUseResult(); - cursor.stmtClose(); - - cursor.fetchall(); - console.log(cursor.fields); - console.log(cursor.data); - - executeUpdate(dropDB); -} - -stmtUseResultSample(); -setTimeout(() => { - conn.close(); -}, 2000); \ No newline at end of file diff --git a/src/connector/nodejs/examples/taosBindParamSample.js b/src/connector/nodejs/examples/taosBindParamSample.js deleted file mode 100644 index cf8f0a263555844535916f91b1492afb36ef536e..0000000000000000000000000000000000000000 --- a/src/connector/nodejs/examples/taosBindParamSample.js +++ /dev/null @@ -1,82 +0,0 @@ -// const TaosBind = require('../nodetaos/taosBind'); -const taos = require('../tdengine'); -var conn = taos.connect({ host: "localhost" }); -var cursor = conn.cursor(); - -function executeUpdate(updateSql){ - console.log(updateSql); - cursor.execute(updateSql); -} -function executeQuery(querySql){ - - let query = cursor.query(querySql); - query.execute().then((result=>{ - console.log(querySql); - result.pretty(); - })); -} - -function stmtBindParamSample(){ - let db = 'node_test_db'; - let table = 'stmt_taos_bind_sample'; - - let createDB = `create database if not exists ${db} keep 3650;`; - let dropDB = `drop database if exists ${db};`; - let useDB = `use ${db}`; - let createTable = `create table if not exists ${table} `+ - `(ts timestamp,`+ - `nil int,`+ - `bl bool,`+ - `i8 tinyint,`+ - `i16 smallint,`+ - `i32 int,`+ - `i64 bigint,`+ - `f32 float,`+ - `d64 double,`+ - `bnr binary(20),`+ - `nchr nchar(20),`+ - `u8 tinyint unsigned,`+ - `u16 smallint unsigned,`+ - `u32 int unsigned,`+ - `u64 bigint unsigned);`; - let querySql = `select * from ${table};`; - let insertSql = `insert into ? values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?);` - - executeUpdate(dropDB); - executeUpdate(createDB); - executeUpdate(useDB); - executeUpdate(createTable); - - let binds = new taos.TaosBind(15); - binds.bindTimestamp(1642435200000); - binds.bindNil(); - binds.bindBool(true); - binds.bindTinyInt(127); - binds.bindSmallInt(32767); - binds.bindInt(1234555); - binds.bindBigInt(-164243520000011111n); - binds.bindFloat(214.02); - binds.bindDouble(2.01); - binds.bindBinary('taosdata涛思数据'); - binds.bindNchar('TDengine数据'); - binds.bindUTinyInt(254); - binds.bindUSmallInt(65534); - binds.bindUInt(4294967294); - binds.bindUBigInt(164243520000011111n); - - cursor.stmtInit(); - cursor.stmtPrepare(insertSql); - cursor.stmtSetTbname(table); - cursor.bindParam(binds.getBind()); - cursor.addBatch(); - cursor.stmtExecute(); - cursor.stmtClose(); - - executeQuery(querySql); - executeUpdate(dropDB); -} - -stmtBindParamSample(); -setTimeout(()=>{ - conn.close(); -},2000); \ No newline at end of file diff --git a/src/connector/nodejs/examples/testJsonTag.js b/src/connector/nodejs/examples/testJsonTag.js deleted file mode 100644 index a922afb8e6b6614b208a6ba7cd82a8d00f983282..0000000000000000000000000000000000000000 --- a/src/connector/nodejs/examples/testJsonTag.js +++ /dev/null @@ -1,280 +0,0 @@ -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(); - -function executeUpdate(sql) { - console.log(sql); - c1.execute(sql); -} -function executeQuery(sql, flag = "all") { - console.log(sql); - c1.execute(sql) - var data = c1.fetchall(); - if (flag == "metadata" || flag == "all") { - // Latest query's Field metadata is stored in cursor.fields - console.log(c1.fields); - } 2 - if (flag == "data" || flag == "all") { - // Latest query's result data is stored in cursor.data, also returned by fetchall. - console.log(c1.data); - } - console.log(""); -} - -function prettyQuery(sql) { - try { - c1.query(sql).execute().then(function (result) { - result.pretty(); - }); - } - catch (err) { - conn.close(); - throw err; - } -} - -function executeError(sql) { - console.log(sql); - try { - c1.execute(sql) - } catch (e) { - console.log(e.message); - console.log(""); - } -} - -executeUpdate("create database if not exists nodedb keep 36500;"); -executeUpdate("use nodedb;"); -console.log("# STEP 1 prepare data & validate json string"); -executeUpdate("create table if not exists jsons1(ts timestamp, dataInt int, dataBool bool, dataStr nchar(50), dataStrBin binary(150)) tags(jtag json);"); -executeUpdate("insert into jsons1_1 using jsons1 tags('{\"tag1\":\"fff\",\"tag2\":5, \"tag3\":true}') values(1591060618000, 1, false, 'json1', '涛思数据') (1591060608000, 23, true, '涛思数据', 'json')"); -executeUpdate("insert into jsons1_2 using jsons1 tags('{\"tag1\":5,\"tag2\":\"beijing\"}') values (1591060628000, 2, true, 'json2', 'sss')"); -executeUpdate("insert into jsons1_3 using jsons1 tags('{\"tag1\":false,\"tag2\":\"beijing\"}') values (1591060668000, 3, false, 'json3', 'efwe')"); -executeUpdate("insert into jsons1_4 using jsons1 tags('{\"tag1\":null,\"tag2\":\"shanghai\",\"tag3\":\"hello\"}') values (1591060728000, 4, true, 'json4', '323sd')"); -executeUpdate("insert into jsons1_5 using jsons1 tags('{\"tag1\":1.232, \"tag2\":null}') values(1591060928000, 1, false, '涛思数据', 'ewe')"); -executeUpdate("insert into jsons1_6 using jsons1 tags('{\"tag1\":11,\"tag2\":\"\",\"tag2\":null}') values(1591061628000, 11, false, '涛思数据','')"); -executeUpdate("insert into jsons1_7 using jsons1 tags('{\"tag1\":\"涛思数据\",\"tag2\":\"\",\"tag3\":null}') values(1591062628000, 2, NULL, '涛思数据', 'dws')"); - -console.log("## test duplicate key using the first one. elimate empty key"); -executeUpdate("CREATE TABLE if not exists jsons1_8 using jsons1 tags('{\"tag1\":null, \"tag1\":true, \"tag1\":45, \"1tag$\":2, \" \":90}')"); - -console.log("## test empty json string, save as jtag is NULL"); -executeUpdate("insert into jsons1_9 using jsons1 tags('\t') values (1591062328000, 24, NULL, '涛思数据', '2sdw')"); -executeUpdate("CREATE TABLE if not exists jsons1_10 using jsons1 tags('')"); -executeUpdate("CREATE TABLE if not exists jsons1_11 using jsons1 tags(' ')"); -executeUpdate("CREATE TABLE if not exists jsons1_12 using jsons1 tags('{}')"); -executeUpdate("CREATE TABLE if not exists jsons1_13 using jsons1 tags('null')"); - -console.log("## test invalidate json"); -executeError("CREATE TABLE if not exists jsons1_14 using jsons1 tags('\"efwewf\"')"); -executeError("CREATE TABLE if not exists jsons1_14 using jsons1 tags('3333')"); -executeError("CREATE TABLE if not exists jsons1_14 using jsons1 tags('33.33')"); -executeError("CREATE TABLE if not exists jsons1_14 using jsons1 tags('false')"); -executeError("CREATE TABLE if not exists jsons1_14 using jsons1 tags('[1,true]')"); -executeError("CREATE TABLE if not exists jsons1_14 using jsons1 tags('{222}')"); -executeError("CREATE TABLE if not exists jsons1_14 using jsons1 tags('{\"fe\"}')"); -executeQuery("select * from jsons1;", "data"); - -console.log("## test invalidate json key, key must can be printed assic char="); -executeError("CREATE TABLE if not exists jsons1_14 using jsons1 tags('{\"tag1\":[1,true]}')"); -executeError("CREATE TABLE if not exists jsons1_14 using jsons1 tags('{\"tag1\":{}}')"); -executeError("CREATE TABLE if not exists jsons1_14 using jsons1 tags('{\"。loc\":\"fff\"}')"); -executeError("CREATE TABLE if not exists jsons1_14 using jsons1 tags('{\"\":\"fff\"}')"); -executeError("CREATE TABLE if not exists jsons1_14 using jsons1 tags('{\"\t\":\"fff\"}')"); -executeError("CREATE TABLE if not exists jsons1_14 using jsons1 tags('{\"涛思数据\":\"fff\"}')"); - -console.log("# STEP 2 alter table json tag"); -executeError("ALTER STABLE jsons1 add tag tag2 nchar(20)"); -executeError("ALTER STABLE jsons1 drop tag jtag"); -executeError("ALTER TABLE jsons1_1 SET TAG jtag=4"); -executeUpdate("ALTER TABLE jsons1_1 SET TAG jtag='{\"tag1\":\"femail\",\"tag2\":35,\"tag3\":true}'") - -console.log("# STEP 3 query table"); -console.log("## test error syntax"); -executeError("select * from jsons1 where jtag->tag1='beijing'"); -executeError("select * from jsons1 where jtag->'location'"); -executeError("select * from jsons1 where jtag->''"); -executeError("select * from jsons1 where jtag->''=9"); -executeError("select -> from jsons1"); -executeError("select * from jsons1 where contains"); -executeError("select * from jsons1 where jtag->"); -executeError("select jtag->location from jsons1"); -executeError("select jtag contains location from jsons1"); -executeError("select * from jsons1 where jtag contains location"); -executeError("select * from jsons1 where jtag contains''"); -executeError("select * from jsons1 where jtag contains 'location'='beijing'"); - -console.log("## test select normal column"); -executeQuery("select dataint from jsons1"); - -console.log("## test select json tag"); -executeQuery("select * from jsons1", "data") -executeQuery("select jtag from jsons1", "data"); -executeQuery("select jtag from jsons1 where jtag is null", "data"); -executeQuery("select jtag from jsons1 where jtag is not null", "data"); -executeQuery("select jtag from jsons1_8", "data"); -executeQuery("select jtag from jsons1_1", "data"); - -console.log("## test jtag is NULL"); -executeQuery("select jtag from jsons1_9", "data"); - -console.log("## test select json tag->'key', value is string"); -executeQuery("select jtag->'tag1' from jsons1_1", "data"); -executeQuery("select jtag->'tag2' from jsons1_6", "data"); - -console.log("### test select json tag->'key', value is int"); -executeQuery("select jtag->'tag2' from jsons1_1", "data"); - -console.log("### test select json tag->'key', value is bool"); -executeQuery("select jtag->'tag3' from jsons1_1", "data"); - -console.log("### test select json tag->'key', value is null"); -executeQuery("select jtag->'tag1' from jsons1_4", "data"); - -console.log("### test select json tag->'key', value is double"); -executeQuery("select jtag->'tag1' from jsons1_5", "data"); - -console.log("### test select json tag->'key', key is not exist"); -executeQuery("select jtag->'tag10' from jsons1_4", "data"); -executeQuery("select jtag->'tag1' from jsons1", "data"); - -console.log("### test header name"); -executeQuery("select jtag->'tag1' from jsons1", "metadata"); - -console.log("## test where with json tag"); -executeError("select * from jsons1_1 where jtag is not null"); -executeError("select * from jsons1 where jtag='{\"tag1\":11,\"tag2\":\"\"}'"); -executeError("select * from jsons1 where jtag->'tag1'={}"); - -console.log("### where json value is string"); -executeQuery("select * from jsons1 where jtag->'tag2'='beijing'", "data"); -executeQuery("select dataint,tbname,jtag->'tag1',jtag from jsons1 where jtag->'tag2'='beijing'"); -executeQuery("select * from jsons1 where jtag->'tag1'='beijing'", "data"); -executeQuery("select * from jsons1 where jtag->'tag1'='涛思数据'", "data"); -executeQuery("select * from jsons1 where jtag->'tag2'>'beijing'", "data"); -executeQuery("select * from jsons1 where jtag->'tag2'>='beijing'", "data"); -executeQuery("select * from jsons1 where jtag->'tag2'<'beijing'", "data"); -executeQuery("select * from jsons1 where jtag->'tag2'<='beijing'", "data"); -executeQuery("select * from jsons1 where jtag->'tag2'!='beijing'", "data"); -executeQuery("select * from jsons1 where jtag->'tag2'=''", "data"); - -console.log("### where json value is int"); -executeQuery("select * from jsons1 where jtag->'tag1'=5", "data"); -executeQuery("select * from jsons1 where jtag->'tag1'=10", "data"); -executeQuery("select * from jsons1 where jtag->'tag1'<54", "data"); -executeQuery("select * from jsons1 where jtag->'tag1'<=11", "data"); -executeQuery("select * from jsons1 where jtag->'tag1'>4", "data"); -executeQuery("select * from jsons1 where jtag->'tag1'>=5", "data"); -executeQuery("select * from jsons1 where jtag->'tag1'!=5", "data"); -executeQuery("select * from jsons1 where jtag->'tag1'!=55", "data"); - -console.log("### where json value is double"); -executeQuery("select * from jsons1 where jtag->'tag1'=1.232", "data"); -executeQuery("select * from jsons1 where jtag->'tag1'<1.232", "data"); -executeQuery("select * from jsons1 where jtag->'tag1'<=1.232", "data"); -executeQuery("select * from jsons1 where jtag->'tag1'>1.23", "data"); -executeQuery("select * from jsons1 where jtag->'tag1'>=1.232", "data"); -executeQuery("select * from jsons1 where jtag->'tag1'!=1.232", "data"); -executeQuery("select * from jsons1 where jtag->'tag1'!=3.232", "data"); -executeError("select * from jsons1 where jtag->'tag1'/0=3", "data"); -executeError("select * from jsons1 where jtag->'tag1'/5=1", "data"); - -console.log("### where json value is bool"); -executeQuery("select * from jsons1 where jtag->'tag1'=true", "data"); -executeQuery("select * from jsons1 where jtag->'tag1'=false", "data"); -executeQuery("select * from jsons1 where jtag->'tag1'!=false", "data"); -executeError("select * from jsons1 where jtag->'tag1'>false"); - -console.log("### where json value is null"); -executeQuery("select * from jsons1 where jtag->'tag1'=null"); //only json suport =null. This synatx will change later. - -console.log("### where json is null"); -executeQuery("select * from jsons1 where jtag is null", "data"); -executeQuery("select * from jsons1 where jtag is not null", "data"); - -console.log("### where json key is null"); -executeQuery("select * from jsons1 where jtag->'tag_no_exist'=3", "data") - -console.log("### where json value is not exist"); -executeQuery("select * from jsons1 where jtag->'tag1' is null", "data"); -executeQuery("select * from jsons1 where jtag->'tag4' is null", "data"); -executeQuery("select * from jsons1 where jtag->'tag3' is not null", "data") - -console.log("### test contains"); -executeQuery("select * from jsons1 where jtag contains 'tag1'", "data") -executeQuery("select * from jsons1 where jtag contains 'tag3'", "data") -executeQuery("select * from jsons1 where jtag contains 'tag_no_exist'", "data") - -console.log("### test json tag in where condition with and/or"); -executeQuery("select * from jsons1 where jtag->'tag1'=false and jtag->'tag2'='beijing'", "data"); -executeQuery("select * from jsons1 where jtag->'tag1'=false or jtag->'tag2'='beijing'", "data"); -executeQuery("select * from jsons1 where jtag->'tag1'=false and jtag->'tag2'='shanghai'", "data"); -executeQuery("select * from jsons1 where jtag->'tag1'=false and jtag->'tag2'='shanghai'", "data"); -executeQuery("select * from jsons1 where jtag->'tag1'=13 or jtag->'tag2'>35", "data"); -executeQuery("select * from jsons1 where jtag->'tag1'=13 or jtag->'tag2'>35", "data"); -executeQuery("select * from jsons1 where jtag->'tag1' is not null and jtag contains 'tag3'", "data"); -executeQuery("select * from jsons1 where jtag->'tag1'='femail' and jtag contains 'tag3'", "data"); - -console.log("### test with tbname/normal column"); -executeQuery("select * from jsons1 where tbname = 'jsons1_1'", "data") -executeQuery("select * from jsons1 where tbname = 'jsons1_1' and jtag contains 'tag3'", "data") -executeQuery("select * from jsons1 where tbname = 'jsons1_1' and jtag contains 'tag3' and dataint=3", "data") -executeQuery("select * from jsons1 where tbname = 'jsons1_1' and jtag contains 'tag3' and dataint=23", "data") - -console.log("### test where condition like"); -executeQuery("select *,tbname from jsons1 where jtag->'tag2' like 'bei%'", "data"); -executeQuery("select *,tbname from jsons1 where jtag->'tag1' like 'fe%' and jtag->'tag2' is not null", "data"); - -console.log("### test where condition in no support in"); -executeError("select * from jsons1 where jtag->'tag1' in ('beijing')"); - -console.log("### test where condition match"); -executeQuery("select * from jsons1 where jtag->'tag1' match 'ma'", "data"); -executeQuery("select * from jsons1 where jtag->'tag1' match 'ma$'", "data"); -executeQuery("select * from jsons1 where jtag->'tag2' match 'jing$'", "data"); -executeQuery("select * from jsons1 where jtag->'tag1' match '收到'", "data"); - -console.log("### test distinct"); -executeUpdate("insert into jsons1_14 using jsons1 tags('{\"tag1\":\"涛思数据\",\"tag2\":\"\",\"tag3\":null}') values(1591062628000, 2, NULL, '涛思数据', 'dws')", "data"); -executeQuery("select distinct jtag->'tag1' from jsons1", "data"); -executeQuery("select distinct jtag from jsons1", "data"); - -console.log("### test dumplicate key with normal colomn"); -executeUpdate("INSERT INTO jsons1_15 using jsons1 tags('{\"tbname\":\"tt\",\"databool\":true,\"datastr\":\"涛思数据\"}') values(1591060828000, 4, false, 'jjsf', \"涛思数据\")"); -executeQuery("select *,tbname,jtag from jsons1 where jtag->'datastr' match '涛思' and datastr match 'js'", "data"); -executeQuery("select tbname,jtag->'tbname' from jsons1 where jtag->'tbname'='tt' and tbname='jsons1_14'", "data"); - -console.log("## test join"); -executeUpdate("create table if not exists jsons2(ts timestamp, dataInt int, dataBool bool, dataStr nchar(50), dataStrBin binary(150)) tags(jtag json)") -executeUpdate("insert into jsons2_1 using jsons2 tags('{\"tag1\":\"fff\",\"tag2\":5, \"tag3\":true}') values(1591060618000, 2, false, 'json2', '你是2')") -executeUpdate("insert into jsons2_2 using jsons2 tags('{\"tag1\":5,\"tag2\":null}') values (1591060628000, 2, true, 'json2', 'sss')") -executeUpdate("create table if not exists jsons3(ts timestamp, dataInt int, dataBool bool, dataStr nchar(50), dataStrBin binary(150)) tags(jtag json)") -executeUpdate("insert into jsons3_1 using jsons3 tags('{\"tag1\":\"fff\",\"tag2\":5, \"tag3\":true}') values(1591060618000, 3, false, 'json3', '你是3')") -executeUpdate("insert into jsons3_2 using jsons3 tags('{\"tag1\":5,\"tag2\":\"beijing\"}') values (1591060638000, 2, true, 'json3', 'sss')") - -executeQuery("select 'sss',33,a.jtag->'tag3' from jsons2 a,jsons3 b where a.ts=b.ts and a.jtag->'tag1'=b.jtag->'tag1'", "data"); -executeQuery("select 'sss',33,a.jtag->'tag3' from jsons2 a,jsons3 b where a.ts=b.ts and a.jtag->'tag1'=b.jtag->'tag1'", "metadata"); - -console.log("## test group by & order by json tag"); - -executeQuery("select count(*) from jsons1 group by jtag->'tag1' order by jtag->'tag1' desc", "data"); -executeQuery("select count(*) from jsons1 group by jtag->'tag1' order by jtag->'tag1' asc", "data"); - -console.log("## test stddev with group by json tag"); -executeQuery("select stddev(dataint) from jsons1 group by jtag->'tag1'", "data"); -executeQuery("select stddev(dataint) from jsons1 group by jsons1.jtag->'tag1'", "metadata"); - -console.log("## test top/bottom with group by json tag"); -executeQuery("select top(dataint,100) from jsons1 group by jtag->'tag1'", "metadata"); - -console.log("## subquery with json tag"); -executeQuery("select * from (select jtag, dataint from jsons1)", "metadata"); -executeQuery("select jtag->'tag1' from (select jtag->'tag1', dataint from jsons1)", "metadata"); -executeQuery("select jtag->'tag1' from (select jtag->'tag1', dataint from jsons1)", "metada"); -executeQuery("select ts,tbname,jtag->'tag1' from (select jtag->'tag1',tbname,ts from jsons1 order by ts)", "data") - - -executeUpdate("drop database nodedb;"); - - -setTimeout(() => conn.close(), 2000); diff --git a/src/connector/nodejs/examples/testMicroseconds.js b/src/connector/nodejs/examples/testMicroseconds.js deleted file mode 100644 index cc65b3d919f92b3b4d7e0e216c6c8ac64a294d7f..0000000000000000000000000000000000000000 --- a/src/connector/nodejs/examples/testMicroseconds.js +++ /dev/null @@ -1,49 +0,0 @@ -const taos = require('../tdengine'); -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) + "\""; -} -function R(l, r) { - return Math.random() * (r - l) - r; -} -function randomBool() { - if (Math.random() < 0.5) { - return true; - } - return false; -} - -// Initialize -//c1.execute('drop database td_connector_test;'); -const dbname = 'nodejs_test_us'; -c1.execute('create database if not exists ' + dbname + ' precision "us"'); -c1.execute('use ' + dbname) -c1.execute('create table if not exists tstest (ts timestamp, _int int);'); -c1.execute('insert into tstest values(1625801548423914, 0)'); -// Select -console.log('select * from tstest'); -c1.execute('select * from tstest'); - -var d = c1.fetchall(); -console.log(c1.fields); -let ts = d[0][0]; -console.log(ts); - -if (ts.taosTimestamp() != 1625801548423914) { - throw "microseconds not match!"; -} -if (ts.getMicroseconds() % 1000 !== 914) { - throw "micronsecond precision error"; -} -setTimeout(function () { - c1.query('drop database nodejs_us_test;'); -}, 200); - -setTimeout(function () { - conn.close(); -}, 2000); diff --git a/src/connector/nodejs/examples/testNanoseconds.js b/src/connector/nodejs/examples/testNanoseconds.js deleted file mode 100644 index c3089aab3eaa4621b36297a70f2698dd08ed5988..0000000000000000000000000000000000000000 --- a/src/connector/nodejs/examples/testNanoseconds.js +++ /dev/null @@ -1,48 +0,0 @@ -const taos = require('../tdengine'); -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) + "\""; -} -function R(l, r) { - return Math.random() * (r - l) - r; -} -function randomBool() { - if (Math.random() < 0.5) { - return true; - } - return false; -} - -// Initialize -//c1.execute('drop database td_connector_test;'); -const dbname = 'nodejs_test_ns'; -c1.execute('create database if not exists ' + dbname + ' precision "ns"'); -c1.execute('use ' + dbname) -c1.execute('create table if not exists tstest (ts timestamp, _int int);'); -c1.execute('insert into tstest values(1625801548423914405, 0)'); -// Select -console.log('select * from tstest'); -c1.execute('select * from tstest'); - -var d = c1.fetchall(); -console.log(c1.fields); -let ts = d[0][0]; -console.log(ts); - -if (ts.taosTimestamp() != 1625801548423914405) { - throw "nanosecond not match!"; -} -if (ts.getNanoseconds() % 1000000 !== 914405) { - throw "nanosecond precision error"; -} -setTimeout(function () { - c1.query('drop database nodejs_ns_test;'); -}, 200); - -setTimeout(function () { - conn.close(); -}, 2000); diff --git a/src/connector/nodejs/examples/testSchemalessInsert.js b/src/connector/nodejs/examples/testSchemalessInsert.js deleted file mode 100644 index 16998425ecda4226e56e5c2a9e49e83ba34bc34a..0000000000000000000000000000000000000000 --- a/src/connector/nodejs/examples/testSchemalessInsert.js +++ /dev/null @@ -1,84 +0,0 @@ -const _ = require('lodash'); -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("drop database if exists nodedb;"); -executeUpdate("create database if not exists nodedb ;"); -executeUpdate("use nodedb;"); - -let tbname1 = "line_protocol_arr"; -let tbname2 = "json_protocol_arr"; -let tbname3 = "json_protocol_str"; -let tbname4 = "line_protocol_str"; - - -let line1 = [tbname1 + ",t1=3i64,t2=4f64,t3=\"t3\" c1=3i64,c3=L\"passit\",c2=false,c4=4f64 1626006833639000000", -tbname1 + ",t1=4i64,t3=\"t4\",t2=5f64,t4=5f64 c1=3i64,c3=L\"passitagin\",c2=true,c4=5f64,c5=5f64 1626006833641000000" -]; -let line2 = ["{" - + "\"metric\": \"" + tbname2 + "\"," - + "\"timestamp\": 1626006833," - + "\"value\": 10," - + "\"tags\": {" - + " \"t1\": true," - + "\"t2\": false," - + "\"t3\": 10," - + "\"t4\": \"123_abc_.!@#$%^&*:;,./?|+-=()[]{}<>\"" - + "}" - + "}" -]; - -let line3 = "{" - + "\"metric\": \"" + tbname3 + "\"," - + "\"timestamp\": 1626006833000," - + "\"value\": 10," - + "\"tags\": {" - + " \"t1\": true," - + "\"t2\": false," - + "\"t3\": 10," - + "\"t4\": \"123_abc_.!@#$%^&*:;,./?|+-=()[]{}<>\"" - + "}" - + "}"; - -let line4 = tbname4 + ",t1=3i64,t2=4f64,t3=\"t3\" c1=3i64,c3=L\"passit\",c2=false,c4=4f64 1626006833639"; - - -try { - - c1.schemalessInsert(line1, taos.SCHEMALESS_PROTOCOL.TSDB_SML_LINE_PROTOCOL, taos.SCHEMALESS_PRECISION.TSDB_SML_TIMESTAMP_NANO_SECONDS); - testSchemaless(tbname1, line1.length); - - c1.schemalessInsert(line2, taos.SCHEMALESS_PROTOCOL.TSDB_SML_JSON_PROTOCOL, taos.SCHEMALESS_PRECISION.TSDB_SML_TIMESTAMP_SECONDS); - testSchemaless(tbname2, line2.length); - - c1.schemalessInsert(line3, taos.SCHEMALESS_PROTOCOL.TSDB_SML_JSON_PROTOCOL, taos.SCHEMALESS_PRECISION.TSDB_SML_TIMESTAMP_MILLI_SECONDS); - testSchemaless(tbname3, 1); - - c1.schemalessInsert(line4, taos.SCHEMALESS_PROTOCOL.TSDB_SML_LINE_PROTOCOL, taos.SCHEMALESS_PRECISION.TSDB_SML_TIMESTAMP_MILLI_SECONDS); - testSchemaless(tbname4, 1); - -} catch (err) { - console.log(err) -} -function executeUpdate(sql) { - console.log(sql); - c1.execute(sql); -} - -function testSchemaless(tbname, numLines) { - let sql = "select count(*) from " + tbname + ";"; - executeUpdate(sql); - let affectRows = _.first(c1.fetchall()); - if (affectRows != numLines) { - console.log(1); - console.log(line2); - throw "protocol " + tbname + " schemaless insert success,but can't select as expect." - } - else { - console.log("protocol " + tbname + " schemaless insert success, can select as expect.") - } - console.log("===================") -} - -setTimeout(() => conn.close(), 2000); diff --git a/src/connector/nodejs/examples/testSubscribe.js b/src/connector/nodejs/examples/testSubscribe.js deleted file mode 100644 index 30fb3f425683f0113873534f2b67255db811edcc..0000000000000000000000000000000000000000 --- a/src/connector/nodejs/examples/testSubscribe.js +++ /dev/null @@ -1,16 +0,0 @@ -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(); -let stime = new Date(); -let interval = 1000; -c1.execute('use td_connector_test'); -let sub = c1.subscribe({ - restart: true, - sql: "select AVG(_int) from td_connector_test.all_Types;", - topic: 'all_Types', - interval: 1000 -}); - -c1.consumeData(sub, (data, fields) => { - console.log(data); -}); \ No newline at end of file diff --git a/src/connector/nodejs/examples/testUnsignedType.js b/src/connector/nodejs/examples/testUnsignedType.js deleted file mode 100644 index 3f0b0c20459959fe7ea863757220ea77fe377694..0000000000000000000000000000000000000000 --- a/src/connector/nodejs/examples/testUnsignedType.js +++ /dev/null @@ -1,40 +0,0 @@ -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(); -function executeUpdate(sql) { - console.log(sql); - c1.execute(sql); -} -function executeQuery(sql) { - c1.execute(sql) - var data = c1.fetchall(); - // Latest query's Field metadata is stored in cursor.fields - console.log(c1.fields); - // Latest query's result data is stored in cursor.data, also returned by fetchall. - console.log(c1.data); -} - -function prettyQuery(sql){ - try { - c1.query(sql).execute().then(function(result){ - result.pretty(); - }); - } - catch (err) { - conn.close(); - throw err; - } -} - -executeUpdate("create database 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("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;"); -prettyQuery("select * from unsigntest;"); -executeUpdate("drop database nodedb;"); - - -setTimeout(()=>conn.close(),2000); - diff --git a/src/connector/nodejs/examples/testnchar.js b/src/connector/nodejs/examples/testnchar.js deleted file mode 100644 index 68fad89c22894ec358d55e9c03746fbd86ce0c99..0000000000000000000000000000000000000000 --- a/src/connector/nodejs/examples/testnchar.js +++ /dev/null @@ -1,33 +0,0 @@ -const taos = require('../tdengine'); -var conn = taos.connect({ host: "localhost" }); -var c1 = conn.cursor(); - - -function checkData(data, row, col, expect) { - let checkdata = data[row][col]; - if (checkdata == expect) { - // console.log('check pass') - } - else { - console.log('check failed, expect ' + expect + ', but is ' + checkdata) - } -} - -c1.execute('drop database if exists testnodejsnchar') -c1.execute('create database testnodejsnchar') -c1.execute('use testnodejsnchar'); -c1.execute('create table tb (ts timestamp, value float, text binary(200))') -c1.execute("insert into tb values('2021-06-10 00:00:00', 24.7, '中文10000000000000000000000');") - -c1.execute('insert into tb values(1623254400150, 24.7, NULL);') -c1.execute('import into tb values(1623254400300, 24.7, "中文3中文10000000000000000000000中文10000000000000000000000中文10000000000000000000000中文10000000000000000000000");') -sql = 'select * from tb;' - -console.log('*******************************************') - -c1.execute(sql); -data = c1.fetchall(); -console.log(data) -//check data about insert data -checkData(data, 0, 2, '中文10000000000000000000000') -checkData(data, 1, 2, null) -checkData(data, 2, 2, '中文3中文10000000000000000000000中文10000000000000000000000中文10000000000000000000000中文10000000000000000000000') \ No newline at end of file diff --git a/src/connector/nodejs/examples/tset.js b/src/connector/nodejs/examples/tset.js deleted file mode 100644 index 06adf912a57bfa369b9567d0b5b3a1c8fb105ce8..0000000000000000000000000000000000000000 --- a/src/connector/nodejs/examples/tset.js +++ /dev/null @@ -1,170 +0,0 @@ -const taos = require('../tdengine'); -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) + "\""; -} -function R(l,r) { - return Math.random() * (r - l) - r; -} -function randomBool() { - if (Math.random() < 0.5) { - return true; - } - return false; -} - -// Initialize -//c1.execute('drop database td_connector_test;'); -c1.execute('create database if not exists td_connector_test;'); -c1.execute('use td_connector_test;') -c1.execute('create table if not exists all_types (ts timestamp, _int int, _bigint bigint, _float float, _double double, _binary binary(40), _smallint smallint, _tinyint tinyint, _bool bool, _nchar nchar(40));'); -c1.execute('create table if not exists stabletest (ts timestamp, v1 int, v2 int, v3 int, v4 double) tags (id int, location binary(20));') - -// Shell Test : The following uses the cursor to imitate the taos shell - -// Insert -for (let i = 0; i < 10000; i++) { - let insertData = ["now+" + i + "s", // Timestamp - parseInt( R(-Math.pow(2,31) + 1 , Math.pow(2,31) - 1) ), // Int - parseInt( R(-Math.pow(2,31) + 1 , Math.pow(2,31) - 1) ), // BigInt - parseFloat( R(-3.4E38, 3.4E38) ), // Float - parseFloat( R(-1.7E30, 1.7E30) ), // Double - "\"Long Binary\"", // Binary - parseInt( R(-32767, 32767) ), // Small Int - parseInt( R(-127, 127) ), // Tiny Int - randomBool(), - "\"Nchars\""]; // Bool - c1.execute('insert into td_connector_test.all_types values(' + insertData.join(',') + ' );', {quiet:true}); - if (i % 1000 == 0) { - console.log("Insert # " , i); - } -} - -// Select -console.log('select * from td_connector_test.all_types limit 3 offset 100;'); -c1.execute('select * from td_connector_test.all_types limit 2 offset 100;'); - -var d = c1.fetchall(); -console.log(c1.fields); -console.log(d); - -// Functions -console.log('select count(*), avg(_int), sum(_float), max(_bigint), min(_double) from td_connector_test.all_types;') -c1.execute('select count(*), avg(_int), sum(_float), max(_bigint), min(_double) from td_connector_test.all_types;'); -var d = c1.fetchall(); -console.log(c1.fields); -console.log(d); - -// Immediate Execution like the Shell - -c1.query('select count(*), stddev(_double), min(_tinyint) from all_types where _tinyint > 50 and _int < 0;', true).then(function(result){ - result.pretty(); -}) - -c1.query('select _tinyint, _bool from all_types where _tinyint > 50 and _int < 0 limit 50;', true).then(function(result){ - result.pretty(); -}) - -c1.query('select stddev(_double), stddev(_bigint), stddev(_float) from all_types;', true).then(function(result){ - result.pretty(); -}) -c1.query('select stddev(_double), stddev(_bigint), stddev(_float) from all_types interval(1m) limit 100;', true).then(function(result){ - result.pretty(); -}) - -// Binding arguments, and then using promise -var q = c1.query('select _nchar from td_connector_test.all_types where ts >= ? and _int > ? limit 100 offset 40;').bind(new Date(1231), 100) -console.log(q.query); -q.execute().then(function(r) { - r.pretty(); -}); - - -// test query null value -c1.execute("create table if not exists td_connector_test.weather(ts timestamp, temperature float, humidity int) tags(location nchar(64))"); -c1.execute("insert into t1 using weather tags('北京') values(now, 11.11, 11)"); -c1.execute("insert into t1(ts, temperature) values(now, 22.22)"); -c1.execute("insert into t1(ts, humidity) values(now, 33)"); -c1.query('select * from td_connector_test.t1', true).then(function (result) { - result.pretty(); -}); - -var q = c1.query('select * from td_connector_test.weather'); -console.log(q.query); -q.execute().then(function(r) { - r.pretty(); -}); - -function sleep(sleepTime) { - for(var start = +new Date; +new Date - start <= sleepTime; ) { } -} - -sleep(10000); - -// Raw Async Testing (Callbacks, not promises) -function cb2(param, result, rowCount, rd) { - console.log('CB2 Callbacked!'); - console.log("RES *", result); - console.log("Async fetched", rowCount, " rows"); - console.log("Passed Param: ", param); - console.log("Fields ", rd.fields); - console.log("Data ", rd.data); -} -function cb1(param,result,code) { - console.log('CB1 Callbacked!'); - console.log("RES * ", result); - console.log("Status: ", code); - console.log("Passed Param ", param); - c1.fetchall_a(result, cb2, param); -} - -c1.execute_a("describe td_connector_test.all_types;", cb1, {myparam:3.141}); - -function cb4(param, result, rowCount, rd) { - console.log('CB4 Callbacked!'); - console.log("RES *", result); - console.log("Async fetched", rowCount, "rows"); - console.log("Passed Param: ", param); - console.log("Fields", rd.fields); - console.log("Data", rd.data); -} -// Without directly calling fetchall_a -var thisRes; -function cb3(param,result,code) { - console.log('CB3 Callbacked!'); - console.log("RES *", result); - console.log("Status:", code); - console.log("Passed Param", param); - thisRes = result; -} -//Test calling execute and fetchall seperately and not through callbacks -var param = c1.execute_a("describe td_connector_test.all_types;", cb3, {e:2.718}); -console.log("Passed Param outside of callback: ", param); -console.log(param); -setTimeout(function(){ - c1.fetchall_a(thisRes, cb4, param); -},100); - - -// Async through promises -var aq = c1.query('select count(*) from td_connector_test.all_types;',false); -aq.execute_a().then(function(data) { - data.pretty(); -}); - -c1.query('describe td_connector_test.stabletest').execute_a().then(function(r){ - r.pretty() -}); - -setTimeout(function(){ - c1.query('drop database td_connector_test;'); -},200); - -setTimeout(function(){ - conn.close(); -},2000); diff --git a/src/connector/nodejs/jest.config.js b/src/connector/nodejs/jest.config.js deleted file mode 100644 index c6ea66f0f08e952a02c76383c37a1ef461d34714..0000000000000000000000000000000000000000 --- a/src/connector/nodejs/jest.config.js +++ /dev/null @@ -1,197 +0,0 @@ -/* - * For a detailed explanation regarding each configuration property, visit: - * https://jestjs.io/docs/configuration - */ - -module.exports = { - // All imported modules in your tests should be mocked automatically - // automock: false, - - // Stop running tests after `n` failures - // bail: 0, - - // The directory where Jest should store its cached dependency information - // cacheDirectory: "/tmp/jest_rt", - - // Automatically clear mock calls, instances and results before every test - // clearMocks: true, - - // Indicates whether the coverage information should be collected while executing the test - // collectCoverage: true, - - // An array of glob patterns indicating a set of files for which coverage information should be collected - // collectCoverageFrom: undefined, - - // The directory where Jest should output its coverage files - // coverageDirectory: "coverage", - - // An array of regexp pattern strings used to skip coverage collection - // coveragePathIgnorePatterns: [ - // "/node_modules/" - // ], - - // Indicates which provider should be used to instrument code for coverage - // coverageProvider: "v8", - - // A list of reporter names that Jest uses when writing coverage reports - // coverageReporters: [ - // "json", - // "text", - // "lcov", - // "clover" - // ], - - // An object that configures minimum threshold enforcement for coverage results - // coverageThreshold: undefined, - - // A path to a custom dependency extractor - // dependencyExtractor: undefined, - - // Make calling deprecated APIs throw helpful error messages - // errorOnDeprecated: false, - - // Force coverage collection from ignored files using an array of glob patterns - // forceCoverageMatch: [], - - // A path to a module which exports an async function that is triggered once before all test suites - // globalSetup: undefined, - - // A path to a module which exports an async function that is triggered once after all test suites - // globalTeardown: undefined, - - // A set of global variables that need to be available in all test environments - // globals: {}, - - // The maximum amount of workers used to run your tests. Can be specified as % or a number. E.g. maxWorkers: 10% will use 10% of your CPU amount + 1 as the maximum worker number. maxWorkers: 2 will use a maximum of 2 workers. - // maxWorkers: "50%", - - // An array of directory names to be searched recursively up from the requiring module's location - // moduleDirectories: [ - // "node_modules" - // ], - - // An array of file extensions your modules use - // moduleFileExtensions: [ - // "js", - // "jsx", - // "ts", - // "tsx", - // "json", - // "node" - // ], - - // A map from regular expressions to module names or to arrays of module names that allow to stub out resources with a single module - // moduleNameMapper: {}, - - // An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader - // modulePathIgnorePatterns: [], - - // Activates notifications for test results - // notify: false, - - // An enum that specifies notification mode. Requires { notify: true } - // notifyMode: "failure-change", - - // A preset that is used as a base for Jest's configuration - // preset: undefined, - - // Run tests from one or more projects - // projects: undefined, - - // Use this configuration option to add custom reporters to Jest - // reporters: undefined, - - // Automatically reset mock state before every test - // resetMocks: false, - - // Reset the module registry before running each individual test - // resetModules: false, - - // A path to a custom resolver - // resolver: undefined, - - // Automatically restore mock state and implementation before every test - // restoreMocks: false, - - // The root directory that Jest should scan for tests and modules within - // rootDir: undefined, - - // A list of paths to directories that Jest should use to search for files in - // roots: [ - // "" - // ], - - // Allows you to use a custom runner instead of Jest's default test runner - // runner: "jest-runner", - - // The paths to modules that run some code to configure or set up the testing environment before each test - // setupFiles: [], - - // A list of paths to modules that run some code to configure or set up the testing framework before each test - // setupFilesAfterEnv: [], - - // The number of seconds after which a test is considered as slow and reported as such in the results. - // slowTestThreshold: 5, - - // A list of paths to snapshot serializer modules Jest should use for snapshot testing - // snapshotSerializers: [], - - // The test environment that will be used for testing - // testEnvironment: "jest-environment-node", - - // Options that will be passed to the testEnvironment - // testEnvironmentOptions: {}, - - // Adds a location field to test results - // testLocationInResults: false, - - // The glob patterns Jest uses to detect test files - // testMatch: [ - // "**/__tests__/**/*.[jt]s?(x)", - // "**/?(*.)+(spec|test).[tj]s?(x)" - // ], - testMatch: [ - "**/test/cases/*.[jt]s?(x)" - ], - - // An array of regexp pattern strings that are matched against all test paths, matched tests are skipped - // testPathIgnorePatterns: [ - // "/node_modules/" - // ], - - // The regexp pattern or array of patterns that Jest uses to detect test files - // testRegex: [], - - // This option allows the use of a custom results processor - // testResultsProcessor: undefined, - - // This option allows use of a custom test runner - // testRunner: "jest-circus/runner", - - // This option sets the URL for the jsdom environment. It is reflected in properties such as location.href - // testURL: "http://localhost", - - // Setting this value to "fake" allows the use of fake timers for functions such as "setTimeout" - // timers: "real", - - // A map from regular expressions to paths to transformers - // transform: undefined, - - // An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation - // transformIgnorePatterns: [ - // "/node_modules/", - // "\\.pnp\\.[^\\/]+$" - // ], - - // An array of regexp pattern strings that are matched against all modules before the module loader will automatically return a mock for them - // unmockedModulePathPatterns: undefined, - - // Indicates whether each individual test should be reported during the run - // verbose: undefined, - - // An array of regexp patterns that are matched against all source file paths before re-running tests in watch mode - // watchPathIgnorePatterns: [], - - // Whether to use watchman for file crawling - // watchman: true, -}; diff --git a/src/connector/nodejs/nodetaos/cinterface.js b/src/connector/nodejs/nodetaos/cinterface.js deleted file mode 100644 index e04b55d9a5fd47fb6ecd50bb0ac360eefb907930..0000000000000000000000000000000000000000 --- a/src/connector/nodejs/nodetaos/cinterface.js +++ /dev/null @@ -1,913 +0,0 @@ -/** - * C Interface with TDengine Module - * @module CTaosInterface - */ - -const ref = require('ref-napi'); -const os = require('os'); -const ffi = require('ffi-napi'); -const ArrayType = require('ref-array-di')(ref); -const Struct = require('ref-struct-di')(ref); -const FieldTypes = require('./constants'); -const errors = require('./error'); -const _ = require('lodash') -const TaosObjects = require('./taosobjects'); - -module.exports = CTaosInterface; -const TAOSFIELD = { - NAME_LENGTH: 65, - TYPE_OFFSET: 65, - BYTES_OFFSET: 66, - STRUCT_SIZE: 68, -} - -function convertTimestamp(data, num_of_rows, nbytes = 0, offset = 0, precision = 0) { - data = ref.reinterpret(data.deref(), nbytes * num_of_rows, offset); - let res = []; - let currOffset = 0; - while (currOffset < data.length) { - let time = data.readInt64LE(currOffset); - currOffset += nbytes; - res.push(new TaosObjects.TaosTimestamp(time, precision)); - } - return res; -} - -function convertBool(data, num_of_rows, nbytes = 0, offset = 0, precision = 0) { - data = ref.reinterpret(data.deref(), nbytes * num_of_rows, offset); - let res = new Array(data.length); - for (let i = 0; i < data.length; i++) { - if (data[i] == 0) { - res[i] = false; - } - else if (data[i] == 1) { - res[i] = true; - } - else if (data[i] == FieldTypes.C_BOOL_NULL) { - res[i] = null; - } - } - return res; -} - -function convertTinyint(data, num_of_rows, nbytes = 0, offset = 0, precision = 0) { - data = ref.reinterpret(data.deref(), nbytes * num_of_rows, offset); - let res = []; - let currOffset = 0; - while (currOffset < data.length) { - let d = data.readIntLE(currOffset, 1); - res.push(d == FieldTypes.C_TINYINT_NULL ? null : d); - currOffset += nbytes; - } - return res; -} - -function convertTinyintUnsigned(data, num_of_rows, nbytes = 0, offset = 0, precision = 0) { - data = ref.reinterpret(data.deref(), nbytes * num_of_rows, offset); - let res = []; - let currOffset = 0; - while (currOffset < data.length) { - let d = data.readUIntLE(currOffset, 1); - res.push(d == FieldTypes.C_TINYINT_UNSIGNED_NULL ? null : d); - currOffset += nbytes; - } - return res; -} - -function convertSmallint(data, num_of_rows, nbytes = 0, offset = 0, precision = 0) { - data = ref.reinterpret(data.deref(), nbytes * num_of_rows, offset); - let res = []; - let currOffset = 0; - while (currOffset < data.length) { - let d = data.readIntLE(currOffset, 2); - res.push(d == FieldTypes.C_SMALLINT_NULL ? null : d); - currOffset += nbytes; - } - return res; -} - -function convertSmallintUnsigned(data, num_of_rows, nbytes = 0, offset = 0, precision = 0) { - data = ref.reinterpret(data.deref(), nbytes * num_of_rows, offset); - let res = []; - let currOffset = 0; - while (currOffset < data.length) { - let d = data.readUIntLE(currOffset, 2); - res.push(d == FieldTypes.C_SMALLINT_UNSIGNED_NULL ? null : d); - currOffset += nbytes; - } - return res; -} - -function convertInt(data, num_of_rows, nbytes = 0, offset = 0, precision = 0) { - data = ref.reinterpret(data.deref(), nbytes * num_of_rows, offset); - let res = []; - let currOffset = 0; - while (currOffset < data.length) { - let d = data.readInt32LE(currOffset); - res.push(d == FieldTypes.C_INT_NULL ? null : d); - currOffset += nbytes; - } - return res; -} - -function convertIntUnsigned(data, num_of_rows, nbytes = 0, offset = 0, precision = 0) { - data = ref.reinterpret(data.deref(), nbytes * num_of_rows, offset); - let res = []; - let currOffset = 0; - while (currOffset < data.length) { - let d = data.readUInt32LE(currOffset); - res.push(d == FieldTypes.C_INT_UNSIGNED_NULL ? null : d); - currOffset += nbytes; - } - return res; -} - -function convertBigint(data, num_of_rows, nbytes = 0, offset = 0, precision = 0) { - data = ref.reinterpret(data.deref(), nbytes * num_of_rows, offset); - let res = []; - let currOffset = 0; - while (currOffset < data.length) { - let d = data.readInt64LE(currOffset); - res.push(d == FieldTypes.C_BIGINT_NULL ? null : BigInt(d)); - currOffset += nbytes; - } - return res; -} - -function convertBigintUnsigned(data, num_of_rows, nbytes = 0, offset = 0, precision = 0) { - data = ref.reinterpret(data.deref(), nbytes * num_of_rows, offset); - let res = []; - let currOffset = 0; - while (currOffset < data.length) { - let d = data.readUInt64LE(currOffset); - res.push(d == FieldTypes.C_BIGINT_UNSIGNED_NULL ? null : BigInt(d)); - currOffset += nbytes; - } - return res; -} - -function convertFloat(data, num_of_rows, nbytes = 0, offset = 0, precision = 0) { - data = ref.reinterpret(data.deref(), nbytes * num_of_rows, offset); - let res = []; - let currOffset = 0; - while (currOffset < data.length) { - let d = parseFloat(data.readFloatLE(currOffset).toFixed(5)); - res.push(isNaN(d) ? null : d); - currOffset += nbytes; - } - return res; -} - -function convertDouble(data, num_of_rows, nbytes = 0, offset = 0, precision = 0) { - data = ref.reinterpret(data.deref(), nbytes * num_of_rows, offset); - let res = []; - let currOffset = 0; - while (currOffset < data.length) { - let d = parseFloat(data.readDoubleLE(currOffset).toFixed(16)); - res.push(isNaN(d) ? null : d); - currOffset += nbytes; - } - return res; -} - -function convertBinary(data, num_of_rows, nbytes = 0, offset = 0, precision = 0) { - data = ref.reinterpret(data.deref(), nbytes * num_of_rows, offset); - let res = []; - - let currOffset = 0; - while (currOffset < data.length) { - let len = data.readIntLE(currOffset, 2); - let dataEntry = data.slice(currOffset + 2, currOffset + len + 2); //one entry in a row under a column; - if (dataEntry[0] == 255) { - res.push(null) - } else { - res.push(dataEntry.toString("utf-8")); - } - currOffset += nbytes; - } - return res; -} - -function convertNchar(data, num_of_rows, nbytes = 0, offset = 0, precision = 0) { - data = ref.reinterpret(data.deref(), nbytes * num_of_rows, offset); - let res = []; - - let currOffset = 0; - while (currOffset < data.length) { - let len = data.readIntLE(currOffset, 2); - let dataEntry = data.slice(currOffset + 2, currOffset + len + 2); //one entry in a row under a column; - if (dataEntry[0] == 255 && dataEntry[1] == 255) { - res.push(null) - } else { - res.push(dataEntry.toString("utf-8")); - } - currOffset += nbytes; - } - return res; -} - -function convertJsonTag(data, num_of_rows, nbytes = 0, offset = 0, precision = 0) { - data = ref.reinterpret(data.deref(), nbytes * num_of_rows, offset); - let res = []; - - let currOffset = 0; - while (currOffset < data.length) { - let len = data.readIntLE(currOffset, 2); - let dataEntry = data.slice(currOffset + 2, currOffset + len + 2); //one entry in a row under a column; - if (dataEntry[0] == 255 && dataEntry[1] == 255) { - res.push(null) - } else { - res.push(dataEntry.toString("utf-8")); - } - currOffset += nbytes; - } - return res; -} - -// Object with all the relevant converters from pblock data to javascript readable data -let convertFunctions = { - [FieldTypes.C_BOOL]: convertBool, - [FieldTypes.C_TINYINT]: convertTinyint, - [FieldTypes.C_SMALLINT]: convertSmallint, - [FieldTypes.C_INT]: convertInt, - [FieldTypes.C_BIGINT]: convertBigint, - [FieldTypes.C_FLOAT]: convertFloat, - [FieldTypes.C_DOUBLE]: convertDouble, - [FieldTypes.C_BINARY]: convertBinary, - [FieldTypes.C_TIMESTAMP]: convertTimestamp, - [FieldTypes.C_NCHAR]: convertNchar, - [FieldTypes.C_TINYINT_UNSIGNED]: convertTinyintUnsigned, - [FieldTypes.C_SMALLINT_UNSIGNED]: convertSmallintUnsigned, - [FieldTypes.C_INT_UNSIGNED]: convertIntUnsigned, - [FieldTypes.C_BIGINT_UNSIGNED]: convertBigintUnsigned, - [FieldTypes.C_JSON_TAG]: convertJsonTag, -} - -// Define TaosField structure -var char_arr = ArrayType(ref.types.char); -var TaosField = Struct({ - 'name': char_arr, -}); -TaosField.fields.name.type.size = 65; -TaosField.defineProperty('type', ref.types.uint8); -TaosField.defineProperty('bytes', ref.types.int16); - -//define schemaless line array -var smlLine = ArrayType(ref.coerceType('char *')) - -/** - * - * @param {Object} config - Configuration options for the interface - * @return {CTaosInterface} - * @class CTaosInterface - * @classdesc The CTaosInterface is the interface through which Node.JS communicates data back and forth with TDengine. It is not advised to - * access this class directly and use it unless you understand what these functions do. - */ -function CTaosInterface(config = null, pass = false) { - ref.types.char_ptr = ref.refType(ref.types.char); - ref.types.void_ptr = ref.refType(ref.types.void); - ref.types.void_ptr2 = ref.refType(ref.types.void_ptr); - /*Declare a bunch of functions first*/ - /* Note, pointers to TAOS_RES, TAOS, are ref.types.void_ptr. The connection._conn buffer is supplied for pointers to TAOS * */ - if ('win32' == os.platform()) { - taoslibname = 'taos'; - } else { - taoslibname = 'libtaos'; - } - this.libtaos = ffi.Library(taoslibname, { - 'taos_options': [ref.types.int, [ref.types.int, ref.types.void_ptr]], - 'taos_init': [ref.types.void, []], - //TAOS *taos_connect(char *ip, char *user, char *pass, char *db, int port) - 'taos_connect': [ref.types.void_ptr, [ref.types.char_ptr, ref.types.char_ptr, ref.types.char_ptr, ref.types.char_ptr, ref.types.int]], - //void taos_close(TAOS *taos) - 'taos_close': [ref.types.void, [ref.types.void_ptr]], - //int *taos_fetch_lengths(TAOS_RES *res); - 'taos_fetch_lengths': [ref.types.void_ptr, [ref.types.void_ptr]], - //int taos_query(TAOS *taos, char *sqlstr) - 'taos_query': [ref.types.void_ptr, [ref.types.void_ptr, ref.types.char_ptr]], - //int taos_affected_rows(TAOS_RES *res) - 'taos_affected_rows': [ref.types.int, [ref.types.void_ptr]], - //int taos_fetch_block(TAOS_RES *res, TAOS_ROW *rows) - 'taos_fetch_block': [ref.types.int, [ref.types.void_ptr, ref.types.void_ptr]], - //int taos_num_fields(TAOS_RES *res); - 'taos_num_fields': [ref.types.int, [ref.types.void_ptr]], - //TAOS_ROW taos_fetch_row(TAOS_RES *res) - //TAOS_ROW is void **, but we set the return type as a reference instead to get the row - 'taos_fetch_row': [ref.refType(ref.types.void_ptr2), [ref.types.void_ptr]], - 'taos_print_row': [ref.types.int, [ref.types.char_ptr, ref.types.void_ptr, ref.types.void_ptr, ref.types.int]], - //int taos_result_precision(TAOS_RES *res) - 'taos_result_precision': [ref.types.int, [ref.types.void_ptr]], - //void taos_free_result(TAOS_RES *res) - 'taos_free_result': [ref.types.void, [ref.types.void_ptr]], - //int taos_field_count(TAOS *taos) - 'taos_field_count': [ref.types.int, [ref.types.void_ptr]], - //TAOS_FIELD *taos_fetch_fields(TAOS_RES *res) - 'taos_fetch_fields': [ref.refType(TaosField), [ref.types.void_ptr]], - //int taos_errno(TAOS *taos) - 'taos_errno': [ref.types.int, [ref.types.void_ptr]], - //char *taos_errstr(TAOS *taos) - 'taos_errstr': [ref.types.char_ptr, [ref.types.void_ptr]], - //void taos_stop_query(TAOS_RES *res); - 'taos_stop_query': [ref.types.void, [ref.types.void_ptr]], - //char *taos_get_server_info(TAOS *taos); - 'taos_get_server_info': [ref.types.char_ptr, [ref.types.void_ptr]], - //char *taos_get_client_info(); - 'taos_get_client_info': [ref.types.char_ptr, []], - - // ASYNC - // void taos_query_a(TAOS *taos, char *sqlstr, void (*fp)(void *, TAOS_RES *, int), void *param) - 'taos_query_a': [ref.types.void, [ref.types.void_ptr, ref.types.char_ptr, ref.types.void_ptr, ref.types.void_ptr]], - // void taos_fetch_rows_a(TAOS_RES *res, void (*fp)(void *param, TAOS_RES *, int numOfRows), void *param); - 'taos_fetch_rows_a': [ref.types.void, [ref.types.void_ptr, ref.types.void_ptr, ref.types.void_ptr]], - - // Subscription - //TAOS_SUB *taos_subscribe(TAOS* taos, int restart, const char* topic, const char *sql, TAOS_SUBSCRIBE_CALLBACK fp, void *param, int interval) - 'taos_subscribe': [ref.types.void_ptr, [ref.types.void_ptr, ref.types.int, ref.types.char_ptr, ref.types.char_ptr, ref.types.void_ptr, ref.types.void_ptr, ref.types.int]], - // TAOS_RES *taos_consume(TAOS_SUB *tsub) - 'taos_consume': [ref.types.void_ptr, [ref.types.void_ptr]], - //void taos_unsubscribe(TAOS_SUB *tsub); - 'taos_unsubscribe': [ref.types.void, [ref.types.void_ptr]], - - //Schemaless insert - //TAOS_RES* taos_schemaless_insert(TAOS* taos, char* lines[], int numLines, int protocol,int precision) - // 'taos_schemaless_insert': [ref.types.void_ptr, [ref.types.void_ptr, ref.types.char_ptr, ref.types.int, ref.types.int, ref.types.int]] - 'taos_schemaless_insert': [ref.types.void_ptr, [ref.types.void_ptr, smlLine, 'int', 'int', 'int']] - - //stmt APIs - // TAOS_STMT* taos_stmt_init(TAOS *taos) - , 'taos_stmt_init': [ref.types.void_ptr, [ref.types.void_ptr]] - - // int taos_stmt_prepare(TAOS_STMT *stmt, const char *sql, unsigned long length) - , 'taos_stmt_prepare': [ref.types.int, [ref.types.void_ptr, ref.types.char_ptr, ref.types.ulong]] - - // int taos_stmt_set_tbname(TAOS_STMT* stmt, const char* name) - , 'taos_stmt_set_tbname': [ref.types.int, [ref.types.void_ptr, ref.types.char_ptr]] - - // int taos_stmt_set_tbname_tags(TAOS_STMT* stmt, const char* name, TAOS_BIND* tags) - , 'taos_stmt_set_tbname_tags': [ref.types.int, [ref.types.void_ptr, ref.types.char_ptr, ref.types.void_ptr]] - - // int taos_stmt_set_sub_tbname(TAOS_STMT* stmt, const char* name) - , 'taos_stmt_set_sub_tbname': [ref.types.int, [ref.types.void_ptr, ref.types.char_ptr]] - - // int taos_stmt_bind_param(TAOS_STMT *stmt, TAOS_BIND *bind) - // , 'taos_stmt_bind_param': [ref.types.int, [ref.types.void_ptr, ref.refType(TAOS_BIND)]] - , 'taos_stmt_bind_param': [ref.types.int, [ref.types.void_ptr, ref.types.void_ptr]] - - - // int taos_stmt_bind_single_param_batch(TAOS_STMT* stmt, TAOS_MULTI_BIND* bind, int colIdx) - , 'taos_stmt_bind_single_param_batch': [ref.types.int, [ref.types.void_ptr, ref.types.void_ptr, ref.types.int]] - // int taos_stmt_bind_param_batch(TAOS_STMT* stmt, TAOS_MULTI_BIND* bind) - , 'taos_stmt_bind_param_batch': [ref.types.int, [ref.types.void_ptr, ref.types.void_ptr]] - - // int taos_stmt_add_batch(TAOS_STMT *stmt) - , 'taos_stmt_add_batch': [ref.types.int, [ref.types.void_ptr]] - - // int taos_stmt_execute(TAOS_STMT *stmt) - , 'taos_stmt_execute': [ref.types.int, [ref.types.void_ptr]] - - // TAOS_RES* taos_stmt_use_result(TAOS_STMT *stmt) - , 'taos_stmt_use_result': [ref.types.void_ptr, [ref.types.void_ptr]] - - // int taos_stmt_close(TAOS_STMT *stmt) - , 'taos_stmt_close': [ref.types.int, [ref.types.void_ptr]] - - // char * taos_stmt_errstr(TAOS_STMT *stmt) - , 'taos_stmt_errstr': [ref.types.char_ptr, [ref.types.void_ptr]] - - // int taos_load_table_info(TAOS *taos, const char* tableNameList) - , 'taos_load_table_info': [ref.types.int, [ref.types.void_ptr, ref.types.char_ptr]] - }); - - if (pass == false) { - if (config == null) { - this._config = ref.alloc(ref.types.char_ptr, ref.NULL); - } - else { - try { - this._config = ref.allocCString(config); - } - catch (err) { - throw "Attribute Error: config is expected as a str"; - } - } - if (config != null) { - this.libtaos.taos_options(3, this._config); - } - this.libtaos.taos_init(); - } - return this; -} - -CTaosInterface.prototype.config = function config() { - return this._config; -} - -CTaosInterface.prototype.connect = function connect(host = null, user = "root", password = "taosdata", db = null, port = 0) { - let _host, _user, _password, _db, _port; - try { - _host = host != null ? ref.allocCString(host) : ref.NULL; - } - catch (err) { - throw "Attribute Error: host is expected as a str"; - } - try { - _user = ref.allocCString(user) - } - catch (err) { - throw "Attribute Error: user is expected as a str"; - } - try { - _password = ref.allocCString(password); - } - catch (err) { - throw "Attribute Error: password is expected as a str"; - } - try { - _db = db != null ? ref.allocCString(db) : ref.NULL; - } - catch (err) { - throw "Attribute Error: db is expected as a str"; - } - try { - _port = ref.alloc(ref.types.int, port); - } - catch (err) { - throw TypeError("port is expected as an int") - } - let connection = this.libtaos.taos_connect(_host, _user, _password, _db, _port); - if (ref.isNull(connection)) { - throw new errors.TDError('Failed to connect to TDengine'); - } - else { - console.log('Successfully connected to TDengine'); - } - return connection; -} - -CTaosInterface.prototype.close = function close(connection) { - this.libtaos.taos_close(connection); - console.log("Connection is closed"); -} - -CTaosInterface.prototype.query = function query(connection, sql) { - return this.libtaos.taos_query(connection, ref.allocCString(sql)); -} - -CTaosInterface.prototype.affectedRows = function affectedRows(result) { - return this.libtaos.taos_affected_rows(result); -} - -CTaosInterface.prototype.useResult = function useResult(result) { - - let fields = []; - let pfields = this.fetchFields(result); - - if (ref.isNull(pfields) == false) { - pfields = ref.reinterpret(pfields, this.fieldsCount(result) * TAOSFIELD.STRUCT_SIZE, 0); - for (let i = 0; i < pfields.length; i += TAOSFIELD.STRUCT_SIZE) { - fields.push({ - name: ref.readCString(ref.reinterpret(pfields, TAOSFIELD.NAME_LENGTH, i)), - type: pfields[i + TAOSFIELD.TYPE_OFFSET], - bytes: pfields[i + TAOSFIELD.BYTES_OFFSET] + pfields[i + TAOSFIELD.BYTES_OFFSET + 1] * 256 - }) - } - } - return fields; -} - -CTaosInterface.prototype.fetchBlock = function fetchBlock(result, fields) { - let pblock = ref.NULL_POINTER; - let num_of_rows = this.libtaos.taos_fetch_block(result, pblock); - if (ref.isNull(pblock.deref()) == true) { - return { block: null, num_of_rows: 0 }; - } - - var fieldL = this.libtaos.taos_fetch_lengths(result); - let precision = this.libtaos.taos_result_precision(result); - - var fieldlens = []; - - if (ref.isNull(fieldL) == false) { - for (let i = 0; i < fields.length; i++) { - let plen = ref.reinterpret(fieldL, 4, i * 4); - let len = plen.readInt32LE(0); - fieldlens.push(len); - } - } - - let blocks = new Array(fields.length); - blocks.fill(null); - num_of_rows = Math.abs(num_of_rows); - let offset = 0; - let ptr = pblock.deref(); - - for (let i = 0; i < fields.length; i++) { - pdata = ref.reinterpret(ptr, 8, i * 8); - if (ref.isNull(pdata.readPointer())) { - blocks[i] = new Array(); - } else { - pdata = ref.ref(pdata.readPointer()); - if (!convertFunctions[fields[i]['type']]) { - throw new errors.DatabaseError("Invalid data type returned from database"); - } - blocks[i] = convertFunctions[fields[i]['type']](pdata, num_of_rows, fieldlens[i], offset, precision); - } - } - return { blocks: blocks, num_of_rows } -} - -CTaosInterface.prototype.fetchRow = function fetchRow(result, fields) { - let row = this.libtaos.taos_fetch_row(result); - return row; -} - -CTaosInterface.prototype.freeResult = function freeResult(result) { - this.libtaos.taos_free_result(result); - result = null; -} - -/** Number of fields returned in this result handle, must use with async */ -CTaosInterface.prototype.numFields = function numFields(result) { - return this.libtaos.taos_num_fields(result); -} - -// Fetch fields count by connection, the latest query -CTaosInterface.prototype.fieldsCount = function fieldsCount(result) { - return this.libtaos.taos_field_count(result); -} - -CTaosInterface.prototype.fetchFields = function fetchFields(result) { - return this.libtaos.taos_fetch_fields(result); -} - -CTaosInterface.prototype.errno = function errno(result) { - return this.libtaos.taos_errno(result); -} - -CTaosInterface.prototype.errStr = function errStr(result) { - return ref.readCString(this.libtaos.taos_errstr(result)); -} - -// Async -CTaosInterface.prototype.query_a = function query_a(connection, sql, callback, param = ref.ref(ref.NULL)) { - // void taos_query_a(TAOS *taos, char *sqlstr, void (*fp)(void *param, TAOS_RES *, int), void *param) - callback = ffi.Callback(ref.types.void, [ref.types.void_ptr, ref.types.void_ptr, ref.types.int], callback); - this.libtaos.taos_query_a(connection, ref.allocCString(sql), callback, param); - return param; -} - -/** Asynchrnously fetches the next block of rows. Wraps callback and transfers a 4th argument to the cursor, the row data as blocks in javascript form - * Note: This isn't a recursive function, in order to fetch all data either use the TDengine cursor object, TaosQuery object, or implement a recrusive - * function yourself using the libtaos.taos_fetch_rows_a function - */ -CTaosInterface.prototype.fetch_rows_a = function fetch_rows_a(result, callback, param = ref.ref(ref.NULL)) { - // void taos_fetch_rows_a(TAOS_RES *res, void (*fp)(void *param, TAOS_RES *, int numOfRows), void *param); - var cti = this; - // wrap callback with a function so interface can access the numOfRows value, needed in order to properly process the binary data - let asyncCallbackWrapper = function (param2, result2, numOfRows2) { - // Data preparation to pass to cursor. Could be bottleneck in query execution callback times. - let row = cti.libtaos.taos_fetch_row(result2); - let fields = cti.fetchFields_a(result2); - - let precision = cti.libtaos.taos_result_precision(result2); - let blocks = new Array(fields.length); - blocks.fill(null); - numOfRows2 = Math.abs(numOfRows2); - let offset = 0; - var fieldL = cti.libtaos.taos_fetch_lengths(result); - var fieldlens = []; - if (ref.isNull(fieldL) == false) { - - for (let i = 0; i < fields.length; i++) { - let plen = ref.reinterpret(fieldL, 8, i * 8); - let len = ref.get(plen, 0, ref.types.int32); - fieldlens.push(len); - } - } - if (numOfRows2 > 0) { - for (let i = 0; i < fields.length; i++) { - if (ref.isNull(pdata.readPointer())) { - blocks[i] = new Array(); - } else { - if (!convertFunctions[fields[i]['type']]) { - throw new errors.DatabaseError("Invalid data type returned from database"); - } - let prow = ref.reinterpret(row, 8, i * 8); - prow = prow.readPointer(); - prow = ref.ref(prow); - blocks[i] = convertFunctions[fields[i]['type']](prow, 1, fieldlens[i], offset, precision); - //offset += fields[i]['bytes'] * numOfRows2; - } - } - } - callback(param2, result2, numOfRows2, blocks); - } - asyncCallbackWrapper = ffi.Callback(ref.types.void, [ref.types.void_ptr, ref.types.void_ptr, ref.types.int], asyncCallbackWrapper); - this.libtaos.taos_fetch_rows_a(result, asyncCallbackWrapper, param); - return param; -} - -// Fetch field meta data by result handle -CTaosInterface.prototype.fetchFields_a = function fetchFields_a(result) { - let pfields = this.fetchFields(result); - let pfieldscount = this.numFields(result); - let fields = []; - if (ref.isNull(pfields) == false) { - pfields = ref.reinterpret(pfields, pfieldscount * TAOSFIELD.STRUCT_SIZE, 0); - for (let i = 0; i < pfields.length; i += TAOSFIELD.STRUCT_SIZE) { - fields.push({ - name: ref.readCString(ref.reinterpret(pfields, TAOSFIELD.NAME_LENGTH, i)), - type: pfields[i + TAOSFIELD.TYPE_OFFSET], - bytes: pfields[i + TAOSFIELD.BYTES_OFFSET] + pfields[i + TAOSFIELD.BYTES_OFFSET + 1] * 256 - }) - } - } - return fields; -} - -// Stop a query by result handle -CTaosInterface.prototype.stopQuery = function stopQuery(result) { - if (result != null) { - this.libtaos.taos_stop_query(result); - } - else { - throw new errors.ProgrammingError("No result handle passed to stop query"); - } -} - -CTaosInterface.prototype.getServerInfo = function getServerInfo(connection) { - return ref.readCString(this.libtaos.taos_get_server_info(connection)); -} - -CTaosInterface.prototype.getClientInfo = function getClientInfo() { - return ref.readCString(this.libtaos.taos_get_client_info()); -} - -// Subscription -CTaosInterface.prototype.subscribe = function subscribe(connection, restart, topic, sql, interval) { - let topicOrig = topic; - let sqlOrig = sql; - try { - sql = sql != null ? ref.allocCString(sql) : ref.alloc(ref.types.char_ptr, ref.NULL); - } - catch (err) { - throw "Attribute Error: sql is expected as a str"; - } - try { - topic = topic != null ? ref.allocCString(topic) : ref.alloc(ref.types.char_ptr, ref.NULL); - } - catch (err) { - throw TypeError("topic is expected as a str"); - } - - restart = ref.alloc(ref.types.int, restart); - - let subscription = this.libtaos.taos_subscribe(connection, restart, topic, sql, null, null, interval); - if (ref.isNull(subscription)) { - throw new errors.TDError('Failed to subscribe to TDengine | Database: ' + dbOrig + ', Table: ' + tableOrig); - } - else { - console.log('Successfully subscribed to TDengine - Topic: ' + topicOrig); - } - return subscription; -} - -CTaosInterface.prototype.consume = function consume(subscription) { - let result = this.libtaos.taos_consume(subscription); - let fields = []; - let pfields = this.fetchFields(result); - if (ref.isNull(pfields) == false) { - pfields = ref.reinterpret(pfields, this.numFields(result) * TAOSFIELD.STRUCT_SIZE, 0); - for (let i = 0; i < pfields.length; i += TAOSFIELD.STRUCT_SIZE) { - fields.push({ - name: ref.readCString(ref.reinterpret(pfields, TAOSFIELD.NAME_LENGTH, i)), - bytes: pfields[TAOSFIELD.TYPE_OFFSET], - type: pfields[i + TAOSFIELD.BYTES_OFFSET] + pfields[i + TAOSFIELD.BYTES_OFFSET + 1] * 256 - }) - } - } - - let data = []; - while (true) { - let { blocks, num_of_rows } = this.fetchBlock(result, fields); - if (num_of_rows == 0) { - break; - } - for (let i = 0; i < num_of_rows; i++) { - data.push([]); - let rowBlock = new Array(fields.length); - for (let j = 0; j < fields.length; j++) { - rowBlock[j] = blocks[j][i]; - } - data[data.length - 1] = (rowBlock); - } - } - return { data: data, fields: fields, result: result }; -} - -CTaosInterface.prototype.unsubscribe = function unsubscribe(subscription) { - //void taos_unsubscribe(TAOS_SUB *tsub); - this.libtaos.taos_unsubscribe(subscription); -} - -//Schemaless insert API -/** - * TAOS* taos, char* lines[], int numLines, int protocol,int precision) - * using taos_errstr get error info, taos_errno get error code. Remember - * to release taos_res, otherwise will lead memory leak. - * TAOS schemaless insert api - * @param {*} connection a valid database connection - * @param {*} lines string data, which satisfied with line protocol - * @param {*} numLines number of rows in param lines. - * @param {*} protocol Line protocol, enum type (0,1,2,3),indicate different line protocol - * @param {*} precision timestamp precision in lines, enum type (0,1,2,3,4,5,6) - * @returns TAOS_RES - * - */ -CTaosInterface.prototype.schemalessInsert = function schemalessInsert(connection, lines, protocal, precision) { - let _numLines = null; - let _lines = null; - - if (_.isString(lines)) { - _numLines = 1; - _lines = Buffer.alloc(_numLines * ref.sizeof.pointer); - ref.set(_lines, 0, ref.allocCString(lines), ref.types.char_ptr); - } - else if (_.isArray(lines)) { - _numLines = lines.length; - _lines = Buffer.alloc(_numLines * ref.sizeof.pointer); - for (let i = 0; i < _numLines; i++) { - ref.set(_lines, i * ref.sizeof.pointer, ref.allocCString(lines[i]), ref.types.char_ptr) - } - } - else { - throw new errors.InterfaceError("Unsupport lines input") - } - return this.libtaos.taos_schemaless_insert(connection, _lines, _numLines, protocal, precision); -} - -//stmt APIs - -/** - * init a TAOS_STMT object for later use.it should be freed with stmtClose. - * @param {*} connection valid taos connection - * @returns Not NULL returned for success, and NULL for failure. - * - */ -CTaosInterface.prototype.stmtInit = function stmtInit(connection) { - return this.libtaos.taos_stmt_init(connection) -} - -/** - * prepare a sql statement,'sql' should be a valid INSERT/SELECT statement, 'length' is not used. - * @param {*} stmt - * @param {string} sql a valid INSERT/SELECT statement - * @param {ulong} length not used - * @returns 0 for success, non-zero for failure. - */ -CTaosInterface.prototype.stmtPrepare = function stmtPrepare(stmt, sql, length) { - return this.libtaos.taos_stmt_prepare(stmt, ref.allocCString(sql), 0); -} - -/** - * For INSERT only. Used to bind table name as a parmeter for the input stmt object. - * @param {*} stmt could be the value returned by 'stmtInit', - * that may be a valid object or NULL. - * @param {TaosBind} tableName target table name you want to bind - * @returns 0 for success, non-zero for failure. - */ -CTaosInterface.prototype.stmtSetTbname = function stmtSetTbname(stmt, tableName) { - return this.libtaos.taos_stmt_set_tbname(stmt, ref.allocCString(tableName)); -} - -/** - * For INSERT only. - * Set a table name for binding table name as parameter and tag values for all tag parameters. - * @param {*} stmt could be the value returned by 'stmtInit', that may be a valid object or NULL. - * @param {*} tableName use to set target table name - * @param {TaosMultiBind} tags use to set tag value for target table. - * @returns - */ -CTaosInterface.prototype.stmtSetTbnameTags = function stmtSetTbnameTags(stmt, tableName, tags) { - return this.libtaos.taos_stmt_set_tbname_tags(stmt, ref.allocCString(tableName), tags); -} - -/** - * For INSERT only. - * Set a table name for binding table name as parameter. Only used for binding all tables - * in one stable, user application must call 'loadTableInfo' API to load all table - * meta before calling this API. If the table meta is not cached locally, it will return error. - * @param {*} stmt could be the value returned by 'StmtInit', that may be a valid object or NULL. - * @param {*} subTableName table name which is belong to an stable - * @returns 0 for success, non-zero for failure. - */ -CTaosInterface.prototype.stmtSetSubTbname = function stmtSetSubTbname(stmt, subTableName) { - return this.libtaos.taos_stmt_set_sub_tbname(stmt, subTableName); -} - -/** - * bind a whole line data, for both INSERT and SELECT. The parameter 'bind' points to an array - * contains the whole line data. Each item in array represents a column's value, the item - * number and sequence should keep consistence with columns in sql statement. The usage of - * structure TAOS_BIND is the same with MYSQL_BIND in MySQL. - * @param {*} stmt could be the value returned by 'stmtInit', that may be a valid object or NULL. - * @param {*} binds points to an array contains the whole line data. - * @returns 0 for success, non-zero for failure. - */ -CTaosInterface.prototype.bindParam = function bindParam(stmt, binds) { - return this.libtaos.taos_stmt_bind_param(stmt, binds); -} - -/** - * Bind a single column's data, INTERNAL used and for INSERT only. - * @param {*} stmt could be the value returned by 'stmtInit', that may be a valid object or NULL. - * @param {TaosMultiBind} mbind points to a column's data which could be the one or more lines. - * @param {*} colIndex the column's index in prepared sql statement, it starts from 0. - * @returns 0 for success, non-zero for failure. - */ -CTaosInterface.prototype.stmtBindSingleParamBatch = function stmtBindSingleParamBatch(stmt, mbind, colIndex) { - return this.libtaos.taos_stmt_bind_single_param_batch(stmt, mbind.ref(), colIndex); -} - -/** - * For INSERT only. - * Bind one or multiple lines data. - * @param {*} stmt could be the value returned by 'stmtInit', - * that may be a valid object or NULL. - * @param {*} mbinds Points to an array contains one or more lines data.The item - * number and sequence should keep consistence with columns - * n sql statement. - * @returns 0 for success, non-zero for failure. - */ -CTaosInterface.prototype.stmtBindParamBatch = function stmtBindParamBatch(stmt, mbinds) { - return this.libtaos.taos_stmt_bind_param_batch(stmt, mbinds); -} -/** - * add all current bound parameters to batch process, for INSERT only. - * Must be called after each call to bindParam/bindSingleParamBatch, - * or all columns binds for one or more lines with bindSingleParamBatch. User - * application can call any bind parameter API again to bind more data lines after calling - * to this API. - * @param {*} stmt - * @returns 0 for success, non-zero for failure. - */ -CTaosInterface.prototype.addBatch = function addBatch(stmt) { - return this.libtaos.taos_stmt_add_batch(stmt); -} -/** - * actually execute the INSERT/SELECT sql statement. User application can continue - * to bind new data after calling to this API. - * @param {*} stmt - * @returns 0 for success, non-zero for failure. - */ -CTaosInterface.prototype.stmtExecute = function stmtExecute(stmt) { - return this.libtaos.taos_stmt_execute(stmt); -} - -/** - * For SELECT only,getting the query result. - * User application should free it with API 'FreeResult' at the end. - * @param {*} stmt could be the value returned by 'stmtInit', that may be a valid object or NULL. - * @returns Not NULL for success, NULL for failure. - */ -CTaosInterface.prototype.stmtUseResult = function stmtUseResult(stmt) { - return this.libtaos.taos_stmt_use_result(stmt); -} - -/** - * user application call this API to load all tables meta info. - * This method must be called before stmtSetSubTbname(IntPtr stmt, string name); - * @param {*} taos taos connection - * @param {*} tableList tables need to load meta info are form in an array - * @returns 0 for success, non-zero for failure. - */ -CTaosInterface.prototype.loadTableInfo = function loadTableInfo(taos, tableList) { - let _tableListBuf = Buffer.alloc(ref.sizeof.pointer); - let _listStr = tableList.toString(); - - if ((_.isString(tableList) )|| (_.isArray(tableList))) { - ref.set(_tableListBuf, 0, ref.allocCString(_listStr), ref.types.char_ptr); - return this.libtaos.taos_load_table_info(taos, _tableListBuf); - } else { - throw new errors.InterfaceError("Unspport tableLis input"); - } -} - -/** - * Close STMT object and free resources. - * @param {*} stmt could be the value returned by 'stmtInit', that may be a valid object or NULL. - * @returns 0 for success, non-zero for failure. - */ -CTaosInterface.prototype.closeStmt = function closeStmt(stmt) { - return this.libtaos.taos_stmt_close(stmt); -} - -/** - * Get detail error message when got failure for any stmt API call. - * If not failure, the result returned by this API is unknown. - * @param {*} stmt Could be the value returned by 'stmtInit', that may be a valid object or NULL. - * @returns error string - */ -CTaosInterface.prototype.stmtErrStr = function stmtErrStr(stmt) { - return ref.readCString(this.libtaos.taos_stmt_errstr(stmt)); -} \ No newline at end of file diff --git a/src/connector/nodejs/nodetaos/connection.js b/src/connector/nodejs/nodetaos/connection.js deleted file mode 100644 index 08186f87053ad0ed0982ec8941f0cf38c4ad0467..0000000000000000000000000000000000000000 --- a/src/connector/nodejs/nodetaos/connection.js +++ /dev/null @@ -1,84 +0,0 @@ -const TDengineCursor = require('./cursor') -const CTaosInterface = require('./cinterface') -module.exports = TDengineConnection; - -/** - * TDengine Connection Class - * @param {object} options - Options for configuring the connection with TDengine - * @return {TDengineConnection} - * @class TDengineConnection - * @constructor - * @example - * //Initialize a new connection - * var conn = new TDengineConnection({host:"127.0.0.1", user:"root", password:"taosdata", config:"/etc/taos",port:0}) - * - */ -function TDengineConnection(options) { - this._conn = null; - this._host = null; - this._user = "root"; //The default user - this._password = "taosdata"; //The default password - this._database = null; - this._port = 0; - this._config = null; - this._chandle = null; - this._configConn(options) - return this; -} -/** - * Configure the connection to TDengine - * @private - * @memberof TDengineConnection - */ -TDengineConnection.prototype._configConn = function _configConn(options) { - if (options['host']) { - this._host = options['host']; - } - if (options['user']) { - this._user = options['user']; - } - if (options['password']) { - this._password = options['password']; - } - if (options['database']) { - this._database = options['database']; - } - if (options['port']) { - this._port = options['port']; - } - if (options['config']) { - this._config = options['config']; - } - this._chandle = new CTaosInterface(this._config); - this._conn = this._chandle.connect(this._host, this._user, this._password, this._database, this._port); -} -/** Close the connection to TDengine */ -TDengineConnection.prototype.close = function close() { - this._chandle.close(this._conn); -} -/** - * Initialize a new cursor to interact with TDengine with - * @return {TDengineCursor} - */ -TDengineConnection.prototype.cursor = function cursor() { - //Pass the connection object to the cursor - return new TDengineCursor(this); -} -TDengineConnection.prototype.commit = function commit() { - return this; -} -TDengineConnection.prototype.rollback = function rollback() { - return this; -} -/** - * Clear the results from connector - * @private - */ -/* - TDengineConnection.prototype._clearResultSet = function _clearResultSet() { - var result = this._chandle.useResult(this._conn).result; - if (result) { - this._chandle.freeResult(result) - } -} -*/ diff --git a/src/connector/nodejs/nodetaos/constants.js b/src/connector/nodejs/nodetaos/constants.js deleted file mode 100644 index b055e0ed01522348556475fa72e8bf34a9d3fe70..0000000000000000000000000000000000000000 --- a/src/connector/nodejs/nodetaos/constants.js +++ /dev/null @@ -1,106 +0,0 @@ - -const SCHEMALESS_PROTOCOL = { - TSDB_SML_UNKNOWN_PROTOCOL: 0, - TSDB_SML_LINE_PROTOCOL: 1, - TSDB_SML_TELNET_PROTOCOL: 2, - TSDB_SML_JSON_PROTOCOL: 3 -} -const SCHEMALESS_PRECISION = { - TSDB_SML_TIMESTAMP_NOT_CONFIGURED: 0, - TSDB_SML_TIMESTAMP_HOURS: 1, - TSDB_SML_TIMESTAMP_MINUTES: 2, - TSDB_SML_TIMESTAMP_SECONDS: 3, - TSDB_SML_TIMESTAMP_MILLI_SECONDS: 4, - TSDB_SML_TIMESTAMP_MICRO_SECONDS: 5, - TSDB_SML_TIMESTAMP_NANO_SECONDS: 6 -} -const typeCodesToName = { - 0: 'Null', - 1: 'Boolean', - 2: 'Tiny Int', - 3: 'Small Int', - 4: 'Int', - 5: 'Big Int', - 6: 'Float', - 7: 'Double', - 8: 'Binary', - 9: 'Timestamp', - 10: 'Nchar', - 11: 'Tinyint Unsigned', - 12: 'Smallint Unsigned', - 13: 'Int Unsigned', - 14: 'Bigint Unsigned', - 15: 'Json', -} - -/** - * @function - * @param {number} typecode - The code to get the name of the type for - * @return {string} Name of the field type - */ -function getType(typecode) { - return typeCodesToName[typecode]; -} -/** - * Contains the the definitions/values assigned to various field types - * @module FieldTypes - */ -/** - * TDengine Field Types and their type codes - * @typedef {Object} FieldTypes - * @global - * @property {number} C_NULL - Null - * @property {number} C_BOOL - Boolean. Note, 0x02 is the C_BOOL_NULL value. - * @property {number} C_TINYINT - Tiny Int, values in the range [-2^7+1, 2^7-1]. Note, -2^7 has been used as the C_TINYINT_NULL value - * @property {number} C_SMALLINT - Small Int, values in the range [-2^15+1, 2^15-1]. Note, -2^15 has been used as the C_SMALLINT_NULL value - * @property {number} C_INT - Int, values in the range [-2^31+1, 2^31-1]. Note, -2^31 has been used as the C_INT_NULL value - * @property {number} C_BIGINT - Big Int, values in the range [-2^59, 2^59]. - * @property {number} C_FLOAT - Float, values in the range [-3.4E38, 3.4E38], accurate up to 6-7 decimal places. - * @property {number} C_DOUBLE - Double, values in the range [-1.7E308, 1.7E308], accurate up to 15-16 decimal places. - * @property {number} C_BINARY - Binary, encoded in utf-8. - * @property {number} C_TIMESTAMP - Timestamp in format "YYYY:MM:DD HH:MM:SS.MMM". Measured in number of milliseconds passed after - 1970-01-01 08:00:00.000 GMT. - * @property {number} C_NCHAR - NChar field type encoded in ASCII, a wide string. - * - * @property {number} C_TIMESTAMP_MILLI - The code for millisecond timestamps, as returned by libtaos.taos_result_precision(result). - * @property {number} C_TIMESTAMP_MICRO - The code for microsecond timestamps, as returned by libtaos.taos_result_precision(result). - */ -module.exports = { - C_NULL: 0, - C_BOOL: 1, - C_TINYINT: 2, - C_SMALLINT: 3, - C_INT: 4, - C_BIGINT: 5, - C_FLOAT: 6, - C_DOUBLE: 7, - C_BINARY: 8, - C_TIMESTAMP: 9, - C_NCHAR: 10, - C_TINYINT_UNSIGNED: 11, - C_SMALLINT_UNSIGNED: 12, - C_INT_UNSIGNED: 13, - C_BIGINT_UNSIGNED: 14, - C_JSON_TAG: 15, - // NULL value definition - // NOTE: These values should change according to C definition in tsdb.h - C_BOOL_NULL: 2, - C_TINYINT_NULL: -128, - C_TINYINT_UNSIGNED_NULL: 255, - C_SMALLINT_NULL: -32768, - C_SMALLINT_UNSIGNED_NULL: 65535, - C_INT_NULL: -2147483648, - C_INT_UNSIGNED_NULL: 4294967295, - C_BIGINT_NULL: -9223372036854775808n, - C_BIGINT_UNSIGNED_NULL: 18446744073709551615n, - C_FLOAT_NULL: 2146435072, - C_DOUBLE_NULL: -9223370937343148032, - C_NCHAR_NULL: 4294967295, - C_BINARY_NULL: 255, - C_TIMESTAMP_MILLI: 0, - C_TIMESTAMP_MICRO: 1, - getType, - SCHEMALESS_PROTOCOL, - SCHEMALESS_PRECISION -} - diff --git a/src/connector/nodejs/nodetaos/cursor.js b/src/connector/nodejs/nodetaos/cursor.js deleted file mode 100644 index afd9fbcf472c8de3f47ffb52d0f705822d23dfcf..0000000000000000000000000000000000000000 --- a/src/connector/nodejs/nodetaos/cursor.js +++ /dev/null @@ -1,716 +0,0 @@ -const ref = require('ref-napi'); -require('./globalfunc.js') -const CTaosInterface = require('./cinterface') -const errors = require('./error') -const TaosQuery = require('./taosquery') -const { PerformanceObserver, performance } = require('perf_hooks'); -module.exports = TDengineCursor; - -/** - * @typedef {Object} Buffer - A Node.js buffer. Please refer to {@link https://nodejs.org/api/buffer.html} for more details - * @global - */ - -/** - * @class TDengineCursor - * @classdesc The TDengine Cursor works directly with the C Interface which works with TDengine. It refrains from - * returning parsed data and majority of functions return the raw data such as cursor.fetchall() as compared to the TaosQuery class which - * has functions that "prettify" the data and add more functionality and can be used through cursor.query("your query"). Instead of - * promises, the class and its functions use callbacks. - * @param {TDengineConnection} - The TDengine Connection this cursor uses to interact with TDengine - * @property {data} - Latest retrieved data from query execution. It is an empty array by default - * @property {fields} - Array of the field objects in order from left to right of the latest data retrieved - * @since 1.0.0 - */ -function TDengineCursor(connection = null) { - //All parameters are store for sync queries only. - this._rowcount = -1; - this._connection = null; - this._result = null; - this._fields = null; - this.data = []; - this.fields = null; - this._stmt = null; - if (connection != null) { - this._connection = connection - this._chandle = connection._chandle //pass through, just need library loaded. - } - else { - throw new errors.ProgrammingError("A TDengineConnection object is required to be passed to the TDengineCursor"); - } - -} -/** - * Get the row counts of the latest query - * @since 1.0.0 - * @return {number} Rowcount - */ -TDengineCursor.prototype.rowcount = function rowcount() { - return this._rowcount; -} -/** - * Close the cursor by setting its connection to null and freeing results from the connection and resetting the results it has stored - * @return {boolean} Whether or not the cursor was succesfully closed - * @since 1.0.0 - */ -TDengineCursor.prototype.close = function close() { - if (this._connection == null) { - return false; - } - // this._connection._clearResultSet(); - this._reset_result(); - this._connection = null; - return true; -} -/** - * Create a TaosQuery object to perform a query to TDengine and retrieve data. - * @param {string} operation - The operation string to perform a query on - * @param {boolean} execute - Whether or not to immedietely perform the query. Default is false. - * @return {TaosQuery | Promise} A TaosQuery object - * @example - * var query = cursor.query("select count(*) from meterinfo.meters"); - * query.execute(); - * @since 1.0.6 - */ -TDengineCursor.prototype.query = function query(operation, execute = false) { - return new TaosQuery(operation, this, execute); -} - -/** - * Execute a query. Also stores all the field meta data returned from the query into cursor.fields. It is preferable to use cursor.query() to create - * queries and execute them instead of using the cursor object directly. - * @param {string} operation - The query operation to execute in the taos shell - * @param {Object} options - Execution options object. quiet : true turns off logging from queries - * @param {boolean} options.quiet - True if you want to surpress logging such as "Query OK, 1 row(s) ..." - * @param {function} callback - A callback function to execute after the query is made to TDengine - * @return {number | Buffer} Number of affected rows or a Buffer that points to the results of the query - * @since 1.0.0 - */ -TDengineCursor.prototype.execute = function execute(operation, options, callback) { - if (operation == undefined) { - throw new errors.ProgrammingError('No operation passed as argument'); - return null; - } - - if (typeof options == 'function') { - callback = options; - } - if (typeof options != 'object') options = {} - if (this._connection == null) { - throw new errors.ProgrammingError('Cursor is not connected'); - } - - this._reset_result(); - - let stmt = operation; - let time = 0; - let res; - if (options['quiet'] != true) { - const obs = new PerformanceObserver((items) => { - time = items.getEntries()[0].duration; - performance.clearMarks(); - }); - obs.observe({ entryTypes: ['measure'] }); - performance.mark('A'); - this._result = this._chandle.query(this._connection._conn, stmt); - performance.mark('B'); - performance.measure('query', 'A', 'B'); - } - else { - this._result = this._chandle.query(this._connection._conn, stmt); - } - res = this._chandle.errno(this._result); - if (res == 0) { - let fieldCount = this._chandle.fieldsCount(this._result); - if (fieldCount == 0) { - let affectedRowCount = this._chandle.affectedRows(this._result); - let response = this._createAffectedResponse(affectedRowCount, time) - if (options['quiet'] != true) { - console.log(response); - } - wrapCB(callback); - return affectedRowCount; //return num of affected rows, common with insert, use statements - } - else { - this._fields = this._chandle.useResult(this._result); - this.fields = this._fields; - wrapCB(callback); - - return this._result; //return a pointer to the result - } - } - else { - throw new errors.ProgrammingError(this._chandle.errStr(this._result)) - } - -} -TDengineCursor.prototype._createAffectedResponse = function (num, time) { - return "Query OK, " + num + " row(s) affected (" + (time * 0.001).toFixed(8) + "s)"; -} -TDengineCursor.prototype._createSetResponse = function (num, time) { - return "Query OK, " + num + " row(s) in set (" + (time * 0.001).toFixed(8) + "s)"; -} -TDengineCursor.prototype.executemany = function executemany() { - -} -TDengineCursor.prototype.fetchone = function fetchone() { - -} -TDengineCursor.prototype.fetchmany = function fetchmany() { - -} -/** - * Fetches all results from a query and also stores results into cursor.data. It is preferable to use cursor.query() to create - * queries and execute them instead of using the cursor object directly. - * @param {function} callback - callback function executing on the complete fetched data - * @return {Array} The resultant array, with entries corresponding to each retreived row from the query results, sorted in - * order by the field name ordering in the table. - * @since 1.0.0 - * @example - * cursor.execute('select * from db.table'); - * var data = cursor.fetchall(function(results) { - * results.forEach(row => console.log(row)); - * }) - */ -TDengineCursor.prototype.fetchall = function fetchall(options, callback) { - if (this._result == null || this._fields == null) { - throw new errors.OperationalError("Invalid use of fetchall, either result or fields from query are null. First execute a query first"); - } - - let num_of_rows = this._chandle.affectedRows(this._result); - let data = new Array(num_of_rows); - - this._rowcount = 0; - - let time = 0; - const obs = new PerformanceObserver((items) => { - time += items.getEntries()[0].duration; - performance.clearMarks(); - }); - obs.observe({ entryTypes: ['measure'] }); - performance.mark('A'); - while (true) { - let blockAndRows = this._chandle.fetchBlock(this._result, this._fields); - // console.log(blockAndRows); - // break; - let block = blockAndRows.blocks; - let num_of_rows = blockAndRows.num_of_rows; - if (num_of_rows == 0) { - break; - } - this._rowcount += num_of_rows; - let numoffields = this._fields.length; - for (let i = 0; i < num_of_rows; i++) { - // data.push([]); - - let rowBlock = new Array(numoffields); - for (let j = 0; j < numoffields; j++) { - rowBlock[j] = block[j][i]; - } - data[this._rowcount - num_of_rows + i] = (rowBlock); - // data.push(rowBlock); - } - - } - - performance.mark('B'); - performance.measure('query', 'A', 'B'); - let response = this._createSetResponse(this._rowcount, time) - console.log(response); - - // this._connection._clearResultSet(); - let fields = this.fields; - this._reset_result(); - this.data = data; - this.fields = fields; - - wrapCB(callback, data); - - return data; -} -/** - * Asynchrnously execute a query to TDengine. NOTE, insertion requests must be done in sync if on the same table. - * @param {string} operation - The query operation to execute in the taos shell - * @param {Object} options - Execution options object. quiet : true turns off logging from queries - * @param {boolean} options.quiet - True if you want to surpress logging such as "Query OK, 1 row(s) ..." - * @param {function} callback - A callback function to execute after the query is made to TDengine - * @return {number | Buffer} Number of affected rows or a Buffer that points to the results of the query - * @since 1.0.0 - */ -TDengineCursor.prototype.execute_a = function execute_a(operation, options, callback, param) { - if (operation == undefined) { - throw new errors.ProgrammingError('No operation passed as argument'); - return null; - } - if (typeof options == 'function') { - //we expect the parameter after callback to be param - param = callback; - callback = options; - } - if (typeof options != 'object') options = {} - if (this._connection == null) { - throw new errors.ProgrammingError('Cursor is not connected'); - } - if (typeof callback != 'function') { - throw new errors.ProgrammingError("No callback function passed to execute_a function"); - } - // Async wrapper for callback; - var cr = this; - - let asyncCallbackWrapper = function (param2, res2, resCode) { - if (typeof callback == 'function') { - callback(param2, res2, resCode); - } - - if (resCode >= 0) { - // let fieldCount = cr._chandle.numFields(res2); - // if (fieldCount == 0) { - // //cr._chandle.freeResult(res2); - // return res2; - // } - // else { - // return res2; - // } - return res2; - - } - else { - throw new errors.ProgrammingError("Error occuring with use of execute_a async function. Status code was returned with failure"); - } - } - - let stmt = operation; - let time = 0; - - // Use ref module to write to buffer in cursor.js instead of taosquery to maintain a difference in levels. Have taosquery stay high level - // through letting it pass an object as param - var buf = ref.alloc('Object'); - ref.writeObject(buf, 0, param); - const obs = new PerformanceObserver((items) => { - time = items.getEntries()[0].duration; - performance.clearMarks(); - }); - obs.observe({ entryTypes: ['measure'] }); - performance.mark('A'); - this._chandle.query_a(this._connection._conn, stmt, asyncCallbackWrapper, buf); - performance.mark('B'); - performance.measure('query', 'A', 'B'); - return param; - - -} -/** - * Fetches all results from an async query. It is preferable to use cursor.query_a() to create - * async queries and execute them instead of using the cursor object directly. - * @param {Object} options - An options object containing options for this function - * @param {function} callback - callback function that is callbacked on the COMPLETE fetched data (it is calledback only once!). - * Must be of form function (param, result, rowCount, rowData) - * @param {Object} param - A parameter that is also passed to the main callback function. Important! Param must be an object, and the key "data" cannot be used - * @return {{param:Object, result:Buffer}} An object with the passed parameters object and the buffer instance that is a pointer to the result handle. - * @since 1.2.0 - * @example - * cursor.execute('select * from db.table'); - * var data = cursor.fetchall(function(results) { - * results.forEach(row => console.log(row)); - * }) - */ -TDengineCursor.prototype.fetchall_a = function fetchall_a(result, options, callback, param = {}) { - if (typeof options == 'function') { - //we expect the parameter after callback to be param - param = callback; - callback = options; - } - if (typeof options != 'object') options = {} - if (this._connection == null) { - throw new errors.ProgrammingError('Cursor is not connected'); - } - if (typeof callback != 'function') { - throw new errors.ProgrammingError('No callback function passed to fetchall_a function') - } - if (param.data) { - throw new errors.ProgrammingError("You aren't allowed to set the key 'data' for the parameters object"); - } - let buf = ref.alloc('Object'); - param.data = []; - var cr = this; - - // This callback wrapper accumulates the data from the fetch_rows_a function from the cinterface. It is accumulated by passing the param2 - // object which holds accumulated data in the data key. - let asyncCallbackWrapper = function asyncCallbackWrapper(param2, result2, numOfRows2, rowData) { - param2 = ref.readObject(param2); //return the object back from the pointer - if (numOfRows2 > 0 && rowData.length != 0) { - // Keep fetching until now rows left. - let buf2 = ref.alloc('Object'); - param2.data.push(rowData); - ref.writeObject(buf2, 0, param2); - cr._chandle.fetch_rows_a(result2, asyncCallbackWrapper, buf2); - } - else { - let finalData = param2.data; - let fields = cr._chandle.fetchFields_a(result2); - let data = []; - for (let i = 0; i < finalData.length; i++) { - let num_of_rows = finalData[i][0].length; //fetched block number i; - let block = finalData[i]; - for (let j = 0; j < num_of_rows; j++) { - data.push([]); - let rowBlock = new Array(fields.length); - for (let k = 0; k < fields.length; k++) { - rowBlock[k] = block[k][j]; - } - data[data.length - 1] = rowBlock; - } - } - cr._chandle.freeResult(result2); // free result, avoid seg faults and mem leaks! - callback(param2, result2, numOfRows2, { data: data, fields: fields }); - - } - } - ref.writeObject(buf, 0, param); - param = this._chandle.fetch_rows_a(result, asyncCallbackWrapper, buf); //returned param - return { param: param, result: result }; -} -/** - * Stop a query given the result handle. - * @param {Buffer} result - The buffer that acts as the result handle - * @since 1.3.0 - */ -TDengineCursor.prototype.stopQuery = function stopQuery(result) { - this._chandle.stopQuery(result); -} -TDengineCursor.prototype._reset_result = function _reset_result() { - this._rowcount = -1; - if (this._result != null) { - this._chandle.freeResult(this._result); - } - this._result = null; - this._fields = null; - this.data = []; - this.fields = null; -} -/** - * Get server info such as version number - * @return {string} - * @since 1.3.0 - */ -TDengineCursor.prototype.getServerInfo = function getServerInfo() { - return this._chandle.getServerInfo(this._connection._conn); -} -/** - * Get client info such as version number - * @return {string} - * @since 1.3.0 - */ -TDengineCursor.prototype.getClientInfo = function getClientInfo() { - return this._chandle.getClientInfo(); -} -/** - * Subscribe to a table from a database in TDengine. - * @param {Object} config - A configuration object containing the configuration options for the subscription - * @param {string} config.restart - whether or not to continue a subscription if it already exits, otherwise start from beginning - * @param {string} config.topic - The unique identifier of a subscription - * @param {string} config.sql - A sql statement for data query - * @param {string} config.interval - The pulling interval - * @return {Buffer} A buffer pointing to the subscription session handle - * @since 1.3.0 - */ -TDengineCursor.prototype.subscribe = function subscribe(config) { - let restart = config.restart ? 1 : 0; - return this._chandle.subscribe(this._connection._conn, restart, config.topic, config.sql, config.interval); -}; -/** - * An infinite loop that consumes the latest data and calls a callback function that is provided. - * @param {Buffer} subscription - A buffer object pointing to the subscription session handle - * @param {function} callback - The callback function that takes the row data, field/column meta data, and the subscription session handle as input - * @since 1.3.0 - */ -TDengineCursor.prototype.consumeData = async function consumeData(subscription, callback) { - while (true) { - let { data, fields, result } = this._chandle.consume(subscription); - callback(data, fields, result); - } -} -/** - * Unsubscribe the provided buffer object pointing to the subscription session handle - * @param {Buffer} subscription - A buffer object pointing to the subscription session handle that is to be unsubscribed - * @since 1.3.0 - */ -TDengineCursor.prototype.unsubscribe = function unsubscribe(subscription) { - this._chandle.unsubscribe(subscription); -} - -/** - * schemaless insert - * @param {*} connection a valid database connection - * @param {*} lines string data, which statisfied with line proctocol - * @param {*} protocal Line protocol, enum type (0,1,2,3),indicate different line protocol - * @param {*} precision timestamp precision in lines, enum type (0,1,2,3,4,5,6) - * @returns TAOS_RES - * - */ -TDengineCursor.prototype.schemalessInsert = function schemalessInsert(lines, protocol, precision) { - this._result = this._chandle.schemalessInsert(this._connection._conn, lines, protocol, precision); - let errorNo = this._chandle.errno(this._result); - if (errorNo != 0) { - throw new errors.InterfaceError(errorNo + ":" + this._chandle.errStr(this._result)); - } - this._chandle.freeResult(this._result); -} - -//STMT -/** - * init a TAOS_STMT object for later use.it should be freed with stmtClose. - * @returns Not NULL returned for success, and NULL for failure. - * - */ -TDengineCursor.prototype.stmtInit = function stmtInit() { - let stmt = null - stmt = this._chandle.stmtInit(this._connection._conn); - if (stmt == null || stmt == undefined) { - throw new errors.DatabaseError(this._chandle.stmtErrStr(stmt)); - } else { - this._stmt = stmt; - } -} - -/** - * prepare a sql statement,'sql' should be a valid INSERT/SELECT statement - * @param {string} sql a valid INSERT/SELECT statement - * @returns {int} 0 for success, non-zero for failure. - */ -TDengineCursor.prototype.stmtPrepare = function stmtPrepare(sql) { - if (this._stmt == null) { - throw new errors.DatabaseError("stmt is null,init stmt first"); - } else { - let stmtPrepare = this._chandle.stmtPrepare(this._stmt, sql, null); - if (stmtPrepare != 0) { - throw new errors.DatabaseError(this._chandle.stmtErrStr(this._stmt)); - } else { - console.log("stmtPrepare success."); - } - } -} - -/** - * For INSERT only. Used to bind table name as a parmeter for the input stmt object. - * @param {TaosBind} tableName target table name you want to bind - * @returns 0 for success, non-zero for failure. - */ -TDengineCursor.prototype.stmtSetTbname = function stmtSetTbname(tableName) { - if (this._stmt == null) { - throw new errors.DatabaseError("stmt is null,init stmt first"); - } else { - let stmtPrepare = this._chandle.stmtSetTbname(this._stmt, tableName); - if (stmtPrepare != 0) { - throw new errors.DatabaseError(this._chandle.stmtErrStr(this._stmt)); - } else { - console.log("stmtSetTbname success."); - } - } -} - -/** - * For INSERT only. - * Set a table name for binding table name as parameter and tag values for all tag parameters. - * @param {*} tableName use to set target table name - * @param {TaosMultiBind} tags use to set tag value for target table. - * @returns - */ -TDengineCursor.prototype.stmtSetTbnameTags = function stmtSetTbnameTags(tableName, tags) { - if (this._stmt == null) { - throw new errors.DatabaseError("stmt is null,init stmt first"); - } else { - let stmtPrepare = this._chandle.stmtSetTbnameTags(this._stmt, tableName, tags); - if (stmtPrepare != 0) { - throw new errors.DatabaseError(this._chandle.stmtErrStr(this._stmt)); - } else { - console.log("stmtSetTbnameTags success."); - } - } -} - -/** - * For INSERT only. - * Set a table name for binding table name as parameter. Only used for binding all tables - * in one stable, user application must call 'loadTableInfo' API to load all table - * meta before calling this API. If the table meta is not cached locally, it will return error. - * @param {*} subTableName table name which is belong to an stable - * @returns 0 for success, non-zero for failure. - */ -TDengineCursor.prototype.stmtSetSubTbname = function stmtSetSubTbname(subTableName) { - if (this._stmt == null) { - throw new errors.DatabaseError("stmt is null,init stmt first"); - } else { - let stmtPrepare = this._chandle.stmtSetSubTbname(this._stmt, subTableName); - if (stmtPrepare != 0) { - throw new errors.DatabaseError(this._chandle.stmtErrStr(this._stmt)); - } else { - console.log("stmtSetSubTbname success."); - } - } -} - -/** - * bind a whole line data, for both INSERT and SELECT. The parameter 'bind' points to an array - * contains the whole line data. Each item in array represents a column's value, the item - * number and sequence should keep consistence with columns in sql statement. The usage of - * structure TAOS_BIND is the same with MYSQL_BIND in MySQL. - * @param {*} binds points to an array contains the whole line data. - * @returns 0 for success, non-zero for failure. - */ -TDengineCursor.prototype.stmtBindParam = function stmtBindParam(binds) { - if (this._stmt == null) { - throw new errors.DatabaseError("stmt is null,init stmt first"); - } else { - let stmtPrepare = this._chandle.bindParam(this._stmt, binds); - if (stmtPrepare != 0) { - throw new errors.DatabaseError(this._chandle.stmtErrStr(this._stmt)); - } else { - console.log("bindParam success."); - } - } -} - -/** - * Bind a single column's data, INTERNAL used and for INSERT only. - * @param {TaosMultiBind} mbind points to a column's data which could be the one or more lines. - * @param {*} colIndex the column's index in prepared sql statement, it starts from 0. - * @returns 0 for success, non-zero for failure. - */ -TDengineCursor.prototype.stmtBindSingleParamBatch = function stmtBindSingleParamBatch(mbind, colIndex) { - if (this._stmt == null) { - throw new errors.DatabaseError("stmt is null,init stmt first"); - } else { - let stmtPrepare = this._chandle.stmtBindSingleParamBatch(this._stmt, mbind, colIndex); - if (stmtPrepare != 0) { - throw new errors.DatabaseError(this._chandle.stmtErrStr(this._stmt)); - } else { - console.log("stmtBindSingleParamBatch success."); - } - } -} - -/** - * For INSERT only. - * Bind one or multiple lines data. - * @param {*} mbinds Points to an array contains one or more lines data.The item - * number and sequence should keep consistence with columns - * n sql statement. - * @returns 0 for success, non-zero for failure. - */ -TDengineCursor.prototype.stmtBindParamBatch = function stmtBindParamBatch(mbinds) { - if (this._stmt == null) { - throw new errors.DatabaseError("stmt is null,init stmt first"); - } else { - let stmtPrepare = this._chandle.stmtBindParamBatch(this._stmt, mbinds); - if (stmtPrepare != 0) { - throw new errors.DatabaseError(this._chandle.stmtErrStr(this._stmt)); - } else { - console.log("stmtBindParamBatch success."); - } - } -} - -/** - * add all current bound parameters to batch process, for INSERT only. - * Must be called after each call to bindParam/bindSingleParamBatch, - * or all columns binds for one or more lines with bindSingleParamBatch. User - * application can call any bind parameter API again to bind more data lines after calling - * to this API. - * @param {*} stmt - * @returns 0 for success, non-zero for failure. - */ -TDengineCursor.prototype.stmtAddBatch = function stmtAddBatch() { - if (this._stmt == null) { - throw new errors.DatabaseError("stmt is null,init stmt first"); - } else { - let addBatchRes = this._chandle.addBatch(this._stmt); - if (addBatchRes != 0) { - throw new errors.DatabaseError(this._chandle.stmtErrStr(this._stmt)); - } - else { - console.log("addBatch success."); - } - } -} - -/** - * actually execute the INSERT/SELECT sql statement. User application can continue - * to bind new data after calling to this API. - * @param {*} stmt - * @returns 0 for success, non-zero for failure. - */ -TDengineCursor.prototype.stmtExecute = function stmtExecute() { - if (this._stmt != null) { - let stmtExecRes = this._chandle.stmtExecute(this._stmt); - if (stmtExecRes != 0) { - throw new errors.DatabaseError(this._chandle.stmtErrStr(this._stmt)); - } else { - console.log("stmtExecute success.") - } - } else { - throw new errors.DatabaseError("stmt is null,init stmt first"); - } -} - -/** - * For SELECT only,getting the query result. - * User application should free it with API 'FreeResult' at the end. - * @returns Not NULL for success, NULL for failure. - */ -TDengineCursor.prototype.stmtUseResult = function stmtUseResult() { - if (this._stmt != null) { - this._result = this._chandle.stmtUseResult(this._stmt); - let res = this._chandle.errno(this._result); - if (res != 0) { - throw new errors.DatabaseError(this._chandle.errStr(this._stmt)); - } else { - console.log("stmtUseResult success."); - let fieldCount = this._chandle.fieldsCount(this._result); - if (fieldCount != 0) { - this._fields = this._chandle.useResult(this._result); - this.fields = this._fields; - } - } - } else { - throw new errors.DatabaseError("stmt is null,init stmt first"); - } -} - -/** - * user application call this API to load all tables meta info. - * This method must be called before stmtSetSubTbname(IntPtr stmt, string name); - * @param {*} tableList tables need to load meta info are form in an array - * @returns 0 for success, non-zero for failure. - */ -TDengineCursor.prototype.loadTableInfo = function loadTableInfo(tableList) { - if (this._connection._conn != null) { - let stmtExecRes = this._chandle.loadTableInfo(this._connection._conn, tableList); - if (stmtExecRes != 0) { - throw new errors.DatabaseError(`loadTableInfo() failed,code ${stmtExecRes}`); - } else { - console.log("loadTableInfo success.") - } - } else { - throw new errors.DatabaseError("taos connection is null."); - } -} - -/** - * close STMT object and free resources. - * @param {*} stmt - * @returns 0 for success, non-zero for failure. - */ -TDengineCursor.prototype.stmtClose = function stmtClose() { - if (this._stmt == null) { - throw new DatabaseError("stmt is null,init stmt first"); - } else { - let closeStmtRes = this._chandle.closeStmt(this._stmt); - if (closeStmtRes != 0) { - throw new DatabaseError(this._chandle.stmtErrStr(this._stmt)); - } - else { - console.log("closeStmt success."); - } - } -} \ No newline at end of file diff --git a/src/connector/nodejs/nodetaos/error.js b/src/connector/nodejs/nodetaos/error.js deleted file mode 100644 index 8ab91a50c7d81a4675246617e0969ee8c81c514e..0000000000000000000000000000000000000000 --- a/src/connector/nodejs/nodetaos/error.js +++ /dev/null @@ -1,96 +0,0 @@ - -/** - * TDengine Error Class - * @ignore - */ -class TDError extends Error { - constructor(args) { - super(args) - this.name = "TDError"; - } -} -/** Exception raised for important warnings like data truncations while inserting. - * @ignore - */ -class Warning extends Error { - constructor(args) { - super(args) - this.name = "Warning"; - } -} -/** Exception raised for errors that are related to the database interface rather than the database itself. - * @ignore - */ -class InterfaceError extends TDError { - constructor(args) { - super(args) - this.name = "TDError.InterfaceError"; - } -} -/** Exception raised for errors that are related to the database. - * @ignore - */ -class DatabaseError extends TDError { - constructor(args) { - super(args) - this.name = "TDError.DatabaseError"; - } -} -/** Exception raised for errors that are due to problems with the processed data like division by zero, numeric value out of range. - * @ignore - */ -class DataError extends DatabaseError { - constructor(args) { - super(args) - this.name = "TDError.DatabaseError.DataError"; - } -} -/** Exception raised for errors that are related to the database's operation and not necessarily under the control of the programmer - * @ignore - */ -class OperationalError extends DatabaseError { - constructor(args) { - super(args) - this.name = "TDError.DatabaseError.OperationalError"; - } -} -/** Exception raised when the relational integrity of the database is affected. - * @ignore - */ -class IntegrityError extends DatabaseError { - constructor(args) { - super(args) - this.name = "TDError.DatabaseError.IntegrityError"; - } -} -/** Exception raised when the database encounters an internal error. - * @ignore - */ -class InternalError extends DatabaseError { - constructor(args) { - super(args) - this.name = "TDError.DatabaseError.InternalError"; - } -} -/** Exception raised for programming errors. - * @ignore - */ -class ProgrammingError extends DatabaseError { - constructor(args) { - super(args) - this.name = "TDError.DatabaseError.ProgrammingError"; - } -} -/** Exception raised in case a method or database API was used which is not supported by the database. - * @ignore - */ -class NotSupportedError extends DatabaseError { - constructor(args) { - super(args) - this.name = "TDError.DatabaseError.NotSupportedError"; - } -} - -module.exports = { - TDError, Warning, InterfaceError, DatabaseError, DataError, OperationalError, IntegrityError, InternalError, ProgrammingError, NotSupportedError -}; diff --git a/src/connector/nodejs/nodetaos/globalfunc.js b/src/connector/nodejs/nodetaos/globalfunc.js deleted file mode 100644 index cf7344c868ee94831eba47ff55369a684e34b02f..0000000000000000000000000000000000000000 --- a/src/connector/nodejs/nodetaos/globalfunc.js +++ /dev/null @@ -1,14 +0,0 @@ -/* Wrap a callback, reduce code amount */ -function wrapCB(callback, input) { - if (typeof callback === 'function') { - callback(input); - } - return; -} -global.wrapCB = wrapCB; -function toTaosTSString(date) { - date = new Date(date); - let tsArr = date.toISOString().split("T") - return tsArr[0] + " " + tsArr[1].substring(0, tsArr[1].length-1); -} -global.toTaosTSString = toTaosTSString; diff --git a/src/connector/nodejs/nodetaos/taosBind.js b/src/connector/nodejs/nodetaos/taosBind.js deleted file mode 100644 index b70d035b9fcf2eff5d0d1edb7114b5549eda83d4..0000000000000000000000000000000000000000 --- a/src/connector/nodejs/nodetaos/taosBind.js +++ /dev/null @@ -1,377 +0,0 @@ -const ref = require('ref-napi'); -const StructType = require('ref-struct-di')(ref); -const taosConst = require('./constants'); -const { TDError } = require('./error'); - -var bufferType = ref.types.int32; -var buffer = ref.refType(ref.types.void); -var bufferLength = ref.types.uint64; -var length = ref.refType(ref.types.uint64); -var isNull = ref.refType(ref.types.int32); -var is_unsigned = ref.types.int; -var error = ref.refType(ref.types.void); -var u = ref.types.int64; -var allocated = ref.types.uint32; - -var TAOS_BIND = StructType({ - buffer_type: bufferType, - buffer: buffer, - buffer_length: bufferLength, - length: length, - is_null: isNull, - is_unsigned: is_unsigned, - error: error, - u: u, - allocated: allocated, -}); - -class TaosBind { - constructor(num) { - this.buf = Buffer.alloc(TAOS_BIND.size * num); - this.num = num; - this.index = 0; - } - /** - * Used to bind null value for all data types that tdengine supports. - */ - bindNil() { - if (!this._isOutOfBound()) { - let nil = new TAOS_BIND({ - buffer_type: taosConst.C_NULL, - is_null: ref.alloc(ref.types.int32, 1), - }); - - TAOS_BIND.set(this.buf, this.index * TAOS_BIND.size, nil); - this.index++ - } else { - throw new TDError(`bindNil() failed,since index:${this.index} is out of Buffer bound ${this.num}.`); - } - } - - /** - * - * @param {bool} val is not null bool value,true or false. - */ - bindBool(val) { - if (!this._isOutOfBound()) { - let bl = new TAOS_BIND({ - buffer_type: taosConst.C_BOOL, - buffer: ref.alloc(ref.types.bool, val), - buffer_length: ref.types.bool.size, - length: ref.alloc(ref.types.uint64, ref.types.bool.size), - is_null: ref.alloc(ref.types.int32, 0), - }); - - TAOS_BIND.set(this.buf, this.index * TAOS_BIND.size, bl); - this.index++ - } else { - throw new TDError(`bindBool() failed with ${val},since index:${this.index} is out of Buffer bound ${this.num}.`); - } - - } - - /** - * - * @param {int8} val is a not null tinyint value. - */ - bindTinyInt(val) { - if (!this._isOutOfBound()) { - let tinnyInt = new TAOS_BIND({ - buffer_type: taosConst.C_TINYINT, - buffer: ref.alloc(ref.types.int8, val), - buffer_length: ref.types.int8.size, - length: ref.alloc(ref.types.uint64, ref.types.int8.size), - is_null: ref.alloc(ref.types.int32, 0), - }); - - TAOS_BIND.set(this.buf, this.index * TAOS_BIND.size, tinnyInt); - this.index++ - } else { - throw new TDError(`bindTinyInt() failed with ${val},since index:${this.index} is out of Buffer bound ${this.num}.`); - } - } - - /** - * - * @param {short} val is a not null small int value. - */ - bindSmallInt(val) { - if (!this._isOutOfBound()) { - let samllint = new TAOS_BIND({ - buffer_type: taosConst.C_SMALLINT, - buffer: ref.alloc(ref.types.int16, val), - buffer_length: ref.types.int16.size, - length: ref.alloc(ref.types.uint64, ref.types.int16.size), - is_null: ref.alloc(ref.types.int32, 0), - }); - TAOS_BIND.set(this.buf, this.index * TAOS_BIND.size, samllint); - this.index++ - } else { - throw new TDError(`bindSmallInt() failed with ${val},since index:${this.index} is out of Buffer bound ${this.num}.`); - } - - } - - /** - * - * @param {int} val is a not null int value. - */ - bindInt(val) { - if (!this._isOutOfBound()) { - let int = new TAOS_BIND({ - buffer_type: taosConst.C_INT, - buffer: ref.alloc(ref.types.int32, val), - buffer_length: ref.types.int32.size, - length: ref.alloc(ref.types.uint64, ref.types.int32.size), - is_null: ref.alloc(ref.types.int32, 0), - }); - TAOS_BIND.set(this.buf, this.index * TAOS_BIND.size, int); - this.index++ - } else { - throw new TDError(`bindInt() failed with ${val},since index:${this.index} is out of Buffer bound ${this.num}.`); - } - - } - - /** - * - * @param {long} val is not null big int value. - */ - bindBigInt(val) { - if (!this._isOutOfBound()) { - let bigint = new TAOS_BIND({ - buffer_type: taosConst.C_BIGINT, - buffer: ref.alloc(ref.types.int64, val.toString()), - buffer_length: ref.types.int64.size, - length: ref.alloc(ref.types.uint64, ref.types.int64.size), - is_null: ref.alloc(ref.types.int32, 0), - }); - TAOS_BIND.set(this.buf, this.index * TAOS_BIND.size, bigint); - this.index++ - } else { - throw new TDError(`bindBigInt() failed with ${val},since index:${this.index} is out of Buffer bound ${this.num}.`); - } - } - - /** - * - * @param {float} val is a not null float value - */ - bindFloat(val) { - if (!this._isOutOfBound()) { - let float = new TAOS_BIND({ - buffer_type: taosConst.C_FLOAT, - buffer: ref.alloc(ref.types.float, val), - buffer_length: ref.types.float.size, - length: ref.alloc(ref.types.uint64, ref.types.float.size), - is_null: ref.alloc(ref.types.int32, 0), - }); - TAOS_BIND.set(this.buf, this.index * TAOS_BIND.size, float); - this.index++ - } else { - throw new TDError(`bindFloat() failed with ${val},since index:${this.index} is out of Buffer bound ${this.num}.`); - } - } - /** - * - * @param {double} val is a not null double value - */ - bindDouble(val) { - if (!this._isOutOfBound()) { - let double = new TAOS_BIND({ - buffer_type: taosConst.C_DOUBLE, - buffer: ref.alloc(ref.types.double, val), - buffer_length: ref.types.double.size, - length: ref.alloc(ref.types.uint64, ref.types.double.size), - is_null: ref.alloc(ref.types.int32, 0), - }); - TAOS_BIND.set(this.buf, this.index * TAOS_BIND.size, double); - this.index++ - } else { - throw new TDError(`bindDouble() failed with ${val},since index:${this.index} is out of Buffer bound ${this.num}.`); - } - } - - /** - * - * @param {string} val is a string. - */ - bindBinary(val) { - let cstringBuf = ref.allocCString(val, 'utf-8'); - if (!this._isOutOfBound()) { - let binary = new TAOS_BIND({ - buffer_type: taosConst.C_BINARY, - buffer: cstringBuf, - buffer_length: cstringBuf.length, - length: ref.alloc(ref.types.uint64, cstringBuf.length - 1), - is_null: ref.alloc(ref.types.int32, 0), - }); - TAOS_BIND.set(this.buf, this.index * TAOS_BIND.size, binary); - this.index++ - } else { - throw new TDError(`bindBinary() failed with ${val},since index:${this.index} is out of Buffer bound ${this.num}.`); - } - } - - /** - * - * @param {long} val is a not null timestamp(long) values. - */ - bindTimestamp(val) { - let ts = new TAOS_BIND({ - buffer_type: taosConst.C_TIMESTAMP, - buffer: ref.alloc(ref.types.int64, val), - buffer_length: ref.types.int64.size, - length: ref.alloc(ref.types.uint64, ref.types.int64.size), - is_null: ref.alloc(ref.types.int32, 0), - }); - - TAOS_BIND.set(this.buf, this.index * TAOS_BIND.size, ts); - this.index++ - } - - /** - * - * @param {string} val is a string. - */ - bindNchar(val) { - let cstringBuf = ref.allocCString(val, 'utf-8'); - if (!this._isOutOfBound()) { - let nchar = new TAOS_BIND({ - buffer_type: taosConst.C_NCHAR, - buffer: cstringBuf, - buffer_length: cstringBuf.length, - length: ref.alloc(ref.types.uint64, cstringBuf.length - 1), - is_null: ref.alloc(ref.types.int32, 0), - }); - TAOS_BIND.set(this.buf, this.index * TAOS_BIND.size, nchar); - this.index++ - } else { - throw new TDError(`bindNchar() failed with ${val},since index:${this.index} is out of Buffer bound ${this.num}.`); - } - } - - /** - * - * @param {uint8} val is a not null unsinged tinyint value. - */ - bindUTinyInt(val) { - if (!this._isOutOfBound()) { - let uTinyInt = new TAOS_BIND({ - buffer_type: taosConst.C_TINYINT_UNSIGNED, - buffer: ref.alloc(ref.types.uint8, val), - buffer_length: ref.types.uint8.size, - length: ref.alloc(ref.types.uint64, ref.types.uint8.size), - is_null: ref.alloc(ref.types.int32, 0), - }); - - TAOS_BIND.set(this.buf, this.index * TAOS_BIND.size, uTinyInt); - this.index++ - } else { - throw new TDError(`bindUTinyInt() failed with ${val},since index:${this.index} is out of Buffer bound ${this.num}.`); - } - } - - /** - * - * @param {uint16} val is a not null unsinged smallint value. - */ - bindUSmallInt(val) { - if (!this._isOutOfBound()) { - let uSmallInt = new TAOS_BIND({ - buffer_type: taosConst.C_SMALLINT_UNSIGNED, - buffer: ref.alloc(ref.types.uint16, val), - buffer_length: ref.types.uint16.size, - length: ref.alloc(ref.types.uint64, ref.types.uint16.size), - is_null: ref.alloc(ref.types.int32, 0), - }); - - TAOS_BIND.set(this.buf, this.index * TAOS_BIND.size, uSmallInt); - this.index++ - } else { - throw new TDError(`bindUSmallInt() failed with ${val},since index:${this.index} is out of Buffer bound ${this.num}.`); - } - } - - /** - * - * @param {uint32} val is a not null unsinged int value. - */ - bindUInt(val) { - if (!this._isOutOfBound()) { - let uInt = new TAOS_BIND({ - buffer_type: taosConst.C_INT_UNSIGNED, - buffer: ref.alloc(ref.types.uint32, val), - buffer_length: ref.types.uint32.size, - length: ref.alloc(ref.types.uint64, ref.types.uint32.size), - is_null: ref.alloc(ref.types.int32, 0), - }); - - TAOS_BIND.set(this.buf, this.index * TAOS_BIND.size, uInt); - this.index++ - } else { - throw new TDError(`bindUInt() failed with ${val},since index:${this.index} is out of Buffer bound ${this.num}.`); - } - } - - /** - * - * @param {uint64} val is a not null unsinged bigint value. - */ - bindUBigInt(val) { - if (!this._isOutOfBound()) { - let uBigInt = new TAOS_BIND({ - buffer_type: taosConst.C_BIGINT_UNSIGNED, - buffer: ref.alloc(ref.types.uint64, val.toString()), - buffer_length: ref.types.uint64.size, - length: ref.alloc(ref.types.uint64, ref.types.uint64.size), - is_null: ref.alloc(ref.types.int32, 0), - }); - - TAOS_BIND.set(this.buf, this.index * TAOS_BIND.size, uBigInt); - this.index++ - } else { - throw new TDError(`bindUBigInt() failed with ${val},since index:${this.index} is out of Buffer bound ${this.num}.`); - } - } - - /** - * - * @param {jsonStr} val is a json string. Such as '{\"key1\":\"taosdata\"}' - */ - bindJson(val) { - let cstringBuf = ref.allocCString(val, 'utf-8'); - if (!this._isOutOfBound()) { - let jsonType = new TAOS_BIND({ - buffer_type: taosConst.C_JSON_TAG, - buffer: cstringBuf, - buffer_length: cstringBuf.length, - length: ref.alloc(ref.types.uint64, cstringBuf.length - 1), - is_null: ref.alloc(ref.types.int32, 0), - }); - - TAOS_BIND.set(this.buf, this.index * TAOS_BIND.size, jsonType); - this.index++ - } else { - throw new TDError(`bindJson() failed with ${val},since index:${this.index} is out of Buffer bound ${this.num}.`); - } - - } - - /** - * - * @returns binded buffer. - */ - getBind() { - return this.buf; - } - - _isOutOfBound() { - if (this.num > this.index) { - return false; - } else { - return true; - } - } -} -module.exports = TaosBind; diff --git a/src/connector/nodejs/nodetaos/taosMultiBind.js b/src/connector/nodejs/nodetaos/taosMultiBind.js deleted file mode 100755 index d4134a9ef6df29f196e9b573a5f8e2e524de21ed..0000000000000000000000000000000000000000 --- a/src/connector/nodejs/nodetaos/taosMultiBind.js +++ /dev/null @@ -1,531 +0,0 @@ -const ref = require('ref-napi'); -const StructType = require('ref-struct-di')(ref); -const taosConst = require('./constants'); - -var TAOS_MULTI_BIND = StructType({ - 'buffer_type': ref.types.int, - 'buffer': ref.refType(ref.types.void), - 'buffer_length': ref.types.ulong, - 'length': ref.refType(ref.types.int), - 'is_null': ref.refType(ref.types.char), - 'num': ref.types.int, -}) - -class TaosMultiBind { - constructor() { - } - - /** - * To bind bool through an array. - * @param {*} boolArray is an boolean array that stores one column's value. - * @returns A instance of struct TAOS_MULTI_BIND that contains one column's data with bool type. - */ - multiBindBool(boolArray) { - let mbindBufferBuf = Buffer.alloc(ref.types.bool.size * boolArray.length); - let mbindLengBuf = Buffer.alloc(ref.types.int.size * boolArray.length); - let mbindIsNullBuf = Buffer.alloc(ref.types.char.size * boolArray.length); - - boolArray.forEach((element, index) => { - ref.set(mbindLengBuf, index * ref.types.int.size, ref.types.bool.size, ref.types.int) - if (element == null || element == undefined) { - // ref.set(mbindBufferBuf,index * ref.types.int64.size,taosConst.C_BIGINT_NULL,ref.types.int64); - ref.set(mbindIsNullBuf, index * ref.types.char.size, 1, ref.types.char); - } else { - ref.set(mbindBufferBuf, index * ref.types.bool.size, element, ref.types.bool); - ref.set(mbindIsNullBuf, index * ref.types.char.size, 0, ref.types.char); - } - - }); - - let mbind = new TAOS_MULTI_BIND({ - buffer_type: taosConst.C_BOOL, - buffer: mbindBufferBuf, - buffer_length: ref.types.bool.size, - length: mbindLengBuf, - is_null: mbindIsNullBuf, - num: boolArray.length, - }) - return mbind; - } - - /** - * to bind tiny int through an array. - * @param {*} tinyIntArray is an array that stores tiny int. - * @returns A instance of struct TAOS_MULTI_BIND that contains one column's data with tiny int. - */ - multiBindTinyInt(tinyIntArray) { - let mbindBufferBuf = Buffer.alloc(ref.types.int8.size * tinyIntArray.length); - let mbindLengBuf = Buffer.alloc(ref.types.int.size * tinyIntArray.length); - let mbindIsNullBuf = Buffer.alloc(ref.types.char.size * tinyIntArray.length); - - tinyIntArray.forEach((element, index) => { - ref.set(mbindLengBuf, index * ref.types.int.size, ref.types.int8.size, ref.types.int) - if (element == null || element == undefined) { - // ref.set(mbindBufferBuf,index * ref.types.int64.size,taosConst.C_BIGINT_NULL,ref.types.int64); - ref.set(mbindIsNullBuf, index * ref.types.char.size, 1, ref.types.char); - } else { - ref.set(mbindBufferBuf, index * ref.types.int8.size, element, ref.types.int8); - ref.set(mbindIsNullBuf, index * ref.types.char.size, 0, ref.types.char); - } - - }); - - let mbind = new TAOS_MULTI_BIND({ - buffer_type: taosConst.C_TINYINT, - buffer: mbindBufferBuf, - buffer_length: ref.types.int8.size, - length: mbindLengBuf, - is_null: mbindIsNullBuf, - num: tinyIntArray.length, - }) - return mbind; - } - - /** - * To bind small int through an array. - * @param {*} smallIntArray is an array that stores small int. - * @returns A instance of struct TAOS_MULTI_BIND that contains one column's data with small int. - */ - multiBindSmallInt(smallIntArray) { - let mbindBufferBuf = Buffer.alloc(ref.types.int16.size * smallIntArray.length); - let mbindLengBuf = Buffer.alloc(ref.types.int.size * smallIntArray.length); - let mbindIsNullBuf = Buffer.alloc(ref.types.char.size * smallIntArray.length); - - smallIntArray.forEach((element, index) => { - ref.set(mbindLengBuf, index * ref.types.int.size, ref.types.int16.size, ref.types.int) - if (element == null || element == undefined) { - ref.set(mbindIsNullBuf, index * ref.types.char.size, 1, ref.types.char); - } else { - ref.set(mbindBufferBuf, index * ref.types.int16.size, element, ref.types.int16); - ref.set(mbindIsNullBuf, index * ref.types.char.size, 0, ref.types.char); - } - - }); - - let mbind = new TAOS_MULTI_BIND({ - buffer_type: taosConst.C_SMALLINT, - buffer: mbindBufferBuf, - buffer_length: ref.types.int16.size, - length: mbindLengBuf, - is_null: mbindIsNullBuf, - num: smallIntArray.length, - }) - return mbind; - } - - /** - * To bind int through an array. - * @param {*} intArray is an array that stores int. - * @returns A instance of struct TAOS_MULTI_BIND that contains one column's data with int. - */ - multiBindInt(intArray) { - let mbindBufferBuf = Buffer.alloc(ref.types.int.size * intArray.length); - let mbindLengBuf = Buffer.alloc(ref.types.int.size * intArray.length); - let mbindIsNullBuf = Buffer.alloc(ref.types.char.size * intArray.length); - - intArray.forEach((element, index) => { - ref.set(mbindLengBuf, index * ref.types.int.size, ref.types.int.size, ref.types.int) - if (element == null || element == undefined) { - ref.set(mbindIsNullBuf, index * ref.types.char.size, 1, ref.types.char); - } else { - ref.set(mbindBufferBuf, index * ref.types.int.size, element, ref.types.int); - ref.set(mbindIsNullBuf, index * ref.types.char.size, 0, ref.types.char); - } - - }); - - let mbind = new TAOS_MULTI_BIND({ - buffer_type: taosConst.C_INT, - buffer: mbindBufferBuf, - buffer_length: ref.types.int.size, - length: mbindLengBuf, - is_null: mbindIsNullBuf, - num: intArray.length, - }) - return mbind; - } - - /** - * To bind big int through an array. - * @param {*} bigIntArray is an array that stores big int. - * @returns A instance of struct TAOS_MULTI_BIND that contains one column's data with big int. - */ - multiBindBigInt(bigIntArray) { - let mbindBufferBuf = Buffer.alloc(ref.types.int64.size * bigIntArray.length); - let mbindLengBuf = Buffer.alloc(ref.types.int.size * bigIntArray.length); - let mbindIsNullBuf = Buffer.alloc(ref.types.char.size * bigIntArray.length); - - bigIntArray.forEach((element, index) => { - ref.set(mbindLengBuf, index * ref.types.int.size, ref.types.int64.size, ref.types.int) - if (element == null || element == undefined) { - ref.set(mbindIsNullBuf, index * ref.types.char.size, 1, ref.types.char); - } else { - ref.writeInt64LE(mbindBufferBuf, index * ref.types.int64.size, element.toString()) - ref.set(mbindIsNullBuf, index * ref.types.char.size, 0, ref.types.char); - } - - }); - - let mbind = new TAOS_MULTI_BIND({ - buffer_type: taosConst.C_BIGINT, - buffer: mbindBufferBuf, - buffer_length: ref.types.int64.size, - length: mbindLengBuf, - is_null: mbindIsNullBuf, - num: bigIntArray.length, - }) - return mbind; - } - - /** - * To bind float through an array. - * @param {*} floatArray is an array that stores float. - * @returns A instance of struct TAOS_MULTI_BIND that contains one column's data with float. - */ - multiBindFloat(floatArray) { - let mbindBufferBuf = Buffer.alloc(ref.types.float.size * floatArray.length); - let mbindLengBuf = Buffer.alloc(ref.types.int.size * floatArray.length); - let mbindIsNullBuf = Buffer.alloc(ref.types.char.size * floatArray.length); - - floatArray.forEach((element, index) => { - ref.set(mbindLengBuf, index * ref.types.int.size, ref.types.float.size, ref.types.int) - if (element == null || element == undefined) { - ref.set(mbindIsNullBuf, index * ref.types.char.size, 1, ref.types.char); - } else { - ref.set(mbindBufferBuf, index * ref.types.float.size, element, ref.types.float); - ref.set(mbindIsNullBuf, index * ref.types.char.size, 0, ref.types.char); - } - - }); - - let mbind = new TAOS_MULTI_BIND({ - buffer_type: taosConst.C_FLOAT, - buffer: mbindBufferBuf, - buffer_length: ref.types.float.size, - length: mbindLengBuf, - is_null: mbindIsNullBuf, - num: floatArray.length, - }) - return mbind; - } - - /** - * To bind double through an array. - * @param {*} doubleArray is an array that stores double. - * @returns A instance of struct TAOS_MULTI_BIND that contains one column's data with double. - */ - multiBindDouble(doubleArray) { - let mbindBufferBuf = Buffer.alloc(ref.types.double.size * doubleArray.length); - let mbindLengBuf = Buffer.alloc(ref.types.int.size * doubleArray.length); - let mbindIsNullBuf = Buffer.alloc(ref.types.char.size * doubleArray.length); - - doubleArray.forEach((element, index) => { - ref.set(mbindLengBuf, index * ref.types.int.size, ref.types.double.size, ref.types.int) - if (element == null || element == undefined) { - ref.set(mbindIsNullBuf, index * ref.types.char.size, 1, ref.types.char); - } else { - ref.set(mbindBufferBuf, index * ref.types.double.size, element, ref.types.double); - ref.set(mbindIsNullBuf, index * ref.types.char.size, 0, ref.types.char); - } - - }); - - let mbind = new TAOS_MULTI_BIND({ - buffer_type: taosConst.C_DOUBLE, - buffer: mbindBufferBuf, - buffer_length: ref.types.double.size, - length: mbindLengBuf, - is_null: mbindIsNullBuf, - num: doubleArray.length, - }) - return mbind; - } - - /** - * To bind tdengine's binary through an array. - * @param {*} strArr is an array that stores string. - * (Null string can be defined as undefined or null,notice '' is not null.) - * @returns A instance of struct TAOS_MULTI_BIND that contains one column's data with binary. - */ - multiBindBinary(strArr) { - let maxStrUFT8Length = this._maxUTF8StrArrLength(strArr); - console.log(`maxStrUFT8Length * strArr.length=${maxStrUFT8Length * strArr.length}`); - let mbindBufferBuf = Buffer.alloc(maxStrUFT8Length * strArr.length); - let mbindLengBuf = Buffer.alloc(ref.types.int.size * strArr.length); - let mbindIsNullBuf = Buffer.alloc(ref.types.char.size * strArr.length); - - strArr.forEach((element, index) => { - ref.set(mbindLengBuf, index * ref.types.int.size, this._stringUTF8Length(element), ref.types.int) - if (element == null || element == undefined) { - ref.set(mbindIsNullBuf, index * ref.types.char.size, 1, ref.types.char); - } else { - ref.writeCString(mbindBufferBuf, index * maxStrUFT8Length, element, 'utf8'); - ref.set(mbindIsNullBuf, index * ref.types.char.size, 0, ref.types.char); - } - }); - - let mbind = new TAOS_MULTI_BIND({ - buffer_type: taosConst.C_BINARY, - buffer: mbindBufferBuf, - buffer_length: maxStrUFT8Length, - length: mbindLengBuf, - is_null: mbindIsNullBuf, - num: strArr.length, - }) - return mbind; - } - - /** - * To bind timestamp through an array. - * @param {*} timestampArray is an array that stores timestamp. - * @returns A instance of struct TAOS_MULTI_BIND that contains one column's data with timestamp. - */ - multiBindTimestamp(timestampArray) { - let mbindBufferBuf = Buffer.alloc(ref.types.int64.size * timestampArray.length); - let mbindLengBuf = Buffer.alloc(ref.types.int.size * timestampArray.length); - let mbindIsNullBuf = Buffer.alloc(ref.types.char.size * timestampArray.length); - - timestampArray.forEach((element, index) => { - ref.set(mbindLengBuf, index * ref.types.int.size, ref.types.int64.size, ref.types.int) - if (element == null || element == undefined) { - ref.set(mbindIsNullBuf, index * ref.types.char.size, 1, ref.types.char); - } else { - ref.writeInt64LE(mbindBufferBuf, index * ref.types.int64.size, element.toString()) - ref.set(mbindIsNullBuf, index * ref.types.char.size, 0, ref.types.char); - } - - }); - - let mbind = new TAOS_MULTI_BIND({ - buffer_type: taosConst.C_TIMESTAMP, - buffer: mbindBufferBuf, - buffer_length: ref.types.int64.size, - length: mbindLengBuf, - is_null: mbindIsNullBuf, - num: timestampArray.length, - }) - return mbind; - } - - /** - * To bind tdengine's nchar through an array. - * @param {*} strArr is an array that stores string. - * (Null string can be defined as undefined or null,notice '' is not null.) - * @returns A instance of struct TAOS_MULTI_BIND that contains one nchar column's data with nchar. - */ - multiBindNchar(strArr) { - let maxStrUFT8Length = this._maxUTF8StrArrLength(strArr); - // console.log(`maxStrUFT8Length * strArr.length=${maxStrUFT8Length * strArr.length}`); - let mbindBufferBuf = Buffer.alloc(maxStrUFT8Length * strArr.length); - let mbindLengBuf = Buffer.alloc(ref.types.int.size * strArr.length); - let mbindIsNullBuf = Buffer.alloc(ref.types.char.size * strArr.length); - - strArr.forEach((element, index) => { - ref.set(mbindLengBuf, index * ref.types.int.size, this._stringUTF8Length(element), ref.types.int) - if (element == null || element == undefined) { - ref.set(mbindIsNullBuf, index * ref.types.char.size, 1, ref.types.char); - } else { - ref.writeCString(mbindBufferBuf, index * maxStrUFT8Length, element, 'utf8'); - ref.set(mbindIsNullBuf, index * ref.types.char.size, 0, ref.types.char); - } - }); - - let mbind = new TAOS_MULTI_BIND({ - buffer_type: taosConst.C_NCHAR, - buffer: mbindBufferBuf, - buffer_length: maxStrUFT8Length, - length: mbindLengBuf, - is_null: mbindIsNullBuf, - num: strArr.length, - }) - return mbind; - } - - /** - * to bind unsigned tiny int through an array. - * @param {*} uTinyIntArray is an array that stores unsigned tiny int. - * @returns A instance of struct TAOS_MULTI_BIND that contains one column's data with unsigned tiny int. - */ - multiBindUTinyInt(uTinyIntArray) { - let mbindBufferBuf = Buffer.alloc(ref.types.uint8.size * uTinyIntArray.length); - let mbindLengBuf = Buffer.alloc(ref.types.int.size * uTinyIntArray.length); - let mbindIsNullBuf = Buffer.alloc(ref.types.char.size * uTinyIntArray.length); - - uTinyIntArray.forEach((element, index) => { - ref.set(mbindLengBuf, index * ref.types.int.size, ref.types.uint8.size, ref.types.int) - if (element == null || element == undefined) { - ref.set(mbindIsNullBuf, index * ref.types.char.size, 1, ref.types.char); - } else { - ref.set(mbindBufferBuf, index * ref.types.uint8.size, element, ref.types.uint8); - ref.set(mbindIsNullBuf, index * ref.types.char.size, 0, ref.types.char); - } - - }); - - let mbind = new TAOS_MULTI_BIND({ - buffer_type: taosConst.C_TINYINT_UNSIGNED, - buffer: mbindBufferBuf, - buffer_length: ref.types.uint8.size, - length: mbindLengBuf, - is_null: mbindIsNullBuf, - num: uTinyIntArray.length, - }) - return mbind; - } - - /** - * To bind unsigned small int through an array. - * @param {*} uSmallIntArray is an array that stores unsigned small int. - * @returns A instance of struct TAOS_MULTI_BIND that contains one column's data with unsigned small int. - */ - multiBindUSmallInt(uSmallIntArray) { - let mbindBufferBuf = Buffer.alloc(ref.types.uint16.size * uSmallIntArray.length); - let mbindLengBuf = Buffer.alloc(ref.types.int.size * uSmallIntArray.length); - let mbindIsNullBuf = Buffer.alloc(ref.types.char.size * uSmallIntArray.length); - - uSmallIntArray.forEach((element, index) => { - ref.set(mbindLengBuf, index * ref.types.int.size, ref.types.uint16.size, ref.types.int) - if (element == null || element == undefined) { - ref.set(mbindIsNullBuf, index * ref.types.char.size, 1, ref.types.char); - } else { - ref.set(mbindBufferBuf, index * ref.types.uint16.size, element, ref.types.uint16); - ref.set(mbindIsNullBuf, index * ref.types.char.size, 0, ref.types.char); - } - - }); - - let mbind = new TAOS_MULTI_BIND({ - buffer_type: taosConst.C_SMALLINT_UNSIGNED, - buffer: mbindBufferBuf, - buffer_length: ref.types.uint16.size, - length: mbindLengBuf, - is_null: mbindIsNullBuf, - num: uSmallIntArray.length, - }) - return mbind; - } - - /** - * To bind unsigned int through an array. - * @param {*} uIntArray is an array that stores unsigned int. - * @returns A instance of struct TAOS_MULTI_BIND that contains one column's data with unsigned int. - */ - multiBindUInt(uIntArray) { - let mbindBufferBuf = Buffer.alloc(ref.types.uint.size * uIntArray.length); - let mbindLengBuf = Buffer.alloc(ref.types.int.size * uIntArray.length); - let mbindIsNullBuf = Buffer.alloc(ref.types.char.size * uIntArray.length); - - uIntArray.forEach((element, index) => { - ref.set(mbindLengBuf, index * ref.types.int.size, ref.types.uint.size, ref.types.int) - if (element == null || element == undefined) { - ref.set(mbindIsNullBuf, index * ref.types.char.size, 1, ref.types.char); - } else { - ref.set(mbindBufferBuf, index * ref.types.uint.size, element, ref.types.uint); - ref.set(mbindIsNullBuf, index * ref.types.char.size, 0, ref.types.char); - } - - }); - - let mbind = new TAOS_MULTI_BIND({ - buffer_type: taosConst.C_INT_UNSIGNED, - buffer: mbindBufferBuf, - buffer_length: ref.types.uint.size, - length: mbindLengBuf, - is_null: mbindIsNullBuf, - num: uIntArray.length, - }) - return mbind; - } - - /** - * To bind unsigned big int through an array. - * @param {*} uBigIntArray is an array that stores unsigned big int. - * @returns A instance of struct TAOS_MULTI_BIND that contains one column's data with unsigned big int. - */ - multiBindUBigInt(uBigIntArray) { - let mbindBufferBuf = Buffer.alloc(ref.types.uint64.size * uBigIntArray.length); - let mbindLengBuf = Buffer.alloc(ref.types.int.size * uBigIntArray.length); - let mbindIsNullBuf = Buffer.alloc(ref.types.char.size * uBigIntArray.length); - - uBigIntArray.forEach((element, index) => { - ref.set(mbindLengBuf, index * ref.types.int.size, ref.types.uint64.size, ref.types.int) - if (element == null || element == undefined) { - ref.set(mbindIsNullBuf, index * ref.types.char.size, 1, ref.types.char); - } else { - - ref.writeUInt64LE(mbindBufferBuf, index * ref.types.uint64.size, element.toString()) - ref.set(mbindIsNullBuf, index * ref.types.char.size, 0, ref.types.char); - } - - }); - - let mbind = new TAOS_MULTI_BIND({ - buffer_type: taosConst.C_BIGINT_UNSIGNED, - buffer: mbindBufferBuf, - buffer_length: ref.types.uint64.size, - length: mbindLengBuf, - is_null: mbindIsNullBuf, - num: uBigIntArray.length, - }) - return mbind; - } - - - // multiBJson(jsonArray) no need to support.Since till now TDengine only support json tag - // and there is no need to support bind json tag in TAOS_MULTI_BIND. - - /** - * - * @param {*} strArr an string array - * @returns return the max length of the element in strArr in "UFT-8" encoding. - */ - _maxUTF8StrArrLength(strArr) { - let max = 0; - strArr.forEach((item) => { - let realLeng = 0; - let itemLength = -1; - if (item == null || item == undefined) { - itemLength = 0; - } else { - itemLength = item.length; - } - - let charCode = -1; - for (let i = 0; i < itemLength; i++) { - charCode = item.charCodeAt(i); - if (charCode >= 0 && charCode <= 128) { - realLeng += 1; - } else { - realLeng += 3; - } - } - if (max < realLeng) { - max = realLeng - }; - }); - return max; - } - - /** - * - * @param {*} str a string. - * @returns return the length of the input string encoding with utf-8. - */ - _stringUTF8Length(str) { - let leng = 0; - if (str == null || str == undefined) { - leng = 0; - } else { - for (let i = 0; i < str.length; i++) { - if (str.charCodeAt(i) >= 0 && str.charCodeAt(i) <= 128) { - leng += 1; - } else { - leng += 3; - } - } - } - return leng; - } -} -// console.log(TAOS_MULTI_BIND.size) -module.exports = { TaosMultiBind, TAOS_MULTI_BIND }; \ No newline at end of file diff --git a/src/connector/nodejs/nodetaos/taosMultiBindArr.js b/src/connector/nodejs/nodetaos/taosMultiBindArr.js deleted file mode 100755 index 68c9c95bddad725b6dc10fe7766c1ad46adc2919..0000000000000000000000000000000000000000 --- a/src/connector/nodejs/nodetaos/taosMultiBindArr.js +++ /dev/null @@ -1,250 +0,0 @@ -const ref = require('ref-napi'); -const { TDError } = require('./error'); -const { TAOS_MULTI_BIND, TaosMultiBind } = require('./taosMultiBind'); - -const TAOS_MULTI_BIND_SIZE = TAOS_MULTI_BIND.size; - -class TaosMultiBindArr extends TaosMultiBind { - /** - * The constructor,initial basic parameters and alloc buffer. - * @param {*} numOfColumns the number of column that you want to bind parameters. - */ - constructor(numOfColumns) { - super(); - this.taosMBindArrBuf = Buffer.alloc(numOfColumns * TAOS_MULTI_BIND_SIZE); - this.index = 0; - this.bound = numOfColumns; - } - - /** - * Used to bind boolean column's values. - * @param {*} boolArray An array of bool value, - * represents the bool values you want to bind. - */ - multiBindBool(boolArray) { - if (this.bound > this.index) { - let mBindBool = super.multiBindBool(boolArray); - TAOS_MULTI_BIND.set(this.taosMBindArrBuf, this.index * TAOS_MULTI_BIND_SIZE, mBindBool); - this.index += 1; - } else { - throw new TDError(`multiBindArrBool() failed,since index:${this.index} is out of Buffer bound ${this.bound}.`) - } - } - - /** - * Used to bind tiny int column's values. - * @param {*} tinyIntArray An array of tiny int value. - * represents the tiny int values you want to bind. - */ - multiBindTinyInt(tinyIntArray) { - if (this.bound > this.index) { - let mBindTinyInt = super.multiBindTinyInt(tinyIntArray); - TAOS_MULTI_BIND.set(this.taosMBindArrBuf, this.index * TAOS_MULTI_BIND_SIZE, mBindTinyInt); - this.index += 1; - } else { - throw new TDError(`multiBindArrTinyInt() failed,since index:${this.index} is out of Buffer bound ${this.bound}.`) - } - } - - /** - * Used to bind small int column's value. - * @param {*} smallIntArray An array of small int values, - * represents the small int values you want to bind. - */ - multiBindSmallInt(smallIntArray) { - if (this.bound > this.index) { - let mBindSmallInt = super.multiBindSmallInt(smallIntArray); - TAOS_MULTI_BIND.set(this.taosMBindArrBuf, this.index * TAOS_MULTI_BIND_SIZE, mBindSmallInt); - this.index += 1; - } else { - throw new TDError(`multiBindSmallInt() failed,since index:${this.index} is out of Buffer bound ${this.bound}.`) - } - - } - - /** - * Used to bind int column's value. - * @param {*} intArray An array of int values, - * represents the int values you want to bind. - */ - multiBindInt(intArray) { - if (this.bound > this.index) { - let mBindInt = super.multiBindInt(intArray); - TAOS_MULTI_BIND.set(this.taosMBindArrBuf, this.index * TAOS_MULTI_BIND_SIZE, mBindInt); - this.index += 1; - } else { - throw new TDError(`multiBindInt() failed,since index:${this.index} is out of Buffer bound ${this.bound}.`) - } - - } - - /** - * Used to bind big int column's value. - * @param {*} bigIntArray An array of big int values, - * represents the big int values you want to bind. - */ - multiBindBigInt(bigIntArray) { - if (this.bound > this.index) { - let mBindBigInt = super.multiBindBigInt(bigIntArray); - TAOS_MULTI_BIND.set(this.taosMBindArrBuf, this.index * TAOS_MULTI_BIND_SIZE, mBindBigInt); - this.index += 1; - } else { - throw new TDError(`multiBindBigInt() failed,since index:${this.index} is out of Buffer bound ${this.bound}.`) - } - - } - - /** - * Used to bind float column's value. - * @param {*} floatArray An array of float values, - * represents the float values you want to bind. - */ - multiBindFloat(floatArray) { - if (this.bound > this.index) { - let mBindFloat = super.multiBindFloat(floatArray); - TAOS_MULTI_BIND.set(this.taosMBindArrBuf, this.index * TAOS_MULTI_BIND_SIZE, mBindFloat); - this.index += 1; - } else { - throw new TDError(`multiBindFloat() failed,since index:${this.index} is out of Buffer bound ${this.bound}.`) - } - - } - - /** - * Used to bind double column's value. - * @param {*} doubleArray An array of double values, - * represents the double values you want to bind. - */ - multiBindDouble(doubleArray) { - if (this.bound > this.index) { - let mBindDouble = super.multiBindDouble(doubleArray); - TAOS_MULTI_BIND.set(this.taosMBindArrBuf, this.index * TAOS_MULTI_BIND_SIZE, mBindDouble); - this.index += 1; - } else { - throw new TDError(`multiBindDouble() failed,since index:${this.index} is out of Buffer bound ${this.bound}.`) - } - - } - - /** - * Used to bind binary column's value. - * @param {*} strArr An array of binary(string) values, - * represents the binary values you want to bind. - * Notice '' is not equal to TDengine's "null" value. - */ - multiBindBinary(strArr) { - if (this.bound > this.index) { - let mBindBinary = super.multiBindBinary(strArr); - TAOS_MULTI_BIND.set(this.taosMBindArrBuf, this.index * TAOS_MULTI_BIND_SIZE, mBindBinary); - this.index += 1; - } else { - throw new TDError(`multiBindBinary() failed,since index:${this.index} is out of Buffer bound ${this.bound}.`) - } - } - - /** - * Used to bind timestamp column's values. - * @param {*} timestampArray An array of timestamp values, - * represents the timestamp values you want to bind. - */ - multiBindTimestamp(timestampArray) { - if (this.bound > this.index) { - let mBindTimestamp = super.multiBindTimestamp(timestampArray); - TAOS_MULTI_BIND.set(this.taosMBindArrBuf, this.index * TAOS_MULTI_BIND_SIZE, mBindTimestamp); - this.index += 1; - } else { - throw new TDError(`multiBindArrTimestamp() failed,since index:${this.index} is out of Buffer bound ${this.bound}.`) - } - } - - /** - * Used to bind nchar column's value. - * @param {*} strArr An array of nchar(string) values, - * represents the nchar values you want to bind. - * Notice '' is not equal to TDengine's "null" value. - */ - multiBindNchar(strArr) { - if (this.bound > this.index) { - let mBindNchar = super.multiBindNchar(strArr); - TAOS_MULTI_BIND.set(this.taosMBindArrBuf, this.index * TAOS_MULTI_BIND_SIZE, mBindNchar); - this.index += 1; - } else { - throw new TDError(`multiBindNchar() failed,since index:${this.index} is out of Buffer bound ${this.bound}.`) - } - } - - /** - * Used to bind unsigned tiny int column's value. - * @param {*} uTinyIntArray An array of unsigned tiny int values, - * represents the unsigned tiny int values you want to bind. - */ - multiBindUTinyInt(uTinyIntArray) { - if (this.bound > this.index) { - let mBindNchar = super.multiBindUTinyInt(uTinyIntArray); - TAOS_MULTI_BIND.set(this.taosMBindArrBuf, this.index * TAOS_MULTI_BIND_SIZE, mBindNchar); - this.index += 1; - } else { - throw new TDError(`multiBindUTinyInt() failed,since index:${this.index} is out of Buffer bound ${this.bound}.`) - } - } - - /** - * Used to bind unsigned small int column's value. - * @param {*} uSmallIntArray An array of unsigned small int value, - * represents the unsigned small int values you want to bind. - */ - multiBindUSmallInt(uSmallIntArray) { - if (this.bound > this.index) { - let mBindUSmallInt = super.multiBindUSmallInt(uSmallIntArray); - TAOS_MULTI_BIND.set(this.taosMBindArrBuf, this.index * TAOS_MULTI_BIND_SIZE, mBindUSmallInt); - this.index += 1; - } else { - throw new TDError(`multiBindUSmallInt() failed,since index:${this.index} is out of Buffer bound ${this.bound}.`) - } - } - - /** - * Used to bind unsigned int column's value. - * @param {*} uIntArray An array of unsigned int column's value, - * represents the unsigned int values you want to bind. - */ - multiBindUInt(uIntArray) { - if (this.bound > this.index) { - let mBindUInt = super.multiBindUInt(uIntArray); - TAOS_MULTI_BIND.set(this.taosMBindArrBuf, this.index * TAOS_MULTI_BIND_SIZE, mBindUInt); - this.index += 1; - } else { - throw new TDError(`multiBindUInt() failed,since index:${this.index} is out of Buffer bound ${this.bound}.`) - } - } - - /** - * Used to bind unsigned big int column's value. - * @param {*} uBigIntArray An array of unsigned big int column's value, - * represents the unsigned big int values you want to bind. - */ - multiBindUBigInt(uBigIntArray) { - if (this.bound > this.index) { - let mBindUBigInt = super.multiBindUBigInt(uBigIntArray); - TAOS_MULTI_BIND.set(this.taosMBindArrBuf, this.index * TAOS_MULTI_BIND_SIZE, mBindUBigInt); - this.index += 1; - } else { - throw new TDError(`multiBindUBigInt() failed,since index:${this.index} is out of Buffer bound ${this.bound}.`) - } - } - - // multiBJson(jsonArray) no need to support.Since till now TDengine only support json tag - // and there is no need to support bind json tag in TAOS_MULTI_BIND. - - - /** - * After all the parameters have been prepared and stored - * in the buffer, Call this method to get the buffer. - * @returns return the buffer which stores all the parameters. - */ - getMultiBindArr() { - return this.taosMBindArrBuf; - } - -} -module.exports = TaosMultiBindArr; \ No newline at end of file diff --git a/src/connector/nodejs/nodetaos/taosobjects.js b/src/connector/nodejs/nodetaos/taosobjects.js deleted file mode 100644 index 3bc0fe0aca060a32daa7a5cebd2dbfb99ac29a7c..0000000000000000000000000000000000000000 --- a/src/connector/nodejs/nodetaos/taosobjects.js +++ /dev/null @@ -1,152 +0,0 @@ -const FieldTypes = require('./constants'); -const util = require('util'); -/** - * Various objects such as TaosRow and TaosColumn that help make parsing data easier - * @module TaosObjects - * - */ - -/** - * The TaosRow object. Contains the data from a retrieved row from a database and functions that parse the data. - * @typedef {Object} TaosRow - A row of data retrieved from a table. - * @global - * @example - * var trow = new TaosRow(row); - * console.log(trow.data); - */ -function TaosRow(row) { - this.data = row; - this.length = row.length; - return this; -} - -/** - * @typedef {Object} TaosField - A field/column's metadata from a table. - * @global - * @example - * var tfield = new TaosField(field); - * console.log(tfield.name); - */ - -function TaosField(field) { - this._field = field; - this.name = field.name; - this.type = FieldTypes.getType(field.type); - return this; -} - -/** - * A TaosTimestamp object, which is the standard date object with added functionality - * @global - * @memberof TaosObjects - * @param {Date} date - A Javascript date time object or the time in milliseconds past 1970-1-1 00:00:00.000 - */ -class TaosTimestamp extends Date { - constructor(date, precision = 0) { - if (precision === 1) { - super(Math.floor(date / 1000)); - this.precisionExtras = date % 1000; - } else if (precision === 2) { - // use BigInt to fix: 1623254400999999999 / 1000000 = 1623254401000 which not expected - super(parseInt(BigInt(date) / 1000000n)); - // use BigInt to fix: 1625801548423914405 % 1000000 = 914496 which not expected (914405) - this.precisionExtras = parseInt(BigInt(date) % 1000000n); - } else { - super(parseInt(date)); - } - this.precision = precision; - } - - /** - * TDengine raw timestamp. - * @returns raw taos timestamp (int64) - */ - taosTimestamp() { - if (this.precision == 1) { - return (this * 1000 + this.precisionExtras); - } else if (this.precision == 2) { - return (this * 1000000 + this.precisionExtras); - } else { - return Math.floor(this); - } - } - - /** - * Gets the microseconds of a Date. - * @return {Int} A microseconds integer - */ - getMicroseconds() { - if (this.precision == 1) { - return this.getMilliseconds() * 1000 + this.precisionExtras; - } else if (this.precision == 2) { - return this.getMilliseconds() * 1000 + this.precisionExtras / 1000; - } else { - return 0; - } - } - /** - * Gets the nanoseconds of a TaosTimestamp. - * @return {Int} A nanoseconds integer - */ - getNanoseconds() { - if (this.precision == 1) { - return this.getMilliseconds() * 1000000 + this.precisionExtras * 1000; - } else if (this.precision == 2) { - return this.getMilliseconds() * 1000000 + this.precisionExtras; - } else { - return 0; - } - } - - /** - * @returns {String} a string for timestamp string format - */ - _precisionExtra() { - if (this.precision == 1) { - return String(this.precisionExtras).padStart(3, '0'); - } else if (this.precision == 2) { - return String(this.precisionExtras).padStart(6, '0'); - } else { - return ''; - } - } - /** - * @function Returns the date into a string usable by TDengine - * @return {string} A Taos Timestamp String - */ - toTaosString() { - var tzo = -this.getTimezoneOffset(), - dif = tzo >= 0 ? '+' : '-', - pad = function (num) { - var norm = Math.floor(Math.abs(num)); - return (norm < 10 ? '0' : '') + norm; - }, - pad2 = function (num) { - var norm = Math.floor(Math.abs(num)); - if (norm < 10) return '00' + norm; - if (norm < 100) return '0' + norm; - if (norm < 1000) return norm; - }; - return this.getFullYear() + - '-' + pad(this.getMonth() + 1) + - '-' + pad(this.getDate()) + - ' ' + pad(this.getHours()) + - ':' + pad(this.getMinutes()) + - ':' + pad(this.getSeconds()) + - '.' + pad2(this.getMilliseconds()) + - '' + this._precisionExtra(); - } - - /** - * Custom console.log - * @returns {String} string format for debug - */ - [util.inspect.custom](depth, opts) { - return this.toTaosString() + JSON.stringify({ precision: this.precision, precisionExtras: this.precisionExtras }, opts); - } - toString() { - return this.toTaosString(); - } -} - -module.exports = { TaosRow, TaosField, TaosTimestamp } diff --git a/src/connector/nodejs/nodetaos/taosquery.js b/src/connector/nodejs/nodetaos/taosquery.js deleted file mode 100644 index 5a6d08fb8f5e74c102ebafaad6d0b1d29a9b741f..0000000000000000000000000000000000000000 --- a/src/connector/nodejs/nodetaos/taosquery.js +++ /dev/null @@ -1,111 +0,0 @@ -var TaosResult = require('./taosresult') -require('./globalfunc.js') -module.exports = TaosQuery; - - -/** - * @class TaosQuery - * @classdesc The TaosQuery class is one level above the TDengine Cursor in that it makes sure to generally return promises from functions, and wrap - * all data with objects such as wrapping a row of data with Taos Row. This is meant to enable an higher level API that allows additional - * functionality and save time whilst also making it easier to debug and enter less problems with the use of promises. - * @param {string} query - Query to construct object from - * @param {TDengineCursor} cursor - The cursor from which this query will execute from - * @param {boolean} execute - Whether or not to immedietely execute the query synchronously and fetch all results. Default is false. - * @property {string} query - The current query in string format the TaosQuery object represents - * @return {TaosQuery} - * @since 1.0.6 - */ -function TaosQuery(query = "", cursor = null, execute = false) { - this.query = query; - this._cursor = cursor; - if (execute == true) { - return this.execute(); - } - return this; -} - -/** - * Executes the query object and returns a Promise - * @memberof TaosQuery - * @return {Promise} A promise that resolves with a TaosResult object, or rejects with an error - * @since 1.0.6 - */ -TaosQuery.prototype.execute = async function execute() { - var taosQuery = this; //store the current instance of taosQuery to avoid async issues? - var executionPromise = new Promise(function(resolve, reject) { - let data = []; - let fields = []; - let result; - try { - taosQuery._cursor.execute(taosQuery.query); - if (taosQuery._cursor._fields) fields = taosQuery._cursor._fields; - if (taosQuery._cursor._result != null) data = taosQuery._cursor.fetchall(); - result = new TaosResult(data, fields) - } - catch(err) { - reject(err); - } - resolve(result) - }); - return executionPromise; -} - -/** - * Executes the query object asynchronously and returns a Promise. Completes query to completion. - * @memberof TaosQuery - * @param {Object} options - Execution options - * @return {Promise} A promise that resolves with a TaosResult object, or rejects with an error - * @since 1.2.0 - */ -TaosQuery.prototype.execute_a = async function execute_a(options = {}) { - var executionPromise = new Promise( (resolve, reject) => { - - }); - var fres; - var frej; - var fetchPromise = new Promise( (resolve, reject) => { - fres = resolve; - frej = reject; - }); - let asyncCallbackFetchall = async function(param, res, numOfRows, blocks) { - if (numOfRows > 0) { - // Likely a query like insert - fres(); - } - else { - fres(new TaosResult(blocks.data, blocks.fields)); - } - } - let asyncCallback = async function(param, res, code) { - //upon success, we fetchall results - this._cursor.fetchall_a(res, options, asyncCallbackFetchall, {}); - } - this._cursor.execute_a(this.query, asyncCallback.bind(this), {}); - return fetchPromise; -} - -/** - * Bind arguments to the query and automatically parses them into the right format - * @param {array | ...args} args - A number of arguments to bind to each ? in the query - * @return {TaosQuery} - * @example - * // An example of binding a javascript date and a number to a query - * var query = cursor.query("select count(*) from meterinfo.meters where ts <= ? and areaid = ?").bind(new Date(), 3); - * var promise1 = query.execute(); - * promise1.then(function(result) { - * result.pretty(); // Log the prettified version of the results. - * }); - * @since 1.0.6 - */ -TaosQuery.prototype.bind = function bind(f, ...args) { - if (typeof f == 'object' && f.constructor.name != 'Array') args.unshift(f); //param is not an array object - else if (typeof f != 'object') args.unshift(f); - else { args = f; } - args.forEach(function(arg) { - if (arg.constructor.name == 'TaosTimestamp') arg = "\"" + arg.toTaosString() + "\""; - else if (arg.constructor.name == 'Date') arg = "\"" + toTaosTSString(arg) + "\""; - else if (typeof arg == 'string') arg = "\"" + arg + "\""; - this.query = this.query.replace(/\?/,arg); - }, this); - return this; -} diff --git a/src/connector/nodejs/nodetaos/taosresult.js b/src/connector/nodejs/nodetaos/taosresult.js deleted file mode 100644 index 1ea5abee9f6c3c2754081ad82ecdb51c3b5bd4d3..0000000000000000000000000000000000000000 --- a/src/connector/nodejs/nodetaos/taosresult.js +++ /dev/null @@ -1,90 +0,0 @@ -require('./globalfunc.js') -const TaosObjects = require('./taosobjects'); -const TaosRow = TaosObjects.TaosRow; -const TaosField = TaosObjects.TaosField; - -module.exports = TaosResult; -/** - * @class TaosResult - * @classdesc A TaosResult class consts of the row data and the fields metadata, all wrapped under various objects for higher functionality. - * @param {Array} data - Array of result rows - * @param {Array} fields - Array of field meta data - * @property {Array} data - Array of TaosRows forming the result data (this does not include field meta data) - * @property {Array} fields - Array of TaosFields forming the fields meta data array. - * @return {TaosResult} - * @since 1.0.6 - */ -function TaosResult(data, fields) { - this.data = data.map(row => new TaosRow(row)); - this.rowcount = this.data.length; - this.fields = fields.map(field => new TaosField(field)); -} -/** - * Pretty print data and the fields meta data as if you were using the taos shell - * @memberof TaosResult - * @function pretty - * @since 1.0.6 - */ - -TaosResult.prototype.pretty = function pretty() { - let fieldsStr = ""; - let sizing = []; - this.fields.forEach((field, i) => { - if (field._field.type == 8 || field._field.type == 10 ) { - sizing.push(Math.max(field.name.length, field._field.bytes)); - } - else { - sizing.push(Math.max(field.name.length, suggestedMinWidths[field._field.type])); - } - fieldsStr += fillEmpty(Math.floor(sizing[i] / 2 - field.name.length / 2)) + field.name + fillEmpty(Math.ceil(sizing[i] / 2 - field.name.length / 2)) + " | "; - }); - var sumLengths = sizing.reduce((a, b) => a += b, (0)) + sizing.length * 3; - - console.log("\n" + fieldsStr); - console.log(printN("=", sumLengths)); - this.data.forEach(row => { - let rowStr = ""; - row.data.forEach((entry, i) => { - if (this.fields[i]._field.type == 9) { - entry = entry.toTaosString(); - } else { - entry = entry == null ? 'null' : entry.toString(); - } - rowStr += entry - rowStr += fillEmpty(sizing[i] - entry.length) + " | "; - }); - console.log(rowStr); - }); -} -const suggestedMinWidths = { - 0: 4, - 1: 4, - 2: 4, - 3: 6, - 4: 11, - 5: 20, - 6: 24, - 7: 24, - 8: 10, - 9: 25, - 10: 10, - 11: 4, - 12: 6, - 13: 11, - 14: 20, - 15: 20, -} -function printN(s, n) { - let f = ""; - for (let i = 0; i < n; i++) { - f += s; - } - return f; -} -function fillEmpty(n) { - let str = ""; - for (let i = 0; i < n; i++) { - str += " "; - } - return str; -} diff --git a/src/connector/nodejs/package.json b/src/connector/nodejs/package.json deleted file mode 100644 index cd1e6fba43ee44693a6611b37d5b664109db5b34..0000000000000000000000000000000000000000 --- a/src/connector/nodejs/package.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "name": "td2.0-connector", - "version": "2.0.11", - "description": "A Node.js connector for TDengine.", - "main": "tdengine.js", - "directories": { - "example": "examples", - "test": "test" - }, - "scripts": { - "test": "jest", - "catalog": "jest --json" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/taosdata/tdengine.git" - }, - "keywords": [ - "TDengine", - "TAOS Data", - "Time Series Database", - "Connector" - ], - "author": "TaosData Inc.", - "license": "AGPL-3.0-or-later", - "bugs": { - "url": "https://github.com/taosdata/tdengine/issues" - }, - "homepage": "https://github.com/taosdata/tdengine#readme", - "dependencies": { - "ffi-napi": "^3.1.0", - "lodash": "^4.17.21", - "ref-array-di": "^1.2.1", - "ref-napi": "^3.0.2", - "ref-struct-di": "^1.1.1" - }, - "devDependencies": { - "jest": "^27.4.7" - } -} diff --git a/src/connector/nodejs/tdengine.js b/src/connector/nodejs/tdengine.js deleted file mode 100644 index 275834bd4f2b5ba5a903049a5973a34287132175..0000000000000000000000000000000000000000 --- a/src/connector/nodejs/tdengine.js +++ /dev/null @@ -1,16 +0,0 @@ -var TDengineConnection = require('./nodetaos/connection.js') -const TDengineConstant = require('./nodetaos/constants.js') -const TaosBind = require('./nodetaos/taosBind') -const { TaosMultiBind } = require('./nodetaos/taosMultiBind') -const TaosMultiBindArr = require('./nodetaos/taosMultiBindArr') - -module.exports = { - connect: function (connection = {}) { - return new TDengineConnection(connection); - }, - SCHEMALESS_PROTOCOL: TDengineConstant.SCHEMALESS_PROTOCOL, - SCHEMALESS_PRECISION: TDengineConstant.SCHEMALESS_PRECISION, - TaosBind, - TaosMultiBind, - TaosMultiBindArr, -} \ No newline at end of file diff --git a/src/connector/nodejs/test/cases/test.cases.js b/src/connector/nodejs/test/cases/test.cases.js deleted file mode 100644 index 2bf92a1c1523cc48a0d2c0b7cabbc778c075cf44..0000000000000000000000000000000000000000 --- a/src/connector/nodejs/test/cases/test.cases.js +++ /dev/null @@ -1,806 +0,0 @@ -// const { testMatch } = require('../../jest.config'); -const taos = require('../../tdengine'); -const { getFeildsFromDll, buildInsertSql, getFieldArr, getResData } = require('../utils/utilTools') - -const author = 'xiaolei'; -const result = 'passed'; -const fileName = __filename.slice(__dirname.length + 1); - -// This is a taos connection -let conn; -// This is a Cursor -let c1; - -function executeUpdate(sql) { - console.log(sql); - c1.execute(sql); -} - -function executeQuery(sql) { - c1.execute(sql, { quiet: true }) - var data = c1.fetchall(); - let fields = c1.fields; - let resArr = []; - - data.forEach(row => { - row.forEach(data => { - if (data instanceof Date) { - // console.log("date obejct:"+data.valueOf()); - resArr.push(data.taosTimestamp()); - } else { - // console.log("not date:"+data); - resArr.push(data); - } - // console.log(data instanceof Date) - }) - }) - return { resData: resArr, resFeilds: fields }; -} - -beforeAll(() => { - conn = taos.connect({ host: "127.0.0.1", user: "root", password: "taosdata", config: "/etc/taos", port: 10 }); - c1 = conn.cursor(); - executeUpdate("create database if not exists node_test_db keep 3650;"); - executeUpdate("use node_test_db;"); -}); - -// Clears the database and adds some testing data. -// Jest will wait for this promise to resolve before running tests. -afterAll(() => { - executeUpdate("drop database if exists node_test_db;"); - c1.close(); - conn.close(); -}); - -describe("test unsigned type", () => { - - test(`name:test unsinged tinnyint ntable;` + - `author:${author};` + - `desc:create,insert,query with unsigned tinnyint;` + - `filename:${fileName};` + - `result:${result}`, () => { - let createSql = "create table if not exists utinnytest(ts timestamp,ut tinyint unsigned,i4 int,rownum nchar(20));"; - executeUpdate(createSql); - let expectResField = getFieldArr(getFeildsFromDll(createSql)); - let expectResData = [1641827743305, 254, 124, 'row1' - , 1641827743306, 0, -123, 'row2' - , 1641827743307, 54, 0, 'row3']; - let insertSql = buildInsertSql('utinnytest', '', expectResData, [], 4); - - executeUpdate(insertSql); - let result = executeQuery("select * from utinnytest;"); - let actualResData = result.resData; - let actualResFields = result.resFeilds; - - //assert result data length - expect(expectResData.length).toEqual(actualResData.length); - //assert result data - expectResData.forEach((item, index) => { - expect(item).toEqual(actualResData[index]); - }); - - //assert result meta data - expectResField.forEach((item, index) => { - expect(item).toEqual(actualResFields[index]) - }) - }); - - test(`name:test unsinged smallint ntable;` + - `author:${author};` + - `desc:create,insert,query with unsigned smallint;` + - `filename:${fileName};` + - `result:${result}`, () => { - let createSql = "create table if not exists usmalltest(ts timestamp,ut smallint unsigned,i4 int,rownum nchar(20));"; - executeUpdate(createSql); - let expectResField = getFieldArr(getFeildsFromDll(createSql)); - let expectResData = [1641827743305, 65534, 124, 'row1', 1641827743306, 0, -123, 'row2', 1641827743307, 79, 0, 'row3']; - let insertSql = buildInsertSql('usmalltest', '', expectResData, [], 4); - - executeUpdate(insertSql); - let result = executeQuery("select * from usmalltest;"); - let actualResData = result.resData; - let actualResFields = result.resFeilds; - - //assert result data length - expect(expectResData.length).toEqual(actualResData.length); - //assert result data - expectResData.forEach((item, index) => { - expect(item).toEqual(actualResData[index]); - }); - - //assert result meta data - expectResField.forEach((item, index) => { - expect(item).toEqual(actualResFields[index]) - }) - }); - - test(`name:test unsinged int ntable;` + - `author:${author};` + - `desc:create,insert,query with unsigned int;` + - `filename:${fileName};` + - `result:${result}`, () => { - let createSql = "create table if not exists uinttest(ts timestamp,ui int unsigned,i4 int,rownum nchar(20));"; - executeUpdate(createSql); - let expectResField = getFieldArr(getFeildsFromDll(createSql)); - let expectResData = [1641827743305, 4294967294, 2147483647, 'row1', 1641827743306, 0, -2147483647, 'row2', 1641827743307, 105, 0, 'row3']; - let insertSql = buildInsertSql('uinttest', '', expectResData, [], 4); - - executeUpdate(insertSql); - let result = executeQuery("select * from uinttest;"); - let actualResData = result.resData; - let actualResFields = result.resFeilds; - - //assert result data length - expect(expectResData.length).toEqual(actualResData.length); - //assert result data - expectResData.forEach((item, index) => { - expect(item).toEqual(actualResData[index]); - }); - - //assert result meta data - expectResField.forEach((item, index) => { - expect(item).toEqual(actualResFields[index]) - }) - }); - - test(`name:test unsinged bigint ntable;` + - `author:${author};` + - `desc:create,insert,query with unsigned bigint;` + - `filename:${fileName};` + - `result:${result}`, () => { - let createSql = "create table if not exists ubigtest(ts timestamp,ui bigint unsigned,i8 bigint,rownum nchar(20));"; - executeUpdate(createSql); - let expectResField = getFieldArr(getFeildsFromDll(createSql)); - let expectResData = [1641827743305, 18446744073709551614n, 9223372036854775807n, 'row1', - 1641827743306, 0n, -9223372036854775807n, 'row2', - 1641827743307, 130n, 0n, 'row3']; - let insertSql = buildInsertSql('ubigtest', '', expectResData, [], 4); - - executeUpdate(insertSql); - let result = executeQuery("select * from ubigtest;"); - let actualResData = result.resData; - let actualResFields = result.resFeilds; - - //assert result data length - expect(expectResData.length).toEqual(actualResData.length); - //assert result data - expectResData.forEach((item, index) => { - expect(item).toEqual(actualResData[index]); - }); - - //assert result meta data - expectResField.forEach((item, index) => { - expect(item).toEqual(actualResFields[index]) - }) - }); - - test(`name:test unsinged type ntable;` + - `author:${author};` + - `desc:create,insert,query with mutiple unsinged type;` + - `filename:${fileName};` + - `result:${result}`, () => { - let createSql = "create table if not exists unsigntest(ts timestamp,ut tinyint unsigned,us smallint unsigned,ui int unsigned,ub bigint unsigned,bi bigint);"; - executeUpdate(createSql); - let expectResField = getFieldArr(getFeildsFromDll(createSql)); - let expectResData = [1641827743305, 254, 65534, 4294967294, 18446744073709551614n, 9223372036854775807n, - 1641827743306, 0, 0, 0, 0n, -9223372036854775807n]; - let insertSql = buildInsertSql('unsigntest', '', expectResData, [], 6); - - executeUpdate(insertSql); - let result = executeQuery("select * from unsigntest;"); - // console.log(`result.data:${result.resData}`); - // console.log(`result.feilds:${result.resFeilds}`); - let actualResData = result.resData; - let actualResFields = result.resFeilds; - - //assert result data length - expect(expectResData.length).toEqual(actualResData.length); - //assert result data - expectResData.forEach((item, index) => { - expect(item).toEqual(actualResData[index]); - }); - - //assert result meta data - expectResField.forEach((item, index) => { - expect(item).toEqual(actualResFields[index]) - }) - }); - - test(`name:test unsinged type stable max value;` + - `author:${author};` + - `desc:this is a description;` + - `filename:${fileName};` + - `result:${result}`, () => { - let createSql = "create table if not exists max_unsigned_tag_test" + - "(ts timestamp" + - ",ut tinyint unsigned" + - ",us smallint unsigned" + - ",ui int unsigned" + - ",ub bigint unsigned" + - ",bi bigint)" + - "tags(" + - "ut1 tinyint unsigned" + - ",us2 smallint unsigned" + - ",ui4 int unsigned" + - ",ubi8 bigint unsigned" + - ",desc_nchr nchar(200)" + - ");"; - executeUpdate(createSql); - let expectResField = getFieldArr(getFeildsFromDll(createSql)); - let colData = [1641827743305, 254, 65534, 4294967294, 18446744073709551614n, 9223372036854775807n, - 1641827743306, 0, 0, 0, 0n, -9223372036854775807n, - 1641827743307, 201, 44, 2, 8n, 1531n]; - let tagData = [254, 65534, 4294967294, 18446744073709551614n, 'max value of unsinged type tag'] - let insertSql = buildInsertSql('max_unsigned_tag_test_sub1', 'max_unsigned_tag_test', colData, tagData, 6); - let expectResData = getResData(colData, tagData, 6); - - executeUpdate(insertSql); - let result = executeQuery("select * from max_unsigned_tag_test;"); - let actualResData = result.resData; - let actualResFields = result.resFeilds; - - //assert result data length - expect(expectResData.length).toEqual(actualResData.length); - //assert result data - expectResData.forEach((item, index) => { - expect(item).toEqual(actualResData[index]); - }); - - //assert result meta data - expectResField.forEach((item, index) => { - expect(item).toEqual(actualResFields[index]) - }) - }); - - test(`name:test unsinged type stable minimal value;` + - `author:${author};` + - `desc:this is a description;` + - `filename:${fileName};` + - `result:${result}`, () => { - let createSql = "create table if not exists min_unsigned_tag_test" + - "(ts timestamp" + - ",ut tinyint unsigned" + - ",us smallint unsigned" + - ",ui int unsigned" + - ",ub bigint unsigned" + - ",bi bigint)" + - "tags(" + - "ut1 tinyint unsigned" + - ",us2 smallint unsigned" + - ",ui4 int unsigned" + - ",ubi8 bigint unsigned" + - ",desc_nchr nchar(200)" + - ");"; - executeUpdate(createSql); - let expectResField = getFieldArr(getFeildsFromDll(createSql)); - let colData = [1641827743305, 254, 65534, 4294967294, 18446744073709551614n, 9223372036854775807n, - 1641827743306, 0, 0, 0, 0n, -9223372036854775807n, - 1641827743307, 201, 44, 2, 8n, 1531n]; - let tagData = [0, 0, 0, 0n, 'minimal value of unsinged type tag'] - let insertSql = buildInsertSql('min_unsigned_tag_test_sub1', 'min_unsigned_tag_test', colData, tagData, 6); - let expectResData = getResData(colData, tagData, 6); - - executeUpdate(insertSql); - let result = executeQuery("select * from min_unsigned_tag_test;"); - let actualResData = result.resData; - let actualResFields = result.resFeilds; - - //assert result data length - console.log("expectResData.length:" + expectResData.length + " actualResData.length:" + actualResData.length); - expect(expectResData.length).toEqual(actualResData.length); - //assert result data - expectResData.forEach((item, index) => { - expect(item).toEqual(actualResData[index]); - }); - - //assert result meta data - expectResField.forEach((item, index) => { - expect(item).toEqual(actualResFields[index]) - }) - }); - - test(`name:test unsinged type stable mixed value;` + - `author:${author};` + - `desc:this is a description;` + - `filename:${fileName};` + - `result:${result}`, () => { - let createSql = "create table if not exists mix_unsigned_tag_test" + - "(ts timestamp" + - ",ut tinyint unsigned" + - ",us smallint unsigned" + - ",ui int unsigned" + - ",ub bigint unsigned" + - ",bi bigint)" + - "tags(" + - "ut1 tinyint unsigned" + - ",us2 smallint unsigned" + - ",ui4 int unsigned" + - ",ubi8 bigint unsigned" + - ",desc_nchr nchar(200)" + - ");"; - executeUpdate(createSql); - let expectResField = getFieldArr(getFeildsFromDll(createSql)); - let colData = [1641827743305, 254, 65534, 4294967294, 18446744073709551614n, 9223372036854775807n, - 1641827743306, 0, 0, 0, 0n, -9223372036854775807n, - 1641827743307, 201, 44, 2, 8n, 1531n]; - let tagData = [1, 20, 300, 4000n, 'mixed value of unsinged type tag'] - let insertSql = buildInsertSql('mix_unsigned_tag_test_sub1', 'mix_unsigned_tag_test', colData, tagData, 6); - let expectResData = getResData(colData, tagData, 6); - - executeUpdate(insertSql); - let result = executeQuery("select * from mix_unsigned_tag_test;"); - let actualResData = result.resData; - let actualResFields = result.resFeilds; - - //assert result data length - expect(expectResData.length).toEqual(actualResData.length); - //assert result data - expectResData.forEach((item, index) => { - expect(item).toEqual(actualResData[index]); - }); - - //assert result meta data - expectResField.forEach((item, index) => { - expect(item).toEqual(actualResFields[index]) - }) - }); - -}) - -describe("test cn character", () => { - test(`name:test cn ntable;` + - `author:${author};` + - `desc:create,insert,query with cn characters;` + - `filename:${fileName};` + - `result:${result}`, () => { - createSql = "create table if not exists nchartest(ts timestamp,value int,text binary(200),detail nchar(200));" - executeUpdate(createSql); - let expectResField = getFieldArr(getFeildsFromDll(createSql)); - let expectResData = [1641827743305, 1, 'taosdata', 'tdengine' - , 1641827743306, 2, 'tasdata', '涛思数据' - , 1641827743307, 3, '涛思数据', 'tdengine' - , 1641827743308, 4, '涛思数据taosdata', 'tdengine' - , 1641827743309, 5, '涛思数据taosdata', 'tdengine涛思数据']; - let insertSql = buildInsertSql('nchartest', '', expectResData, [], 4); - - executeUpdate(insertSql); - let result = executeQuery("select * from nchartest;"); - let actualResData = result.resData; - let actualResFields = result.resFeilds; - - //assert result data length - expect(expectResData.length).toEqual(actualResData.length); - //assert result data - expectResData.forEach((item, index) => { - expect(item).toEqual(actualResData[index]); - }); - //assert result meta data - expectResField.forEach((item, index) => { - expect(item).toEqual(actualResFields[index]) - }) - }) - - test(`name:test cn stable;` + - `author:${author};` + - `desc:create,insert,query with cn characters;` + - `filename:${fileName};` + - `result:${result}`, () => { - createSql = "create table if not exists nchartest_s(ts timestamp,value int,text binary(200),detail nchar(200))tags(tag_bi binary(50),tag_nchr nchar(50));" - executeUpdate(createSql); - let expectResField = getFieldArr(getFeildsFromDll(createSql)); - let colData = [1641827743305, 1, 'taosdata', 'tdengine' - , 1641827743306, 2, 'tasdata', '涛思数据' - , 1641827743307, 3, '涛思数据', 'tdengine' - , 1641827743308, 4, '涛思数据taosdata', 'tdengine' - , 1641827743309, 5, '涛思数据taosdata', 'tdengine涛思数据']; - let tagData = ['tags涛思', '数据tags']; - let insertSql = buildInsertSql('sb_1', 'nchartest_s', colData, tagData, 4); - let expectResData = getResData(colData, tagData, 4); - - executeUpdate(insertSql); - let result = executeQuery("select * from nchartest_s;"); - let actualResData = result.resData; - let actualResFields = result.resFeilds; - - //assert result data length - expect(expectResData.length).toEqual(actualResData.length); - //assert result data - expectResData.forEach((item, index) => { - expect(item).toEqual(actualResData[index]); - }); - - //assert result meta data - expectResField.forEach((item, index) => { - expect(item).toEqual(actualResFields[index]) - }) - }) -}) - -describe("test schemaless", () => { - test(`name:sml line protocal using string;` + - `author:${author};` + - `desc:using line protocal to schemaless insert with a string;` + - `filename:${fileName};` + - `result:${result}`, () => { - let stablename = 'line_protocal_string'; - createSql = `create table if not exists ${stablename}(ts timestamp,c1 bigint,c3 nchar(6),c2 bool,c4 double)` - + `tags(t1 nchar(4),t2 nchar(4),t3 nchar(4));` - - executeUpdate(createSql); - let expectResField = getFieldArr(getFeildsFromDll(createSql)); - let colData = [1626006833639, 3n, 'passit', false, 4.000000000]; - let tagData = ['3i64', '4f64', '\"t3\"']; - let expectResData = getResData(colData, tagData, 5); - let lineStr = stablename + ",t1=3i64,t2=4f64,t3=\"t3\" c1=3i64,c3=L\"passit\",c2=false,c4=4f64 1626006833639"; - - - c1.schemalessInsert(lineStr, taos.SCHEMALESS_PROTOCOL.TSDB_SML_LINE_PROTOCOL, taos.SCHEMALESS_PRECISION.TSDB_SML_TIMESTAMP_MILLI_SECONDS); - let result = executeQuery(`select * from ${stablename};`); - let actualResData = result.resData; - let actualResFields = result.resFeilds; - - //assert result data length - expect(expectResData.length).toEqual(actualResData.length); - //assert result data - expectResData.forEach((item, index) => { - expect(item).toEqual(actualResData[index]); - }); - - //assert result meta data - expectResField.forEach((item, index) => { - expect(item).toEqual(actualResFields[index]) - }) - }) - - test(`name:sml line protocal using Array;` + - `author:${author};` + - `desc:using line protocal to schemaless insert with an Array;` + - `filename:${fileName};` + - `result:${result}`, () => { - let stablename = 'line_protocol_arr'; - - createSql = `create table if not exists ${stablename}(ts timestamp,c1 bigint,c3 nchar(10),c2 bool,c4 double,c5 double)` - + `tags(t1 nchar(4),t2 nchar(4),t3 nchar(4),t4 nchar(4));` - - executeUpdate(createSql); - let expectResField = getFieldArr(getFeildsFromDll(createSql)); - let colData1 = [1626006833641, 3n, 'passitagin', true, 5, 5] - let colData2 = [1626006833639, 3n, 'passit', false, 4, null]; - let tagData1 = ['4i64', '5f64', '\"t4\"', '5f64']; - let tagData2 = ['3i64', '4f64', '\"t3\"', null]; - let expectResDataTable1 = getResData(colData1, tagData1, 6); - let expectResDataTable2 = getResData(colData2, tagData2, 6); - let expectResData = expectResDataTable1.concat(expectResDataTable2); - - let lineStr = [stablename + ",t1=3i64,t2=4f64,t3=\"t3\" c1=3i64,c3=L\"passit\",c2=false,c4=4f64 1626006833639000000", - stablename + ",t1=4i64,t3=\"t4\",t2=5f64,t4=5f64 c1=3i64,c3=L\"passitagin\",c2=true,c4=5f64,c5=5f64 1626006833641000000" - ]; - - c1.schemalessInsert(lineStr, taos.SCHEMALESS_PROTOCOL.TSDB_SML_LINE_PROTOCOL, taos.SCHEMALESS_PRECISION.TSDB_SML_TIMESTAMP_NANO_SECONDS); - let result = executeQuery(`select * from ${stablename};`); - let actualResData = result.resData; - let actualResFields = result.resFeilds; - - //assert result data length - expect(expectResData.length).toEqual(actualResData.length); - //assert result data - expectResData.forEach((item, index) => { - expect(item).toEqual(actualResData[index]); - }); - - //assert result meta data - expectResField.forEach((item, index) => { - expect(item).toEqual(actualResFields[index]) - }) - }) - - test(`name:sml json protocal using string;` + - `author:${author};` + - `desc:using json protocal to schemaless insert with a json string;` + - `filename:${fileName};` + - `result:${result}`, () => { - let stablename = 'json_protocol_str'; - - createSql = `create table if not exists ${stablename}(ts timestamp,value double)` - + `tags(t1 bool,t2 bool,t3 double,t4 nchar(35));` - - executeUpdate(createSql); - let expectResField = getFieldArr(getFeildsFromDll(createSql)); - let colData1 = [1626006833000, 10] - let tagData1 = [true, false, 10, '123_abc_.!@#$%^&*:;,./?|+-=()[]{}<>']; - let expectResData = getResData(colData1, tagData1, 2); - - let jsonStr = "{" - + "\"metric\": \"" + stablename + "\"," - + "\"timestamp\": 1626006833000," - + "\"value\": 10," - + "\"tags\": {" - + " \"t1\": true," - + "\"t2\": false," - + "\"t3\": 10," - + "\"t4\": \"123_abc_.!@#$%^&*:;,./?|+-=()[]{}<>\"" - + "}" - + "}"; - - c1.schemalessInsert(jsonStr, taos.SCHEMALESS_PROTOCOL.TSDB_SML_JSON_PROTOCOL, taos.SCHEMALESS_PRECISION.TSDB_SML_TIMESTAMP_MILLI_SECONDS); - - let result = executeQuery(`select * from ${stablename};`); - let actualResData = result.resData; - let actualResFields = result.resFeilds; - - //assert result data length - expect(expectResData.length).toEqual(actualResData.length); - //assert result data - expectResData.forEach((item, index) => { - expect(item).toEqual(actualResData[index]); - }); - - //assert result meta data - expectResField.forEach((item, index) => { - expect(item).toEqual(actualResFields[index]) - }) - }) - - test(`name:sml json protocal using Array;` + - `author:${author};` + - `desc:using json protocal to schemaless insert with a json array;` + - `filename:${fileName};` + - `result:${result}`, () => { - let stablename = 'json_protocol_arr'; - - createSql = `create table if not exists ${stablename}(ts timestamp,value double)` - + `tags(t1 bool,t2 bool,t3 double,t4 nchar(35));` - - executeUpdate(createSql); - let expectResField = getFieldArr(getFeildsFromDll(createSql)); - let colData1 = [1626006833000, 10] - let tagData1 = [true, false, 10, '123_abc_.!@#$%^&*:;,./?|+-=()[]{}<>']; - let expectResData = getResData(colData1, tagData1, 2); - - let jsonArr = ["{" - + "\"metric\": \"" + stablename + "\"," - + "\"timestamp\": 1626006833," - + "\"value\": 10," - + "\"tags\": {" - + " \"t1\": true," - + "\"t2\": false," - + "\"t3\": 10," - + "\"t4\": \"123_abc_.!@#$%^&*:;,./?|+-=()[]{}<>\"" - + "}" - + "}" - ]; - - c1.schemalessInsert(jsonArr, taos.SCHEMALESS_PROTOCOL.TSDB_SML_JSON_PROTOCOL, taos.SCHEMALESS_PRECISION.TSDB_SML_TIMESTAMP_SECONDS); - - let result = executeQuery(`select * from ${stablename};`); - let actualResData = result.resData; - let actualResFields = result.resFeilds; - - //assert result data length - expect(expectResData.length).toEqual(actualResData.length); - //assert result data - expectResData.forEach((item, index) => { - expect(item).toEqual(actualResData[index]); - }); - - //assert result meta data - expectResField.forEach((item, index) => { - expect(item).toEqual(actualResFields[index]) - }) - }) -}) - -describe("test support microsecond", () => { - test(`name:ms support ntable;` + - `author:${author};` + - `desc:test normal table supports microseconds;` + - `filename:${fileName};` + - `result:${result}`, () => { - let db = 'nodejs_support_ms_ntable'; - let table = 'us_test_ntable'; - let expectResData = [1625801548423914, 1, 1625801548423914, - 1625801548423915, 2, 1625801548423914, - 1625801548423916, 3, 1625801548423914, - 1625801548423917, 4, 1625801548423914]; - - let createDB = `create database if not exists ${db} keep 3650 precision \'us\';`; - let createSql = `create table if not exists ${db}.${table} (ts timestamp, seq int,record_date timestamp);`; - let dropDB = `drop database if exists ${db};`; - let insertSql = buildInsertSql(db + '.' + table, '',expectResData, [], 3); - let querySql = `select * from ${db}.${table};`; - let expectResField = getFieldArr(getFeildsFromDll(createSql)); - - executeUpdate(dropDB); - executeUpdate(createDB); - executeUpdate(createSql); - executeUpdate(insertSql); - let result = executeQuery(querySql); - - let actualResData = result.resData; - let actualResFields = result.resFeilds; - - //assert result data length - expect(expectResData.length).toEqual(actualResData.length); - //assert result data - expectResData.forEach((item, index) => { - expect(item).toEqual(actualResData[index]); - }); - - //assert result meta data - expectResField.forEach((item, index) => { - expect(item).toEqual(actualResFields[index]) - }) - executeUpdate(dropDB); - - }); - - test(`name:ms support stable;` + - `author:${author};` + - `desc:test stable supports microseconds;` + - `filename:${fileName};` + - `result:${result}`, () => { - let db = 'nodejs_support_ms_stable'; - let stable = 'us_test_stable'; - let table = "sub_1"; - let colData = [1625801548423914, 1, 1625801548423914, - 1625801548423915, 2, 1625801548423914, - 1625801548423916, 3, 1625801548423914, - 1625801548423917, 4, 1625801548423914]; - let tagData = [1,1625801548423914]; - let createDB = `create database if not exists ${db} keep 3650 precision \'us\';`; - let createSql = `create table if not exists ${db}.${stable} (ts timestamp,seq int,`+ - `record_date timestamp)tags(id int,htime timestamp);`; - let dropDB = `drop database if exists ${db};`; - let insertSql = buildInsertSql(db + '.' + table, db + '.' + stable, colData,tagData, 3); - let querySql = `select * from ${db}.${stable};`; - let expectResField = getFieldArr(getFeildsFromDll(createSql)); - let expectResData = getResData(colData, tagData, 3); - - executeUpdate(dropDB); - executeUpdate(createDB); - executeUpdate(createSql); - executeUpdate(insertSql); - let result = executeQuery(querySql); - - let actualResData = result.resData; - let actualResFields = result.resFeilds; - - //assert result data length - expect(expectResData.length).toEqual(actualResData.length); - //assert result data - expectResData.forEach((item, index) => { - expect(item).toEqual(actualResData[index]); - }); - - //assert result meta data - expectResField.forEach((item, index) => { - expect(item).toEqual(actualResFields[index]) - }) - executeUpdate(dropDB); - }) -}) - -describe("test support nanosecond", () => { - test(`name:ns support ntable;` + - `author:${author};` + - `desc:test normal table supports nanoseconds;` + - `filename:${fileName};` + - `result:${result}`, () => { - let db = 'nodejs_support_ns_ntable'; - let table = 'ns_test_ntable'; - let expectResData = [1625801548423914100, 1, 1625801548423914 - ,1625801548423914200, 2, 1625801548423914 - ]; - - let createDB = `create database if not exists ${db} keep 3650 precision \'ns\';`; - let createSql = `create table if not exists ${db}.${table} (ts timestamp, seq int,record_date timestamp);`; - let dropDB = `drop database if exists ${db};`; - let insertSql = buildInsertSql(db + '.' + table, '',expectResData, [], 3); - let querySql = `select * from ${db}.${table};`; - let expectResField = getFieldArr(getFeildsFromDll(createSql)); - - executeUpdate(dropDB); - executeUpdate(createDB); - executeUpdate(createSql); - executeUpdate(insertSql); - console.log(querySql); - let result = executeQuery(querySql); - - let actualResData = result.resData; - let actualResFields = result.resFeilds; - - //assert result data length - expect(expectResData.length).toEqual(actualResData.length); - //assert result data - expectResData.forEach((item, index) => { - console.log((index)); - expect(item).toEqual(actualResData[index]); - }); - - //assert result meta data - expectResField.forEach((item, index) => { - expect(item).toEqual(actualResFields[index]) - }) - executeUpdate(dropDB); - }); - - test(`name:ns support stable;` + - `author:${author};` + - `desc:test stable supports nanoseconds;` + - `filename:${fileName};` + - `result:${result}`, () => { - let db = 'nodejs_support_ns_stable'; - let stable = 'ns_test_stable'; - let table = "sub_1"; - let colData = [1625801548423914100, 1, 1625801548423914, - 1625801548423914200, 2, 1625801548423914]; - let tagData = [1,1625801548423914100]; - let createDB = `create database if not exists ${db} keep 3650 precision \'ns\';`; - let createSql = `create table if not exists ${db}.${stable} (ts timestamp,seq int,`+ - `record_date timestamp)tags(id int,htime timestamp);`; - let dropDB = `drop database if exists ${db};`; - let insertSql = buildInsertSql(db + '.' + table, db + '.' + stable, colData,tagData, 3); - let querySql = `select * from ${db}.${stable};`; - let expectResField = getFieldArr(getFeildsFromDll(createSql)); - let expectResData = getResData(colData, tagData, 3); - - executeUpdate(dropDB); - executeUpdate(createDB); - executeUpdate(createSql); - executeUpdate(insertSql); - let result = executeQuery(querySql); - - let actualResData = result.resData; - let actualResFields = result.resFeilds; - - //assert result data length - expect(expectResData.length).toEqual(actualResData.length); - //assert result data - expectResData.forEach((item, index) => { - expect(item).toEqual(actualResData[index]); - }); - - //assert result meta data - expectResField.forEach((item, index) => { - expect(item).toEqual(actualResFields[index]) - }) - executeUpdate(dropDB); - }) -}) - -describe("test json tag", () => { - test(`name:json tag;` + - `author:${author};` + - `desc:create,insert,query with json tag;` + - `filename:${fileName};` + - `result:${result}`, () => { - let tableName = 'jsons1'; - let createSql = `create table if not exists ${tableName}(ts timestamp, dataInt int, dataBool bool, dataStr nchar(50), dataStrBin binary(150)) tags(jtag json);`; - - executeUpdate(createSql); - let expectResField = getFieldArr(getFeildsFromDll(createSql)); - let colData = [1591060618000, 1, false, 'json1', '涛思数据' - , 1591060628000, 23, true, '涛思数据', 'json' - , 1591060638000, 54, false, 'tdengine', 'taosdata']; - let tagData = ['{\"tag1\":\"fff\",\"tag2\":5,\"tag3\":true}'] - let insertSql = buildInsertSql('json_sub_1', tableName, colData, tagData, 5); - let expectResData = getResData(colData, tagData, 5); - - executeUpdate(insertSql); - let result = executeQuery(`select * from ${tableName};`); - let actualResData = result.resData; - let actualResFields = result.resFeilds; - - //assert result data length - expect(expectResData.length).toEqual(actualResData.length); - //assert result data - expectResData.forEach((item, index) => { - expect(item).toEqual(actualResData[index]); - }); - - //assert result meta data - expectResField.forEach((item, index) => { - expect(item).toEqual(actualResFields[index]) - }) - }) -}) \ No newline at end of file diff --git a/src/connector/nodejs/test/cases/test.stmt.js b/src/connector/nodejs/test/cases/test.stmt.js deleted file mode 100644 index 78893479d8cd37c79f26bb6329e9bcbb56f825c4..0000000000000000000000000000000000000000 --- a/src/connector/nodejs/test/cases/test.stmt.js +++ /dev/null @@ -1,916 +0,0 @@ -const taos = require('../../tdengine'); -const { getFeildsFromDll, buildInsertSql, getFieldArr, getResData } = require('../utils/utilTools') - -const author = 'xiaolei'; -const result = 'passed'; -const fileName = __filename.slice(__dirname.length + 1); - -// This is a taos connection -let conn; -// This is a Cursor -let c1; - -// prepare data -let dbName = 'node_test_stmt_db'; -let tsArr = [1642435200000, 1642435300000, 1642435400000, 1642435500000, 1642435600000]; -let boolArr = [true, false, true, false, null]; -let tinyIntArr = [-127, 3, 127, 0, null]; -let smallIntArr = [-32767, 16, 32767, 0, null]; -let intArr = [-2147483647, 17, 2147483647, 0, null]; -let bigIntArr = [-9223372036854775807n, 9223372036854775807n, 18n, 0n, null]; -let floatArr = [3.4028234663852886e+38, -3.4028234663852886e+38, 19, 0, null]; -let doubleArr = [1.7976931348623157e+308, -1.7976931348623157e+308, 20, 0, null]; -let binaryArr = ['TDengine_Binary', 'taosdata涛思数据', '~!@#$%^&*()', '', null]; -let ncharArr = ['TDengine_Nchar', 'taosdata涛思数据', '~!@#$$%^&*()', '', null]; -let uTinyIntArr = [0, 127, 254, 23, null]; -let uSmallIntArr = [0, 256, 65534, 24, null]; -let uIntArr = [0, 1233, 4294967294, 25, null]; -let uBigIntArr = [0n, 36424354000001111n, 18446744073709551614n, 26n, null]; - -//prepare tag data. -let tagData1 = [true, 1, 32767, 1234555, -164243520000011111n, 214.02, 2.01, 'taosdata涛思数据', 'TDengine数据', 254, 65534, 4294967290 / 2, 164243520000011111n]; -let tagData2 = [true, 2, 32767, 1234555, -164243520000011111n, 214.02, 2.01, 'taosdata涛思数据', 'TDengine数据', 254, 65534, 4294967290 / 2, 164243520000011111n]; -let tagData3 = [true, 3, 32767, 1234555, -164243520000011111n, 214.02, 2.01, 'taosdata涛思数据', 'TDengine数据', 254, 65534, 4294967290 / 2, 164243520000011111n]; - -/** - * Combine individual array of every tdengine type that - * has been declared and then return a new array. - * @returns return data array. - */ -function getBindData() { - let bindDataArr = []; - for (let i = 0; i < 5; i++) { - bindDataArr.push(tsArr[i]); - bindDataArr.push(boolArr[i]); - bindDataArr.push(tinyIntArr[i]); - bindDataArr.push(smallIntArr[i]); - bindDataArr.push(intArr[i]); - bindDataArr.push(bigIntArr[i]); - bindDataArr.push(floatArr[i]); - bindDataArr.push(doubleArr[i]); - bindDataArr.push(binaryArr[i]); - bindDataArr.push(ncharArr[i]); - bindDataArr.push(uTinyIntArr[i]); - bindDataArr.push(uSmallIntArr[i]); - bindDataArr.push(uIntArr[i]); - bindDataArr.push(uBigIntArr[i]); - } - return bindDataArr; -} - -function executeUpdate(sql) { - console.log(sql); - c1.execute(sql); -} - -function executeQuery(sql) { - c1.execute(sql, { quiet: true }) - var data = c1.fetchall(); - let fields = c1.fields; - let resArr = []; - - data.forEach(row => { - row.forEach(data => { - if (data instanceof Date) { - // console.log("date obejct:"+data.valueOf()); - resArr.push(data.taosTimestamp()); - } else { - // console.log("not date:"+data); - resArr.push(data); - } - // console.log(data instanceof Date) - }) - }) - return { resData: resArr, resFeilds: fields }; -} - -beforeAll(() => { - conn = taos.connect({ host: "127.0.0.1", user: "root", password: "taosdata", config: "/etc/taos", port: 10 }); - c1 = conn.cursor(); - executeUpdate(`create database if not exists ${dbName} keep 3650;`); - executeUpdate(`use ${dbName};`); -}); - -// Clears the database and adds some testing data. -// Jest will wait for this promise to resolve before running tests. -afterAll(() => { - executeUpdate(`drop database if exists ${dbName};`); - c1.close(); - conn.close(); -}); - -describe("stmt_bind_single_param", () => { - test(`name:bindSingleParamWithOneTable;` + - `author:${author};` + - `desc:Using stmtBindSingleParam() bind one table in a batch;` + - `filename:${fileName};` + - `result:${result}`, () => { - let table = 'bindsingleparambatch_121'; - let createSql = `create table if not exists ${table} ` + - `(ts timestamp,` + - `bl bool,` + - `i8 tinyint,` + - `i16 smallint,` + - `i32 int,` + - `i64 bigint,` + - `f32 float,` + - `d64 double,` + - `bnr binary(20),` + - `nchr nchar(20),` + - `u8 tinyint unsigned,` + - `u16 smallint unsigned,` + - `u32 int unsigned,` + - `u64 bigint unsigned` + - `)tags(` + - `t_bl bool,` + - `t_i8 tinyint,` + - `t_i16 smallint,` + - `t_i32 int,` + - `t_i64 bigint,` + - `t_f32 float,` + - `t_d64 double,` + - `t_bnr binary(20),` + - `t_nchr nchar(20),` + - `t_u8 tinyint unsigned,` + - `t_u16 smallint unsigned,` + - `t_u32 int unsigned,` + - `t_u64 bigint unsigned` + - `);`; - let insertSql = `insert into ? using ${table} tags(?,?,?,?,?,?,?,?,?,?,?,?,?) values (?,?,?,?,?,?,?,?,?,?,?,?,?,?);`; - let querySql = `select * from ${table}`; - let expectResField = getFieldArr(getFeildsFromDll(createSql)); - let expectResData = getResData(getBindData(), tagData1, 14); - - // prepare tag TAOS_BIND - let tagBind1 = new taos.TaosBind(14); - tagBind1.bindBool(true); - tagBind1.bindTinyInt(1); - tagBind1.bindSmallInt(32767); - tagBind1.bindInt(1234555); - tagBind1.bindBigInt(-164243520000011111n); - tagBind1.bindFloat(214.02); - tagBind1.bindDouble(2.01); - tagBind1.bindBinary('taosdata涛思数据'); - tagBind1.bindNchar('TDengine数据'); - tagBind1.bindUTinyInt(254); - tagBind1.bindUSmallInt(65534); - tagBind1.bindUInt(4294967290 / 2); - tagBind1.bindUBigInt(164243520000011111n); - - //Prepare TAOS_MULTI_BIND data - let mBind1 = new taos.TaosMultiBind(); - - executeUpdate(createSql); - c1.stmtInit(); - c1.stmtPrepare(insertSql); - c1.stmtSetTbnameTags(`${table}_s01`, tagBind1.getBind()); - c1.stmtBindSingleParamBatch(mBind1.multiBindTimestamp(tsArr), 0); - c1.stmtBindSingleParamBatch(mBind1.multiBindBool(boolArr), 1); - c1.stmtBindSingleParamBatch(mBind1.multiBindTinyInt(tinyIntArr), 2); - c1.stmtBindSingleParamBatch(mBind1.multiBindSmallInt(smallIntArr), 3); - c1.stmtBindSingleParamBatch(mBind1.multiBindInt(intArr), 4); - c1.stmtBindSingleParamBatch(mBind1.multiBindBigInt(bigIntArr), 5); - c1.stmtBindSingleParamBatch(mBind1.multiBindFloat(floatArr), 6); - c1.stmtBindSingleParamBatch(mBind1.multiBindDouble(doubleArr), 7); - c1.stmtBindSingleParamBatch(mBind1.multiBindBinary(binaryArr), 8); - c1.stmtBindSingleParamBatch(mBind1.multiBindNchar(ncharArr), 9); - c1.stmtBindSingleParamBatch(mBind1.multiBindUTinyInt(uTinyIntArr), 10); - c1.stmtBindSingleParamBatch(mBind1.multiBindUSmallInt(uSmallIntArr), 11); - c1.stmtBindSingleParamBatch(mBind1.multiBindUInt(uIntArr), 12); - c1.stmtBindSingleParamBatch(mBind1.multiBindUBigInt(uBigIntArr), 13); - c1.stmtAddBatch(); - c1.stmtExecute(); - c1.stmtClose(); - - let result = executeQuery(querySql); - let actualResData = result.resData; - let actualResFields = result.resFeilds; - - //assert result data length - expect(expectResData.length).toEqual(actualResData.length); - //assert result data - expectResData.forEach((item, index) => { - expect(item).toEqual(actualResData[index]); - }); - - //assert result meta data - expectResField.forEach((item, index) => { - expect(item).toEqual(actualResFields[index]) - }) - }); - - test(`name:bindSingleParamWithMultiTable;` + - `author:${author};` + - `desc:Using stmtBindSingleParam() bind multiple tables in a batch;` + - `filename:${fileName};` + - `result:${result}`, () => { - let table = 'bindsingleparambatch_m21';//bind multiple table to one batch - let createSql = `create table if not exists ${table} ` + - `(ts timestamp,` + - `bl bool,` + - `i8 tinyint,` + - `i16 smallint,` + - `i32 int,` + - `i64 bigint,` + - `f32 float,` + - `d64 double,` + - `bnr binary(20),` + - `nchr nchar(20),` + - `u8 tinyint unsigned,` + - `u16 smallint unsigned,` + - `u32 int unsigned,` + - `u64 bigint unsigned` + - `)tags(` + - `t_bl bool,` + - `t_i8 tinyint,` + - `t_i16 smallint,` + - `t_i32 int,` + - `t_i64 bigint,` + - `t_f32 float,` + - `t_d64 double,` + - `t_bnr binary(20),` + - `t_nchr nchar(20),` + - `t_u8 tinyint unsigned,` + - `t_u16 smallint unsigned,` + - `t_u32 int unsigned,` + - `t_u64 bigint unsigned` + - `);`; - let insertSql = `insert into ? using ${table} tags(?,?,?,?,?,?,?,?,?,?,?,?,?) values (?,?,?,?,?,?,?,?,?,?,?,?,?,?);`; - let querySql = `select * from ${table}`; - let expectResField = getFieldArr(getFeildsFromDll(createSql)); - let expectResData = getResData(getBindData(), tagData1, 14).concat(getResData(getBindData(), tagData2, 14)).concat(getResData(getBindData(), tagData3, 14)); - - // prepare tag TAOS_BIND - let tagBind1 = new taos.TaosBind(14); - tagBind1.bindBool(true); - tagBind1.bindTinyInt(1); - tagBind1.bindSmallInt(32767); - tagBind1.bindInt(1234555); - tagBind1.bindBigInt(-164243520000011111n); - tagBind1.bindFloat(214.02); - tagBind1.bindDouble(2.01); - tagBind1.bindBinary('taosdata涛思数据'); - tagBind1.bindNchar('TDengine数据'); - tagBind1.bindUTinyInt(254); - tagBind1.bindUSmallInt(65534); - tagBind1.bindUInt(4294967290 / 2); - tagBind1.bindUBigInt(164243520000011111n); - - let tagBind2 = new taos.TaosBind(14); - tagBind2.bindBool(true); - tagBind2.bindTinyInt(2); - tagBind2.bindSmallInt(32767); - tagBind2.bindInt(1234555); - tagBind2.bindBigInt(-164243520000011111n); - tagBind2.bindFloat(214.02); - tagBind2.bindDouble(2.01); - tagBind2.bindBinary('taosdata涛思数据'); - tagBind2.bindNchar('TDengine数据'); - tagBind2.bindUTinyInt(254); - tagBind2.bindUSmallInt(65534); - tagBind2.bindUInt(4294967290 / 2); - tagBind2.bindUBigInt(164243520000011111n); - - let tagBind3 = new taos.TaosBind(14); - tagBind3.bindBool(true); - tagBind3.bindTinyInt(3); - tagBind3.bindSmallInt(32767); - tagBind3.bindInt(1234555); - tagBind3.bindBigInt(-164243520000011111n); - tagBind3.bindFloat(214.02); - tagBind3.bindDouble(2.01); - tagBind3.bindBinary('taosdata涛思数据'); - tagBind3.bindNchar('TDengine数据'); - tagBind3.bindUTinyInt(254); - tagBind3.bindUSmallInt(65534); - tagBind3.bindUInt(4294967290 / 2); - tagBind3.bindUBigInt(164243520000011111n); - - //Prepare TAOS_MULTI_BIND data - let mBind = new taos.TaosMultiBind(); - - executeUpdate(createSql); - c1.stmtInit(); - c1.stmtPrepare(insertSql); - // ========bind for 1st table ============= - c1.stmtSetTbnameTags(`${table}_s01`, tagBind1.getBind()); - c1.stmtBindSingleParamBatch(mBind.multiBindTimestamp(tsArr), 0); - c1.stmtBindSingleParamBatch(mBind.multiBindBool(boolArr), 1); - c1.stmtBindSingleParamBatch(mBind.multiBindTinyInt(tinyIntArr), 2); - c1.stmtBindSingleParamBatch(mBind.multiBindSmallInt(smallIntArr), 3); - c1.stmtBindSingleParamBatch(mBind.multiBindInt(intArr), 4); - c1.stmtBindSingleParamBatch(mBind.multiBindBigInt(bigIntArr), 5); - c1.stmtBindSingleParamBatch(mBind.multiBindFloat(floatArr), 6); - c1.stmtBindSingleParamBatch(mBind.multiBindDouble(doubleArr), 7); - c1.stmtBindSingleParamBatch(mBind.multiBindBinary(binaryArr), 8); - c1.stmtBindSingleParamBatch(mBind.multiBindNchar(ncharArr), 9); - c1.stmtBindSingleParamBatch(mBind.multiBindUTinyInt(uTinyIntArr), 10); - c1.stmtBindSingleParamBatch(mBind.multiBindUSmallInt(uSmallIntArr), 11); - c1.stmtBindSingleParamBatch(mBind.multiBindUInt(uIntArr), 12); - c1.stmtBindSingleParamBatch(mBind.multiBindUBigInt(uBigIntArr), 13); - c1.stmtAddBatch(); - // c1.stmtExecute(); - - // ========bind for 2nd table ============= - c1.stmtSetTbnameTags(`${table}_s02`, tagBind2.getBind()); - c1.stmtBindSingleParamBatch(mBind.multiBindTimestamp(tsArr), 0); - c1.stmtBindSingleParamBatch(mBind.multiBindBool(boolArr), 1); - c1.stmtBindSingleParamBatch(mBind.multiBindTinyInt(tinyIntArr), 2); - c1.stmtBindSingleParamBatch(mBind.multiBindSmallInt(smallIntArr), 3); - c1.stmtBindSingleParamBatch(mBind.multiBindInt(intArr), 4); - c1.stmtBindSingleParamBatch(mBind.multiBindBigInt(bigIntArr), 5); - c1.stmtBindSingleParamBatch(mBind.multiBindFloat(floatArr), 6); - c1.stmtBindSingleParamBatch(mBind.multiBindDouble(doubleArr), 7); - c1.stmtBindSingleParamBatch(mBind.multiBindBinary(binaryArr), 8); - c1.stmtBindSingleParamBatch(mBind.multiBindNchar(ncharArr), 9); - c1.stmtBindSingleParamBatch(mBind.multiBindUTinyInt(uTinyIntArr), 10); - c1.stmtBindSingleParamBatch(mBind.multiBindUSmallInt(uSmallIntArr), 11); - c1.stmtBindSingleParamBatch(mBind.multiBindUInt(uIntArr), 12); - c1.stmtBindSingleParamBatch(mBind.multiBindUBigInt(uBigIntArr), 13); - c1.stmtAddBatch(); - // c1.stmtExecute(); - - // ========bind for 3rd table ============= - c1.stmtSetTbnameTags(`${table}_s0`, tagBind3.getBind()); - c1.stmtBindSingleParamBatch(mBind.multiBindTimestamp(tsArr), 0); - c1.stmtBindSingleParamBatch(mBind.multiBindBool(boolArr), 1); - c1.stmtBindSingleParamBatch(mBind.multiBindTinyInt(tinyIntArr), 2); - c1.stmtBindSingleParamBatch(mBind.multiBindSmallInt(smallIntArr), 3); - c1.stmtBindSingleParamBatch(mBind.multiBindInt(intArr), 4); - c1.stmtBindSingleParamBatch(mBind.multiBindBigInt(bigIntArr), 5); - c1.stmtBindSingleParamBatch(mBind.multiBindFloat(floatArr), 6); - c1.stmtBindSingleParamBatch(mBind.multiBindDouble(doubleArr), 7); - c1.stmtBindSingleParamBatch(mBind.multiBindBinary(binaryArr), 8); - c1.stmtBindSingleParamBatch(mBind.multiBindNchar(ncharArr), 9); - c1.stmtBindSingleParamBatch(mBind.multiBindUTinyInt(uTinyIntArr), 10); - c1.stmtBindSingleParamBatch(mBind.multiBindUSmallInt(uSmallIntArr), 11); - c1.stmtBindSingleParamBatch(mBind.multiBindUInt(uIntArr), 12); - c1.stmtBindSingleParamBatch(mBind.multiBindUBigInt(uBigIntArr), 13); - c1.stmtAddBatch(); - c1.stmtExecute(); - c1.stmtClose(); - - let result = executeQuery(querySql); - let actualResData = result.resData; - let actualResFields = result.resFeilds; - - //assert result data length - expect(expectResData.length).toEqual(actualResData.length); - //assert result data - expectResData.forEach((item, index) => { - expect(item).toEqual(actualResData[index]); - }); - //assert result meta data - expectResField.forEach((item, index) => { - expect(item).toEqual(actualResFields[index]) - }) - }); -}) - -describe("stmt_bind_para_batch", () => { - test(`name:bindParamBatchWithOneTable;` + - `author:${author};` + - `desc:Using stmtBindParamBatch() bind one table in a batch;` + - `filename:${fileName};` + - `result:${result}`, () => { - let table = 'bindparambatch_121';//bind one table to one batch - let createSql = `create table if not exists ${table} ` + - `(ts timestamp,` + - `bl bool,` + - `i8 tinyint,` + - `i16 smallint,` + - `i32 int,` + - `i64 bigint,` + - `f32 float,` + - `d64 double,` + - `bnr binary(20),` + - `nchr nchar(20),` + - `u8 tinyint unsigned,` + - `u16 smallint unsigned,` + - `u32 int unsigned,` + - `u64 bigint unsigned` + - `)tags(` + - `t_bl bool,` + - `t_i8 tinyint,` + - `t_i16 smallint,` + - `t_i32 int,` + - `t_i64 bigint,` + - `t_f32 float,` + - `t_d64 double,` + - `t_bnr binary(20),` + - `t_nchr nchar(20),` + - `t_u8 tinyint unsigned,` + - `t_u16 smallint unsigned,` + - `t_u32 int unsigned,` + - `t_u64 bigint unsigned` + - `);`; - let insertSql = `insert into ? using ${table} tags(?,?,?,?,?,?,?,?,?,?,?,?,?) values (?,?,?,?,?,?,?,?,?,?,?,?,?,?);`; - let querySql = `select * from ${table}`; - let expectResField = getFieldArr(getFeildsFromDll(createSql)); - let expectResData = getResData(getBindData(), tagData1, 14); - - //prepare tag TAO_BIND - let tagBind = new taos.TaosBind(14); - tagBind.bindBool(true); - tagBind.bindTinyInt(1); - tagBind.bindSmallInt(32767); - tagBind.bindInt(1234555); - tagBind.bindBigInt(-164243520000011111n); - tagBind.bindFloat(214.02); - tagBind.bindDouble(2.01); - tagBind.bindBinary('taosdata涛思数据'); - tagBind.bindNchar('TDengine数据'); - tagBind.bindUTinyInt(254); - tagBind.bindUSmallInt(65534); - tagBind.bindUInt(4294967290 / 2); - tagBind.bindUBigInt(164243520000011111n); - - //Prepare TAOS_MULTI_BIND data array - let mBinds = new taos.TaosMultiBindArr(14); - mBinds.multiBindTimestamp(tsArr); - mBinds.multiBindBool(boolArr); - mBinds.multiBindTinyInt(tinyIntArr); - mBinds.multiBindSmallInt(smallIntArr); - mBinds.multiBindInt(intArr); - mBinds.multiBindBigInt(bigIntArr); - mBinds.multiBindFloat(floatArr); - mBinds.multiBindDouble(doubleArr); - mBinds.multiBindBinary(binaryArr); - mBinds.multiBindNchar(ncharArr); - mBinds.multiBindUTinyInt(uTinyIntArr); - mBinds.multiBindUSmallInt(uSmallIntArr); - mBinds.multiBindUInt(uIntArr); - mBinds.multiBindUBigInt(uBigIntArr); - - executeUpdate(createSql); - c1.stmtInit(); - c1.stmtPrepare(insertSql); - c1.stmtSetTbnameTags(`${table}_s01`, tagBind.getBind()); - c1.stmtBindParamBatch(mBinds.getMultiBindArr()); - c1.stmtAddBatch(); - c1.stmtExecute(); - c1.stmtClose(); - - let result = executeQuery(querySql); - let actualResData = result.resData; - let actualResFields = result.resFeilds; - - //assert result data length - expect(expectResData.length).toEqual(actualResData.length); - //assert result data - expectResData.forEach((item, index) => { - expect(item).toEqual(actualResData[index]); - }); - - //assert result meta data - expectResField.forEach((item, index) => { - expect(item).toEqual(actualResFields[index]) - }) - }); - - test(`name:bindParamBatchWithMultiTable;` + - `author:${author};` + - `desc:Using stmtBindParamBatch() bind multiple tables in a batch;` + - `filename:${fileName};` + - `result:${result}`, () => { - let table = 'bindparambatch_m21';//bind multiple tables to one batch - let createSql = `create table if not exists ${table} ` + - `(ts timestamp,` + - `bl bool,` + - `i8 tinyint,` + - `i16 smallint,` + - `i32 int,` + - `i64 bigint,` + - `f32 float,` + - `d64 double,` + - `bnr binary(20),` + - `nchr nchar(20),` + - `u8 tinyint unsigned,` + - `u16 smallint unsigned,` + - `u32 int unsigned,` + - `u64 bigint unsigned` + - `)tags(` + - `t_bl bool,` + - `t_i8 tinyint,` + - `t_i16 smallint,` + - `t_i32 int,` + - `t_i64 bigint,` + - `t_f32 float,` + - `t_d64 double,` + - `t_bnr binary(20),` + - `t_nchr nchar(20),` + - `t_u8 tinyint unsigned,` + - `t_u16 smallint unsigned,` + - `t_u32 int unsigned,` + - `t_u64 bigint unsigned` + - `);`; - let insertSql = `insert into ? using ${table} tags(?,?,?,?,?,?,?,?,?,?,?,?,?) values (?,?,?,?,?,?,?,?,?,?,?,?,?,?);`; - let querySql = `select * from ${table}`; - let expectResField = getFieldArr(getFeildsFromDll(createSql)); - let expectResData = getResData(getBindData(), tagData1, 14).concat(getResData(getBindData(), tagData2, 14)).concat(getResData(getBindData(), tagData3, 14)); - - - // prepare tag TAOS_BIND - let tagBind1 = new taos.TaosBind(14); - tagBind1.bindBool(true); - tagBind1.bindTinyInt(1); - tagBind1.bindSmallInt(32767); - tagBind1.bindInt(1234555); - tagBind1.bindBigInt(-164243520000011111n); - tagBind1.bindFloat(214.02); - tagBind1.bindDouble(2.01); - tagBind1.bindBinary('taosdata涛思数据'); - tagBind1.bindNchar('TDengine数据'); - tagBind1.bindUTinyInt(254); - tagBind1.bindUSmallInt(65534); - tagBind1.bindUInt(4294967290 / 2); - tagBind1.bindUBigInt(164243520000011111n); - - let tagBind2 = new taos.TaosBind(14); - tagBind2.bindBool(true); - tagBind2.bindTinyInt(2); - tagBind2.bindSmallInt(32767); - tagBind2.bindInt(1234555); - tagBind2.bindBigInt(-164243520000011111n); - tagBind2.bindFloat(214.02); - tagBind2.bindDouble(2.01); - tagBind2.bindBinary('taosdata涛思数据'); - tagBind2.bindNchar('TDengine数据'); - tagBind2.bindUTinyInt(254); - tagBind2.bindUSmallInt(65534); - tagBind2.bindUInt(4294967290 / 2); - tagBind2.bindUBigInt(164243520000011111n); - - let tagBind3 = new taos.TaosBind(14); - tagBind3.bindBool(true); - tagBind3.bindTinyInt(3); - tagBind3.bindSmallInt(32767); - tagBind3.bindInt(1234555); - tagBind3.bindBigInt(-164243520000011111n); - tagBind3.bindFloat(214.02); - tagBind3.bindDouble(2.01); - tagBind3.bindBinary('taosdata涛思数据'); - tagBind3.bindNchar('TDengine数据'); - tagBind3.bindUTinyInt(254); - tagBind3.bindUSmallInt(65534); - tagBind3.bindUInt(4294967290 / 2); - tagBind3.bindUBigInt(164243520000011111n); - - //Prepare TAOS_MULTI_BIND data array - let mBinds = new taos.TaosMultiBindArr(14); - mBinds.multiBindTimestamp(tsArr); - mBinds.multiBindBool(boolArr); - mBinds.multiBindTinyInt(tinyIntArr); - mBinds.multiBindSmallInt(smallIntArr); - mBinds.multiBindInt(intArr); - mBinds.multiBindBigInt(bigIntArr); - mBinds.multiBindFloat(floatArr); - mBinds.multiBindDouble(doubleArr); - mBinds.multiBindBinary(binaryArr); - mBinds.multiBindNchar(ncharArr); - mBinds.multiBindUTinyInt(uTinyIntArr); - mBinds.multiBindUSmallInt(uSmallIntArr); - mBinds.multiBindUInt(uIntArr); - mBinds.multiBindUBigInt(uBigIntArr); - - executeUpdate(createSql); - c1.stmtInit(); - c1.stmtPrepare(insertSql); - // ===========bind for 1st table ========== - c1.stmtSetTbnameTags(`${table}_s01`, tagBind1.getBind()); - c1.stmtBindParamBatch(mBinds.getMultiBindArr()); - c1.stmtAddBatch(); - // c1.stmtExecute(); - - // ===========bind for 2nd table ========== - c1.stmtSetTbnameTags(`${table}_s02`, tagBind2.getBind()); - c1.stmtBindParamBatch(mBinds.getMultiBindArr()); - c1.stmtAddBatch(); - // c1.stmtExecute(); - - // ===========bind for 3rd table ========== - c1.stmtSetTbnameTags(`${table}_s03`, tagBind3.getBind()); - c1.stmtBindParamBatch(mBinds.getMultiBindArr()); - c1.stmtAddBatch(); - c1.stmtExecute(); - c1.stmtClose(); - - let result = executeQuery(querySql); - let actualResData = result.resData; - let actualResFields = result.resFeilds; - - //assert result data length - expect(expectResData.length).toEqual(actualResData.length); - //assert result data - expectResData.forEach((item, index) => { - expect(item).toEqual(actualResData[index]); - }); - - //assert result meta data - expectResField.forEach((item, index) => { - expect(item).toEqual(actualResFields[index]) - }) - - - }); -}) - -describe("stmt_bind_param", () => { - test(`name:bindParamWithOneTable;` + - `author:${author};` + - `desc:using stmtBindParam() bind one table in a batch;` + - `filename:${fileName};` + - `result:${result}`, () => { - let table = 'bindparam_121';//bind one table to one batch - let createSql = `create table if not exists ${table} ` + - `(ts timestamp,` + - `bl bool,` + - `i8 tinyint,` + - `i16 smallint,` + - `i32 int,` + - `i64 bigint,` + - `f32 float,` + - `d64 double,` + - `bnr binary(20),` + - `nchr nchar(20),` + - `u8 tinyint unsigned,` + - `u16 smallint unsigned,` + - `u32 int unsigned,` + - `u64 bigint unsigned` + - `)tags(` + - `t_bl bool,` + - `t_i8 tinyint,` + - `t_i16 smallint,` + - `t_i32 int,` + - `t_i64 bigint,` + - `t_f32 float,` + - `t_d64 double,` + - `t_bnr binary(20),` + - `t_nchr nchar(20),` + - `t_u8 tinyint unsigned,` + - `t_u16 smallint unsigned,` + - `t_u32 int unsigned,` + - `t_u64 bigint unsigned` + - `);`; - let insertSql = `insert into ? using ${table} tags(?,?,?,?,?,?,?,?,?,?,?,?,?) values (?,?,?,?,?,?,?,?,?,?,?,?,?,?);`; - let querySql = `select * from ${table}`; - let expectResField = getFieldArr(getFeildsFromDll(createSql)); - let data = getBindData(); - let expectResData = getResData(data, tagData1, 14); - - //prepare tag data - let tags = new taos.TaosBind(13); - tags.bindBool(true); - tags.bindTinyInt(1); - tags.bindSmallInt(32767); - tags.bindInt(1234555); - tags.bindBigInt(-164243520000011111n); - tags.bindFloat(214.02); - tags.bindDouble(2.01); - tags.bindBinary('taosdata涛思数据'); - tags.bindNchar('TDengine数据'); - tags.bindUTinyInt(254); - tags.bindUSmallInt(65534); - tags.bindUInt(4294967290 / 2); - tags.bindUBigInt(164243520000011111n); - executeUpdate(createSql); - - c1.stmtInit(); - c1.stmtPrepare(insertSql); - c1.stmtSetTbnameTags(`${table}_s01`, tags.getBind()); - for (let i = 0; i < data.length - 14; i += 14) { - let bind = new taos.TaosBind(14); - bind.bindTimestamp(data[i]); - bind.bindBool(data[i + 1]); - bind.bindTinyInt(data[i + 2]); - bind.bindSmallInt(data[i + 3]); - bind.bindInt(data[i + 4]); - bind.bindBigInt(data[i + 5]); - bind.bindFloat(data[i + 6]); - bind.bindDouble(data[i + 7]); - bind.bindBinary(data[i + 8]); - bind.bindNchar(data[i + 9]); - bind.bindUTinyInt(data[i + 10]); - bind.bindUSmallInt(data[i + 11]); - bind.bindUInt(data[i + 12]); - bind.bindUBigInt(data[i + 13]); - c1.stmtBindParam(bind.getBind()); - c1.stmtAddBatch(); - } - let bind2 = new taos.TaosBind(14); - bind2.bindTimestamp(data[14 * 4]); - for (let j = 0; j < 13; j++) { - bind2.bindNil(); - } - c1.stmtBindParam(bind2.getBind()); - c1.stmtAddBatch(); - c1.stmtExecute(); - c1.stmtClose(); - - let result = executeQuery(querySql); - let actualResData = result.resData; - let actualResFields = result.resFeilds; - - //assert result data length - expect(expectResData.length).toEqual(actualResData.length); - //assert result data - expectResData.forEach((item, index) => { - expect(item).toEqual(actualResData[index]); - }); - - //assert result meta data - expectResField.forEach((item, index) => { - expect(item).toEqual(actualResFields[index]) - }) - }); - - test(`name:bindParamWithMultiTable;` + - `author:${author};` + - `desc:using stmtBindParam() bind multiple tables in a batch;` + - `filename:${fileName};` + - `result:${result}`, () => { - let table = 'bindparam_m21';//bind one table to one batch - let createSql = `create table if not exists ${table} ` + - `(ts timestamp,` + - `bl bool,` + - `i8 tinyint,` + - `i16 smallint,` + - `i32 int,` + - `i64 bigint,` + - `f32 float,` + - `d64 double,` + - `bnr binary(20),` + - `nchr nchar(20),` + - `u8 tinyint unsigned,` + - `u16 smallint unsigned,` + - `u32 int unsigned,` + - `u64 bigint unsigned` + - `)tags(` + - `t_bl bool,` + - `t_i8 tinyint,` + - `t_i16 smallint,` + - `t_i32 int,` + - `t_i64 bigint,` + - `t_f32 float,` + - `t_d64 double,` + - `t_bnr binary(20),` + - `t_nchr nchar(20),` + - `t_u8 tinyint unsigned,` + - `t_u16 smallint unsigned,` + - `t_u32 int unsigned,` + - `t_u64 bigint unsigned` + - `);`; - let insertSql = `insert into ? using ${table} tags(?,?,?,?,?,?,?,?,?,?,?,?,?) values (?,?,?,?,?,?,?,?,?,?,?,?,?,?);`; - let querySql = `select * from ${table}`; - let expectResField = getFieldArr(getFeildsFromDll(createSql)); - let data = getBindData(); - let expectResData = getResData(data, tagData1, 14).concat(getResData(data, tagData2, 14)).concat(getResData(data, tagData3, 14)); - - // prepare tag TAOS_BIND - let tagBind1 = new taos.TaosBind(14); - tagBind1.bindBool(true); - tagBind1.bindTinyInt(1); - tagBind1.bindSmallInt(32767); - tagBind1.bindInt(1234555); - tagBind1.bindBigInt(-164243520000011111n); - tagBind1.bindFloat(214.02); - tagBind1.bindDouble(2.01); - tagBind1.bindBinary('taosdata涛思数据'); - tagBind1.bindNchar('TDengine数据'); - tagBind1.bindUTinyInt(254); - tagBind1.bindUSmallInt(65534); - tagBind1.bindUInt(4294967290 / 2); - tagBind1.bindUBigInt(164243520000011111n); - - let tagBind2 = new taos.TaosBind(14); - tagBind2.bindBool(true); - tagBind2.bindTinyInt(2); - tagBind2.bindSmallInt(32767); - tagBind2.bindInt(1234555); - tagBind2.bindBigInt(-164243520000011111n); - tagBind2.bindFloat(214.02); - tagBind2.bindDouble(2.01); - tagBind2.bindBinary('taosdata涛思数据'); - tagBind2.bindNchar('TDengine数据'); - tagBind2.bindUTinyInt(254); - tagBind2.bindUSmallInt(65534); - tagBind2.bindUInt(4294967290 / 2); - tagBind2.bindUBigInt(164243520000011111n); - - let tagBind3 = new taos.TaosBind(14); - tagBind3.bindBool(true); - tagBind3.bindTinyInt(3); - tagBind3.bindSmallInt(32767); - tagBind3.bindInt(1234555); - tagBind3.bindBigInt(-164243520000011111n); - tagBind3.bindFloat(214.02); - tagBind3.bindDouble(2.01); - tagBind3.bindBinary('taosdata涛思数据'); - tagBind3.bindNchar('TDengine数据'); - tagBind3.bindUTinyInt(254); - tagBind3.bindUSmallInt(65534); - tagBind3.bindUInt(4294967290 / 2); - tagBind3.bindUBigInt(164243520000011111n); - - executeUpdate(createSql); - c1.stmtInit(); - c1.stmtPrepare(insertSql); - // ========= bind for 1st table ================= - c1.stmtSetTbnameTags(`${table}_s01`, tagBind1.getBind()); - for (let i = 0; i < data.length - 14; i += 14) { - let bind = new taos.TaosBind(14); - bind.bindTimestamp(data[i]); - bind.bindBool(data[i + 1]); - bind.bindTinyInt(data[i + 2]); - bind.bindSmallInt(data[i + 3]); - bind.bindInt(data[i + 4]); - bind.bindBigInt(data[i + 5]); - bind.bindFloat(data[i + 6]); - bind.bindDouble(data[i + 7]); - bind.bindBinary(data[i + 8]); - bind.bindNchar(data[i + 9]); - bind.bindUTinyInt(data[i + 10]); - bind.bindUSmallInt(data[i + 11]); - bind.bindUInt(data[i + 12]); - bind.bindUBigInt(data[i + 13]); - c1.stmtBindParam(bind.getBind()); - c1.stmtAddBatch(); - } - let bind2 = new taos.TaosBind(14); - bind2.bindTimestamp(data[14 * 4]); - for (let j = 0; j < 13; j++) { - bind2.bindNil(); - } - c1.stmtBindParam(bind2.getBind()); - c1.stmtAddBatch(); - // c1.stmtExecute(); - - // ========= bind for 2nd table ================= - c1.stmtSetTbnameTags(`${table}_s02`, tagBind2.getBind()); - for (let i = 0; i < data.length - 14; i += 14) { - let bind = new taos.TaosBind(14); - bind.bindTimestamp(data[i]); - bind.bindBool(data[i + 1]); - bind.bindTinyInt(data[i + 2]); - bind.bindSmallInt(data[i + 3]); - bind.bindInt(data[i + 4]); - bind.bindBigInt(data[i + 5]); - bind.bindFloat(data[i + 6]); - bind.bindDouble(data[i + 7]); - bind.bindBinary(data[i + 8]); - bind.bindNchar(data[i + 9]); - bind.bindUTinyInt(data[i + 10]); - bind.bindUSmallInt(data[i + 11]); - bind.bindUInt(data[i + 12]); - bind.bindUBigInt(data[i + 13]); - c1.stmtBindParam(bind.getBind()); - c1.stmtAddBatch(); - } - c1.stmtBindParam(bind2.getBind()); - c1.stmtAddBatch(); - // c1.stmtExecute(); - - // ========= bind for 3rd table ================= - c1.stmtSetTbnameTags(`${table}_s03`, tagBind3.getBind()); - for (let i = 0; i < data.length - 14; i += 14) { - let bind = new taos.TaosBind(14); - bind.bindTimestamp(data[i]); - bind.bindBool(data[i + 1]); - bind.bindTinyInt(data[i + 2]); - bind.bindSmallInt(data[i + 3]); - bind.bindInt(data[i + 4]); - bind.bindBigInt(data[i + 5]); - bind.bindFloat(data[i + 6]); - bind.bindDouble(data[i + 7]); - bind.bindBinary(data[i + 8]); - bind.bindNchar(data[i + 9]); - bind.bindUTinyInt(data[i + 10]); - bind.bindUSmallInt(data[i + 11]); - bind.bindUInt(data[i + 12]); - bind.bindUBigInt(data[i + 13]); - c1.stmtBindParam(bind.getBind()); - c1.stmtAddBatch(); - } - c1.stmtBindParam(bind2.getBind()); - c1.stmtAddBatch(); - c1.stmtExecute(); - c1.stmtClose(); - - let result = executeQuery(querySql); - let actualResData = result.resData; - let actualResFields = result.resFeilds; - - //assert result data length - expect(expectResData.length).toEqual(actualResData.length); - //assert result data - expectResData.forEach((item, index) => { - expect(item).toEqual(actualResData[index]); - }); - - //assert result meta data - expectResField.forEach((item, index) => { - expect(item).toEqual(actualResFields[index]) - }) - }); -}) - diff --git a/src/connector/nodejs/test/utils/utilTools.js b/src/connector/nodejs/test/utils/utilTools.js deleted file mode 100644 index ae057b2dd106559d021f738e1a6046572aad5afb..0000000000000000000000000000000000000000 --- a/src/connector/nodejs/test/utils/utilTools.js +++ /dev/null @@ -1,177 +0,0 @@ -/** - * This is an util function will return the column info based on the create sql. - * @param {*} sql - * @returns Return an Array about the column names and column type. - * - */ -function getFeildsFromDll(sql) { - let fields = []; - - let firstBracket = sql.indexOf('('); - let lastBracket = sql.lastIndexOf(')') - - let metaStr = sql.slice(firstBracket, lastBracket + 1); - let splitTags = metaStr.split("tags"); - - splitTags.forEach((item, index, arr) => { - arr[index] = item.slice(1, item.length - 1) - }) - splitTags.forEach((item) => { - let tmp = item.split(","); - tmp.forEach((item) => { - let newItem = item.trim(); - let spaceInd = newItem.indexOf(' ', 1) - fields.push(newItem.slice(0, spaceInd)); - fields.push(newItem.slice(spaceInd + 1, newItem.length)) - }) - }) - return fields; -} - -/** - * Based on the input array, it will generate sql that could be used to insert the data of array into the db. - * @param {*} tableName It could be the table name that you want to insert data. - * @param {*} stable If you want to using stable as template to create table automatically, - * set this to your stable name. Deault if ''; - * @param {*} dataArr An Array of data that you want insert (it could be mutilple lines) - * @param {*} tagArr An Array used to store one sub table's tag info - * @param {*} numOfColumn The number of columns that the target table has. - * @returns Return an insert sql string. - */ -function buildInsertSql(tableName, stable = '', dataArr, tagArr = [], numOfColumn) { - let insertSql = ""; - let dataPartial = "("; - let tagPart = "("; - - dataArr.forEach((item, index) => { - // let item = dataArr[index]; - if (typeof item == "string") { - dataPartial += '\'' + item + '\''; - } else { - dataPartial += item; - } - if ((index + 1) % numOfColumn == 0 && (index + 1) != dataArr.length) { - dataPartial += ")(" - } else if ((index + 1) % numOfColumn == 0 && (index + 1) == dataArr.length) { - dataPartial += ")" - } else { - dataPartial += "," - } - - }) - if (stable != '') { - tagArr.forEach((item, index) => { - if (typeof item == "string") { - tagPart += '\'' + item + '\''; - } else { - tagPart += item; - } - - if (index != tagArr.length - 1) { - tagPart += ","; - } else { - tagPart += ")"; - } - }) - } - - if (stable == '') { - insertSql += `insert into ${tableName} values ${dataPartial};` - } else { - insertSql += `insert into ${tableName} using ${stable} tags ${tagPart} values ${dataPartial};` - } - - return insertSql; -} -/** - * used to mapping the data type of an create clause into TDengine's datatype code - */ -const TDengineTypeCode = { - 'null': 0, - 'bool': 1, - 'tinyint': 2, - 'smallint': 3, - 'int': 4, - 'bigint': 5, - 'float': 6, - 'double': 7, - 'binary': 8, - 'timestamp': 9, - 'nchar': 10, - 'tinyint unsigned': 11, - 'smallint unsigned': 12, - 'int unsigned': 13, - 'bigint unsigned': 14, - 'json': 15, -} - -/** - * Mapping the data type with corresponing size that has defined in tdengine - */ -const TDengineTypeBytes = { - 'null': 0, - 'bool': 1, - 'tinyint': 1, - 'smallint': 2, - 'int': 4, - 'bigint': 8, - 'float': 4, - 'double': 8, - 'timestamp': 8, - 'tinyint unsigned': 1, - 'smallint unsigned': 2, - 'int unsigned': 4, - 'bigint unsigned': 8, - 'json': 4096, -} - -/** - * Used to create an array of taos feilds object. - * @param {*} arr This should be the return array from the method getFeildsFromDll() - * @returns Return an array of taosFeild Object - */ -function getFieldArr(arr) { - let feild = []; - for (let i = 0; i < arr.length;) { - let bracetPosi = arr[i + 1].indexOf('('); - let type = ''; - let size = -1; - - if (bracetPosi == -1) { - type = TDengineTypeCode[arr[i + 1]]; - size = TDengineTypeBytes[arr[i + 1]]; - }else{ - type = TDengineTypeCode[arr[i + 1].slice(0, bracetPosi)]; - size = Number(arr[i + 1].slice(bracetPosi + 1, arr[i + 1].indexOf(')'))); - } - let fieldObj = { - name: arr[i].toLowerCase(), - type: type, - bytes: size - } - feild.push(fieldObj); - i = i + 2; - } - return feild; -} -/** - * Conbine arrays of data info and tag info together, and return a new array. This array construction is simmilar with query result - * from the tdengine by taos shell.This method only can be used by a subtable. - * @param {*} dataArr An array holds columns' data that will be insert into the db. - * @param {*} tagArr An array holds tags' data that is belong to a sub table. - * @param {*} numOfcolumn - * @returns return the an array of column data and tag data. - */ -function getResData(dataArr, tagArr, numOfcolumn) { - let resData = []; - dataArr.forEach((item, index) => { - resData.push(item); - if ((index + 1) % numOfcolumn == 0) { - tagArr.forEach((element) => { - resData.push(element); - }) ; - } - }); - return resData; -} -module.exports = { getFeildsFromDll, buildInsertSql, getFieldArr, getResData }; \ No newline at end of file diff --git a/src/connector/odbc/CMakeLists.txt b/src/connector/odbc/CMakeLists.txt index d955d0c238099a488ea693d1aedf62f0494ca0f7..5e8095c7ddfa577767eb6ca03624c0c7278e174d 100644 --- a/src/connector/odbc/CMakeLists.txt +++ b/src/connector/odbc/CMakeLists.txt @@ -1,71 +1,74 @@ CMAKE_MINIMUM_REQUIRED(VERSION 3.0...3.20) PROJECT(TDengine) -IF (TD_LINUX_64) - find_program(HAVE_ODBCINST NAMES odbcinst) - IF (HAVE_ODBCINST) - include(CheckSymbolExists) - # shall we revert CMAKE_REQUIRED_LIBRARIES and how? - set(CMAKE_REQUIRED_LIBRARIES odbc) - check_symbol_exists(SQLExecute "sql.h" HAVE_ODBC_DEV) - if(NOT (HAVE_ODBC_DEV)) - unset(HAVE_ODBC_DEV CACHE) - message(WARNING "unixodbc-dev is not installed yet, you may install it under ubuntu by typing: sudo apt install unixodbc-dev") - else () - message(STATUS "unixodbc/unixodbc-dev are installed, and odbc connector will be built") - find_package(FLEX) - if(NOT FLEX_FOUND) - message(WARNING "you need to install flex first") - else () - if (CMAKE_C_COMPILER_ID STREQUAL "GNU" AND CMAKE_C_COMPILER_VERSION VERSION_LESS 5.0.0) - message(WARNING "gcc 4.8.0 will complain too much about flex-generated code, we just bypass building ODBC driver in such case") - else () - SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ") - SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ") - ADD_SUBDIRECTORY(src) - ADD_SUBDIRECTORY(tools) - ADD_SUBDIRECTORY(examples) - endif () - endif() - endif() - ELSE () - message(WARNING "unixodbc is not installed yet, you may install it under ubuntu by typing: sudo apt install unixodbc") +macro(check_odbc_requirement) + find_package(FLEX) + IF (NOT FLEX_FOUND) + message(WARNING "you need to install flex first") + return () + ENDIF () + IF (CMAKE_C_COMPILER_ID STREQUAL "GNU" AND CMAKE_C_COMPILER_VERSION VERSION_LESS 5.0.0) + message(WARNING "gcc 4.8.0 will complain too much about flex-generated code, we just bypass building ODBC driver in such case") + return () ENDIF () -ENDIF () -IF (TD_DARWIN) - find_program(HAVE_ODBCINST NAMES odbcinst) - IF (HAVE_ODBCINST) - include(CheckSymbolExists) - # shall we revert CMAKE_REQUIRED_LIBRARIES and how? - set(CMAKE_REQUIRED_LIBRARIES odbc) - set(CMAKE_REQUIRED_INCLUDES /usr/local/include) - set(CMAKE_REQUIRED_LINK_OPTIONS -L/usr/local/lib) - check_symbol_exists(SQLExecute "sql.h" HAVE_ODBC_DEV) - if(NOT (HAVE_ODBC_DEV)) - unset(HAVE_ODBC_DEV CACHE) - message(WARNING "unixodbc-dev is not installed yet, you may install it with homebrew by typing: brew install unixodbc") - else () - message(STATUS "unixodbc/unixodbc-dev are installed, and odbc connector will be built") - find_package(FLEX) - if(NOT FLEX_FOUND) - message(WARNING "you need to install flex first") - else () - if (CMAKE_C_COMPILER_ID STREQUAL "GNU" AND CMAKE_C_COMPILER_VERSION VERSION_LESS 5.0.0) - message(WARNING "gcc 4.8.0 will complain too much about flex-generated code, we just bypass building ODBC driver in such case") - else () - SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wconversion") - SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Wconversion") - ADD_SUBDIRECTORY(src) - ADD_SUBDIRECTORY(tools) - ADD_SUBDIRECTORY(examples) - endif () - endif() - endif() - ELSE () - message(WARNING "unixodbc is not installed yet, you may install it under ubuntu by typing: brew install unixodbc") + find_program(TD_ODBCINST_INSTALLED NAMES odbcinst) + IF (NOT TD_ODBCINST_INSTALLED) + IF (TD_DARWIN) + message(WARNING "unixodbc is not installed yet, you may install it under macOS by typing: brew install unixodbc") + ELSE () + message(WARNING "odbcinst is not installed yet, you may install it under Ubuntu by typing: sudo apt install odbcinst") + ENDIF () + return () ENDIF () -ENDIF () + + find_program(TD_ISQL_INSTALLED NAMES isql) + IF (NOT TD_ISQL_INSTALLED) + IF (TD_DARWIN) + message(WARNING "unixodbc is not installed yet, you may install it under macOS by typing: brew install unixodbc") + ELSE () + message(WARNING "unixodbc is not installed yet, you may install it under Ubuntu by typing: sudo apt install unixodbc") + ENDIF () + return () + ENDIF () + + find_program(TD_PKG_CONFIG_INSTALLED NAMES pkg-config) + IF (NOT TD_PKG_CONFIG_INSTALLED) + IF (TD_DARWIN) + message(WARNING "pkg-config is not installed yet, you may install it under macOS by typing: brew install pkg-config") + ELSE () + message(WARNING "pkg-config is not installed yet, you may install it under Ubuntu by typing: sudo apt install pkg-config") + ENDIF () + return () + ENDIF () + + EXECUTE_PROCESS(COMMAND pkg-config --variable=includedir odbc ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE ODBC_INCLUDE_DIRECTORY) + EXECUTE_PROCESS(COMMAND pkg-config --variable=libdir odbc ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE ODBC_LIBRARY_DIRECTORY) + EXECUTE_PROCESS(COMMAND pkg-config --libs-only-L odbc ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE ODBC_LINK_OPTIONS) + + EXECUTE_PROCESS(COMMAND pkg-config --variable=includedir odbcinst ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE ODBCINST_INCLUDE_DIRECTORY) + EXECUTE_PROCESS(COMMAND pkg-config --variable=libdir odbcinst ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE ODBCINST_LIBRARY_DIRECTORY) + EXECUTE_PROCESS(COMMAND pkg-config --libs-only-L odbcinst ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE ODBCINST_LINK_OPTIONS) + + include(CheckSymbolExists) + + set(CMAKE_REQUIRED_LIBRARIES odbc odbcinst) + set(CMAKE_REQUIRED_INCLUDES ${ODBC_INCLUDE_DIRECTORY} ${ODBCINST_INCLUDE_DIRECTORY}) + set(CMAKE_REQUIRED_LINK_OPTIONS ${ODBC_LINK_OPTIONS} ${ODBCINST_LINK_OPTIONS}) + + check_symbol_exists(SQLExecute "sql.h" HAVE_ODBC_DEV) + IF (NOT HAVE_ODBC_DEV) + message(WARNING "odbc requirement not satisfied, check detail in ${CMAKE_BINARY_DIR}/CMakeFiles/CMakeError.log") + return () + ENDIF () + + check_symbol_exists(SQLInstallODBC "odbcinst.h" HAVE_ODBCINST_DEV) + IF (NOT HAVE_ODBCINST_DEV) + message(WARNING "odbc requirement not satisfied, check detail in ${CMAKE_BINARY_DIR}/CMakeFiles/CMakeError.log") + return () + ENDIF () + +endmacro() IF (TD_WINDOWS_64) find_package(ODBC) @@ -86,5 +89,14 @@ IF (TD_WINDOWS_64) ADD_SUBDIRECTORY(tools) ADD_SUBDIRECTORY(examples) endif() +ELSE () + check_odbc_requirement() + IF (TD_DARWIN) + SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wconversion") + SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Wconversion") + ENDIF () + ADD_SUBDIRECTORY(src) + ADD_SUBDIRECTORY(tools) + ADD_SUBDIRECTORY(examples) ENDIF () diff --git a/src/connector/odbc/examples/c/CMakeLists.txt b/src/connector/odbc/examples/c/CMakeLists.txt index 7821f894d072e129be563805a10901e403e3cf2a..42985496554adf5023a5078f7ec7650413a18bb4 100644 --- a/src/connector/odbc/examples/c/CMakeLists.txt +++ b/src/connector/odbc/examples/c/CMakeLists.txt @@ -3,14 +3,11 @@ PROJECT(TDengine) ADD_EXECUTABLE(tcodbc main.c ../../src/todbc_log.c) IF (TD_LINUX OR TD_DARWIN) + target_include_directories(tcodbc PRIVATE ${ODBC_INCLUDE_DIRECTORY}) + target_link_directories(tcodbc PUBLIC ${ODBC_LIBRARY_DIRECTORY}) TARGET_LINK_LIBRARIES(tcodbc taos odbc) ENDIF () -IF (TD_DARWIN) - target_include_directories(tcodbc PRIVATE /usr/local/include) - target_link_directories(tcodbc PUBLIC /usr/local/lib) -ENDIF () - IF (TD_WINDOWS_64) SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /GL") SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /GL") diff --git a/src/connector/odbc/src/CMakeLists.txt b/src/connector/odbc/src/CMakeLists.txt index 3fe9e19d5fbaeecb93a05840da147c503f115f08..f0df94795ac35f2b2e9537b7d437c34e2af193e2 100644 --- a/src/connector/odbc/src/CMakeLists.txt +++ b/src/connector/odbc/src/CMakeLists.txt @@ -18,7 +18,8 @@ IF (TD_LINUX_64) SET_TARGET_PROPERTIES(todbc PROPERTIES CLEAN_DIRECT_OUTPUT 1) SET_TARGET_PROPERTIES(todbc PROPERTIES VERSION ${TD_VER_NUMBER} SOVERSION 1) TARGET_LINK_LIBRARIES(todbc todbc_base taos odbcinst) - target_include_directories(todbc PUBLIC .) + target_include_directories(todbc PRIVATE . ${ODBC_INCLUDE_DIRECTORY}) + target_link_directories(todbc PUBLIC ${ODBC_LIBRARY_DIRECTORY}) install(CODE "execute_process(COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/install.sh ${CMAKE_BINARY_DIR})") ENDIF () @@ -39,9 +40,8 @@ IF (TD_DARWIN) SET_TARGET_PROPERTIES(todbc PROPERTIES CLEAN_DIRECT_OUTPUT 1) SET_TARGET_PROPERTIES(todbc PROPERTIES VERSION ${TD_VER_NUMBER} SOVERSION 1) TARGET_LINK_LIBRARIES(todbc todbc_base taos odbcinst) - target_include_directories(todbc PUBLIC .) - target_include_directories(todbc PRIVATE /usr/local/include) - target_link_directories(todbc PUBLIC /usr/local/lib) + target_include_directories(todbc PRIVATE . ${ODBCINST_INCLUDE_DIRECTORY}) + target_link_directories(todbc PUBLIC ${ODBCINST_LIBRARY_DIRECTORY}) install(CODE "execute_process(COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/install.sh ${CMAKE_BINARY_DIR})") ENDIF () diff --git a/src/connector/odbc/src/base/CMakeLists.txt b/src/connector/odbc/src/base/CMakeLists.txt index 7e731334ed27f43f12d411ac329dc34df971ffaa..40f2aaf972fd2786e4d341475a29d53b595e5034 100644 --- a/src/connector/odbc/src/base/CMakeLists.txt +++ b/src/connector/odbc/src/base/CMakeLists.txt @@ -4,7 +4,7 @@ PROJECT(TDengine) aux_source_directory(. SRC) add_library(todbc_base STATIC ${SRC}) -if (TD_DARWIN) - target_include_directories(todbc_base PRIVATE /usr/local/include) +if (TD_LINUX OR TD_DARWIN) + target_include_directories(todbc_base PRIVATE ${ODBC_INCLUDE_DIRECTORY}) endif () diff --git a/src/connector/odbc/tools/CMakeLists.txt b/src/connector/odbc/tools/CMakeLists.txt index e543d245c8c3ef19f541832b3f2c8889860db2f9..d49d334ef5019786a557263d0c04a7e71c9e715f 100644 --- a/src/connector/odbc/tools/CMakeLists.txt +++ b/src/connector/odbc/tools/CMakeLists.txt @@ -4,14 +4,12 @@ ADD_EXECUTABLE(todbcinst main.c) ADD_EXECUTABLE(tconv tconv.c) IF (TD_LINUX OR TD_DARWIN) + target_include_directories(todbcinst PRIVATE . ${ODBC_INCLUDE_DIRECTORY} ${ODBCINST_INCLUDE_DIRECTORY}) + target_link_directories(todbcinst PUBLIC ${ODBC_LIBRARY_DIRECTORY} ${ODBCINST_LIBRARY_DIRECTORY}) TARGET_LINK_LIBRARIES(todbcinst odbc odbcinst) ENDIF () IF (TD_DARWIN) - target_include_directories(todbcinst PRIVATE /usr/local/include) - target_link_directories(todbcinst PUBLIC /usr/local/lib) - target_include_directories(tconv PRIVATE /usr/local/include) - target_link_directories(tconv PUBLIC /usr/local/lib) TARGET_LINK_LIBRARIES(tconv iconv) ENDIF () diff --git a/src/kit/taos-tools b/src/kit/taos-tools index 9815e306333f4b0d8cf31499ba6c1e3a21fe104c..d25265d2449c2db91dfd1e4789876c553da3e950 160000 --- a/src/kit/taos-tools +++ b/src/kit/taos-tools @@ -1 +1 @@ -Subproject commit 9815e306333f4b0d8cf31499ba6c1e3a21fe104c +Subproject commit d25265d2449c2db91dfd1e4789876c553da3e950 diff --git a/src/os/src/detail/osFile.c b/src/os/src/detail/osFile.c index f18fb6a6a8ebe0ae87811f0afbd37d44ff3dc02b..910e6f15be48e9a757b87939dd95b3541967f9c3 100644 --- a/src/os/src/detail/osFile.c +++ b/src/os/src/detail/osFile.c @@ -179,7 +179,7 @@ int64_t taosFSendFile(FILE *out_file, FILE *in_file, int64_t *offset, int64_t co fwrite(buffer, 1, rlen, out_file); return (int64_t)(writeLen + rlen); } else { - fwrite(buffer, 1, _SEND_FILE_STEP_, in_file); + fwrite(buffer, 1, _SEND_FILE_STEP_, out_file); writeLen += _SEND_FILE_STEP_; } } @@ -223,7 +223,7 @@ int64_t taosSendFile(SocketFd dfd, FileFd sfd, int64_t *offset, int64_t count) { if (rlen <= 0) { return writeLen; } else { - taosWriteSocket(sfd, buffer, (int32_t)remain); + taosWriteSocket(dfd, buffer, (int32_t)remain); writeLen += remain; } } diff --git a/src/os/tests/CMakeLists.txt b/src/os/tests/CMakeLists.txt index ef2c387e079b5b592c162b8533308c3dfd7ca07b..59f4ebbf7fbe6ded16720d96b3a3fdd195522a80 100644 --- a/src/os/tests/CMakeLists.txt +++ b/src/os/tests/CMakeLists.txt @@ -1,9 +1,14 @@ CMAKE_MINIMUM_REQUIRED(VERSION 3.0...3.20) PROJECT(TDengine) -FIND_PATH(HEADER_GTEST_INCLUDE_DIR gtest.h /usr/include/gtest /usr/local/include/gtest) -FIND_LIBRARY(LIB_GTEST_STATIC_DIR libgtest.a /usr/lib/ /usr/local/lib /usr/lib64) -FIND_LIBRARY(LIB_GTEST_SHARED_DIR libgtest.so /usr/lib/ /usr/local/lib /usr/lib64) +IF (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + SET(HOMEBREW_LIB_PATH "/opt/homebrew/lib") + SET(HOMEBREW_INC_PATH "/opt/homebrew/include/gtest") +ENDIF () + +FIND_PATH(HEADER_GTEST_INCLUDE_DIR gtest.h /usr/include/gtest /usr/local/include/gtest ${HOMEBREW_INC_PATH}) +FIND_LIBRARY(LIB_GTEST_STATIC_DIR libgtest.a /usr/lib/ /usr/local/lib /usr/lib64 ${HOMEBREW_LIB_PATH}) +FIND_LIBRARY(LIB_GTEST_SHARED_DIR libgtest.so /usr/lib/ /usr/local/lib /usr/lib64 ${HOMEBREW_LIB_PATH}) IF (HEADER_GTEST_INCLUDE_DIR AND (LIB_GTEST_STATIC_DIR OR LIB_GTEST_SHARED_DIR)) MESSAGE(STATUS "gTest library found, build unit test") @@ -11,11 +16,16 @@ IF (HEADER_GTEST_INCLUDE_DIR AND (LIB_GTEST_STATIC_DIR OR LIB_GTEST_SHARED_DIR)) # GoogleTest requires at least C++11 SET(CMAKE_CXX_STANDARD 11) - INCLUDE_DIRECTORIES(/usr/include /usr/local/include) - LINK_DIRECTORIES(/usr/lib /usr/local/lib) + get_filename_component(HEADER_GTEST_PATH ${HEADER_GTEST_INCLUDE_DIR} PATH) + INCLUDE_DIRECTORIES(/usr/include /usr/local/include ${HEADER_GTEST_PATH}) AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} SOURCE_LIST) - ADD_EXECUTABLE(osTest ${SOURCE_LIST}) - TARGET_LINK_LIBRARIES(osTest taos os cJson tutil common gtest pthread) + IF (LIB_GTEST_STATIC_DIR) + get_filename_component(GTEST_LIB_PATH ${LIB_GTEST_STATIC_DIR} PATH) + MESSAGE(STATUS "${Green} found libtest.a in ${GTEST_LIB_PATH}, will build osTest ${ColourReset}") + LINK_DIRECTORIES(/usr/lib /usr/local/lib ${GTEST_LIB_PATH}) + ADD_EXECUTABLE(osTest ${SOURCE_LIST}) + TARGET_LINK_LIBRARIES(osTest taos os cJson tutil common gtest pthread) + ENDIF() ENDIF() diff --git a/src/query/inc/qResultbuf.h b/src/query/inc/qResultbuf.h index 5191ddab46411032e25f4663122b04931281b132..7c33f729acca052b6123b5139c235195231bb9f2 100644 --- a/src/query/inc/qResultbuf.h +++ b/src/query/inc/qResultbuf.h @@ -79,9 +79,9 @@ typedef struct SDiskbasedResultBuf { #define DEFAULT_INTERN_BUF_PAGE_SIZE (1024L) // in bytes #define PAGE_INFO_INITIALIZER (SPageDiskInfo){-1, -1} #define MAX_UNIQUE_RESULT_ROWS (10000) -#define MAX_UNIQUE_RESULT_SIZE (1024*1024*10) -#define MAX_MODE_INNER_RESULT_ROWS (1000000) -#define MAX_MODE_INNER_RESULT_SIZE (1024*1024*10) +#define MAX_UNIQUE_RESULT_SIZE (1024*1024) +#define MAX_MODE_INNER_RESULT_ROWS (10000) +#define MAX_MODE_INNER_RESULT_SIZE (1024*1024) /** * create disk-based result buffer * @param pResultBuf diff --git a/src/query/src/qAggMain.c b/src/query/src/qAggMain.c index b9834b45b0d89c66e886365bd525001b995ca7a6..5701f95f0078ac707d401b2d072972d1853f81e7 100644 --- a/src/query/src/qAggMain.c +++ b/src/query/src/qAggMain.c @@ -5185,10 +5185,6 @@ static bool elapsedSetup(SQLFunctionCtx *pCtx, SResultRowCellInfo* pResInfo) { return true; } -static int32_t elapsedRequired(SQLFunctionCtx *pCtx, STimeWindow* w, int32_t colId) { - return BLK_DATA_NO_NEEDED; -} - static void elapsedFunction(SQLFunctionCtx *pCtx) { SElapsedInfo *pInfo = getOutputInfo(pCtx); if (pCtx->preAggVals.isSet) { @@ -6509,7 +6505,7 @@ SAggFunctionInfo aAggs[TSDB_FUNC_MAX_NUM] = {{ elapsedFunction, elapsedFinalizer, elapsedMerge, - elapsedRequired, + dataBlockRequired, }, { //38 diff --git a/src/query/src/qExecutor.c b/src/query/src/qExecutor.c index 5e035463f835102ff444466fdcc65e5e02b5425a..1facab0b34e271394c37486ee2b900ec89c8f71c 100644 --- a/src/query/src/qExecutor.c +++ b/src/query/src/qExecutor.c @@ -330,11 +330,11 @@ SSDataBlock* createOutputBuf(SExprInfo* pExpr, int32_t numOfOutput, int32_t numO int64_t tmp = idata.info.bytes; tmp *= numOfRows; - if (tmp >= 1024*1024*1024) { // 1G - qError("size is too large, failed to allocate column buffer for output buffer"); + if (tmp >= INT32_MAX) { + qError("size is too large, failed to allocate column buffer for output buffer:%" PRId64, tmp); tmp = 128*1024*1024; } - int32_t size = (int32_t)MAX(tmp, minSize); + size_t size = (size_t)MAX(tmp, minSize); idata.pData = calloc(1, size); // at least to hold a pointer on x64 platform if (idata.pData == NULL) { qError("failed to allocate column buffer for output buffer"); @@ -2131,7 +2131,7 @@ static int32_t setupQueryRuntimeEnv(SQueryRuntimeEnv *pRuntimeEnv, int32_t numOf pRuntimeEnv->sasArray = calloc(pQueryAttr->numOfOutput, sizeof(SScalarExprSupport)); if (pRuntimeEnv->sasArray == NULL || pRuntimeEnv->pResultRowHashTable == NULL || pRuntimeEnv->keyBuf == NULL || - pRuntimeEnv->prevRow == NULL || pRuntimeEnv->tagVal == NULL) { + pRuntimeEnv->prevRow == NULL || pRuntimeEnv->tagVal == NULL || pRuntimeEnv->pool == NULL) { goto _clean; } diff --git a/src/query/src/qTsbuf.c b/src/query/src/qTsbuf.c index bb124dec06e49be23f3a1572d8a878a694811977..2c7e09b84408beae3814cdd943388eb031639257 100644 --- a/src/query/src/qTsbuf.c +++ b/src/query/src/qTsbuf.c @@ -125,6 +125,13 @@ STSBuf* tsBufCreateFromFile(const char* path, bool autoDelete) { ret = fseek(pTSBuf->f, 0, SEEK_END); UNUSED(ret); + + // file meta data may be cached, close and reopen the file for accurate file size. + fclose(pTSBuf->f); + pTSBuf->f = fopen(pTSBuf->path, "rb+"); + if (pTSBuf->f == NULL) { + return pTSBuf; + } struct stat fileStat; if (fstat(fileno(pTSBuf->f), &fileStat) != 0) { diff --git a/src/query/src/qUtil.c b/src/query/src/qUtil.c index 67dfc130ed58d416500d278c60945114ef8a3fe4..1628c2d5111268111ca88cbe511095e8334453ed 100644 --- a/src/query/src/qUtil.c +++ b/src/query/src/qUtil.c @@ -204,9 +204,9 @@ SResultRowPool* initResultRowPool(size_t size) { p->elemSize = (int32_t) size; int64_t tmp = p->elemSize; tmp *= p->numOfElemPerBlock; - if (tmp > 1024*1024*1024){ + if (tmp > INT32_MAX){ qError("ResultRow blockSize is too large:%" PRId64, tmp); - tmp = 128*1024*1024; + return NULL; } p->blockSize = (int32_t)tmp; p->position.pos = 0; @@ -223,6 +223,7 @@ SResultRow* getNewResultRow(SResultRowPool* p) { void* ptr = NULL; if (p->position.pos == 0) { ptr = calloc(1, p->blockSize); + if(ptr == NULL) return NULL; taosArrayPush(p->pData, &ptr); } else { diff --git a/src/query/tests/CMakeLists.txt b/src/query/tests/CMakeLists.txt index 6f3268377cd816bdc9f8e3bedf5eb0484519840a..5143c0fdc161fcc29278d5f772ced1c2717de064 100644 --- a/src/query/tests/CMakeLists.txt +++ b/src/query/tests/CMakeLists.txt @@ -1,9 +1,14 @@ CMAKE_MINIMUM_REQUIRED(VERSION 3.0...3.20) PROJECT(TDengine) -FIND_PATH(HEADER_GTEST_INCLUDE_DIR gtest.h /usr/include/gtest /usr/local/include/gtest) -FIND_LIBRARY(LIB_GTEST_STATIC_DIR libgtest.a /usr/lib/ /usr/local/lib /usr/lib64) -FIND_LIBRARY(LIB_GTEST_SHARED_DIR libgtest.so /usr/lib/ /usr/local/lib /usr/lib64) +IF (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + SET(HOMEBREW_LIB_PATH "/opt/homebrew/lib") + SET(HOMEBREW_INC_PATH "/opt/homebrew/include/gtest") +ENDIF () + +FIND_PATH(HEADER_GTEST_INCLUDE_DIR gtest.h /usr/include/gtest /usr/local/include/gtest ${HOMEBREW_INC_PATH}) +FIND_LIBRARY(LIB_GTEST_STATIC_DIR libgtest.a /usr/lib/ /usr/local/lib /usr/lib64 ${HOMEBREW_LIB_PATH}) +FIND_LIBRARY(LIB_GTEST_SHARED_DIR libgtest.so /usr/lib/ /usr/local/lib /usr/lib64 ${HOMEBREW_LIB_PATH}) IF (HEADER_GTEST_INCLUDE_DIR AND (LIB_GTEST_STATIC_DIR OR LIB_GTEST_SHARED_DIR)) MESSAGE(STATUS "gTest library found, build unit test") @@ -11,14 +16,18 @@ IF (HEADER_GTEST_INCLUDE_DIR AND (LIB_GTEST_STATIC_DIR OR LIB_GTEST_SHARED_DIR)) # GoogleTest requires at least C++11 SET(CMAKE_CXX_STANDARD 11) - INCLUDE_DIRECTORIES(/usr/include /usr/local/include) - LINK_DIRECTORIES(/usr/lib /usr/local/lib) + get_filename_component(HEADER_GTEST_PATH ${HEADER_GTEST_INCLUDE_DIR} PATH) + INCLUDE_DIRECTORIES(/usr/include /usr/local/include ${HEADER_GTEST_PATH}) - INCLUDE_DIRECTORIES(${HEADER_GTEST_INCLUDE_DIR}) AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} SOURCE_LIST) - ADD_EXECUTABLE(queryTest ${SOURCE_LIST}) - TARGET_LINK_LIBRARIES(queryTest taos cJson query gtest pthread) + IF (LIB_GTEST_STATIC_DIR) + get_filename_component(GTEST_LIB_PATH ${LIB_GTEST_STATIC_DIR} PATH) + MESSAGE(STATUS "${Green} found libtest.a in ${GTEST_LIB_PATH}, will build queryTest ${ColourReset}") + LINK_DIRECTORIES(/usr/lib /usr/local/lib ${GTEST_LIB_PATH}) + ADD_EXECUTABLE(queryTest ${SOURCE_LIST}) + TARGET_LINK_LIBRARIES(queryTest taos cJson query gtest pthread) + ENDIF() ENDIF() SET_SOURCE_FILES_PROPERTIES(./astTest.cpp PROPERTIES COMPILE_FLAGS -w) diff --git a/tests/develop-test/2-query/TD-14745.py b/tests/develop-test/2-query/TD-14745.py new file mode 100644 index 0000000000000000000000000000000000000000..f5360ee91bef6fefa09eff9606d8ce99e5052e7e --- /dev/null +++ b/tests/develop-test/2-query/TD-14745.py @@ -0,0 +1,43 @@ +import sys +from util.log import * +from util.cases import * +from util.sql import * +from util.dnodes import tdDnodes +from math import inf + +class TDTestCase: + def caseDescription(self): + ''' + case1: [TD-13946]core dump of sampling binary column so that when result from vnode exceeds INT16_MAX bytes + ''' + return + + def init(self, conn, logSql): + tdLog.debug("start to execute %s" % __file__) + tdSql.init(conn.cursor(), logSql) + self._conn = conn + + def run(self): + print("running {}".format(__file__)) + tdSql.execute("drop database if exists td14745") + tdSql.execute("create database td14745") + tdSql.execute("use td14745") + + tdSql.execute("create table st ( ts timestamp, i int) tags (t1 int)") + tdSql.execute("create table ct1 using st tags(1)") + + for i in range(100): + tdSql.execute("insert into ct1 values(now+{}a, {})".format(100*i, i)) + + tdSql.query("select sample(i,3) from ct1 interval(1s)") + tdSql.checkCols(2) + + tdSql.query("select sample(i,3) from ct1 session(ts, 200a)") + tdSql.checkCols(2) + def stop(self): + tdSql.close() + tdLog.success("%s successfully executed" % __file__) + +tdCases.addWindows(__file__, TDTestCase()) +tdCases.addLinux(__file__, TDTestCase()) + diff --git a/tests/develop-test/2-query/TD-14763.py b/tests/develop-test/2-query/TD-14763.py new file mode 100644 index 0000000000000000000000000000000000000000..e1c82e3ebf90621217899b79d93c6a49286c1cf8 --- /dev/null +++ b/tests/develop-test/2-query/TD-14763.py @@ -0,0 +1,47 @@ +import sys +from util.log import * +from util.cases import * +from util.sql import * +from util.dnodes import tdDnodes +from math import inf + +class TDTestCase: + def caseDescription(self): + ''' + case1: [TD-14763]csum can not be used on state window + ''' + return + + def init(self, conn, logSql): + tdLog.debug("start to execute %s" % __file__) + tdSql.init(conn.cursor(), logSql) + self._conn = conn + + def run(self): + print("running {}".format(__file__)) + tdSql.execute("drop database if exists td14763") + tdSql.execute("create database td14763") + tdSql.execute("use td14763") + + tdSql.execute("create table st ( ts timestamp, i int, b bool) tags (t1 int)") + tdSql.execute("create table ct1 using st tags(1)") + tdSql.execute("create table ct2 using st tags(2)") + + for i in range(0, 4000, 2): + b = True if i%3 == 0 else False + tdSql.execute("insert into ct1 values(now + {}a, {}, {})".format(i, i, b)) + tdSql.execute("insert into ct2 values(now + {}a, {}, {})".format(i+1, i+1, b)) + + tdSql.error("select csum(i) from ct1 state_window(b)") + tdSql.error("select csum(i) from (select * from st) state_window(b)") + tdSql.query("select csum(i) from ct1"); + + tdSql.execute('drop database td14763') + + def stop(self): + tdSql.close() + tdLog.success("%s successfully executed" % __file__) + +tdCases.addWindows(__file__, TDTestCase()) +tdCases.addLinux(__file__, TDTestCase()) + diff --git a/tests/develop-test/2-query/function_histogram.py b/tests/develop-test/2-query/function_histogram.py index 87c38f35c91c54473653d2881936b033a555bbff..b16db06850f2e5cce537231ecca48279642d5112 100644 --- a/tests/develop-test/2-query/function_histogram.py +++ b/tests/develop-test/2-query/function_histogram.py @@ -2535,21 +2535,21 @@ class TDTestCase: tdSql.checkData(4, 0, '{"lower_bin":9, "upper_bin":15, "count":2}'); #select session - tdSql.query('select histogram(col_int, "user_input", "[0,10]", 0) from tb session (col_timestamp, 1w);') - tdSql.checkRows(1) - tdSql.checkData(0, 1, '{"lower_bin":0, "upper_bin":10, "count":10}'); + #tdSql.query('select histogram(col_int, "user_input", "[0,10]", 0) from tb session (col_timestamp, 1w);') + #tdSql.checkRows(1) + #tdSql.checkData(0, 1, '{"lower_bin":0, "upper_bin":10, "count":10}'); - tdSql.query('select histogram(col_int, "user_input", "[0,10]", 0) from tb session (col_timestamp, 1d);') - tdSql.checkRows(1) - tdSql.checkData(0, 1, '{"lower_bin":0, "upper_bin":10, "count":10}'); + #tdSql.query('select histogram(col_int, "user_input", "[0,10]", 0) from tb session (col_timestamp, 1d);') + #tdSql.checkRows(1) + #tdSql.checkData(0, 1, '{"lower_bin":0, "upper_bin":10, "count":10}'); - tdSql.query('select histogram(col_int, "user_input", "[0,10]", 0) from tb session (col_timestamp, 1h);') - tdSql.checkRows(1) - tdSql.checkData(0, 1, '{"lower_bin":0, "upper_bin":10, "count":10}'); + #tdSql.query('select histogram(col_int, "user_input", "[0,10]", 0) from tb session (col_timestamp, 1h);') + #tdSql.checkRows(1) + #tdSql.checkData(0, 1, '{"lower_bin":0, "upper_bin":10, "count":10}'); - tdSql.query('select histogram(col_int, "user_input", "[0,10]", 0) from tb session (col_timestamp, 1m);') - tdSql.checkRows(1) - tdSql.checkData(0, 1, '{"lower_bin":0, "upper_bin":10, "count":10}'); + #tdSql.query('select histogram(col_int, "user_input", "[0,10]", 0) from tb session (col_timestamp, 1m);') + #tdSql.checkRows(1) + #tdSql.checkData(0, 1, '{"lower_bin":0, "upper_bin":10, "count":10}'); #tdSql.query('select histogram(col_int, "user_input", "[0,10]", 0) from tb session (col_timestamp, 1s);') #tdSql.checkRows(16) @@ -2602,100 +2602,100 @@ class TDTestCase: tdSql.error('select histogram(col_int, "user_input", "[0,10]", 0) from tb state_window(col_nchar);') #select interval/sliding/fill - tdSql.query('select histogram(col_int, "user_input", "[0,10]", 0) from tb interval(1y);') - tdSql.checkRows(1) - tdSql.checkData(0, 1, '{"lower_bin":0, "upper_bin":10, "count":10}'); - - tdSql.query('select histogram(col_int, "user_input", "[0,10]", 0) from tb interval(1n);') - tdSql.checkRows(1) - tdSql.checkData(0, 1, '{"lower_bin":0, "upper_bin":10, "count":10}'); + #tdSql.query('select histogram(col_int, "user_input", "[0,10]", 0) from tb interval(1y);') + #tdSql.checkRows(1) + #tdSql.checkData(0, 1, '{"lower_bin":0, "upper_bin":10, "count":10}'); - tdSql.query('select histogram(col_int, "user_input", "[0,10]", 0) from tb interval(1w);') - tdSql.checkRows(1) - tdSql.checkData(0, 1, '{"lower_bin":0, "upper_bin":10, "count":10}'); + #tdSql.query('select histogram(col_int, "user_input", "[0,10]", 0) from tb interval(1n);') + #tdSql.checkRows(1) + #tdSql.checkData(0, 1, '{"lower_bin":0, "upper_bin":10, "count":10}'); - tdSql.query('select histogram(col_int, "user_input", "[0,10]", 0) from tb interval(1d);') - tdSql.checkRows(1) - tdSql.checkData(0, 1, '{"lower_bin":0, "upper_bin":10, "count":10}'); + #tdSql.query('select histogram(col_int, "user_input", "[0,10]", 0) from tb interval(1w);') + #tdSql.checkRows(1) + #tdSql.checkData(0, 1, '{"lower_bin":0, "upper_bin":10, "count":10}'); - tdSql.query('select histogram(col_int, "user_input", "[0,10]", 0) from tb interval(1h);') - tdSql.checkRows(1) - tdSql.checkData(0, 1, '{"lower_bin":0, "upper_bin":10, "count":10}'); - - tdSql.query('select histogram(col_int, "user_input", "[0,10]", 0) from tb interval(1s);') - tdSql.checkRows(16) - tdSql.checkData(0, 1, '{"lower_bin":0, "upper_bin":10, "count":0}'); - tdSql.checkData(1, 1, '{"lower_bin":0, "upper_bin":10, "count":0}'); - tdSql.checkData(2, 1, '{"lower_bin":0, "upper_bin":10, "count":1}'); - tdSql.checkData(3, 1, '{"lower_bin":0, "upper_bin":10, "count":1}'); - tdSql.checkData(4, 1, '{"lower_bin":0, "upper_bin":10, "count":1}'); - tdSql.checkData(5, 1, '{"lower_bin":0, "upper_bin":10, "count":1}'); - tdSql.checkData(6, 1, '{"lower_bin":0, "upper_bin":10, "count":1}'); - tdSql.checkData(7, 1, '{"lower_bin":0, "upper_bin":10, "count":1}'); - tdSql.checkData(8, 1, '{"lower_bin":0, "upper_bin":10, "count":1}'); - tdSql.checkData(9, 1, '{"lower_bin":0, "upper_bin":10, "count":1}'); - tdSql.checkData(10, 1, '{"lower_bin":0, "upper_bin":10, "count":1}'); - tdSql.checkData(11, 1, '{"lower_bin":0, "upper_bin":10, "count":1}'); - tdSql.checkData(12, 1, '{"lower_bin":0, "upper_bin":10, "count":0}'); - tdSql.checkData(13, 1, '{"lower_bin":0, "upper_bin":10, "count":0}'); - tdSql.checkData(14, 1, '{"lower_bin":0, "upper_bin":10, "count":0}'); - tdSql.checkData(15, 1, '{"lower_bin":0, "upper_bin":10, "count":0}'); - tdSql.query('select histogram(col_int, "user_input", "[0,10]", 0) from tb interval(1a);') - tdSql.checkRows(16) - tdSql.checkData(0, 1, '{"lower_bin":0, "upper_bin":10, "count":0}'); - tdSql.checkData(1, 1, '{"lower_bin":0, "upper_bin":10, "count":0}'); - tdSql.checkData(2, 1, '{"lower_bin":0, "upper_bin":10, "count":1}'); - tdSql.checkData(3, 1, '{"lower_bin":0, "upper_bin":10, "count":1}'); - tdSql.checkData(4, 1, '{"lower_bin":0, "upper_bin":10, "count":1}'); - tdSql.checkData(5, 1, '{"lower_bin":0, "upper_bin":10, "count":1}'); - tdSql.checkData(6, 1, '{"lower_bin":0, "upper_bin":10, "count":1}'); - tdSql.checkData(7, 1, '{"lower_bin":0, "upper_bin":10, "count":1}'); - tdSql.checkData(8, 1, '{"lower_bin":0, "upper_bin":10, "count":1}'); - tdSql.checkData(9, 1, '{"lower_bin":0, "upper_bin":10, "count":1}'); - tdSql.checkData(10, 1, '{"lower_bin":0, "upper_bin":10, "count":1}'); - tdSql.checkData(11, 1, '{"lower_bin":0, "upper_bin":10, "count":1}'); - tdSql.checkData(12, 1, '{"lower_bin":0, "upper_bin":10, "count":0}'); - tdSql.checkData(13, 1, '{"lower_bin":0, "upper_bin":10, "count":0}'); - tdSql.checkData(14, 1, '{"lower_bin":0, "upper_bin":10, "count":0}'); - tdSql.checkData(15, 1, '{"lower_bin":0, "upper_bin":10, "count":0}'); - - tdSql.query('select histogram(col_int, "user_input", "[0,10]", 0) from tb interval(1w) sliding(1w);') - tdSql.checkRows(1) - tdSql.checkData(0, 1, '{"lower_bin":0, "upper_bin":10, "count":10}'); + #tdSql.query('select histogram(col_int, "user_input", "[0,10]", 0) from tb interval(1d);') + #tdSql.checkRows(1) + #tdSql.checkData(0, 1, '{"lower_bin":0, "upper_bin":10, "count":10}'); - tdSql.query('select histogram(col_int, "user_input", "[0,10]", 0) from tb interval(1d) sliding(1d);') - tdSql.checkRows(1) - tdSql.checkData(0, 1, '{"lower_bin":0, "upper_bin":10, "count":10}'); + #tdSql.query('select histogram(col_int, "user_input", "[0,10]", 0) from tb interval(1h);') + #tdSql.checkRows(1) + #tdSql.checkData(0, 1, '{"lower_bin":0, "upper_bin":10, "count":10}'); - tdSql.query('select histogram(col_int, "user_input", "[0,10]", 0) from tb interval(1h) sliding(1h);') - tdSql.checkRows(1) - tdSql.checkData(0, 1, '{"lower_bin":0, "upper_bin":10, "count":10}'); - - tdSql.query('select histogram(col_int, "user_input", "[0,10]", 0) from tb interval(1s) sliding(1s);') - tdSql.checkRows(16) - tdSql.checkData(0, 1, '{"lower_bin":0, "upper_bin":10, "count":0}'); - tdSql.checkData(1, 1, '{"lower_bin":0, "upper_bin":10, "count":0}'); - tdSql.checkData(2, 1, '{"lower_bin":0, "upper_bin":10, "count":1}'); - tdSql.checkData(3, 1, '{"lower_bin":0, "upper_bin":10, "count":1}'); - tdSql.checkData(4, 1, '{"lower_bin":0, "upper_bin":10, "count":1}'); - tdSql.checkData(5, 1, '{"lower_bin":0, "upper_bin":10, "count":1}'); - tdSql.checkData(6, 1, '{"lower_bin":0, "upper_bin":10, "count":1}'); - tdSql.checkData(7, 1, '{"lower_bin":0, "upper_bin":10, "count":1}'); - tdSql.checkData(8, 1, '{"lower_bin":0, "upper_bin":10, "count":1}'); - tdSql.checkData(9, 1, '{"lower_bin":0, "upper_bin":10, "count":1}'); - tdSql.checkData(10, 1, '{"lower_bin":0, "upper_bin":10, "count":1}'); - tdSql.checkData(11, 1, '{"lower_bin":0, "upper_bin":10, "count":1}'); - tdSql.checkData(12, 1, '{"lower_bin":0, "upper_bin":10, "count":0}'); - tdSql.checkData(13, 1, '{"lower_bin":0, "upper_bin":10, "count":0}'); - tdSql.checkData(14, 1, '{"lower_bin":0, "upper_bin":10, "count":0}'); - tdSql.checkData(15, 1, '{"lower_bin":0, "upper_bin":10, "count":0}'); - - tdSql.error('select histogram(col_int, "user_input", "[0,10]", 0) from tb where col_timestamp > now - 1w and col_timestamp < now + 1w interval(1w) fill(NULL);') - tdSql.error('select histogram(col_int, "user_input", "[0,10]", 0) from tb where col_timestamp > now - 1d and col_timestamp < now + 1d interval(1d) fill(None);') - tdSql.error('select histogram(col_int, "user_input", "[0,10]", 0) from tb where col_timestamp > now - 1h and col_timestamp < now + 1h interval(1h) fill(Prev);') - tdSql.error('select histogram(col_int, "user_input", "[0,10]", 0) from tb where col_timestamp > now - 1m and col_timestamp < now + 1m interval(1m) fill(Next);') - tdSql.error('select histogram(col_int, "user_input", "[0,10]", 0) from tb where col_timestamp > now - 1s and col_timestamp < now + 1s interval(1s) fill(Linear);') - tdSql.error('select histogram(col_int, "user_input", "[0,10]", 0) from tb where col_timestamp > now - 1a and col_timestamp < now + 1a interval(1a) fill(Value, 1);') + #tdSql.query('select histogram(col_int, "user_input", "[0,10]", 0) from tb interval(1s);') + #tdSql.checkRows(16) + #tdSql.checkData(0, 1, '{"lower_bin":0, "upper_bin":10, "count":0}'); + #tdSql.checkData(1, 1, '{"lower_bin":0, "upper_bin":10, "count":0}'); + #tdSql.checkData(2, 1, '{"lower_bin":0, "upper_bin":10, "count":1}'); + #tdSql.checkData(3, 1, '{"lower_bin":0, "upper_bin":10, "count":1}'); + #tdSql.checkData(4, 1, '{"lower_bin":0, "upper_bin":10, "count":1}'); + #tdSql.checkData(5, 1, '{"lower_bin":0, "upper_bin":10, "count":1}'); + #tdSql.checkData(6, 1, '{"lower_bin":0, "upper_bin":10, "count":1}'); + #tdSql.checkData(7, 1, '{"lower_bin":0, "upper_bin":10, "count":1}'); + #tdSql.checkData(8, 1, '{"lower_bin":0, "upper_bin":10, "count":1}'); + #tdSql.checkData(9, 1, '{"lower_bin":0, "upper_bin":10, "count":1}'); + #tdSql.checkData(10, 1, '{"lower_bin":0, "upper_bin":10, "count":1}'); + #tdSql.checkData(11, 1, '{"lower_bin":0, "upper_bin":10, "count":1}'); + #tdSql.checkData(12, 1, '{"lower_bin":0, "upper_bin":10, "count":0}'); + #tdSql.checkData(13, 1, '{"lower_bin":0, "upper_bin":10, "count":0}'); + #tdSql.checkData(14, 1, '{"lower_bin":0, "upper_bin":10, "count":0}'); + #tdSql.checkData(15, 1, '{"lower_bin":0, "upper_bin":10, "count":0}'); + #tdSql.query('select histogram(col_int, "user_input", "[0,10]", 0) from tb interval(1a);') + #tdSql.checkRows(16) + #tdSql.checkData(0, 1, '{"lower_bin":0, "upper_bin":10, "count":0}'); + #tdSql.checkData(1, 1, '{"lower_bin":0, "upper_bin":10, "count":0}'); + #tdSql.checkData(2, 1, '{"lower_bin":0, "upper_bin":10, "count":1}'); + #tdSql.checkData(3, 1, '{"lower_bin":0, "upper_bin":10, "count":1}'); + #tdSql.checkData(4, 1, '{"lower_bin":0, "upper_bin":10, "count":1}'); + #tdSql.checkData(5, 1, '{"lower_bin":0, "upper_bin":10, "count":1}'); + #tdSql.checkData(6, 1, '{"lower_bin":0, "upper_bin":10, "count":1}'); + #tdSql.checkData(7, 1, '{"lower_bin":0, "upper_bin":10, "count":1}'); + #tdSql.checkData(8, 1, '{"lower_bin":0, "upper_bin":10, "count":1}'); + #tdSql.checkData(9, 1, '{"lower_bin":0, "upper_bin":10, "count":1}'); + #tdSql.checkData(10, 1, '{"lower_bin":0, "upper_bin":10, "count":1}'); + #tdSql.checkData(11, 1, '{"lower_bin":0, "upper_bin":10, "count":1}'); + #tdSql.checkData(12, 1, '{"lower_bin":0, "upper_bin":10, "count":0}'); + #tdSql.checkData(13, 1, '{"lower_bin":0, "upper_bin":10, "count":0}'); + #tdSql.checkData(14, 1, '{"lower_bin":0, "upper_bin":10, "count":0}'); + #tdSql.checkData(15, 1, '{"lower_bin":0, "upper_bin":10, "count":0}'); + + #tdSql.query('select histogram(col_int, "user_input", "[0,10]", 0) from tb interval(1w) sliding(1w);') + #tdSql.checkRows(1) + #tdSql.checkData(0, 1, '{"lower_bin":0, "upper_bin":10, "count":10}'); + + #tdSql.query('select histogram(col_int, "user_input", "[0,10]", 0) from tb interval(1d) sliding(1d);') + #tdSql.checkRows(1) + #tdSql.checkData(0, 1, '{"lower_bin":0, "upper_bin":10, "count":10}'); + + #tdSql.query('select histogram(col_int, "user_input", "[0,10]", 0) from tb interval(1h) sliding(1h);') + #tdSql.checkRows(1) + #tdSql.checkData(0, 1, '{"lower_bin":0, "upper_bin":10, "count":10}'); + + #tdSql.query('select histogram(col_int, "user_input", "[0,10]", 0) from tb interval(1s) sliding(1s);') + #tdSql.checkRows(16) + #tdSql.checkData(0, 1, '{"lower_bin":0, "upper_bin":10, "count":0}'); + #tdSql.checkData(1, 1, '{"lower_bin":0, "upper_bin":10, "count":0}'); + #tdSql.checkData(2, 1, '{"lower_bin":0, "upper_bin":10, "count":1}'); + #tdSql.checkData(3, 1, '{"lower_bin":0, "upper_bin":10, "count":1}'); + #tdSql.checkData(4, 1, '{"lower_bin":0, "upper_bin":10, "count":1}'); + #tdSql.checkData(5, 1, '{"lower_bin":0, "upper_bin":10, "count":1}'); + #tdSql.checkData(6, 1, '{"lower_bin":0, "upper_bin":10, "count":1}'); + #tdSql.checkData(7, 1, '{"lower_bin":0, "upper_bin":10, "count":1}'); + #tdSql.checkData(8, 1, '{"lower_bin":0, "upper_bin":10, "count":1}'); + #tdSql.checkData(9, 1, '{"lower_bin":0, "upper_bin":10, "count":1}'); + #tdSql.checkData(10, 1, '{"lower_bin":0, "upper_bin":10, "count":1}'); + #tdSql.checkData(11, 1, '{"lower_bin":0, "upper_bin":10, "count":1}'); + #tdSql.checkData(12, 1, '{"lower_bin":0, "upper_bin":10, "count":0}'); + #tdSql.checkData(13, 1, '{"lower_bin":0, "upper_bin":10, "count":0}'); + #tdSql.checkData(14, 1, '{"lower_bin":0, "upper_bin":10, "count":0}'); + #tdSql.checkData(15, 1, '{"lower_bin":0, "upper_bin":10, "count":0}'); + + #tdSql.error('select histogram(col_int, "user_input", "[0,10]", 0) from tb where col_timestamp > now - 1w and col_timestamp < now + 1w interval(1w) fill(NULL);') + #tdSql.error('select histogram(col_int, "user_input", "[0,10]", 0) from tb where col_timestamp > now - 1d and col_timestamp < now + 1d interval(1d) fill(None);') + #tdSql.error('select histogram(col_int, "user_input", "[0,10]", 0) from tb where col_timestamp > now - 1h and col_timestamp < now + 1h interval(1h) fill(Prev);') + #tdSql.error('select histogram(col_int, "user_input", "[0,10]", 0) from tb where col_timestamp > now - 1m and col_timestamp < now + 1m interval(1m) fill(Next);') + #tdSql.error('select histogram(col_int, "user_input", "[0,10]", 0) from tb where col_timestamp > now - 1s and col_timestamp < now + 1s interval(1s) fill(Linear);') + #tdSql.error('select histogram(col_int, "user_input", "[0,10]", 0) from tb where col_timestamp > now - 1a and col_timestamp < now + 1a interval(1a) fill(Value, 1);') #select group by tdSql.error('select histogram(col_int, "user_input", "[0,10]", 0) from stb group by col_tinyint;') diff --git a/tests/develop-test/2-query/session_two_stage.py b/tests/develop-test/2-query/session_two_stage.py index 723919233c722eefbf1629146de1d8d7cc914f8b..5a95a80c882379f67bc550590f016ea60e68aa59 100644 --- a/tests/develop-test/2-query/session_two_stage.py +++ b/tests/develop-test/2-query/session_two_stage.py @@ -92,13 +92,6 @@ class TDTestCase: tdSql.query('select elapsed(ts,10s) from sub_1 where ts>="2015-01-01 00:00:00.000" and ts < "2015-01-01 00:10:00.000" session(ts,1d) ;') - cfg_path = self.getcfgPath() - print(cfg_path) - tdSql.query('select elapsed(ts,10s) from st where ts>="2015-01-01 00:00:00.000" and ts < "2015-01-01 00:10:00.000" session(ts,1d) group by tbname;') # session not support super table - tdSql.checkRows(10) - - - def stop(self): tdSql.close() tdLog.success("%s successfully executed" % __file__) diff --git a/tests/docs-examples-test/test_c.sh b/tests/docs-examples-test/test_c.sh index 520f795f09f66298e6590edac84e7b4ccfab96a5..2d47eff585b26659cb90a1669317efe074f1adde 100755 --- a/tests/docs-examples-test/test_c.sh +++ b/tests/docs-examples-test/test_c.sh @@ -16,6 +16,9 @@ taos -s "drop database if exists power" gcc -o insert_example insert_example.c -ltaos ./insert_example +gcc -o async_query_example async_query_example.c -ltaos +./async_query_example + # 3 taos -s "drop database if exists power" gcc -o stmt_example stmt_example.c -ltaos diff --git a/tests/docs-examples-test/test_python.sh b/tests/docs-examples-test/test_python.sh index e145f1bd6dbb811c9888a51b912e14b01dd14a15..22297ad92fc4c2efd821aaa197936ec08a89ef31 100755 --- a/tests/docs-examples-test/test_python.sh +++ b/tests/docs-examples-test/test_python.sh @@ -42,6 +42,6 @@ taos -s "drop database test" python3 json_protocol_example.py # 10 -python3 subscribe_demo.py +# python3 subscribe_demo.py diff --git a/tests/parallel_test/cases.task b/tests/parallel_test/cases.task index f1abeeab32a3a908805c125e04cfa61e8b5f9175..ca3586a95e8bd0896206fa3ee17b8016cf848e7f 100644 --- a/tests/parallel_test/cases.task +++ b/tests/parallel_test/cases.task @@ -638,6 +638,7 @@ 6,,pytest,python3 test.py -f alter/alterColMultiTimes.py 6,,develop-test,python3 ./test.py -f 2-query/ts_2016.py 6,,develop-test,python3 ./test.py -f 2-query/escape.py +6,,develop-test,python3 ./test.py -f 2-query/TD-14763.py 5,,system-test,python3 ./test.py -f 4-taosAdapter/taosAdapter_insert.py 5,,system-test,python3 ./test.py -f 2-query/TD-12340-12342.py 5,,system-test,python3 ./test.py -f 2-query/TD-12276.py @@ -725,6 +726,7 @@ 5,,develop-test,python3 ./test.py -f 2-query/scalar_triangle.py 5,,develop-test,python3 ./test.py -f 2-query/scalar_expression.py 5,,develop-test,python3 ./test.py -f 2-query/scalar_powlog.py +5,,develop-test,python3 ./test.py -f 2-query/TD-14745.py 4,,system-test,python3 test.py -f 4-taosAdapter/TD-12163.py 4,,system-test,python3 ./test.py -f 3-connectors/restful/restful_binddbname.py 4,,system-test,python3 ./test.py -f 2-query/TD-12614.py diff --git a/tests/system-test/2-query/TD-12344.py b/tests/system-test/2-query/TD-12344.py index 5c05b417e271248f449f4495f12b05182a3ccaac..b1a2d69a7b2732fcfb479ff87f4d4b0e1e6eee62 100644 --- a/tests/system-test/2-query/TD-12344.py +++ b/tests/system-test/2-query/TD-12344.py @@ -94,22 +94,22 @@ class TDTestCase: cfg_path = self.getcfgPath() print(cfg_path) - tdSql.execute('select elapsed(ts,10s) from testdb.st where ts>=\"2015-01-01 00:00:00.000\" and ts < \"2015-01-01 00:10:00.000\" session(ts,1d) group by tbname;') + tdSql.error('select elapsed(ts,10s) from testdb.st where ts>=\"2015-01-01 00:00:00.000\" and ts < \"2015-01-01 00:10:00.000\" session(ts,1d) group by tbname;') - datas = tdSql.getResult('select elapsed(ts,10s) from testdb.st where ts>=\"2015-01-01 00:00:00.000\" and ts < \"2015-01-01 00:10:00.000\" session(ts,1d) group by tbname;') + # datas = tdSql.getResult('select elapsed(ts,10s) from testdb.st where ts>=\"2015-01-01 00:00:00.000\" and ts < \"2015-01-01 00:10:00.000\" session(ts,1d) group by tbname;') table_names = ["sub_%s"%str(i) for i in range(10)] # print(table_names) for index , table_name in enumerate(table_names): tdSql.query("select elapsed(ts,10s) from testdb.%s where ts>=\"2015-01-01 00:00:00.000\" and ts < \"2015-01-01 00:10:00.000\" session(ts,1d) ;"%table_name) # print(datas) - tdSql.checkData(0,1,datas[index][1]) + # tdSql.checkData(0,1,datas[index][1]) - for i in range(10): - taos_cmd1= "taos -c %s -s 'select elapsed(ts,10s) from testdb.st where ts>=\"2015-01-01 00:00:00.000\" and ts < \"2015-01-01 00:10:00.000\" session(ts,1d) group by tbname;' " % (cfg_path) + # for i in range(10): + # taos_cmd1= "taos -c %s -s 'select elapsed(ts,10s) from testdb.st where ts>=\"2015-01-01 00:00:00.000\" and ts < \"2015-01-01 00:10:00.000\" session(ts,1d) group by tbname;' " % (cfg_path) # print(taos_cmd1) - _ = subprocess.check_output(taos_cmd1, shell=True).decode("utf-8") + # _ = subprocess.check_output(taos_cmd1, shell=True).decode("utf-8") def stop(self): tdSql.close() diff --git a/tests/system-test/2-query/function_elapsed.py b/tests/system-test/2-query/function_elapsed.py index 7b9b436bbe64dda5ecc301be79709326dc07a810..8a9b3faaf65b8e43f45dbb7e6bf88e1d95066121 100644 --- a/tests/system-test/2-query/function_elapsed.py +++ b/tests/system-test/2-query/function_elapsed.py @@ -1497,7 +1497,7 @@ class TDTestCase: # case TD-12344 # session not support stable - tdSql.execute('select elapsed(ts,10s) from stable_1 where ts>="2015-01-01 00:00:00.000" and ts < "2015-01-01 00:10:00.000" session(ts ,10s) group by tbname,ind order by ts asc ') + tdSql.error('select elapsed(ts,10s) from stable_1 where ts>="2015-01-01 00:00:00.000" and ts < "2015-01-01 00:10:00.000" session(ts ,10s) group by tbname,ind order by ts asc ') tdSql.query('select elapsed(ts,10s) from sub_table1_1 session(ts,1w) ; ') tdSql.checkRows(1) diff --git a/tests/system-test/fulltest-query.sh b/tests/system-test/fulltest-query.sh index 269274f9d92527a41a60134cc3401b3a38785c45..81daa564f9c943319e6d62efcf4d424d5bb0e0dc 100755 --- a/tests/system-test/fulltest-query.sh +++ b/tests/system-test/fulltest-query.sh @@ -14,7 +14,7 @@ python3 ./test.py -f 2-query/TD-12165.py python3 ./test.py -f 2-query/TD-12228.py python3 ./test.py -f 2-query/TD-12229.py python3 ./test.py -f 2-query/TD-12276.py -python3 ./test.py -f 2-query/TD-12344.py +#python3 ./test.py -f 2-query/TD-12344.py #python3 ./test.py -f 2-query/TD-12388.py #python3 ./test.py -f 2-query/TD-12593.py #python3 ./test.py -f 2-query/TD-12594.py