diff --git a/.gitmodules b/.gitmodules index 57cf1a87a14f638527478e2d8a993d8c0d329601..524ac8079ffa5533a5b87091ede373a7ac6b4c3a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -20,3 +20,6 @@ path = tests url = https://github.com/taosdata/tests branch = develop +[submodule "examples/rust"] + path = examples/rust + url = https://github.com/songtianyi/tdengine-rust-bindings.git diff --git a/documentation20/cn/02.getting-started/docs.md b/documentation20/cn/02.getting-started/docs.md index 2cd9177ee018e91a992e9d37514eb9cd095a8cde..0d7b2cb4e55d6efe3aec0cb621ff9adce5c522ae 100644 --- a/documentation20/cn/02.getting-started/docs.md +++ b/documentation20/cn/02.getting-started/docs.md @@ -2,7 +2,10 @@ ## 快捷安装 -TDengine 软件分为服务器、客户端和报警模块三部分,目前 2.0 版服务器仅能在 Linux 系统上安装和运行,后续会支持 Windows、Mac OS 等系统。客户端可以在 Windows 或 Linux 上安装和运行。任何 OS 的应用也可以选择 RESTful 接口连接服务器 taosd,其中 2.4 之后版本默认使用单独运行的独立组件 taosAdapter 提供 http 服务,之前版本使用内置 http 服务。CPU 支持 X64/ARM64/MIPS64/Alpha64,后续会支持 ARM32、RISC-V 等 CPU 架构。用户可根据需求选择通过 [源码](https://www.taosdata.com/cn/getting-started/#通过源码安装) 或者 [安装包](https://www.taosdata.com/cn/getting-started/#通过安装包安装) 来安装。 +TDengine 软件分为服务器、客户端,目前 2.0 版服务器仅能在 Linux 系统上安装和运行,后续会支持 Windows、Mac OS 等系统。客户端可以在 Windows 或 Linux 上安装和运行。任何 OS 的应用也可以选择 RESTful 接口连接服务器 taosd,其中 2.4 之后版本默认使用单独运行的独立组件 taosAdapter 提供 http 服务,之前版本使用内置 http 服务。支持 X64/ARM64/MIPS64/Alpha64,后续会支持 ARM32、RISC-V 等 CPU 架构。用户可根据需求选择通过 [源码](https://www.taosdata.com/getting-started/#source-install) 或者 [安装包](https://www.taosdata.com/getting-started/#package-install) 来安装。 + +* 查看完整的Release notes,请点击[这里](https://github.com/taosdata/TDengine/releases)。 +* 下载其他组件、最新beta版及之前版本的安装包,请点击[这里](https://www.taosdata.com/cn/all-downloads/)。 ### 通过源码安装 @@ -20,13 +23,38 @@ docker run -d -p 6030-6049:6030-6049 -p 6030-6049:6030-6049/udp tdengine/tdengin ### 通过安装包安装 -TDengine 的安装非常简单,从下载到安装成功仅仅只要几秒钟。服务端安装包包含客户端和连接器,我们提供三种安装包,您可以根据需要选择: +TDengine 的安装非常简单,从下载到安装成功仅仅只要几秒钟。为方便使用,标准的服务端安装包包含了客户端程序、各种编程语言的连接器和示例代码;如果您只需要用到服务端程序和客户端连接的 C/C++ 语言支持,那么也可以仅下载 lite 版本的安装包。在安装包格式上,我们提供 rpm、deb、tar.gz 三种,以方便在特定操作系统上使用。版本还分稳定版和Beta版,Beta版含有更多新功能,正式上线或测试,建议安装稳定版。您可以根据需要选择下载: -安装包下载在 [这里](https://www.taosdata.com/cn/getting-started/#通过安装包安装)。 + 具体的安装过程,请参见 [TDengine 多种安装包的安装和卸载](https://www.taosdata.com/blog/2019/08/09/566.html) 以及 [视频教程](https://www.taosdata.com/blog/2020/11/11/1941.html)。 + +## taosBenchmark 详细功能列表 + +taosBenchmark (曾命名 taosdemo)命令本身带有很多选项,配置表的数目、记录条数等等,请执行 `taosBenchmark --help` 详细列出。您可以设置不同参数进行体验。 +taosBenchmark 详细使用方法请参照 [如何使用taosBenchmark对TDengine进行性能测试](https://www.taosdata.com/2021/10/09/3111.html)。 + +## 客户端 + +如果客户端和服务端运行在不同的电脑上,可以单独安装客户端。下载时请注意,所选择的客户端版本号应该和在上面下载的服务端版本号精确匹配。Linux 和 Windows 安装包如下(其中 lite 版本的安装包仅带有 C/C++ 语言的连接支持,而标准版本的安装包还包含 Java、Python、Go、Node.js 等编程语言的连接器支持和示例代码): + + + +## taosTools + +taosTools 是多个用于 TDengine 的辅助工具软件集合。 + +推荐下载 deb 或 rpm 安装包,方便安装依赖软件。如果使用 tar.gz 格式安装包,需要自行安装依赖包。其中: + +* Debian/Ubuntu 系统需要安装 libjansson4 和 libsnappy1v5 +* CentOS/RHEL 系统需要安装 jansson 和 snappy + +以及 TDengine server 或 TDengine client 安装包 -### 使用 apt-get 安装 + + + +## 使用 apt-get 安装 如果使用 Debian 或 Ubuntu 系统,也可以使用 apt-get 从官方仓库安装,设置方法为: @@ -181,15 +209,7 @@ taos> select avg(current), max(voltage), min(phase) from test.meters where group ```mysql taos> select avg(current), max(voltage), min(phase) from test.d10 interval(10s); ``` - -## taosBenchmark 详细功能列表 - -taosBenchmark (曾命名 taosdemo)命令本身带有很多选项,配置表的数目、记录条数等等,请执行 `taosBenchmark --help` 详细列出。您可以设置不同参数进行体验。 -taosBenchmark 详细使用方法请参照 [如何使用taosBenchmark对TDengine进行性能测试](https://www.taosdata.com/2021/10/09/3111.html)。 - -## 客户端 - -如果客户端和服务端运行在不同的电脑上,可以单独安装客户端。Linux 和 Windows 安装包可以在 [这里](https://www.taosdata.com/cn/getting-started/#客户端) 下载。 + ## 支持平台列表 diff --git a/documentation20/en/02.getting-started/docs.md b/documentation20/en/02.getting-started/docs.md index 21149f09e9f88555b0767cad76926d0eac406bab..c3f08b49432a9abd3e29d73a68ead06ec47dcf9b 100644 --- a/documentation20/en/02.getting-started/docs.md +++ b/documentation20/en/02.getting-started/docs.md @@ -1,8 +1,8 @@ -# Quick Start +# Getting Started ## Quick Install -TDengine software consists of 3 parts: server, client, and alarm module. At the moment, TDengine server only runs on Linux (Windows, mac OS and more OS supports will come soon), but client can run on either Windows or Linux. TDengine client can be installed and run on Windows or Linux. Applications based-on any OSes can all connect to server taosd via a RESTful interface. From 2.4 and later version, TDengine use a stand-alone software, taosAdapteer to provide http service. The early version uses the http server embedded in the taosd. About CPU, TDengine supports X64/ARM64/MIPS64/Alpha64, and ARM32、RISC-V, other more CPU architectures will be supported soon. You can set up and install TDengine server either from the [source code](https://www.taosdata.com/en/getting-started/#Install-from-Source) or the [packages](https://www.taosdata.com/en/getting-started/#Install-from-Package). +TDengine software consists of 3 parts: server, client, and alart module. At the moment, TDengine server only runs on Linux (Windows, mac OS and more OS supports will come soon), but client can run on either Windows or Linux. TDengine client can be installed and run on Windows or Linux. Applications based-on any OSes can all connect to server taosd via a RESTful interface. From 2.4 and later version, TDengine use a stand-alone software, taosAdapteer to provide http service. The early version uses the http server embedded in the taosd. About CPU, TDengine supports X64/ARM64/MIPS64/Alpha64, and ARM32、RISC-V, other more CPU architectures will be supported soon. You can set up and install TDengine server either from the [source code](https://www.taosdata.com/en/getting-started/#Install-from-Source) or the [packages](https://www.taosdata.com/en/getting-started/#Install-from-Package). ### Install from Source @@ -184,23 +184,11 @@ taos> select avg(f1), max(f2), min(f3) from test.meters where areaid=10; taos> select avg(f1), max(f2), min(f3) from test.t10 interval(10s); ``` -## Using taosBenchmark in detail +### Using taosBenchmark in detail you can run command `taosBenchmark` with many options, like number of tables, rows of records and so on. To know more about these options, you can execute `taosBenchmark --help` and then take a try using different options. Please refer to [How to use taosBenchmark to test the performance of TDengine](https://tdengine.com/2021/10/09/3114.html) for detail. -## Client and Alarm Module - -If your client and server running on different machines, please install the client separately. Linux and Windows packages are provided: - -- TDengine-client-2.0.10.0-Linux-x64.tar.gz(3.0M) -- TDengine-client-2.0.10.0-Windows-x64.exe(2.8M) -- TDengine-client-2.0.10.0-Windows-x86.exe(2.8M) - -Linux package of Alarm Module is as following (please refer [How to Use Alarm Module](https://github.com/taosdata/TDengine/blob/master/alert/README_cn.md)): - -- TDengine-alert-2.0.10.0-Linux-x64.tar.gz (8.1M) - ## List of Supported Platforms List of platforms supported by TDengine server diff --git a/examples/rust b/examples/rust new file mode 160000 index 0000000000000000000000000000000000000000..1c8924dc668e6aa848214c2fc54e3ace3f5bf8df --- /dev/null +++ b/examples/rust @@ -0,0 +1 @@ +Subproject commit 1c8924dc668e6aa848214c2fc54e3ace3f5bf8df diff --git a/packaging/docker/Dockerfile b/packaging/docker/Dockerfile index 4f847f949a25e157261cc42b20ece0c9072e328f..f6a0950e24cc1bd065e5f60f05998e000b74ecec 100644 --- a/packaging/docker/Dockerfile +++ b/packaging/docker/Dockerfile @@ -4,6 +4,7 @@ WORKDIR /root ARG pkgFile ARG dirName +ARG cpuType RUN echo ${pkgFile} && echo ${dirName} COPY ${pkgFile} /root/ @@ -21,6 +22,11 @@ ENV LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/lib" \ EXPOSE 6030-6049 EXPOSE 6030-6039/udp COPY ./bin/* /usr/bin/ -ENTRYPOINT ["/usr/bin/entrypoint.sh"] + +ENV TINI_VERSION v0.19.0 +RUN bash -c 'echo -e "Downloading tini-${cpuType} ..."' +ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini-${cpuType} /tini +RUN chmod +x /tini +ENTRYPOINT ["/tini", "--", "/usr/bin/entrypoint.sh"] CMD ["taosd"] VOLUME [ "/var/lib/taos", "/var/log/taos", "/corefile" ] diff --git a/packaging/docker/dockerbuild.sh b/packaging/docker/dockerbuild.sh index c0e52f6dce5a95f3a073251fd8f221c648e4e7f9..3729131c0e20859488d0a7c0c100463c818aaf8c 100755 --- a/packaging/docker/dockerbuild.sh +++ b/packaging/docker/dockerbuild.sh @@ -89,7 +89,7 @@ cp -f ${comunityArchiveDir}/${pkgFile} . echo "dirName=${dirName}" -docker build --rm -f "Dockerfile" --network=host -t tdengine/tdengine-${dockername}:${version} "." --build-arg pkgFile=${pkgFile} --build-arg dirName=${dirName} +docker build --rm -f "Dockerfile" --network=host -t tdengine/tdengine-${dockername}:${version} "." --build-arg pkgFile=${pkgFile} --build-arg dirName=${dirName} --build-arg cpuType=${cpuType} docker login -u tdengine -p ${passWord} #replace the docker registry username and password docker push tdengine/tdengine-${dockername}:${version} @@ -98,4 +98,4 @@ docker tag tdengine/tdengine-${dockername}:${version} tdengine/tdengine-${docker docker push tdengine/tdengine-${dockername}:latest -rm -f ${pkgFile} \ No newline at end of file +rm -f ${pkgFile} diff --git a/src/connector/node-red-contrib-tdengine/package-lock.json b/src/connector/node-red-contrib-tdengine/package-lock.json index 37d4784caaa8e225290991cf8f598df2d7d122e8..3d2f9977419c62649b3eb332014f4baaa7b0810f 100644 --- a/src/connector/node-red-contrib-tdengine/package-lock.json +++ b/src/connector/node-red-contrib-tdengine/package-lock.json @@ -1192,9 +1192,9 @@ } }, "follow-redirects": { - "version": "1.14.7", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.7.tgz", - "integrity": "sha512-+hbxoLbFMbRKDwohX8GkTataGqO6Jb7jGwpAlwgy2bIz25XtRm7KEzJM76R1WiNT5SwZkX4Y75SwBolkpmE7iQ==" + "version": "1.14.8", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.8.tgz", + "integrity": "sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA==" }, "form-data": { "version": "4.0.0", diff --git a/src/connector/nodejs/examples/stmtBindParamBatchSample.js b/src/connector/nodejs/examples/stmtBindParamBatchSample.js new file mode 100755 index 0000000000000000000000000000000000000000..030958bfd16faf88f79c6d4476defb76c0a3e990 --- /dev/null +++ b/src/connector/nodejs/examples/stmtBindParamBatchSample.js @@ -0,0 +1,111 @@ +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),` + + `blob 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_blob 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 / 2); + 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 new file mode 100644 index 0000000000000000000000000000000000000000..ee1354aff0a1052a67d961de39c147c6cbe616dd --- /dev/null +++ b/src/connector/nodejs/examples/stmtBindParamSample.js @@ -0,0 +1,82 @@ +// 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),` + + `blob 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 new file mode 100755 index 0000000000000000000000000000000000000000..3b424b8d0cdc0d18997c2224fdac499e42c0c57d --- /dev/null +++ b/src/connector/nodejs/examples/stmtBindSingleParamBatchSample.js @@ -0,0 +1,101 @@ +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),` + + `blob 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 new file mode 100755 index 0000000000000000000000000000000000000000..b9f55545b0892d575c952308febfa9055a4f570a --- /dev/null +++ b/src/connector/nodejs/examples/stmtUseResultSample.js @@ -0,0 +1,100 @@ +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),` + + `blob 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/nodetaos/cinterface.js b/src/connector/nodejs/nodetaos/cinterface.js index 380d96505de0d6af4cf0cbf5573ffe204453850d..0a81a0c79b21b2c2869e8e747df76e673c65b2eb 100644 --- a/src/connector/nodejs/nodetaos/cinterface.js +++ b/src/connector/nodejs/nodetaos/cinterface.js @@ -373,7 +373,7 @@ function CTaosInterface(config = null, pass = false) { , '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.int, [ref.types.void_ptr]] + , '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]] @@ -934,7 +934,15 @@ CTaosInterface.prototype.stmtUseResult = function stmtUseResult(stmt) { * @returns 0 for success, non-zero for failure. */ CTaosInterface.prototype.loadTableInfo = function loadTableInfo(taos, tableList) { - return this.libtaos.taos_load_table_info(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"); + } } /** diff --git a/src/connector/nodejs/nodetaos/cursor.js b/src/connector/nodejs/nodetaos/cursor.js index 4d2251b9799d1afb89a7ce90297d3918747144e9..5969d4f344affa49ebbf81329729bff4733e116b 100644 --- a/src/connector/nodejs/nodetaos/cursor.js +++ b/src/connector/nodejs/nodetaos/cursor.js @@ -30,6 +30,7 @@ function TDengineCursor(connection = 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. @@ -488,7 +489,6 @@ TDengineCursor.prototype.schemalessInsert = function schemalessInsert(lines, pro 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); } this._chandle.freeResult(this._result); } @@ -499,7 +499,7 @@ TDengineCursor.prototype.schemalessInsert = function schemalessInsert(lines, pro * @returns Not NULL returned for success, and NULL for failure. * */ - TDengineCursor.prototype.stmtInit = function stmtInit() { +TDengineCursor.prototype.stmtInit = function stmtInit() { let stmt = null stmt = this._chandle.stmtInit(this._connection._conn); if (stmt == null || stmt == undefined) { @@ -532,7 +532,7 @@ TDengineCursor.prototype.stmtPrepare = function stmtPrepare(sql) { * @param {TaosBind} tableName target table name you want to bind * @returns 0 for success, non-zero for failure. */ -TDengineCursor.prototype.stmtSetTbname = function stmtSetTbname(tableName){ +TDengineCursor.prototype.stmtSetTbname = function stmtSetTbname(tableName) { if (this._stmt == null) { throw new errors.DatabaseError("stmt is null,init stmt first"); } else { @@ -552,11 +552,11 @@ TDengineCursor.prototype.stmtSetTbname = function stmtSetTbname(tableName){ * @param {TaosMultiBind} tags use to set tag value for target table. * @returns */ -TDengineCursor.prototype.stmtSetTbnameTags = function stmtSetTbnameTags(tableName,tags){ +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); + let stmtPrepare = this._chandle.stmtSetTbnameTags(this._stmt, tableName, tags); if (stmtPrepare != 0) { throw new errors.DatabaseError(this._chandle.stmtErrStr(this._stmt)); } else { @@ -573,7 +573,7 @@ TDengineCursor.prototype.stmtSetTbnameTags = function stmtSetTbnameTags(tableNam * @param {*} subTableName table name which is belong to an stable * @returns 0 for success, non-zero for failure. */ -TDengineCursor.prototype.stmtSetSubTbname = function stmtSetSubTbname(subTableName){ +TDengineCursor.prototype.stmtSetSubTbname = function stmtSetSubTbname(subTableName) { if (this._stmt == null) { throw new errors.DatabaseError("stmt is null,init stmt first"); } else { @@ -594,7 +594,7 @@ TDengineCursor.prototype.stmtSetSubTbname = function stmtSetSubTbname(subTableNa * @param {*} binds points to an array contains the whole line data. * @returns 0 for success, non-zero for failure. */ -TDengineCursor.prototype.bindParam = function bindParam(binds) { +TDengineCursor.prototype.stmtBindParam = function stmtBindParam(binds) { if (this._stmt == null) { throw new errors.DatabaseError("stmt is null,init stmt first"); } else { @@ -613,11 +613,11 @@ TDengineCursor.prototype.bindParam = function bindParam(binds) { * @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){ +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); + let stmtPrepare = this._chandle.stmtBindSingleParamBatch(this._stmt, mbind, colIndex); if (stmtPrepare != 0) { throw new errors.DatabaseError(this._chandle.stmtErrStr(this._stmt)); } else { @@ -634,7 +634,7 @@ TDengineCursor.prototype.stmtBindSingleParamBatch = function stmtBindSingleParam * n sql statement. * @returns 0 for success, non-zero for failure. */ -TDengineCursor.prototype.stmtBindParamBatch = function stmtBindParamBatch(mbinds){ +TDengineCursor.prototype.stmtBindParamBatch = function stmtBindParamBatch(mbinds) { if (this._stmt == null) { throw new errors.DatabaseError("stmt is null,init stmt first"); } else { @@ -656,7 +656,7 @@ TDengineCursor.prototype.stmtBindParamBatch = function stmtBindParamBatch(mbinds * @param {*} stmt * @returns 0 for success, non-zero for failure. */ -TDengineCursor.prototype.addBatch = function addBatch() { +TDengineCursor.prototype.stmtAddBatch = function stmtAddBatch() { if (this._stmt == null) { throw new errors.DatabaseError("stmt is null,init stmt first"); } else { @@ -694,13 +694,19 @@ TDengineCursor.prototype.stmtExecute = function stmtExecute() { * User application should free it with API 'FreeResult' at the end. * @returns Not NULL for success, NULL for failure. */ -TDengineCursor.prototype.stmtUseResult = function stmtUseResult(){ +TDengineCursor.prototype.stmtUseResult = function stmtUseResult() { if (this._stmt != null) { - let stmtExecRes = this._chandle.stmtUseResult(this._stmt); - if (stmtExecRes != 0) { - throw new errors.DatabaseError(this._chandle.stmtErrStr(this._stmt)); + 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.") + 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"); @@ -713,11 +719,11 @@ TDengineCursor.prototype.stmtUseResult = function stmtUseResult(){ * @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){ +TDengineCursor.prototype.loadTableInfo = function loadTableInfo(tableList) { if (this._connection._conn != null) { - let stmtExecRes = this._chandle.loadTableInfo(this._connection._conn,tableList); + let stmtExecRes = this._chandle.loadTableInfo(this._connection._conn, tableList); if (stmtExecRes != 0) { - throw new errors.DatabaseError(this._chandle.stmtErrStr(this._stmt)); + throw new errors.DatabaseError(`loadTableInfo() failed,code ${stmtExecRes}`); } else { console.log("loadTableInfo success.") } diff --git a/src/connector/nodejs/nodetaos/taosBind.js b/src/connector/nodejs/nodetaos/taosBind.js index 161e56ee709020c439184bc7a0f7c76ab6b3c139..b70d035b9fcf2eff5d0d1edb7114b5549eda83d4 100644 --- a/src/connector/nodejs/nodetaos/taosBind.js +++ b/src/connector/nodejs/nodetaos/taosBind.js @@ -14,20 +14,19 @@ 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, + 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) { - console.log(TAOS_BIND.size); this.buf = Buffer.alloc(TAOS_BIND.size * num); this.num = num; this.index = 0; @@ -36,15 +35,15 @@ class TaosBind { * Used to bind null value for all data types that tdengine supports. */ bindNil() { - if(!this._isOutOfBound()){ + if (!this._isOutOfBound()) { let nil = new TAOS_BIND({ - buffer_type : taosConst.C_NULL, - is_null : ref.alloc(ref.types.int32, 1), + 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{ + } else { throw new TDError(`bindNil() failed,since index:${this.index} is out of Buffer bound ${this.num}.`); } } @@ -54,18 +53,18 @@ class TaosBind { * @param {bool} val is not null bool value,true or false. */ bindBool(val) { - if(!this._isOutOfBound()){ + 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), + 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{ + } else { throw new TDError(`bindBool() failed with ${val},since index:${this.index} is out of Buffer bound ${this.num}.`); } @@ -75,19 +74,19 @@ class TaosBind { * * @param {int8} val is a not null tinyint value. */ - bindTinyInt(val){ - if(!this._isOutOfBound()){ + 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), + 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{ + this.index++ + } else { throw new TDError(`bindTinyInt() failed with ${val},since index:${this.index} is out of Buffer bound ${this.num}.`); } } @@ -96,39 +95,39 @@ class TaosBind { * * @param {short} val is a not null small int value. */ - bindSmallInt(val){ - if(!this._isOutOfBound()){ + 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), + 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{ + 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()){ + 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), + 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{ + this.index++ + } else { throw new TDError(`bindInt() failed with ${val},since index:${this.index} is out of Buffer bound ${this.num}.`); } @@ -139,37 +138,37 @@ class TaosBind { * @param {long} val is not null big int value. */ bindBigInt(val) { - if(!this._isOutOfBound()){ + 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), + 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{ + } 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 - */ + /** + * + * @param {float} val is a not null float value + */ bindFloat(val) { - if(!this._isOutOfBound()){ + 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), + 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{ + } else { throw new TDError(`bindFloat() failed with ${val},since index:${this.index} is out of Buffer bound ${this.num}.`); } } @@ -177,18 +176,18 @@ class TaosBind { * * @param {double} val is a not null double value */ - bindDouble(val){ - if(!this._isOutOfBound()){ + 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), + 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{ + } else { throw new TDError(`bindDouble() failed with ${val},since index:${this.index} is out of Buffer bound ${this.num}.`); } } @@ -197,19 +196,19 @@ class TaosBind { * * @param {string} val is a string. */ - bindBinary(val){ - let cstringBuf = ref.allocCString(val,'utf-8'); - if(!this._isOutOfBound()){ + 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), - is_null : ref.alloc(ref.types.int32, 0), + 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{ + } else { throw new TDError(`bindBinary() failed with ${val},since index:${this.index} is out of Buffer bound ${this.num}.`); } } @@ -220,11 +219,11 @@ class TaosBind { */ 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), + 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); @@ -235,61 +234,61 @@ class TaosBind { * * @param {string} val is a string. */ - bindNchar(val){ - let cstringBuf = ref.allocCString(val,'utf-8'); - if(!this._isOutOfBound()){ + 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), - is_null : ref.alloc(ref.types.int32, 0), + 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{ + } 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()){ + /** + * + * @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), + 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{ + 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()){ + 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), + 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{ + this.index++ + } else { throw new TDError(`bindUSmallInt() failed with ${val},since index:${this.index} is out of Buffer bound ${this.num}.`); } } @@ -298,19 +297,19 @@ class TaosBind { * * @param {uint32} val is a not null unsinged int value. */ - bindUInt(val){ - if(!this._isOutOfBound()){ + 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), + 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{ + this.index++ + } else { throw new TDError(`bindUInt() failed with ${val},since index:${this.index} is out of Buffer bound ${this.num}.`); } } @@ -319,23 +318,46 @@ class TaosBind { * * @param {uint64} val is a not null unsinged bigint value. */ - bindUBigInt(val){ - if(!this._isOutOfBound()){ + 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), + 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{ + 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. @@ -344,10 +366,10 @@ class TaosBind { return this.buf; } - _isOutOfBound(){ - if(this.num>this.index){ + _isOutOfBound() { + if (this.num > this.index) { return false; - }else{ + } else { return true; } } diff --git a/src/connector/nodejs/nodetaos/taosMultiBind.js b/src/connector/nodejs/nodetaos/taosMultiBind.js new file mode 100755 index 0000000000000000000000000000000000000000..deead6d2f702ea2d40584a2c57574da5f75f4de7 --- /dev/null +++ b/src/connector/nodejs/nodetaos/taosMultiBind.js @@ -0,0 +1,530 @@ +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.writeInt64LE(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 new file mode 100755 index 0000000000000000000000000000000000000000..68c9c95bddad725b6dc10fe7766c1ad46adc2919 --- /dev/null +++ b/src/connector/nodejs/nodetaos/taosMultiBindArr.js @@ -0,0 +1,250 @@ +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/tdengine.js b/src/connector/nodejs/tdengine.js index b33069bd9dd46a5f6c050d85ea1f73fab6f51a64..275834bd4f2b5ba5a903049a5973a34287132175 100644 --- a/src/connector/nodejs/tdengine.js +++ b/src/connector/nodejs/tdengine.js @@ -1,6 +1,9 @@ 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); @@ -8,4 +11,6 @@ module.exports = { SCHEMALESS_PROTOCOL: TDengineConstant.SCHEMALESS_PROTOCOL, SCHEMALESS_PRECISION: TDengineConstant.SCHEMALESS_PRECISION, TaosBind, + TaosMultiBind, + TaosMultiBindArr, } \ No newline at end of file diff --git a/src/mnode/src/mnodeUser.c b/src/mnode/src/mnodeUser.c index e2fda182d7287f61311f658b83134132a4e8d9a1..b3e3ba6cd9698b08aceb86841bd858a7c6f05220 100644 --- a/src/mnode/src/mnodeUser.c +++ b/src/mnode/src/mnodeUser.c @@ -355,13 +355,41 @@ static int32_t mnodeGetUserMeta(STableMetaMsg *pMeta, SShowObj *pShow, void *pCo static int32_t mnodeRetrieveUsers(SShowObj *pShow, char *data, int32_t rows, void *pConn) { int32_t numOfRows = 0; SUserObj *pUser = NULL; + SUserObj *userObj = NULL; + char *user = NULL; int32_t cols = 0; + size_t len1 = 0; + size_t len2; + int32_t acctId = -1; char *pWrite; + if (pConn) { + userObj = mnodeGetUserFromConn(pConn); + if (userObj && userObj->pAcct) { + user = userObj->pAcct->user; + if (user) { + len1 = strlen(user); + if (len1 == 0) { + user = NULL; + } + } + + acctId = userObj->pAcct->acctId; + } + } + while (numOfRows < rows) { pShow->pIter = mnodeGetNextUser(pShow->pIter, &pUser); if (pUser == NULL) break; - + + if (user && pUser->pAcct) { + len2 = strlen(pUser->pAcct->user); + + if ((len1 != len2 || strncmp(user, pUser->pAcct->user, len1)) && acctId != pUser->pAcct->acctId) { + continue; + } + } + cols = 0; pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; @@ -643,4 +671,4 @@ int32_t mnodeCompactUsers() { mInfo("end to compact users table..."); return 0; -} \ No newline at end of file +} diff --git a/src/query/src/qFilter.c b/src/query/src/qFilter.c index 8d63ab4f91ca2de8e246293dafef1b31e93c3e22..d6a7dac7fcb6f525f6bf599d9d45b72f3d8c60f5 100644 --- a/src/query/src/qFilter.c +++ b/src/query/src/qFilter.c @@ -807,7 +807,8 @@ int32_t filterGetFiledByData(SFilterInfo *info, int32_t type, void *v, int32_t d return -1; } - +// In the params, we should use void *data instead of void **data, there is no need to use tfree(*data) to set *data = 0 +// Besides, fields data value is a pointer, so dataLen should be POINTER_BYTES for better. int32_t filterAddField(SFilterInfo *info, void *desc, void **data, int32_t type, SFilterFieldId *fid, int32_t dataLen, bool freeIfExists) { int32_t idx = -1; uint32_t *num; @@ -1285,7 +1286,7 @@ int32_t filterAddUnitFromUnit(SFilterInfo *dst, SFilterInfo *src, SFilterUnit* u void *data = FILTER_UNIT_VAL_DATA(src, u); if (IS_VAR_DATA_TYPE(type)) { if (FILTER_UNIT_OPTR(u) == TSDB_RELATION_IN) { - filterAddField(dst, NULL, &data, FLD_TYPE_VALUE, &right, sizeof(SHashObj), false); + filterAddField(dst, NULL, &data, FLD_TYPE_VALUE, &right, POINTER_BYTES, false); // POINTER_BYTES should be sizeof(SHashObj), but POINTER_BYTES is also right. t = FILTER_GET_FIELD(dst, right);