提交 9d97d89e 编写于 作者: G Ganlin Zhao

[TD-11222]<feature>(query): Histogram function

......@@ -70,5 +70,6 @@ INCLUDE(cmake/install.inc)
ADD_SUBDIRECTORY(deps)
ADD_SUBDIRECTORY(src)
ADD_SUBDIRECTORY(tests)
ADD_SUBDIRECTORY(examples/c)
INCLUDE(CPack)
......@@ -92,8 +92,6 @@ TDengine是一个高效的存储、查询、分析时序大数据的平台,专
## [与其他工具的连接](/connections)
* [Grafana](/connections#grafana):获取并可视化保存在TDengine的数据
* [MATLAB](/connections#matlab):通过配置MATLAB的JDBC数据源访问保存在TDengine的数据
* [R](/connections#r):通过配置R的JDBC数据源访问保存在TDengine的数据
* [IDEA Database](https://www.taosdata.com/blog/2020/08/27/1767.html):通过IDEA 数据库管理工具可视化使用 TDengine
## [TDengine集群的安装、管理](/cluster)
......
......@@ -792,8 +792,8 @@ Query OK, 1 row(s) in set (0.000141s)
## 在框架中使用
* Spring JdbcTemplate 中使用 taos-jdbcdriver,可参考 [SpringJdbcTemplate](https://github.com/taosdata/TDengine/tree/develop/tests/examples/JDBC/SpringJdbcTemplate)
* Springboot + Mybatis 中使用,可参考 [springbootdemo](https://github.com/taosdata/TDengine/tree/develop/tests/examples/JDBC/springbootdemo)
* Spring JdbcTemplate 中使用 taos-jdbcdriver,可参考 [SpringJdbcTemplate](https://github.com/taosdata/TDengine/tree/develop/examples/JDBC/SpringJdbcTemplate)
* Springboot + Mybatis 中使用,可参考 [springbootdemo](https://github.com/taosdata/TDengine/tree/develop/examples/JDBC/springbootdemo)
## 示例程序
......@@ -803,7 +803,7 @@ Query OK, 1 row(s) in set (0.000141s)
* Springbootdemo:springboot示例源程序
* SpringJdbcTemplate:SpringJDBC模板
请参考:[JDBC example](https://github.com/taosdata/TDengine/tree/develop/tests/examples/JDBC)
请参考:[JDBC example](https://github.com/taosdata/TDengine/tree/develop/examples/JDBC)
## 常见问题
* 使用Statement的addBatch和executeBatch来执行“批量写入/更行”,为什么没有带来性能上的提升?
......
......@@ -164,7 +164,7 @@ C/C++的API类似于MySQL的C API。应用程序使用时,需要包含TDengine
### 示例程序
使用C/C++连接器的示例代码请参见 https://github.com/taosdata/TDengine/tree/develop/tests/examples/c 。
使用C/C++连接器的示例代码请参见 https://github.com/taosdata/TDengine/tree/develop/examples/c 。
示例程序源码也可以在安装目录下的 examples/c 路径下找到:
......@@ -1080,7 +1080,7 @@ HTTP 请求 URL 采用 `sqlutc` 时,返回结果集的时间戳将采用 UTC
示例程序源码位于
* {client_install_directory}/examples/C#
* [github C# example source code](https://github.com/taosdata/TDengine/tree/develop/tests/examples/C%2523)
* [github C# example source code](https://github.com/taosdata/TDengine/tree/develop/examples/C%2523)
**注意:** TDengineTest.cs C#示例源程序,包含了数据库连接参数,以及如何执行数据插入、查询等操作。
......@@ -1112,7 +1112,7 @@ dotnet add package TDengine.Connector
```c#
using TDengineDriver;
```
* 用户可以参考[TDengineTest.cs](https://github.com/taosdata/TDengine/tree/develop/tests/examples/C%2523/TDengineTest)来定义数据库连接参数,以及如何执行数据插入、查询等操作。
* 用户可以参考[TDengineTest.cs](https://github.com/taosdata/TDengine/tree/develop/examples/C%2523/TDengineTest)来定义数据库连接参数,以及如何执行数据插入、查询等操作。
**注意:**
......@@ -1150,7 +1150,7 @@ Go连接器支持的系统有:
### 示例程序
使用 Go 连接器的示例代码请参考 https://github.com/taosdata/TDengine/tree/develop/tests/examples/go 以及[视频教程](https://www.taosdata.com/blog/2020/11/11/1951.html)
使用 Go 连接器的示例代码请参考 https://github.com/taosdata/TDengine/tree/develop/examples/go 以及[视频教程](https://www.taosdata.com/blog/2020/11/11/1951.html)
示例程序源码也位于安装目录下的 examples/go/taosdemo.go 文件中。
......@@ -1285,7 +1285,7 @@ Node-example-raw.js
验证方法:
1. 新建安装验证目录,例如:`~/tdengine-test`,拷贝github上nodejsChecker.js源程序。下载地址:(https://github.com/taosdata/TDengine/tree/develop/tests/examples/nodejs/nodejsChecker.js)。
1. 新建安装验证目录,例如:`~/tdengine-test`,拷贝github上nodejsChecker.js源程序。下载地址:(https://github.com/taosdata/TDengine/tree/develop/examples/nodejs/nodejsChecker.js)。
2. 在命令行中执行以下命令:
......@@ -1389,6 +1389,6 @@ promise2.then(function(result) {
### 示例
[node-example.js](https://github.com/taosdata/TDengine/tree/master/tests/examples/nodejs/node-example.js)提供了一个使用NodeJS 连接器建表,插入天气数据并查询插入的数据的代码示例。
[node-example.js](https://github.com/taosdata/tests/tree/master/examples/nodejs/node-example.js)提供了一个使用NodeJS 连接器建表,插入天气数据并查询插入的数据的代码示例。
[node-example-raw.js](https://github.com/taosdata/TDengine/tree/master/tests/examples/nodejs/node-example-raw.js)同样是一个使用NodeJS 连接器建表,插入天气数据并查询插入的数据的代码示例,但和上面不同的是,该示例只使用`cursor`
[node-example-raw.js](https://github.com/taosdata/tests/tree/master/examples/nodejs/node-example-raw.js)同样是一个使用NodeJS 连接器建表,插入天气数据并查询插入的数据的代码示例,但和上面不同的是,该示例只使用`cursor`
......@@ -52,7 +52,7 @@ GF_PLUGINS_ALLOW_LOADING_UNSIGNED_PLUGINS=tdengine-datasource
#### 配置数据源
用户可以直接通过 <http://localhost:3000> 的网址,登录 Grafana 服务器(用户名/密码:admin/admin),通过左侧 `Configuration -> Data Sources` 可以添加数据源,如下图所示:
用户可以直接通过 http://localhost:3000 的网址,登录 Grafana 服务器(用户名/密码:admin/admin),通过左侧 `Configuration -> Data Sources` 可以添加数据源,如下图所示:
![img](../images/connections/add_datasource1.jpg)
......
......@@ -149,7 +149,7 @@ taosd -C
| 31 | streamCompDelayRatio | | **S** | | 连续查询的延迟时间计算系数 | 0.1-0.9 | 0.1 | |
| 32 | maxVgroupsPerDb | | **S** | | 每个DB中 能够使用的最大vnode个数 | 0-8192 | | |
| 33 | maxTablesPerVnode | | **S** | | 每个vnode中能够创建的最大表个数 | | 1000000 | |
| 34 | minTablesPerVnode | YES | **S** | | 每个vnode中必须创建的最小表个数 | | 100 | |
| 34 | minTablesPerVnode | YES | **S** | | 每个vnode中必须创建的最小表个数 | | 1000 | |
| 35 | tableIncStepPerVnode | YES | **S** | | 每个vnode中超过最小表数后递增步长 | | 1000 | |
| 36 | cache | | **S** | MB | 内存块的大小 | | 16 | |
| 37 | blocks | | **S** | | 每个vnode(tsdb)中有多少cache大小的内存块。因此一个vnode的用的内存大小粗略为(cache * blocks) | | 6 | |
......@@ -162,7 +162,7 @@ taosd -C
| 44 | walLevel | | **S** | | WAL级别 | 1:写wal, 但不执行fsync; 2:写wal, 而且执行fsync | 1 | |
| 45 | fsync | | **S** | 毫秒 | 当wal设置为2时,执行fsync的周期 | 最小为0,表示每次写入,立即执行fsync;最大为180000(三分钟) | 3000 | |
| 46 | replica | | **S** | | 副本个数 | 1-3 | 1 | |
| 47 | mqttHostName | YES | **S** | | mqtt uri | | | [mqtt://username:password@hostname:1883/taos/](mqtt://username:password@hostname:1883/taos/) |
| 47 | mqttHostName | YES | **S** | | mqtt uri | | | mqtt://username:password@hostname:1883/taos/ |
| 48 | mqttPort | YES | **S** | | mqtt client name | | | 1883 |
| 49 | mqttTopic | YES | **S** | | | | | /test |
| 50 | compressMsgSize | | **S** | bytes | 客户端与服务器之间进行消息通讯过程中,对通讯的消息进行压缩的阈值。如果要压缩消息,建议设置为64330字节,即大于64330字节的消息体才进行压缩。 | `0 `表示对所有的消息均进行压缩 >0: 超过该值的消息才进行压缩 -1: 不压缩 | -1 | |
......@@ -602,7 +602,7 @@ chmod +x TDinsight.sh
-T '{"alarm_level":"%s","time":"%s","name":"%s","content":"%s"}'
```
运行程序并重启 Grafana 服务,打开面板:<http://localhost:3000/d/tdinsight>
运行程序并重启 Grafana 服务,打开面板:http://localhost:3000/d/tdinsight
更多使用场景和限制请参考[TDinsight](https://github.com/taosdata/grafanaplugin/blob/master/dashboards/TDinsight.md) 文档。
......
......@@ -753,12 +753,12 @@ Query OK, 1 row(s) in set (0.000141s)
## Integrated with framework
- Please refer to [SpringJdbcTemplate](https://github.com/taosdata/TDengine/tree/develop/tests/examples/JDBC/SpringJdbcTemplate) if using taos-jdbcdriver in Spring JdbcTemplate.
- Please refer to [springbootdemo](https://github.com/taosdata/TDengine/tree/develop/tests/examples/JDBC/springbootdemo) if using taos-jdbcdriver in Spring JdbcTemplate.
- Please refer to [SpringJdbcTemplate](https://github.com/taosdata/TDengine/tree/develop/examples/JDBC/SpringJdbcTemplate) if using taos-jdbcdriver in Spring JdbcTemplate.
- Please refer to [springbootdemo](https://github.com/taosdata/TDengine/tree/develop/examples/JDBC/springbootdemo) if using taos-jdbcdriver in Spring JdbcTemplate.
## Example Codes
you see sample code here: [JDBC example](https://github.com/taosdata/TDengine/tree/develop/tests/examples/JDBC)
you see sample code here: [JDBC example](https://github.com/taosdata/TDengine/tree/develop/examples/JDBC)
## FAQ
- Why does not addBatch and executeBatch provide a performance benefit for executing "batch writes/updates"?
......
......@@ -164,10 +164,10 @@ The C/C++ API is similar to MySQL's C API. When application use it, it needs to
Note:
- The TDengine dynamic library needs to be linked at compiling. The library in Linux is [libtaos.so](http://libtaos.so/), which installed at/usr/local/taos/driver. By Windows, it is taos.dll and installed at C:\ TDengine.
- The TDengine dynamic library needs to be linked at compiling. The library in Linux is *libtaos.so*, which installed at/usr/local/taos/driver. By Windows, it is taos.dll and installed at C:\ TDengine.
- Unless otherwise specified, when the return value of API is an integer, 0 represents success, others are error codes representing the cause of failure, and when the return value is a pointer, NULL represents failure.
More sample codes for using C/C++ connectors, please visit https://github.com/taosdata/TDengine/tree/develop/tests/examples/c.
More sample codes for using C/C++ connectors, please visit https://github.com/taosdata/TDengine/tree/develop/examples/c.
### Basic API
......@@ -891,7 +891,7 @@ Only some configuration parameters related to RESTful interface are listed below
### Example Source Code
you can find sample code under follow directions:
* {client_install_directory}/examples/C#
* [github C# example source code](https://github.com/taosdata/TDengine/tree/develop/tests/examples/C%2523)
* [github C# example source code](https://github.com/taosdata/TDengine/tree/develop/examples/C%2523)
**Tips:** TDengineTest.cs One of C# connector's sample code that include basic examples like connection,sql executions and so on.
......@@ -924,7 +924,7 @@ dotnet add package TDengine.Connector
```C#
using TDengineDriver;
```
* user can reference from[TDengineTest.cs](https://github.com/taosdata/TDengine/tree/develop/tests/examples/C%2523/TDengineTest) and learn how to define database connection,query,insert and other basic data manipulations.
* user can reference from[TDengineTest.cs](https://github.com/taosdata/TDengine/tree/develop/examples/C%2523/TDengineTest) and learn how to define database connection,query,insert and other basic data manipulations.
**Note:**
......@@ -951,7 +951,7 @@ https://www.taosdata.com/blog/2020/11/02/1901.html
The TDengine provides the GO driver taosSql. taosSql implements the GO language's built-in interface database/sql/driver. Users can access TDengine in the application by simply importing the package as follows, see https://github.com/taosdata/driver-go/blob/develop/taosSql/driver_test.go for details.
Sample code for using the Go connector can be found in https://github.com/taosdata/TDengine/tree/develop/tests/examples/go .
Sample code for using the Go connector can be found in https://github.com/taosdata/TDengine/tree/develop/examples/go .
```Go
import (
......@@ -1067,7 +1067,7 @@ After installing the TDengine client, the nodejsChecker.js program can verify wh
Steps:
1. Create a new installation verification directory, for example: `~/tdengine-test`, copy the nodejsChecker.js source program on github. Download address: (https://github.com/taosdata/TDengine/tree/develop/tests/examples/nodejs/nodejsChecker.js).
1. Create a new installation verification directory, for example: `~/tdengine-test`, copy the nodejsChecker.js source program on github. Download address: (https://github.com/taosdata/TDengine/tree/develop/examples/nodejs/nodejsChecker.js).
2. Execute the following command:
......@@ -1171,6 +1171,6 @@ promise2.then(function(result) {
### Example
[node-example.js](https://github.com/taosdata/TDengine/tree/master/tests/examples/nodejs/node-example.js) provides a code example that uses the NodeJS connector to create a table, insert weather data, and query the inserted data.
[node-example.js](https://github.com/taosdata/tests/tree/master/examples/nodejs/node-example.js) provides a code example that uses the NodeJS connector to create a table, insert weather data, and query the inserted data.
[node-example-raw.js](https://github.com/taosdata/TDengine/tree/master/tests/examples/nodejs/node-example-raw.js) is also a code example that uses the NodeJS connector to create a table, insert weather data, and query the inserted data, but unlike the above, this example only uses cursor.
[node-example-raw.js](https://github.com/taosdata/tests/tree/master/examples/nodejs/node-example-raw.js) is also a code example that uses the NodeJS connector to create a table, insert weather data, and query the inserted data, but unlike the above, this example only uses cursor.
......@@ -63,7 +63,7 @@ Enter the data source configuration page and modify the corresponding configurat
![img](../images/connections/add_datasource3.jpg)
- Host: IP address of any server in TDengine cluster and port number of TDengine RESTful interface (6041), use [http://localhost:6041](http://localhost:6041/) to access the interface by default. Note the 2.4 and later version of TDengine use a stand-alone software, taosAdapter to provide RESTful interface. Please refer to its document for configuration and deployment.
- Host: IP address of any server in TDengine cluster and port number of TDengine RESTful interface (6041), use `http://localhost:6041` to access the interface by default. Note the 2.4 and later version of TDengine use a stand-alone software, taosAdapter to provide RESTful interface. Please refer to its document for configuration and deployment.
- User: TDengine username.
- Password: TDengine user password.
......
......@@ -2,7 +2,7 @@
Multiple TDengine servers, that is, multiple running instances of taosd, can form a cluster to ensure the highly reliable operation of TDengine and provide scale-out features. To understand cluster management in TDengine 2.0, it is necessary to understand the basic concepts of clustering. Please refer to the chapter "Overall Architecture of TDengine 2.0". And before installing the cluster, please follow the chapter ["Getting started"](https://www.taosdata.com/en/documentation/getting-started/) to install and experience the single node TDengine.
Each data node of the cluster is uniquely identified by End Point, which is composed of FQDN (Fully Qualified Domain Name) plus Port, such as [h1.taosdata.com](http://h1.taosdata.com/):6030. The general FQDN is the hostname of the server, which can be obtained through the Linux command `hostname -f` (how to configure FQDN, please refer to: [All about FQDN of TDengine](https://www.taosdata.com/blog/2020/09/11/1824.html)). Port is the external service port number of this data node. The default is 6030, but it can be modified by configuring the parameter serverPort in taos.cfg. A physical node may be configured with multiple hostnames, and TDengine will automatically get the first one, but it can also be specified through the configuration parameter `fqdn` in taos.cfg. If you want to access via direct IP address, you can set the parameter `fqdn` to the IP address of this node.
Each data node of the cluster is uniquely identified by End Point, which is composed of FQDN (Fully Qualified Domain Name) plus Port, such as h1.taosdata.com:6030. The general FQDN is the hostname of the server, which can be obtained through the Linux command `hostname -f` (how to configure FQDN, please refer to: [All about FQDN of TDengine](https://www.taosdata.com/blog/2020/09/11/1824.html)). Port is the external service port number of this data node. The default is 6030, but it can be modified by configuring the parameter serverPort in taos.cfg. A physical node may be configured with multiple hostnames, and TDengine will automatically get the first one, but it can also be specified through the configuration parameter `fqdn` in taos.cfg. If you want to access via direct IP address, you can set the parameter `fqdn` to the IP address of this node.
The cluster management of TDengine is extremely simple. Except for manual intervention in adding and deleting nodes, all other tasks are completed automatically, thus minimizing the workload of operation. This chapter describes the operations of cluster management in detail.
......@@ -29,7 +29,7 @@ Please refer to the [video tutorial](https://www.taosdata.com/blog/2020/11/11/19
3. From the physical node where the application runs, ping the data node where taosd runs. If the ping fails, the application cannot connect to taosd. Please check the DNS settings or hosts file of the physical node where the application is located;
4. The End Point of each data node is the output hostname plus the port number, for example, `h1.taosdata.com:6030`
**Step 5:** Modify the TDengine configuration file (the file/etc/taos/taos.cfg for all nodes needs to be modified). Assume that the first data node End Point to be started is [h1.taosdata.com](http://h1.taosdata.com/): 6030, and its parameters related to cluster configuration are as follows:
**Step 5:** Modify the TDengine configuration file (the file/etc/taos/taos.cfg for all nodes needs to be modified). Assume that the first data node End Point to be started is h1.taosdata.com:6030, and its parameters related to cluster configuration are as follows:
```
// firstEp is the first data node connected after each data node’s first launch
......@@ -64,7 +64,7 @@ The parameters that must be modified are firstEp and fqdn. At each data node, ev
## <a class="anchor" id="node-one"></a> Launch the First Data Node
Follow the instructions in "[Getting started](https://www.taosdata.com/en/documentation/getting-started/)", launch the first data node, such as [h1.taosdata.com](http://h1.taosdata.com/), then execute taos, start the taos shell, and execute command "show dnodes" from the shell; ", as follows:
Follow the instructions in "[Getting started](https://www.taosdata.com/en/documentation/getting-started/)", launch the first data node, such as h1.taosdata.com, then execute taos, start the taos shell, and execute command "show dnodes" from the shell; ", as follows:
```
Welcome to the TDengine shell from Linux, Client Version:2.0.0.0
......
......@@ -447,7 +447,7 @@ Some CLI options are needed to use the script:
-T '{"alarm_level":"%s","time":"%s","name":"%s","content":"%s"}'
```
Follow the usage of the script and then restart grafana-server service, here we go `http://localhost:3000/d/tdinsight`.
Follow the usage of the script and then restart grafana-server service, here we go http://localhost:3000/d/tdinsight.
Refer to [TDinsight](https://github.com/taosdata/grafanaplugin/blob/master/dashboards/TDinsight.md) README for more scenario and limitations of the script, and the metrics descriptions for all of the TDinsight.
......
C#checker/bin/
C#checker/obj/
TDengineTest/bin/
TDengineTest/obj/
schemaless/bin/
schemaless/obj/
stmt/TDengineDriver.cs
stmt/TaosBind.cs
stmt/TaosMultiBind.cs
stmt/bin/
stmt/obj/
taosdemo/bin/
taosdemo/obj/
jsonTag/bin/
jsonTag/obj/
insertCn/bin/
insertCn/obj/
\ No newline at end of file
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Text;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Collections;
namespace TDengineDriver
{
class TDengineTest
{
//connect parameters
private string host;
private string configDir;
private string user;
private string password;
private short port = 0;
//sql parameters
private string dbName;
private string tbName;
private string precision;
private bool isInsertData;
private bool isQueryData;
private long tableCount;
private long totalRows;
private long batchRows;
private long beginTimestamp = 1551369600000L;
private IntPtr conn = IntPtr.Zero;
private long rowsInserted = 0;
static void Main(string[] args)
{
TDengineTest tester = new TDengineTest();
tester.ReadArgument(args);
tester.InitTDengine();
tester.ConnectTDengine();
tester.createDatabase();
tester.useDatabase();
tester.checkDropTable();
tester.createTable();
tester.checkInsert();
tester.checkSelect();
tester.checkDropTable();
tester.dropDatabase();
tester.CloseConnection();
tester.cleanup();
}
public long GetArgumentAsLong(String[] argv, String argName, int minVal, int maxVal, int defaultValue)
{
int argc = argv.Length;
for (int i = 0; i < argc; ++i)
{
if (argName != argv[i])
{
continue;
}
if (i < argc - 1)
{
String tmp = argv[i + 1];
if (tmp[0] == '-')
{
Console.WriteLine("option {0:G} requires an argument", tmp);
ExitProgram();
}
long tmpVal = Convert.ToInt64(tmp);
if (tmpVal < minVal || tmpVal > maxVal)
{
Console.WriteLine("option {0:G} should in range [{1:G}, {2:G}]", argName, minVal, maxVal);
ExitProgram();
}
return tmpVal;
}
}
return defaultValue;
}
public String GetArgumentAsString(String[] argv, String argName, String defaultValue)
{
int argc = argv.Length;
for (int i = 0; i < argc; ++i)
{
if (argName != argv[i])
{
continue;
}
if (i < argc - 1)
{
String tmp = argv[i + 1];
if (tmp[0] == '-')
{
Console.WriteLine("option {0:G} requires an argument", tmp);
ExitProgram();
}
return tmp;
}
}
return defaultValue;
}
public void PrintHelp(String[] argv)
{
for (int i = 0; i < argv.Length; ++i)
{
if ("--help" == argv[i])
{
String indent = " ";
Console.WriteLine("taosTest is simple example to operate TDengine use C# Language.\n");
Console.WriteLine("{0:G}{1:G}", indent, "-h");
Console.WriteLine("{0:G}{1:G}{2:G}", indent, indent, "TDEngine server IP address to connect");
Console.WriteLine("{0:G}{1:G}", indent, "-u");
Console.WriteLine("{0:G}{1:G}{2:G}", indent, indent, "The TDEngine user name to use when connecting to the server, default is root");
Console.WriteLine("{0:G}{1:G}", indent, "-p");
Console.WriteLine("{0:G}{1:G}{2:G}", indent, indent, "The TDEngine user name to use when connecting to the server, default is taosdata");
Console.WriteLine("{0:G}{1:G}", indent, "-d");
Console.WriteLine("{0:G}{1:G}{2:G}", indent, indent, "Database used to create table or import data, default is db");
Console.WriteLine("{0:G}{1:G}", indent, "-s");
Console.WriteLine("{0:G}{1:G}{2:G}", indent, indent, "Super Tables used to create table, default is mt");
Console.WriteLine("{0:G}{1:G}", indent, "-t");
Console.WriteLine("{0:G}{1:G}{2:G}", indent, indent, "Table prefixs, default is t");
Console.WriteLine("{0:G}{1:G}", indent, "-w");
Console.WriteLine("{0:G}{1:G}{2:G}", indent, indent, "Whether to insert data");
Console.WriteLine("{0:G}{1:G}", indent, "-r");
Console.WriteLine("{0:G}{1:G}{2:G}", indent, indent, "Whether to query data");
Console.WriteLine("{0:G}{1:G}", indent, "-n");
Console.WriteLine("{0:G}{1:G}{2:G}", indent, indent, "How many Tables to create, default is 10");
Console.WriteLine("{0:G}{1:G}", indent, "-b");
Console.WriteLine("{0:G}{1:G}{2:G}", indent, indent, "How many rows per insert batch, default is 10");
Console.WriteLine("{0:G}{1:G}", indent, "-i");
Console.WriteLine("{0:G}{1:G}{2:G}", indent, indent, "How many rows to insert, default is 100");
Console.WriteLine("{0:G}{1:G}", indent, "-c");
Console.WriteLine("{0:G}{1:G}{2:G}", indent, indent, "Configuration directory");
//
Console.WriteLine("{0:G}{1:G}", indent, "-ps");
Console.WriteLine("{0:G}{1:G}{2:G}", indent, indent, "Configurate db precision,default millisecond");
ExitProgram();
}
}
}
public void ReadArgument(String[] argv)
{
PrintHelp(argv);
host = this.GetArgumentAsString(argv, "-h", "127.0.0.1");
user = this.GetArgumentAsString(argv, "-u", "root");
password = this.GetArgumentAsString(argv, "-p", "taosdata");
dbName = this.GetArgumentAsString(argv, "-d", "test");
tbName = this.GetArgumentAsString(argv, "-s", "weather");
precision = this.GetArgumentAsString(argv, "-ps", "ms");
isInsertData = this.GetArgumentAsLong(argv, "-w", 0, 1, 1) != 0;
isQueryData = this.GetArgumentAsLong(argv, "-r", 0, 1, 1) != 0;
tableCount = this.GetArgumentAsLong(argv, "-n", 1, 10000, 10);
batchRows = this.GetArgumentAsLong(argv, "-b", 1, 1000, 500);
totalRows = this.GetArgumentAsLong(argv, "-i", 1, 10000000, 10000);
configDir = this.GetArgumentAsString(argv, "-c", "C:/TDengine/cfg");
}
public void InitTDengine()
{
TDengine.Options((int)TDengineInitOption.TDDB_OPTION_CONFIGDIR, this.configDir);
TDengine.Options((int)TDengineInitOption.TDDB_OPTION_SHELL_ACTIVITY_TIMER, "60");
Console.WriteLine("init...");
TDengine.Init();
Console.WriteLine("get connection starting...");
}
public void ConnectTDengine()
{
string db = "";
this.conn = TDengine.Connect(this.host, this.user, this.password, db, this.port);
if (this.conn == IntPtr.Zero)
{
Console.WriteLine("connection failed: " + this.host);
ExitProgram();
}
else
{
Console.WriteLine("[ OK ] Connection established.");
}
}
public void createDatabase()
{
StringBuilder sql = new StringBuilder();
sql.Append("create database if not exists ").Append(this.dbName).Append(" precision '").Append(this.precision).Append("'");
execute(sql.ToString());
}
public void useDatabase()
{
StringBuilder sql = new StringBuilder();
sql.Append("use ").Append(this.dbName);
execute(sql.ToString());
}
public void checkSelect()
{
StringBuilder sql = new StringBuilder();
sql.Append("select * from ").Append(this.dbName).Append(".").Append(this.tbName);
ExecuteQuery(sql.ToString());
}
public void createTable()
{
StringBuilder sql = new StringBuilder();
sql.Append("create table if not exists ").Append(this.dbName).Append(".").Append(this.tbName).Append("(ts timestamp, temperature float, humidity int)");
execute(sql.ToString());
}
public void checkInsert()
{
StringBuilder sql = new StringBuilder();
sql.Append("insert into ").Append(this.dbName).Append(".").Append(this.tbName).Append("(ts, temperature, humidity) values(now, 20.5, 34)");
execute(sql.ToString());
}
public void checkDropTable()
{
StringBuilder sql = new StringBuilder();
sql.Append("drop table if exists ").Append(this.dbName).Append(".").Append(this.tbName).Append("");
execute(sql.ToString());
}
public void dropDatabase()
{
StringBuilder sql = new StringBuilder();
sql.Append("drop database if exists ").Append(this.dbName);
execute(sql.ToString());
}
public void execute(string sql)
{
DateTime dt1 = DateTime.Now;
IntPtr res = TDengine.Query(this.conn, sql.ToString());
DateTime dt2 = DateTime.Now;
TimeSpan span = dt2 - dt1;
if ((res == IntPtr.Zero) || (TDengine.ErrorNo(res) != 0))
{
Console.Write(sql.ToString() + " failure, ");
if (res != IntPtr.Zero) {
Console.Write("reason: " + TDengine.Error(res));
}
Console.WriteLine("");
ExitProgram();
}
else
{
Console.WriteLine(sql.ToString() + " success");
}
TDengine.FreeResult(res);
}
public void ExecuteQuery(string sql)
{
DateTime dt1 = DateTime.Now;
long queryRows = 0;
IntPtr res = TDengine.Query(conn, sql);
getPrecision(res);
if ((res == IntPtr.Zero) || (TDengine.ErrorNo(res) != 0))
{
Console.Write(sql.ToString() + " failure, ");
if (res != IntPtr.Zero) {
Console.Write("reason: " + TDengine.Error(res));
}
Console.WriteLine("");
ExitProgram();
}
DateTime dt2 = DateTime.Now;
TimeSpan span = dt2 - dt1;
Console.WriteLine("[OK] time cost: " + span.ToString() + "ms, execute statement ====> " + sql.ToString());
int fieldCount = TDengine.FieldCount(res);
List<TDengineMeta> metas = TDengine.FetchFields(res);
for (int j = 0; j < metas.Count; j++)
{
TDengineMeta meta = (TDengineMeta)metas[j];
}
IntPtr rowdata;
StringBuilder builder = new StringBuilder();
while ((rowdata = TDengine.FetchRows(res)) != IntPtr.Zero)
{
queryRows++;
for (int fields = 0; fields < fieldCount; ++fields)
{
TDengineMeta meta = metas[fields];
int offset = IntPtr.Size * fields;
IntPtr data = Marshal.ReadIntPtr(rowdata, offset);
builder.Append("---");
if (data == IntPtr.Zero)
{
builder.Append("NULL");
continue;
}
switch ((TDengineDataType)meta.type)
{
case TDengineDataType.TSDB_DATA_TYPE_BOOL:
bool v1 = Marshal.ReadByte(data) == 0 ? false : true;
builder.Append(v1);
break;
case TDengineDataType.TSDB_DATA_TYPE_TINYINT:
byte v2 = Marshal.ReadByte(data);
builder.Append(v2);
break;
case TDengineDataType.TSDB_DATA_TYPE_SMALLINT:
short v3 = Marshal.ReadInt16(data);
builder.Append(v3);
break;
case TDengineDataType.TSDB_DATA_TYPE_INT:
int v4 = Marshal.ReadInt32(data);
builder.Append(v4);
break;
case TDengineDataType.TSDB_DATA_TYPE_BIGINT:
long v5 = Marshal.ReadInt64(data);
builder.Append(v5);
break;
case TDengineDataType.TSDB_DATA_TYPE_FLOAT:
float v6 = (float)Marshal.PtrToStructure(data, typeof(float));
builder.Append(v6);
break;
case TDengineDataType.TSDB_DATA_TYPE_DOUBLE:
double v7 = (double)Marshal.PtrToStructure(data, typeof(double));
builder.Append(v7);
break;
case TDengineDataType.TSDB_DATA_TYPE_BINARY:
string v8 = Marshal.PtrToStringAnsi(data);
builder.Append(v8);
break;
case TDengineDataType.TSDB_DATA_TYPE_TIMESTAMP:
long v9 = Marshal.ReadInt64(data);
builder.Append(v9);
break;
case TDengineDataType.TSDB_DATA_TYPE_NCHAR:
string v10 = Marshal.PtrToStringAnsi(data);
builder.Append(v10);
break;
}
}
builder.Append("---");
if (queryRows <= 10)
{
Console.WriteLine(builder.ToString());
}
builder.Clear();
}
if (TDengine.ErrorNo(res) != 0)
{
Console.Write("Query is not complete, Error {0:G}", TDengine.ErrorNo(res), TDengine.Error(res));
}
Console.WriteLine("");
TDengine.FreeResult(res);
}
public void CloseConnection()
{
if (this.conn != IntPtr.Zero)
{
TDengine.Close(this.conn);
Console.WriteLine("connection closed.");
}
}
static void ExitProgram()
{
System.Environment.Exit(0);
}
public void cleanup()
{
Console.WriteLine("clean up...");
System.Environment.Exit(0);
}
// method to get db precision
public void getPrecision(IntPtr res)
{
int psc=TDengine.ResultPrecision(res);
switch(psc)
{
case 0:
Console.WriteLine("db:[{0:G}]'s precision is {1:G}",this.dbName,"millisecond");
break;
case 1:
Console.WriteLine("db:[{0:G}]'s precision is {1:G}",this.dbName,"microsecond");
break;
case 2:
Console.WriteLine("db:[{0:G}]'s precision is {1:G}",this.dbName,"nanosecond");
break;
}
}
}
}
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
<RootNamespace>C_checker</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="TDengine.Connector" Version="1.0.2" />
</ItemGroup>
</Project>
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Text;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Collections;
namespace TDengineDriver
{
class TDengineTest
{
//connect parameters
private string host;
private string configDir;
private string user;
private string password;
private short port = 0;
//sql parameters
private string dbName;
private string stableName;
private string tablePrefix;
private bool isInsertData;
private bool isQueryData;
private long tableCount;
private long totalRows;
private long batchRows;
private long beginTimestamp = 1551369600000L;
private IntPtr conn = IntPtr.Zero;
private long rowsInserted = 0;
static void Main(string[] args)
{
TDengineTest tester = new TDengineTest();
tester.ReadArgument(args);
Console.WriteLine("---------------------------------------------------------------");
Console.WriteLine("Starting Testing...");
Console.WriteLine("---------------------------------------------------------------");
tester.InitTDengine();
tester.ConnectTDengine();
tester.CreateDbAndTable();
tester.ExecuteInsert();
tester.ExecuteQuery();
tester.CloseConnection();
Console.WriteLine("---------------------------------------------------------------");
Console.WriteLine("Stop Testing...");
Console.WriteLine("---------------------------------------------------------------");
}
public long GetArgumentAsLong(String[] argv, String argName, int minVal, int maxVal, int defaultValue)
{
int argc = argv.Length;
for (int i = 0; i < argc; ++i)
{
if (argName != argv[i])
{
continue;
}
if (i < argc - 1)
{
String tmp = argv[i + 1];
if (tmp[0] == '-')
{
Console.WriteLine("option {0:G} requires an argument", tmp);
ExitProgram();
}
long tmpVal = Convert.ToInt64(tmp);
if (tmpVal < minVal || tmpVal > maxVal)
{
Console.WriteLine("option {0:G} should in range [{1:G}, {2:G}]", argName, minVal, maxVal);
ExitProgram();
}
return tmpVal;
}
}
return defaultValue;
}
public String GetArgumentAsString(String[] argv, String argName, String defaultValue)
{
int argc = argv.Length;
for (int i = 0; i < argc; ++i)
{
if (argName != argv[i])
{
continue;
}
if (i < argc - 1)
{
String tmp = argv[i + 1];
if (tmp[0] == '-')
{
Console.WriteLine("option {0:G} requires an argument", tmp);
ExitProgram();
}
return tmp;
}
}
return defaultValue;
}
public void PrintHelp(String[] argv)
{
for (int i = 0; i < argv.Length; ++i)
{
if ("--help" == argv[i])
{
String indent = " ";
Console.WriteLine("taosTest is simple example to operate TDengine use C# Language.\n");
Console.WriteLine("{0:G}{1:G}", indent, "-h");
Console.WriteLine("{0:G}{1:G}{2:G}", indent, indent, "TDEngine server IP address to connect");
Console.WriteLine("{0:G}{1:G}", indent, "-u");
Console.WriteLine("{0:G}{1:G}{2:G}", indent, indent, "The TDEngine user name to use when connecting to the server, default is root");
Console.WriteLine("{0:G}{1:G}", indent, "-p");
Console.WriteLine("{0:G}{1:G}{2:G}", indent, indent, "The TDEngine user name to use when connecting to the server, default is taosdata");
Console.WriteLine("{0:G}{1:G}", indent, "-d");
Console.WriteLine("{0:G}{1:G}{2:G}", indent, indent, "Database used to create table or import data, default is db");
Console.WriteLine("{0:G}{1:G}", indent, "-s");
Console.WriteLine("{0:G}{1:G}{2:G}", indent, indent, "Super Tables used to create table, default is mt");
Console.WriteLine("{0:G}{1:G}", indent, "-t");
Console.WriteLine("{0:G}{1:G}{2:G}", indent, indent, "Table prefixs, default is t");
Console.WriteLine("{0:G}{1:G}", indent, "-w");
Console.WriteLine("{0:G}{1:G}{2:G}", indent, indent, "Whether to insert data");
Console.WriteLine("{0:G}{1:G}", indent, "-r");
Console.WriteLine("{0:G}{1:G}{2:G}", indent, indent, "Whether to query data");
Console.WriteLine("{0:G}{1:G}", indent, "-n");
Console.WriteLine("{0:G}{1:G}{2:G}", indent, indent, "How many Tables to create, default is 10");
Console.WriteLine("{0:G}{1:G}", indent, "-b");
Console.WriteLine("{0:G}{1:G}{2:G}", indent, indent, "How many rows per insert batch, default is 10");
Console.WriteLine("{0:G}{1:G}", indent, "-i");
Console.WriteLine("{0:G}{1:G}{2:G}", indent, indent, "How many rows to insert, default is 100");
Console.WriteLine("{0:G}{1:G}", indent, "-c");
Console.WriteLine("{0:G}{1:G}{2:G}", indent, indent, "Configuration directory");
ExitProgram();
}
}
}
public void ReadArgument(String[] argv)
{
PrintHelp(argv);
host = this.GetArgumentAsString(argv, "-h", "127.0.0.1");
user = this.GetArgumentAsString(argv, "-u", "root");
password = this.GetArgumentAsString(argv, "-p", "taosdata");
dbName = this.GetArgumentAsString(argv, "-d", "tdengint_test_cs");
stableName = this.GetArgumentAsString(argv, "-s", "st");
tablePrefix = this.GetArgumentAsString(argv, "-t", "t");
isInsertData = this.GetArgumentAsLong(argv, "-w", 0, 1, 1) != 0;
isQueryData = this.GetArgumentAsLong(argv, "-r", 0, 1, 1) != 0;
tableCount = this.GetArgumentAsLong(argv, "-n", 1, 10000, 10);
batchRows = this.GetArgumentAsLong(argv, "-b", 1, 1000,500 );
totalRows = this.GetArgumentAsLong(argv, "-i", 1, 10000000, 10000);
configDir = this.GetArgumentAsString(argv, "-c", "C:/TDengine/cfg");
}
public void InitTDengine()
{
TDengine.Options((int)TDengineInitOption.TDDB_OPTION_CONFIGDIR, this.configDir);
TDengine.Options((int)TDengineInitOption.TDDB_OPTION_SHELL_ACTIVITY_TIMER, "60");
TDengine.Init();
Console.WriteLine("TDengine Initialization finished");
}
public void ConnectTDengine()
{
string db = "";
Console.WriteLine("Host:{0}", this.host);
this.conn = TDengine.Connect(this.host, this.user, this.password, db, this.port);
if (this.conn == IntPtr.Zero)
{
Console.WriteLine("Connect to TDengine failed");
ExitProgram();
}
else
{
Console.WriteLine("Connect to TDengine success");
}
}
public void CreateDbAndTable()
{
if (!this.isInsertData)
{
return;
}
StringBuilder sql = new StringBuilder();
sql.Append("create database if not exists ").Append(this.dbName);
IntPtr res = TDengine.Query(this.conn, sql.ToString());
if ((res == IntPtr.Zero) || (TDengine.ErrorNo(res) != 0))
{
Console.Write(sql.ToString() + " failure, ");
if (res != IntPtr.Zero)
{
Console.Write("reason: " + TDengine.Error(res));
}
Console.WriteLine("");
ExitProgram();
}
else
{
Console.WriteLine(sql.ToString() + " success");
}
TDengine.FreeResult(res);
sql.Clear();
sql.Append("use ").Append(this.dbName);
res = TDengine.Query(this.conn, sql.ToString());
if ((res == IntPtr.Zero) || (TDengine.ErrorNo(res) != 0))
{
Console.Write(sql.ToString() + " failure, ");
if (res != IntPtr.Zero)
{
Console.Write("reason: " + TDengine.Error(res));
}
Console.WriteLine("");
ExitProgram();
}
else
{
Console.WriteLine(sql.ToString() + " success");
}
TDengine.FreeResult(res);
sql.Clear();
sql.Append("create table if not exists ").Append(this.stableName).Append("(ts timestamp, v1 bool, v2 tinyint, v3 smallint, v4 int, v5 bigint, v6 float, v7 double, v8 binary(10), v9 nchar(10)) tags(t1 int)");
res = TDengine.Query(this.conn, sql.ToString());
if ((res == IntPtr.Zero) || (TDengine.ErrorNo(res) != 0))
{
Console.Write(sql.ToString() + " failure, ");
if (res != IntPtr.Zero)
{
Console.Write("reason: " + TDengine.Error(res));
}
Console.WriteLine("");
ExitProgram();
}
else
{
Console.WriteLine(sql.ToString() + " success");
}
TDengine.FreeResult(res);
for (int i = 0; i < this.tableCount; i++)
{
sql.Clear();
sql = sql.Append("create table if not exists ").Append(this.tablePrefix).Append(i)
.Append(" using ").Append(this.stableName).Append(" tags(").Append(i).Append(")");
res = TDengine.Query(this.conn, sql.ToString());
if ((res == IntPtr.Zero) || (TDengine.ErrorNo(res) != 0))
{
Console.Write(sql.ToString() + " failure, ");
if (res != IntPtr.Zero)
{
Console.Write("reason: " + TDengine.Error(res));
}
Console.WriteLine("");
ExitProgram();
}
else
{
Console.WriteLine(sql.ToString() + " success");
}
TDengine.FreeResult(res);
}
Console.WriteLine("create db and table success");
}
public void ExecuteInsert()
{
if (!this.isInsertData)
{
return;
}
System.DateTime start = new System.DateTime();
long loopCount = this.totalRows / this.batchRows;
for (int table = 0; table < this.tableCount; ++table)
{
for (long loop = 0; loop < loopCount; loop++)
{
StringBuilder sql = new StringBuilder();
sql.Append("insert into ").Append(this.tablePrefix).Append(table).Append(" values");
for (int batch = 0; batch < this.batchRows; ++batch)
{
long rows = loop * this.batchRows + batch;
sql.Append("(")
.Append(this.beginTimestamp + rows)
.Append(", 1, 2, 3,")
.Append(rows)
.Append(", 5, 6, 7, 'abc', 'def')");
}
IntPtr res = TDengine.Query(this.conn,sql.ToString() );
if ((res == IntPtr.Zero) || (TDengine.ErrorNo(res) != 0))
{
Console.Write(sql.ToString() + " failure, ");
if (res != IntPtr.Zero)
{
Console.Write("reason: " + TDengine.Error(res));
}
Console.WriteLine("");
}
int affectRows = TDengine.AffectRows(res);
this.rowsInserted += affectRows;
TDengine.FreeResult(res);
}
}
System.DateTime end = new System.DateTime();
TimeSpan ts = end - start;
Console.Write("Total {0:G} rows inserted, {1:G} rows failed, time spend {2:G} seconds.\n"
, this.rowsInserted, this.totalRows * this.tableCount - this.rowsInserted, ts.TotalSeconds);
}
public void ExecuteQuery()
{
if (!this.isQueryData)
{
return;
}
System.DateTime start = new System.DateTime();
long queryRows = 0;
for (int i = 0; i < 1/*this.tableCount*/; ++i)
{
String sql = "select * from " + this.dbName + "." + tablePrefix + i;
Console.WriteLine(sql);
IntPtr res = TDengine.Query(conn, sql);
if ((res == IntPtr.Zero) || (TDengine.ErrorNo(res) != 0))
{
Console.Write(sql.ToString() + " failure, ");
if (res != IntPtr.Zero)
{
Console.Write("reason: " + TDengine.Error(res));
}
Console.WriteLine("");
ExitProgram();
}
int fieldCount = TDengine.FieldCount(res);
Console.WriteLine("field count: " + fieldCount);
List<TDengineMeta> metas = TDengine.FetchFields(res);
for (int j = 0; j < metas.Count; j++)
{
TDengineMeta meta = (TDengineMeta)metas[j];
Console.WriteLine("index:" + j + ", type:" + meta.type + ", typename:" + meta.TypeName() + ", name:" + meta.name + ", size:" + meta.size);
}
IntPtr rowdata;
StringBuilder builder = new StringBuilder();
while ((rowdata = TDengine.FetchRows(res)) != IntPtr.Zero)
{
queryRows++;
for (int fields = 0; fields < fieldCount; ++fields)
{
TDengineMeta meta = metas[fields];
int offset = IntPtr.Size * fields;
IntPtr data = Marshal.ReadIntPtr(rowdata, offset);
builder.Append("---");
if (data == IntPtr.Zero)
{
builder.Append("NULL");
continue;
}
switch ((TDengineDataType)meta.type)
{
case TDengineDataType.TSDB_DATA_TYPE_BOOL:
bool v1 = Marshal.ReadByte(data) == 0 ? false : true;
builder.Append(v1);
break;
case TDengineDataType.TSDB_DATA_TYPE_TINYINT:
byte v2 = Marshal.ReadByte(data);
builder.Append(v2);
break;
case TDengineDataType.TSDB_DATA_TYPE_SMALLINT:
short v3 = Marshal.ReadInt16(data);
builder.Append(v3);
break;
case TDengineDataType.TSDB_DATA_TYPE_INT:
int v4 = Marshal.ReadInt32(data);
builder.Append(v4);
break;
case TDengineDataType.TSDB_DATA_TYPE_BIGINT:
long v5 = Marshal.ReadInt64(data);
builder.Append(v5);
break;
case TDengineDataType.TSDB_DATA_TYPE_FLOAT:
float v6 = (float)Marshal.PtrToStructure(data, typeof(float));
builder.Append(v6);
break;
case TDengineDataType.TSDB_DATA_TYPE_DOUBLE:
double v7 = (double)Marshal.PtrToStructure(data, typeof(double));
builder.Append(v7);
break;
case TDengineDataType.TSDB_DATA_TYPE_BINARY:
string v8 = Marshal.PtrToStringAnsi(data);
builder.Append(v8);
break;
case TDengineDataType.TSDB_DATA_TYPE_TIMESTAMP:
long v9 = Marshal.ReadInt64(data);
builder.Append(v9);
break;
case TDengineDataType.TSDB_DATA_TYPE_NCHAR:
string v10 = Marshal.PtrToStringAnsi(data);
builder.Append(v10);
break;
case TDengineDataType.TSDB_DATA_TYPE_UTINYINT:
byte v11 = Marshal.ReadByte(data);
builder.Append(v11);
break;
case TDengineDataType.TSDB_DATA_TYPE_USMALLINT:
ushort v12 = (ushort)Marshal.ReadInt16(data);
builder.Append(v12);
break;
case TDengineDataType.TSDB_DATA_TYPE_UINT:
uint v13 = (uint)Marshal.ReadInt32(data);
builder.Append(v13);
break;
case TDengineDataType.TSDB_DATA_TYPE_UBIGINT:
ulong v14 = (ulong)Marshal.ReadInt64(data);
builder.Append(v14);
break;
}
}
builder.Append("---");
if (queryRows <= 10)
{
Console.WriteLine(builder.ToString());
}
builder.Clear();
}
if (TDengine.ErrorNo(res) != 0)
{
Console.Write("Query is not complete, Error {0:G}",
TDengine.ErrorNo(res), TDengine.Error(res));
}
Console.WriteLine("");
TDengine.FreeResult(res);
}
System.DateTime end = new System.DateTime();
TimeSpan ts = end - start;
Console.Write("Total {0:G} rows inserted, {1:G} rows query, time spend {2:G} seconds.\n"
, this.rowsInserted, queryRows, ts.TotalSeconds);
}
public void CloseConnection()
{
if (this.conn != IntPtr.Zero)
{
TDengine.Close(this.conn);
}
}
static void ExitProgram()
{
TDengine.Cleanup();
System.Environment.Exit(0);
}
}
}
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="TDengine.Connector" Version="1.0.2" />
</ItemGroup>
</Project>
using System;
using Test.UtilsTools;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using Test.UtilsTools.ResultSet;
namespace insertCn
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
IntPtr conn = UtilsTools.TDConnection();
string dbName = "insert_cn_to_nchar_sample_dotnet";
string createDB = $"create database if not exists {dbName};";
string dropDB = $"drop database if exists {dbName};";
string useDB = $"use {dbName};";
string table = "t1";
string stable = "stb";
UtilsTools.ExecuteUpdate(conn,createDB);
UtilsTools.ExecuteUpdate(conn,useDB);
Console.WriteLine("=====================ntable====================");
TestNtable(conn,table);
Console.WriteLine("=====================stable====================");
TestStable(conn,stable);
UtilsTools.ExecuteUpdate(conn,dropDB);
UtilsTools.CloseConnection(conn);
}
static void TestStable(IntPtr conn,string stable)
{
string createSql = $"create table if not exists {stable} (ts timestamp," +
$"v4 int," +
$"blob nchar(200)," +
$"locate nchar(200)," +
$"country binary(200)," +
$"city binary(50)" +
$")tags(" +
$"id int," +
$"name nchar(50)," +
$"addr nchar(200)," +
$"en_name binary(200));";
String dropTb = "drop table if exists " + stable;
String table = stable + "_subtable_1";
var colData = new List<Object>{1637064040000,1,"涛思数据","保利广场","Beijing","China",
1637064041000,2,"涛思数据taosdata","保利广场baoli","Beijing","China",
1637064042000,3,"TDegnine涛思数据","time广场","NewYork","US",
1637064043000,4,"4涛思数据","4广场南部","London","UK",
1637064044000,5,"涛思数据5","!广场路中部123","Tokyo","JP",
1637064045000,6,"taos涛思数据6","青年广场123号!","Washin","DC",
1637064046000,7,"7涛思数据taos","asdf#壮年广场%#endregion","NewYork","US",
1637064047000,8,"8&涛思数据taos","incluse阿斯顿发","NewYork","US",
1637064048000,9,"&涛思数据taos9","123黑化肥werq会挥……&¥%发!afsdfa","NewYork","US",
};
var tagData = new List<Object>{1,"涛思数据","中国北方&南方长江黄河!49wq","tdengine"};
string insertSql = UtilsTools.ConstructInsertSql(table, stable, colData, tagData, 9);
string selectSql = $"select * from {stable};";
List<Object> insertData = UtilsTools.CombineColAndTagData(colData,tagData,9);
UtilsTools.ExecuteUpdate(conn,dropTb);
UtilsTools.ExecuteUpdate(conn,createSql);
UtilsTools.ExecuteUpdate(conn,insertSql);
IntPtr res = UtilsTools.ExecuteQuery(conn,selectSql);
ResultSet resultSet = new ResultSet(res);
List<Object> queryResult = resultSet.GetResultData();
//display
int fieldsCount = resultSet.GetFieldsNum();
for(int i = 0 ; i<queryResult.Count;i++){
Console.Write(queryResult[i].ToString());
Console.Write("\t");
if((i+1)%fieldsCount == 0)
{
Console.WriteLine("");
}
}
if(insertData.Count == queryResult.Count)
{
Console.WriteLine("insert data count = retrieve data count");
for(int i = 0 ; i<queryResult.Count;i++)
{
if(!queryResult[i].Equals(insertData[i]))
{
Console.Write("[Unequal Data]");
Console.WriteLine("InsertData:{0},QueryData:{1}",queryResult[i],insertData[i]);
}
}
}
}
static void TestNtable(IntPtr conn,string tableName)
{
var colData = new List<Object>{1637064040000,1,"涛思数据","保利广场","Beijing","China",
1637064041000,2,"涛思数据taosdata","保利广场baoli","Beijing","China",
1637064042000,3,"TDegnine涛思数据","time广场","NewYork","US",
1637064043000,4,"4涛思数据","4广场南部","London","UK",
1637064044000,5,"涛思数据5","!广场路中部123","Tokyo","JP",
1637064045000,6,"taos涛思数据6","青年广场123号!","Washin","DC",
1637064046000,7,"7涛思数据taos","asdf#壮年广场%#endregion","NewYork","US",
1637064047000,8,"8&涛思数据taos","incluse阿斯顿发","NewYork","US",
1637064048000,9,"&涛思数据taos9","123黑化肥werq会挥……&¥%发!afsdfa","NewYork","US",
};
String dropTb = "drop table if exists " + tableName;
String createTb = $"create table if not exists {tableName} (ts timestamp,v4 int,blob nchar(200),location nchar(200),city binary(100),coutry nchar(200));";
String insertSql = UtilsTools.ConstructInsertSql(tableName, "", colData, null, 9);
String selectSql = "select * from " + tableName;
UtilsTools.ExecuteUpdate(conn, dropTb);
UtilsTools.ExecuteUpdate(conn, createTb);
UtilsTools.ExecuteUpdate(conn, insertSql);
IntPtr res = UtilsTools.ExecuteQuery(conn, selectSql);
ResultSet resultSet = new ResultSet(res);
List<Object> queryResult = resultSet.GetResultData();
int fieldsCount = resultSet.GetFieldsNum();
//display
for(int i = 0 ; i<queryResult.Count;i++){
Console.Write(queryResult[i].ToString());
Console.Write("\t");
if((i+1)%fieldsCount == 0)
{
Console.WriteLine("");
}
}
if(colData.Count == queryResult.Count)
{
Console.WriteLine("insert data count = retrieve data count");
for(int i = 0 ; i<queryResult.Count;i++)
{
if(!queryResult[i].Equals(colData[i]))
{
Console.Write("[Unequal Data]");
Console.WriteLine("InsertData:{0},QueryData:{1}",queryResult[i],colData[i]);
}
}
}
}
}
}
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace TDengineDriver
{
public enum TDengineDataType
{
TSDB_DATA_TYPE_NULL = 0, // 1 bytes
TSDB_DATA_TYPE_BOOL = 1, // 1 bytes
TSDB_DATA_TYPE_TINYINT = 2, // 1 bytes
TSDB_DATA_TYPE_SMALLINT = 3, // 2 bytes
TSDB_DATA_TYPE_INT = 4, // 4 bytes
TSDB_DATA_TYPE_BIGINT = 5, // 8 bytes
TSDB_DATA_TYPE_FLOAT = 6, // 4 bytes
TSDB_DATA_TYPE_DOUBLE = 7, // 8 bytes
TSDB_DATA_TYPE_BINARY = 8, // string
TSDB_DATA_TYPE_TIMESTAMP = 9,// 8 bytes
TSDB_DATA_TYPE_NCHAR = 10, // unicode string
TSDB_DATA_TYPE_UTINYINT = 11,// 1 byte
TSDB_DATA_TYPE_USMALLINT = 12,// 2 bytes
TSDB_DATA_TYPE_UINT = 13, // 4 bytes
TSDB_DATA_TYPE_UBIGINT = 14, // 8 bytes
TSDB_DATA_TYPE_JSONTAG = 15 //4096 bytes
}
public enum TDengineInitOption
{
TSDB_OPTION_LOCALE = 0,
TSDB_OPTION_CHARSET = 1,
TSDB_OPTION_TIMEZONE = 2,
TDDB_OPTION_CONFIGDIR = 3,
TDDB_OPTION_SHELL_ACTIVITY_TIMER = 4
}
enum TaosField
{
STRUCT_SIZE = 68,
NAME_LENGTH = 65,
TYPE_OFFSET = 65,
BYTES_OFFSET = 66,
}
public class TDengineMeta
{
public string name;
public short size;
public byte type;
public string TypeName()
{
switch ((TDengineDataType)type)
{
case TDengineDataType.TSDB_DATA_TYPE_BOOL:
return "BOOL";
case TDengineDataType.TSDB_DATA_TYPE_TINYINT:
return "TINYINT";
case TDengineDataType.TSDB_DATA_TYPE_SMALLINT:
return "SMALLINT";
case TDengineDataType.TSDB_DATA_TYPE_INT:
return "INT";
case TDengineDataType.TSDB_DATA_TYPE_BIGINT:
return "BIGINT";
case TDengineDataType.TSDB_DATA_TYPE_UTINYINT:
return "TINYINT UNSIGNED";
case TDengineDataType.TSDB_DATA_TYPE_USMALLINT:
return "SMALLINT UNSIGNED";
case TDengineDataType.TSDB_DATA_TYPE_UINT:
return "INT UNSIGNED";
case TDengineDataType.TSDB_DATA_TYPE_UBIGINT:
return "BIGINT UNSIGNED";
case TDengineDataType.TSDB_DATA_TYPE_FLOAT:
return "FLOAT";
case TDengineDataType.TSDB_DATA_TYPE_DOUBLE:
return "DOUBLE";
case TDengineDataType.TSDB_DATA_TYPE_BINARY:
return "BINARY";
case TDengineDataType.TSDB_DATA_TYPE_TIMESTAMP:
return "TIMESTAMP";
case TDengineDataType.TSDB_DATA_TYPE_NCHAR:
return "NCHAR";
case TDengineDataType.TSDB_DATA_TYPE_JSONTAG:
return "JSON";
default:
return "undefine";
}
}
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct TAOS_BIND
{
// column type
public int buffer_type;
// one column value
public IntPtr buffer;
// unused
public Int32 buffer_length;
// actual value length in buffer
public IntPtr length;
// indicates the column value is null or not
public IntPtr is_null;
// unused
public int is_unsigned;
// unused
public IntPtr error;
public Int64 u;
public uint allocated;
}
[StructLayout(LayoutKind.Sequential)]
public struct TAOS_MULTI_BIND
{
// column type
public int buffer_type;
// array, one or more lines column value
public IntPtr buffer;
//length of element in TAOS_MULTI_BIND.buffer (for binary and nchar it is the longest element's length)
public ulong buffer_length;
//array, actual data length for each value
public IntPtr length;
//array, indicates each column value is null or not
public IntPtr is_null;
// line number, or the values number in buffer
public int num;
}
public class TDengine
{
public const int TSDB_CODE_SUCCESS = 0;
[DllImport("taos", EntryPoint = "taos_init", CallingConvention = CallingConvention.Cdecl)]
static extern public void Init();
[DllImport("taos", EntryPoint = "taos_cleanup", CallingConvention = CallingConvention.Cdecl)]
static extern public void Cleanup();
[DllImport("taos", EntryPoint = "taos_options", CallingConvention = CallingConvention.Cdecl)]
static extern public void Options(int option, string value);
[DllImport("taos", EntryPoint = "taos_connect", CallingConvention = CallingConvention.Cdecl)]
static extern public IntPtr Connect(string ip, string user, string password, string db, short port);
[DllImport("taos", EntryPoint = "taos_errstr", CallingConvention = CallingConvention.Cdecl)]
static extern private IntPtr taos_errstr(IntPtr res);
static public string Error(IntPtr res)
{
IntPtr errPtr = taos_errstr(res);
return Marshal.PtrToStringAnsi(errPtr);
}
[DllImport("taos", EntryPoint = "taos_errno", CallingConvention = CallingConvention.Cdecl)]
static extern public int ErrorNo(IntPtr res);
[DllImport("taos", EntryPoint = "taos_query", CallingConvention = CallingConvention.Cdecl)]
// static extern public IntPtr Query(IntPtr conn, string sqlstr);
static extern private IntPtr Query(IntPtr conn, IntPtr byteArr);
static public IntPtr Query(IntPtr conn,string command)
{
IntPtr res = IntPtr.Zero;
IntPtr commandBuffer = Marshal.StringToCoTaskMemUTF8(command);
res = Query(conn,commandBuffer);
return res;
}
[DllImport("taos", EntryPoint = "taos_affected_rows", CallingConvention = CallingConvention.Cdecl)]
static extern public int AffectRows(IntPtr res);
[DllImport("taos", EntryPoint = "taos_field_count", CallingConvention = CallingConvention.Cdecl)]
static extern public int FieldCount(IntPtr res);
[DllImport("taos", EntryPoint = "taos_fetch_fields", CallingConvention = CallingConvention.Cdecl)]
static extern private IntPtr taos_fetch_fields(IntPtr res);
static public List<TDengineMeta> FetchFields(IntPtr res)
{
// const int fieldSize = 68;
List<TDengineMeta> metas = new List<TDengineMeta>();
if (res == IntPtr.Zero)
{
return metas;
}
int fieldCount = FieldCount(res);
IntPtr fieldsPtr = taos_fetch_fields(res);
for (int i = 0; i < fieldCount; ++i)
{
int offset = i * (int)TaosField.STRUCT_SIZE;
TDengineMeta meta = new TDengineMeta();
meta.name = Marshal.PtrToStringAnsi(fieldsPtr + offset);
meta.type = Marshal.ReadByte(fieldsPtr + offset + (int)TaosField.TYPE_OFFSET);
meta.size = Marshal.ReadInt16(fieldsPtr + offset + (int)TaosField.BYTES_OFFSET);
metas.Add(meta);
}
return metas;
}
[DllImport("taos", EntryPoint = "taos_fetch_row", CallingConvention = CallingConvention.Cdecl)]
static extern public IntPtr FetchRows(IntPtr res);
[DllImport("taos", EntryPoint = "taos_free_result", CallingConvention = CallingConvention.Cdecl)]
static extern public IntPtr FreeResult(IntPtr res);
[DllImport("taos", EntryPoint = "taos_close", CallingConvention = CallingConvention.Cdecl)]
static extern public int Close(IntPtr taos);
//get precision of restultset
[DllImport("taos", EntryPoint = "taos_result_precision", CallingConvention = CallingConvention.Cdecl)]
static extern public int ResultPrecision(IntPtr taos);
//stmt APIs:
/// <summary>
/// init a TAOS_STMT object for later use.
/// </summary>
/// <param name="taos">a valid taos connection</param>
/// <returns>
/// Not NULL returned for success, NULL for failure. And it should be freed with taos_stmt_close.
/// </returns>
[DllImport("taos", EntryPoint = "taos_stmt_init", CallingConvention = CallingConvention.Cdecl)]
static extern public IntPtr StmtInit(IntPtr taos);
/// <summary>
/// prepare a sql statement,'sql' should be a valid INSERT/SELECT statement.
/// </summary>
/// <param name="stmt">could be the value returned by 'StmtInit', that may be a valid object or NULL.</param>
/// <param name="sql">sql string,used to bind parameters with</param>
/// <param name="length">no used</param>
/// <returns>0 for success, non-zero for failure.</returns>
[DllImport("taos", EntryPoint = "taos_stmt_prepare", CallingConvention = CallingConvention.Cdecl)]
static extern public int StmtPrepare(IntPtr stmt, string sql);
/// <summary>
/// For INSERT only. Used to bind table name as a parmeter for the input stmt object.
/// </summary>
/// <param name="stmt">could be the value returned by 'StmtInit', that may be a valid object or NULL.</param>
/// <param name="name">table name you want to bind</param>
/// <returns>0 for success, non-zero for failure.</returns>
[DllImport("taos", EntryPoint = "taos_stmt_set_tbname", CallingConvention = CallingConvention.Cdecl)]
static extern public int StmtSetTbname(IntPtr stmt, string name);
/// <summary>
/// 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.
/// </summary>
/// <param name="stmt">could be the value returned by 'StmtInit', that may be a valid object or NULL.</param>
/// <param name="name">table name which is belong to an stable</param>
/// <returns>0 for success, non-zero for failure.</returns>
[DllImport("taos", EntryPoint = "taos_stmt_set_sub_tbname", CallingConvention = CallingConvention.Cdecl)]
static extern public int StmtSetSubTbname(IntPtr stmt, string name);
/// <summary>
/// For INSERT only.
/// set a table name for binding table name as parameter and tag values for all tag parameters.
/// </summary>
/// <param name="stmt">could be the value returned by 'StmtInit', that may be a valid object or NULL.</param>
/// <param name="name">use to set table name</param>
/// <param name="tags">
/// is an array contains all tag values,each item in the array represents a tag column's value.
/// the item number and sequence should keep consistence with that in stable tag definition.
/// </param>
/// <returns>0 for success, non-zero for failure.</returns>
[DllImport("taos", EntryPoint = "taos_stmt_set_tbname_tags", CallingConvention = CallingConvention.Cdecl)]
static extern public int StmtSetTbnameTags(IntPtr stmt, string name, TAOS_BIND[] tags);
/// <summary>
/// For both INSERT and SELECT.
/// bind a whole line data.
/// The usage of structure TAOS_BIND is the same with MYSQL_BIND in MySQL.
/// </summary>
/// <param name="stmt">could be the value returned by 'StmtInit', that may be a valid object or NULL.</param>
/// <param name="bind">
/// points to an array contains the whole line data.
/// the item number and sequence should keep consistence with columns in sql statement.
/// </param>
/// <returns>0 for success, non-zero for failure.</returns>
[DllImport("taos", EntryPoint = "taos_stmt_bind_param", CallingConvention = CallingConvention.Cdecl, SetLastError = true)]
static extern public int StmtBindParam(IntPtr stmt, TAOS_BIND[] bind);
/// <summary>
/// bind a single column's data, INTERNAL used and for INSERT only.
/// </summary>
/// <param name="stmt">could be the value returned by 'StmtInit', that may be a valid object or NULL.</param>
/// <param name="bind">points to a column's data which could be the one or more lines. </param>
/// <param name="colIdx">the column's index in prepared sql statement, it starts from 0.</param>
/// <returns>0 for success, non-zero for failure.</returns>
[DllImport("taos", EntryPoint = "taos_stmt_bind_single_param_batch", CallingConvention = CallingConvention.Cdecl)]
static extern public int StmtBindSingleParamBatch(IntPtr stmt, ref TAOS_MULTI_BIND bind, int colIdx);
/// <summary>
/// for INSERT only
/// bind one or multiple lines data. The parameter 'bind'
/// </summary>
/// <param name="stmt">could be the value returned by 'StmtInit', that may be a valid object or NULL.</param>
/// <param name="bind">
/// points to an array contains one or more lines data.Each item in array represents a column's value(s),
/// the item number and sequence should keep consistence with columns in sql statement.
/// </param>
/// <returns>0 for success, non-zero for failure.</returns>
[DllImport("taos", EntryPoint = "taos_stmt_bind_param_batch", CallingConvention = CallingConvention.Cdecl)]
static extern public int StmtBindParamBatch(IntPtr stmt, [In, Out] TAOS_MULTI_BIND[] bind);
/// <summary>
/// For INSERT only.
/// add all current bound parameters to batch process. Must be called after each call to
/// StmtBindParam/StmtBindSingleParamBatch, or all columns binds for one or more lines
/// with StmtBindSingleParamBatch. User application can call any bind parameter
/// API again to bind more data lines after calling to this API.
/// </summary>
/// <param name="stmt">could be the value returned by 'StmtInit', that may be a valid object or NULL.</param>
/// <returns>0 for success, non-zero for failure.</returns>
[DllImport("taos", EntryPoint = "taos_stmt_add_batch", CallingConvention = CallingConvention.Cdecl)]
static extern public int StmtAddBatch(IntPtr stmt);
/// <summary>
/// actually execute the INSERT/SELECT sql statement.
/// User application can continue to bind new data after calling to this API.
/// </summary>
/// <param name="stmt">could be the value returned by 'StmtInit', that may be a valid object or NULL.</param>
/// <returns></returns>
[DllImport("taos", EntryPoint = "taos_stmt_execute", CallingConvention = CallingConvention.Cdecl)]
static extern public int StmtExecute(IntPtr stmt);
/// <summary>
/// For SELECT only,getting the query result. User application should free it with API 'FreeResult' at the end.
/// </summary>
/// <param name="stmt">could be the value returned by 'StmtInit', that may be a valid object or NULL.</param>
/// <returns>Not NULL for success, NULL for failure.</returns>
[DllImport("taos", EntryPoint = "taos_stmt_use_result", CallingConvention = CallingConvention.Cdecl)]
static extern public IntPtr StmtUseResult(IntPtr stmt);
/// <summary>
/// close STMT object and free resources.
/// </summary>
/// <param name="stmt">could be the value returned by 'StmtInit', that may be a valid object or NULL.</param>
/// <returns>0 for success, non-zero for failure.</returns>
[DllImport("taos", EntryPoint = "taos_stmt_close", CallingConvention = CallingConvention.Cdecl)]
static extern public int StmtClose(IntPtr stmt);
[DllImport("taos", EntryPoint = "taos_load_table_info", CallingConvention = CallingConvention.Cdecl)]
/// <summary>
/// user application must call this API to load all tables meta,
/// </summary>
/// <param name="taos">taos connection</param>
/// <param name="tableList">tablelist</param>
/// <returns></returns>
static extern private int LoadTableInfoDll(IntPtr taos, string tableList);
/// <summary>
/// user application call this API to load all tables meta,this method call the native
/// method LoadTableInfoDll.
/// this method must be called before StmtSetSubTbname(IntPtr stmt, string name);
/// </summary>
/// <param name="taos">taos connection</param>
/// <param name="tableList">tables need to load meta info are form in an array</param>
/// <returns></returns>
static public int LoadTableInfo(IntPtr taos, string[] tableList)
{
string listStr = string.Join(",", tableList);
return LoadTableInfoDll(taos, listStr);
}
/// <summary>
/// get detail error message when got failure for any stmt API call. If not failure, the result
/// returned in this API is unknown.
/// </summary>
/// <param name="stmt">could be the value returned by 'StmtInit', that may be a valid object or NULL.</param>
/// <returns>piont the error message</returns>
[DllImport("taos", EntryPoint = "taos_stmt_errstr", CallingConvention = CallingConvention.Cdecl)]
static extern private IntPtr StmtErrPtr(IntPtr stmt);
/// <summary>
/// get detail error message when got failure for any stmt API call. If not failure, the result
/// returned in this API is unknown.
/// </summary>
/// <param name="stmt">could be the value returned by 'StmtInit', that may be a valid object or NULL.</param>
/// <returns>error string</returns>
static public string StmtErrorStr(IntPtr stmt)
{
IntPtr stmtErrPrt = StmtErrPtr(stmt);
return Marshal.PtrToStringAnsi(stmtErrPrt);
}
[DllImport("taos", EntryPoint = "taos_fetch_lengths", CallingConvention = CallingConvention.Cdecl)]
static extern public IntPtr FetchLengths(IntPtr taos);
}
}
<Project Sdk="Microsoft.NET.Sdk">
<!-- <ItemGroup>
<ProjectReference Include="..\src\TDengineDriver\TDengineDriver.csproj" />
</ItemGroup> -->
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
</Project>
using System;
using Utils;
namespace Cases
{
class Program
{
static void Main(string[] args)
{
IntPtr conn = IntPtr.Zero;
Console.WriteLine("===================JsonTagTest====================");
conn = conn = UtilsTools.TDConnection("127.0.0.1", "root", "taosdata", "", 0);
UtilsTools.ExecuteUpdate(conn, "create database if not exists csharp_sample keep 3650");
UtilsTools.ExecuteUpdate(conn, "use csharp");
JsonTagSample jsonTagSample = new JsonTagSample();
jsonTagSample.Test(conn);
}
}
public class JsonTagSample
{
public void Test(IntPtr conn)
{
Console.WriteLine("STEP 1 prepare data & validate json string===== ");
UtilsTools.ExecuteQuery(conn, "create table if not exists jsons1(ts timestamp, dataInt int, dataBool bool, dataStr nchar(50), dataStrBin binary(150)) tags(jtag json)");
UtilsTools.ExecuteQuery(conn, "insert into jsons1_1 using jsons1 tags('{\"tag1\":\"fff\",\"tag2\":5, \"tag3\":true}') values(1591060618000, 1, false, 'json1', '涛思数据') (1591060608000, 23, true, '涛思数据', 'json')");
UtilsTools.ExecuteQuery(conn, "insert into jsons1_2 using jsons1 tags('{\"tag1\":5,\"tag2\":\"beijing\"}') values (1591060628000, 2, true, 'json2', 'sss')");
UtilsTools.ExecuteQuery(conn, "insert into jsons1_3 using jsons1 tags('{\"tag1\":false,\"tag2\":\"beijing\"}') values (1591060668000, 3, false, 'json3', 'efwe')");
UtilsTools.ExecuteQuery(conn, "insert into jsons1_4 using jsons1 tags('{\"tag1\":null,\"tag2\":\"shanghai\",\"tag3\":\"hello\"}') values (1591060728000, 4, true, 'json4', '323sd')");
UtilsTools.ExecuteQuery(conn, "insert into jsons1_5 using jsons1 tags('{\"tag1\":1.232, \"tag2\":null}') values(1591060928000, 1, false, '涛思数据', 'ewe')");
UtilsTools.ExecuteQuery(conn, "insert into jsons1_6 using jsons1 tags('{\"tag1\":11,\"tag2\":\"\",\"tag2\":null}') values(1591061628000, 11, false, '涛思数据','')");
UtilsTools.ExecuteQuery(conn, "insert into jsons1_7 using jsons1 tags('{\"tag1\":\"涛思数据\",\"tag2\":\"\",\"tag3\":null}') values(1591062628000, 2, NULL, '涛思数据', 'dws')");
Console.WriteLine("");
Console.WriteLine("test duplicate key using the first one. elimate empty key======== ");
UtilsTools.ExecuteQuery(conn, "CREATE TABLE if not exists jsons1_8 using jsons1 tags('{\"tag1\":null, \"tag1\":true, \"tag1\":45, \"1tag$\":2, \" \":90}')");
Console.WriteLine("");
Console.WriteLine("test empty json string, save as jtag is NULL========== ");
UtilsTools.ExecuteQuery(conn, "insert into jsons1_9 using jsons1 tags('\t') values (1591062328000, 24, NULL, '涛思数据', '2sdw')");
UtilsTools.ExecuteQuery(conn, "CREATE TABLE if not exists jsons1_10 using jsons1 tags('')");
UtilsTools.ExecuteQuery(conn, "CREATE TABLE if not exists jsons1_11 using jsons1 tags(' ')");
UtilsTools.ExecuteQuery(conn, "CREATE TABLE if not exists jsons1_12 using jsons1 tags('{}')");
UtilsTools.ExecuteQuery(conn, "CREATE TABLE if not exists jsons1_13 using jsons1 tags('null')");
Console.WriteLine("");
Console.WriteLine("test invalidate json==================== ");
UtilsTools.ExecuteErrorQuery(conn, "CREATE TABLE if not exists jsons1_14 using jsons1 tags('\"efwewf\"')");
UtilsTools.ExecuteErrorQuery(conn, "CREATE TABLE if not exists jsons1_14 using jsons1 tags('3333')");
UtilsTools.ExecuteErrorQuery(conn, "CREATE TABLE if not exists jsons1_14 using jsons1 tags('33.33')");
UtilsTools.ExecuteErrorQuery(conn, "CREATE TABLE if not exists jsons1_14 using jsons1 tags('false')");
UtilsTools.ExecuteErrorQuery(conn, "CREATE TABLE if not exists jsons1_14 using jsons1 tags('[1,true]')");
UtilsTools.ExecuteErrorQuery(conn, "CREATE TABLE if not exists jsons1_14 using jsons1 tags('{222}')");
UtilsTools.ExecuteErrorQuery(conn, "CREATE TABLE if not exists jsons1_14 using jsons1 tags('{\"fe\"}')");
Console.WriteLine("");
Console.WriteLine("test invalidate json key, key must can be printed assic char========== ");
UtilsTools.ExecuteErrorQuery(conn, "CREATE TABLE if not exists jsons1_14 using jsons1 tags('{\"tag1\":[1,true]}')");
UtilsTools.ExecuteErrorQuery(conn, "CREATE TABLE if not exists jsons1_14 using jsons1 tags('{\"tag1\":{}}')");
UtilsTools.ExecuteErrorQuery(conn, "CREATE TABLE if not exists jsons1_14 using jsons1 tags('{\"。loc\":\"fff\"}')");
UtilsTools.ExecuteErrorQuery(conn, "CREATE TABLE if not exists jsons1_14 using jsons1 tags('{\"\":\"fff\"}')");
UtilsTools.ExecuteErrorQuery(conn, "CREATE TABLE if not exists jsons1_14 using jsons1 tags('{\"\t\":\"fff\"}')");
UtilsTools.ExecuteErrorQuery(conn, "CREATE TABLE if not exists jsons1_14 using jsons1 tags('{\"试试\":\"fff\"}')");
Console.WriteLine("");
Console.WriteLine("STEP 2 alter table json tag============");
UtilsTools.ExecuteErrorQuery(conn, "ALTER STABLE jsons1 add tag tag2 nchar(20)");
UtilsTools.ExecuteErrorQuery(conn, "ALTER STABLE jsons1 drop tag jtag");
UtilsTools.ExecuteErrorQuery(conn, "ALTER TABLE jsons1_1 SET TAG jtag=4");
UtilsTools.ExecuteQuery(conn, "ALTER TABLE jsons1_1 SET TAG jtag='{\"tag1\":\"femail\",\"tag2\":35,\"tag3\":true}'");
Console.WriteLine("");
Console.WriteLine("STEP 3 query table============");
Console.WriteLine("test error syntax============");
UtilsTools.ExecuteErrorQuery(conn, "select * from jsons1 where jtag->tag1='beijing'");
UtilsTools.ExecuteErrorQuery(conn, "select * from jsons1 where jtag->'location'");
UtilsTools.ExecuteErrorQuery(conn, "select * from jsons1 where jtag->''");
UtilsTools.ExecuteErrorQuery(conn, "select * from jsons1 where jtag->''=9");
UtilsTools.ExecuteErrorQuery(conn, "select -> from jsons1");
UtilsTools.ExecuteErrorQuery(conn, "select * from jsons1 where contains");
UtilsTools.ExecuteErrorQuery(conn, "select * from jsons1 where jtag->");
UtilsTools.ExecuteErrorQuery(conn, "select jtag->location from jsons1");
UtilsTools.ExecuteErrorQuery(conn, "select jtag contains location from jsons1");
UtilsTools.ExecuteErrorQuery(conn, "select * from jsons1 where jtag contains location");
UtilsTools.ExecuteErrorQuery(conn, "select * from jsons1 where jtag contains''");
UtilsTools.ExecuteErrorQuery(conn, "select * from jsons1 where jtag contains 'location'='beijing'");
Console.WriteLine("");
Console.WriteLine("test select normal column===========");
IntPtr res = IntPtr.Zero;
res = UtilsTools.ExecuteQuery(conn, "select dataint from jsons1");
UtilsTools.DisplayRes(res);
Console.WriteLine("test select json tag===========");
res = UtilsTools.ExecuteQuery(conn, "select * from jsons1");
UtilsTools.DisplayRes(res);
res = UtilsTools.ExecuteQuery(conn, "select jtag from jsons1");
UtilsTools.DisplayRes(res);
res = UtilsTools.ExecuteQuery(conn, "select jtag from jsons1 where jtag is null");
UtilsTools.DisplayRes(res);
res = UtilsTools.ExecuteQuery(conn, "select jtag from jsons1 where jtag is not null");
UtilsTools.DisplayRes(res);
Console.WriteLine("test #line 41===========");
res = UtilsTools.ExecuteQuery(conn, "select jtag from jsons1_8");
UtilsTools.DisplayRes(res);
Console.WriteLine("test #line 72===========");
res = UtilsTools.ExecuteQuery(conn, "select jtag from jsons1_1");
UtilsTools.DisplayRes(res);
Console.WriteLine("test jtag is NULL===========");
res = UtilsTools.ExecuteQuery(conn, "select jtag from jsons1_9");
UtilsTools.DisplayRes(res);
Console.WriteLine("test select json tag->'key', value is string ===========");
res = UtilsTools.ExecuteQuery(conn, "select jtag->'tag1' from jsons1_1");
UtilsTools.DisplayRes(res);
res = UtilsTools.ExecuteQuery(conn, "select jtag->'tag2' from jsons1_6");
UtilsTools.DisplayRes(res);
Console.WriteLine("test select json tag->'key', value is int===========");
res = UtilsTools.ExecuteQuery(conn, "select jtag->'tag2' from jsons1_1");
UtilsTools.DisplayRes(res);
Console.WriteLine("test select json tag->'key', value is bool===========");
res = UtilsTools.ExecuteQuery(conn, "select jtag->'tag3' from jsons1_1");
UtilsTools.DisplayRes(res);
Console.WriteLine("test select json tag->'key', value is null===========");
res = UtilsTools.ExecuteQuery(conn, "select jtag->'tag1' from jsons1_4");
UtilsTools.DisplayRes(res);
Console.WriteLine("test select json tag->'key', value is double===========");
res = UtilsTools.ExecuteQuery(conn, "select jtag->'tag1' from jsons1_5");
UtilsTools.DisplayRes(res);
Console.WriteLine("test select json tag->'key', key is not exist===========");
res = UtilsTools.ExecuteQuery(conn, "select jtag->'tag10' from jsons1_4");
UtilsTools.DisplayRes(res);
res = UtilsTools.ExecuteQuery(conn, "select jtag->'tag1' from jsons1");
UtilsTools.DisplayRes(res);
Console.WriteLine("test header name===========");
res = UtilsTools.ExecuteQuery(conn, "select jtag->'tag1' from jsons1");
UtilsTools.DisplayRes(res);
Console.WriteLine("test where with json tag===========");
UtilsTools.ExecuteErrorQuery(conn, "select * from jsons1_1 where jtag is not null");
UtilsTools.ExecuteErrorQuery(conn, "select * from jsons1 where jtag='{\"tag1\":11,\"tag2\":\"\"}'");
UtilsTools.ExecuteErrorQuery(conn, "select * from jsons1 where jtag->'tag1'={}");
Console.WriteLine("where json value is string===========");
res = UtilsTools.ExecuteQuery(conn, "select * from jsons1 where jtag->'tag2'='beijing'");
UtilsTools.DisplayRes(res);
res = UtilsTools.ExecuteQuery(conn, "select dataint,tbname,jtag->'tag1',jtag from jsons1 where jtag->'tag2'='beijing'");
UtilsTools.DisplayRes(res);
res = UtilsTools.ExecuteQuery(conn, "select * from jsons1 where jtag->'tag1'='beijing'");
UtilsTools.DisplayRes(res);
res = UtilsTools.ExecuteQuery(conn, "select * from jsons1 where jtag->'tag1'='涛思数据'");
UtilsTools.DisplayRes(res);
res = UtilsTools.ExecuteQuery(conn, "select * from jsons1 where jtag->'tag2'>'beijing'");
UtilsTools.DisplayRes(res);
res = UtilsTools.ExecuteQuery(conn, "select * from jsons1 where jtag->'tag2'>='beijing'");
UtilsTools.DisplayRes(res);
res = UtilsTools.ExecuteQuery(conn, "select * from jsons1 where jtag->'tag2'<'beijing'");
UtilsTools.DisplayRes(res);
res = UtilsTools.ExecuteQuery(conn, "select * from jsons1 where jtag->'tag2'<='beijing'");
UtilsTools.DisplayRes(res);
res = UtilsTools.ExecuteQuery(conn, "select * from jsons1 where jtag->'tag2'!='beijing'");
UtilsTools.DisplayRes(res);
res = UtilsTools.ExecuteQuery(conn, "select * from jsons1 where jtag->'tag2'=''");
UtilsTools.DisplayRes(res);
Console.WriteLine("where json value is int===========");
res = UtilsTools.ExecuteQuery(conn, "select * from jsons1 where jtag->'tag1'=5");
UtilsTools.DisplayRes(res);
res = UtilsTools.ExecuteQuery(conn, "select * from jsons1 where jtag->'tag1'=10");
UtilsTools.DisplayRes(res);
res = UtilsTools.ExecuteQuery(conn, "select * from jsons1 where jtag->'tag1'<54");
UtilsTools.DisplayRes(res);
res = UtilsTools.ExecuteQuery(conn, "select * from jsons1 where jtag->'tag1'<=11");
UtilsTools.DisplayRes(res);
res = UtilsTools.ExecuteQuery(conn, "select * from jsons1 where jtag->'tag1'>4");
UtilsTools.DisplayRes(res);
res = UtilsTools.ExecuteQuery(conn, "select * from jsons1 where jtag->'tag1'>=5");
UtilsTools.DisplayRes(res);
res = UtilsTools.ExecuteQuery(conn, "select * from jsons1 where jtag->'tag1'!=5");
UtilsTools.DisplayRes(res);
res = UtilsTools.ExecuteQuery(conn, "select * from jsons1 where jtag->'tag1'!=55");
UtilsTools.DisplayRes(res);
Console.WriteLine("where json value is double===========");
res = UtilsTools.ExecuteQuery(conn, "select * from jsons1 where jtag->'tag1'=1.232");
UtilsTools.DisplayRes(res);
res = UtilsTools.ExecuteQuery(conn, "select * from jsons1 where jtag->'tag1'<1.232");
UtilsTools.DisplayRes(res);
res = UtilsTools.ExecuteQuery(conn, "select * from jsons1 where jtag->'tag1'<=1.232");
UtilsTools.DisplayRes(res);
res = UtilsTools.ExecuteQuery(conn, "select * from jsons1 where jtag->'tag1'>1.23");
UtilsTools.DisplayRes(res);
res = UtilsTools.ExecuteQuery(conn, "select * from jsons1 where jtag->'tag1'>=1.232");
UtilsTools.DisplayRes(res);
res = UtilsTools.ExecuteQuery(conn, "select * from jsons1 where jtag->'tag1'!=1.232");
UtilsTools.DisplayRes(res);
res = UtilsTools.ExecuteQuery(conn, "select * from jsons1 where jtag->'tag1'!=3.232");
UtilsTools.DisplayRes(res);
UtilsTools.ExecuteErrorQuery(conn, "select * from jsons1 where jtag->'tag1'/0=3");
UtilsTools.ExecuteErrorQuery(conn, "select * from jsons1 where jtag->'tag1'/5=1");
Console.WriteLine("where json value is bool===========");
res = UtilsTools.ExecuteQuery(conn, "select * from jsons1 where jtag->'tag1'=true");
UtilsTools.DisplayRes(res);
res = UtilsTools.ExecuteQuery(conn, "select * from jsons1 where jtag->'tag1'=false");
UtilsTools.DisplayRes(res);
res = UtilsTools.ExecuteQuery(conn, "select * from jsons1 where jtag->'tag1'!=false");
UtilsTools.DisplayRes(res);
UtilsTools.ExecuteErrorQuery(conn, "select * from jsons1 where jtag->'tag1'>false");
Console.WriteLine("where json value is null===========");
Console.WriteLine("only json suport =null. This synatx will change later.===========");
res = UtilsTools.ExecuteQuery(conn, "select * from jsons1 where jtag->'tag1'=null");
UtilsTools.DisplayRes(res);
Console.WriteLine("where json is null===========");
res = UtilsTools.ExecuteQuery(conn, "select * from jsons1 where jtag is null");
UtilsTools.DisplayRes(res);
res = UtilsTools.ExecuteQuery(conn, "select * from jsons1 where jtag is not null");
UtilsTools.DisplayRes(res);
Console.WriteLine("where json key is null===========");
res = UtilsTools.ExecuteQuery(conn, "select * from jsons1 where jtag->'tag_no_exist'=3");
UtilsTools.DisplayRes(res);
Console.WriteLine("where json value is not exist===========");
res = UtilsTools.ExecuteQuery(conn, "select * from jsons1 where jtag->'tag1' is null");
UtilsTools.DisplayRes(res);
res = UtilsTools.ExecuteQuery(conn, "select * from jsons1 where jtag->'tag4' is null");
UtilsTools.DisplayRes(res);
res = UtilsTools.ExecuteQuery(conn, "select * from jsons1 where jtag->'tag3' is not null");
UtilsTools.DisplayRes(res);
Console.WriteLine("test contains===========");
res = UtilsTools.ExecuteQuery(conn, "select * from jsons1 where jtag contains 'tag1'");
UtilsTools.DisplayRes(res);
res = UtilsTools.ExecuteQuery(conn, "select * from jsons1 where jtag contains 'tag3'");
UtilsTools.DisplayRes(res);
res = UtilsTools.ExecuteQuery(conn, "select * from jsons1 where jtag contains 'tag_no_exist'");
UtilsTools.DisplayRes(res);
Console.WriteLine("test json tag in where condition with and/or===========");
res = UtilsTools.ExecuteQuery(conn, "select * from jsons1 where jtag->'tag1'=false and jtag->'tag2'='beijing'");
UtilsTools.DisplayRes(res);
res = UtilsTools.ExecuteQuery(conn, "select * from jsons1 where jtag->'tag1'=false or jtag->'tag2'='beijing'");
UtilsTools.DisplayRes(res);
res = UtilsTools.ExecuteQuery(conn, "select * from jsons1 where jtag->'tag1'=false and jtag->'tag2'='shanghai'");
UtilsTools.DisplayRes(res);
res = UtilsTools.ExecuteQuery(conn, "select * from jsons1 where jtag->'tag1'=false and jtag->'tag2'='shanghai'");
UtilsTools.DisplayRes(res);
res = UtilsTools.ExecuteQuery(conn, "select * from jsons1 where jtag->'tag1'=13 or jtag->'tag2'>35");
UtilsTools.DisplayRes(res);
res = UtilsTools.ExecuteQuery(conn, "select * from jsons1 where jtag->'tag1'=13 or jtag->'tag2'>35");
UtilsTools.DisplayRes(res);
res = UtilsTools.ExecuteQuery(conn, "select * from jsons1 where jtag->'tag1' is not null and jtag contains 'tag3'");
UtilsTools.DisplayRes(res);
res = UtilsTools.ExecuteQuery(conn, "select * from jsons1 where jtag->'tag1'='femail' and jtag contains 'tag3'");
UtilsTools.DisplayRes(res);
Console.WriteLine("test with tbname/normal column===========");
res = UtilsTools.ExecuteQuery(conn, "select * from jsons1 where tbname = 'jsons1_1'");
UtilsTools.DisplayRes(res);
res = UtilsTools.ExecuteQuery(conn, "select * from jsons1 where tbname = 'jsons1_1' and jtag contains 'tag3'");
UtilsTools.DisplayRes(res);
res = UtilsTools.ExecuteQuery(conn, "select * from jsons1 where tbname = 'jsons1_1' and jtag contains 'tag3' and dataint=3");
UtilsTools.DisplayRes(res);
res = UtilsTools.ExecuteQuery(conn, "select * from jsons1 where tbname = 'jsons1_1' and jtag contains 'tag3' and dataint=23");
UtilsTools.DisplayRes(res);
Console.WriteLine("test where condition like===========");
res = UtilsTools.ExecuteQuery(conn, "select *,tbname from jsons1 where jtag->'tag2' like 'bei%'");
UtilsTools.DisplayRes(res);
res = UtilsTools.ExecuteQuery(conn, "select *,tbname from jsons1 where jtag->'tag1' like 'fe%' and jtag->'tag2' is not null");
UtilsTools.DisplayRes(res);
Console.WriteLine("test where condition in no support in===========");
UtilsTools.ExecuteErrorQuery(conn, "select * from jsons1 where jtag->'tag1' in ('beijing')");
Console.WriteLine("test where condition match===========");
res = UtilsTools.ExecuteQuery(conn, "select * from jsons1 where jtag->'tag1' match 'ma'");
UtilsTools.DisplayRes(res);
res = UtilsTools.ExecuteQuery(conn, "select * from jsons1 where jtag->'tag1' match 'ma$'");
UtilsTools.DisplayRes(res);
res = UtilsTools.ExecuteQuery(conn, "select * from jsons1 where jtag->'tag2' match 'jing$'");
UtilsTools.DisplayRes(res);
res = UtilsTools.ExecuteQuery(conn, "select * from jsons1 where jtag->'tag1' match '收到'");
UtilsTools.DisplayRes(res);
Console.WriteLine("test distinct===========");
UtilsTools.ExecuteQuery(conn, "insert into jsons1_14 using jsons1 tags('{\"tag1\":\"涛思数据\",\"tag2\":\"\",\"tag3\":null}') values(1591062628000, 2, NULL, '涛思数据', 'dws')");
res = UtilsTools.ExecuteQuery(conn, "select distinct jtag->'tag1' from jsons1");
UtilsTools.DisplayRes(res);
res = UtilsTools.ExecuteQuery(conn, "select distinct jtag from jsons1");
UtilsTools.DisplayRes(res);
Console.WriteLine("test dumplicate key with normal colomn===========");
UtilsTools.ExecuteQuery(conn, "INSERT INTO jsons1_15 using jsons1 tags('{\"tbname\":\"tt\",\"databool\":true,\"datastr\":\"涛思数据\"}') values(1591060828000, 4, false, 'jjsf', \"你就会\")");
res = UtilsTools.ExecuteQuery(conn, "select *,tbname,jtag from jsons1 where jtag->'datastr' match '涛思数据' and datastr match 'js'");
UtilsTools.DisplayRes(res);
res = UtilsTools.ExecuteQuery(conn, "select tbname,jtag->'tbname' from jsons1 where jtag->'tbname'='tt' and tbname='jsons1_14'");
UtilsTools.DisplayRes(res);
Console.WriteLine("test join===========");
UtilsTools.ExecuteQuery(conn, "create table if not exists jsons2(ts timestamp, dataInt int, dataBool bool, dataStr nchar(50), dataStrBin binary(150)) tags(jtag json)");
UtilsTools.ExecuteQuery(conn, "insert into jsons2_1 using jsons2 tags('{\"tag1\":\"fff\",\"tag2\":5, \"tag3\":true}') values(1591060618000, 2, false, 'json2', '涛思数据2')");
UtilsTools.ExecuteQuery(conn, "insert into jsons2_2 using jsons2 tags('{\"tag1\":5,\"tag2\":null}') values (1591060628000, 2, true, 'json2', 'sss')");
UtilsTools.ExecuteQuery(conn, "create table if not exists jsons3(ts timestamp, dataInt int, dataBool bool, dataStr nchar(50), dataStrBin binary(150)) tags(jtag json)");
UtilsTools.ExecuteQuery(conn, "insert into jsons3_1 using jsons3 tags('{\"tag1\":\"fff\",\"tag2\":5, \"tag3\":true}') values(1591060618000, 3, false, 'json3', '涛思数据3')");
UtilsTools.ExecuteQuery(conn, "insert into jsons3_2 using jsons3 tags('{\"tag1\":5,\"tag2\":\"beijing\"}') values (1591060638000, 2, true, 'json3', 'sss')");
res = UtilsTools.ExecuteQuery(conn, "select 'sss',33,a.jtag->'tag3' from jsons2 a,jsons3 b where a.ts=b.ts and a.jtag->'tag1'=b.jtag->'tag1'");
UtilsTools.DisplayRes(res);
res = UtilsTools.ExecuteQuery(conn, "select 'sss',33,a.jtag->'tag3' from jsons2 a,jsons3 b where a.ts=b.ts and a.jtag->'tag1'=b.jtag->'tag1'");
UtilsTools.DisplayRes(res);
Console.WriteLine("test group by & order by json tag===========");
res = UtilsTools.ExecuteQuery(conn, "select count(*) from jsons1 group by jtag->'tag1' order by jtag->'tag1' desc");
UtilsTools.DisplayRes(res);
res = UtilsTools.ExecuteQuery(conn, "select count(*) from jsons1 group by jtag->'tag1' order by jtag->'tag1' asc");
UtilsTools.DisplayRes(res);
Console.WriteLine("test stddev with group by json tag===========");
res = UtilsTools.ExecuteQuery(conn, "select stddev(dataint) from jsons1 group by jtag->'tag1'");
UtilsTools.DisplayRes(res);
res = UtilsTools.ExecuteQuery(conn, "select stddev(dataint) from jsons1 group by jsons1.jtag->'tag1'");
UtilsTools.DisplayRes(res);
Console.WriteLine("test top/bottom with group by json tag===========");
res = UtilsTools.ExecuteQuery(conn, "select top(dataint,100) from jsons1 group by jtag->'tag1'");
UtilsTools.DisplayRes(res);
Console.WriteLine("subquery with json tag===========");
res = UtilsTools.ExecuteQuery(conn, "select * from (select jtag, dataint from jsons1)");
UtilsTools.DisplayRes(res);
res = UtilsTools.ExecuteQuery(conn, "select jtag->'tag1' from (select jtag->'tag1', dataint from jsons1)");
UtilsTools.DisplayRes(res);
res = UtilsTools.ExecuteQuery(conn, "select jtag->'tag1' from (select jtag->'tag1', dataint from jsons1)");
UtilsTools.DisplayRes(res);
res = UtilsTools.ExecuteQuery(conn, "select ts,tbname,jtag->'tag1' from (select jtag->'tag1',tbname,ts from jsons1 order by ts)");
UtilsTools.DisplayRes(res);
Console.WriteLine("");
}
}
}
\ No newline at end of file
using System;
using TDengineDriver;
using System.Runtime.InteropServices;
using System.Text;
using System.Collections.Generic;
namespace Utils
{
public class UtilsTools
{
static string configDir = "/etc/taos";//"C:/TDengine/cfg";
public static IntPtr TDConnection(string ip, string user, string password, string db, short port)
{
TDengine.Options((int)TDengineInitOption.TDDB_OPTION_CONFIGDIR, configDir);
TDengine.Options((int)TDengineInitOption.TDDB_OPTION_SHELL_ACTIVITY_TIMER, "60");
TDengine.Init();
return TDengine.Connect(ip, user, password, db, port);
}
public static IntPtr ExecuteQuery(IntPtr conn, String sql)
{
IntPtr res = TDengine.Query(conn, sql);
if ((res == IntPtr.Zero) || (TDengine.ErrorNo(res) != 0))
{
Console.Write(sql.ToString() + " failure, ");
if (res != IntPtr.Zero)
{
Console.Write("reason: " + TDengine.Error(res));
}
Console.WriteLine("");
ExitProgram();
}
else
{
Console.WriteLine(sql.ToString() + " success");
}
return res;
}
public static IntPtr ExecuteErrorQuery(IntPtr conn, String sql)
{
IntPtr res = TDengine.Query(conn, sql);
if ((res == IntPtr.Zero) || (TDengine.ErrorNo(res) != 0))
{
Console.Write(sql.ToString() + " failure, ");
if (res != IntPtr.Zero)
{
Console.Write("reason: " + TDengine.Error(res));
}
Console.WriteLine("");
}
else
{
Console.WriteLine(sql.ToString() + " success");
}
return res;
}
public static void ExecuteUpdate(IntPtr conn, String sql)
{
IntPtr res = TDengine.Query(conn, sql);
if ((res == IntPtr.Zero) || (TDengine.ErrorNo(res) != 0))
{
Console.Write(sql.ToString() + " failure, ");
if (res != IntPtr.Zero)
{
Console.Write("reason: " + TDengine.Error(res));
}
Console.WriteLine("");
ExitProgram();
}
else
{
Console.WriteLine(sql.ToString() + " success");
}
TDengine.FreeResult(res);
}
public static void DisplayRes(IntPtr res)
{
long queryRows = 0;
if ((res == IntPtr.Zero) || (TDengine.ErrorNo(res) != 0))
{
if (res != IntPtr.Zero)
{
Console.Write("reason: " + TDengine.Error(res));
}
Console.WriteLine("");
ExitProgram();
}
int fieldCount = TDengine.FieldCount(res);
List<TDengineMeta> metas = TDengine.FetchFields(res);
for (int j = 0; j < metas.Count; j++)
{
TDengineMeta meta = (TDengineMeta)metas[j];
}
IntPtr rowdata;
StringBuilder builder = new StringBuilder();
while ((rowdata = TDengine.FetchRows(res)) != IntPtr.Zero)
{
queryRows++;
IntPtr colLengthPtr = TDengine.FetchLengths(res);
int[] colLengthArr = new int[fieldCount];
Marshal.Copy(colLengthPtr, colLengthArr, 0, fieldCount);
for (int fields = 0; fields < fieldCount; ++fields)
{
TDengineMeta meta = metas[fields];
int offset = IntPtr.Size * fields;
IntPtr data = Marshal.ReadIntPtr(rowdata, offset);
builder.Append("---");
if (data == IntPtr.Zero)
{
builder.Append("NULL");
continue;
}
switch ((TDengineDataType)meta.type)
{
case TDengineDataType.TSDB_DATA_TYPE_BOOL:
bool v1 = Marshal.ReadByte(data) == 0 ? false : true;
builder.Append(v1);
break;
case TDengineDataType.TSDB_DATA_TYPE_TINYINT:
byte v2 = Marshal.ReadByte(data);
builder.Append(v2);
break;
case TDengineDataType.TSDB_DATA_TYPE_SMALLINT:
short v3 = Marshal.ReadInt16(data);
builder.Append(v3);
break;
case TDengineDataType.TSDB_DATA_TYPE_INT:
int v4 = Marshal.ReadInt32(data);
builder.Append(v4);
break;
case TDengineDataType.TSDB_DATA_TYPE_BIGINT:
long v5 = Marshal.ReadInt64(data);
builder.Append(v5);
break;
case TDengineDataType.TSDB_DATA_TYPE_FLOAT:
float v6 = (float)Marshal.PtrToStructure(data, typeof(float));
builder.Append(v6);
break;
case TDengineDataType.TSDB_DATA_TYPE_DOUBLE:
double v7 = (double)Marshal.PtrToStructure(data, typeof(double));
builder.Append(v7);
break;
case TDengineDataType.TSDB_DATA_TYPE_BINARY:
string v8 = Marshal.PtrToStringAnsi(data, colLengthArr[fields]);
builder.Append(v8);
break;
case TDengineDataType.TSDB_DATA_TYPE_TIMESTAMP:
long v9 = Marshal.ReadInt64(data);
builder.Append(v9);
break;
case TDengineDataType.TSDB_DATA_TYPE_NCHAR:
string v10 = Marshal.PtrToStringAnsi(data, colLengthArr[fields]);
builder.Append(v10);
break;
case TDengineDataType.TSDB_DATA_TYPE_JSONTAG:
string v11 = Marshal.PtrToStringAnsi(data);
builder.Append(v11);
break;
}
}
builder.Append("---");
if (queryRows <= 10)
{
Console.WriteLine(builder.ToString());
}
builder.Clear();
}
if (TDengine.ErrorNo(res) != 0)
{
Console.Write("Query is not complete, Error {0:G}", TDengine.ErrorNo(res), TDengine.Error(res));
}
TDengine.FreeResult(res); Console.WriteLine("");
}
public static bool IsValidResult(IntPtr res)
{
if ((res == IntPtr.Zero) || (TDengine.ErrorNo(res) != 0))
{
if (res != IntPtr.Zero)
{
Console.Write("reason: " + TDengine.Error(res));
return false;
}
Console.WriteLine("");
return false;
}
return true;
}
public static void CloseConnection(IntPtr conn)
{
if (conn != IntPtr.Zero)
{
if (TDengine.Close(conn) == 0)
{
Console.WriteLine("close connection sucess");
}
else
{
Console.WriteLine("close Connection failed");
}
}
}
public static void ExitProgram()
{
TDengine.Cleanup();
System.Environment.Exit(0);
}
}
}
\ No newline at end of file
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="TDengine.Connector" Version="1.0.3" />
</ItemGroup>
</Project>
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace TDengineDriver
{
enum TDengineDataType
{
TSDB_DATA_TYPE_NULL = 0, // 1 bytes
TSDB_DATA_TYPE_BOOL = 1, // 1 bytes
TSDB_DATA_TYPE_TINYINT = 2, // 1 bytes
TSDB_DATA_TYPE_SMALLINT = 3, // 2 bytes
TSDB_DATA_TYPE_INT = 4, // 4 bytes
TSDB_DATA_TYPE_BIGINT = 5, // 8 bytes
TSDB_DATA_TYPE_FLOAT = 6, // 4 bytes
TSDB_DATA_TYPE_DOUBLE = 7, // 8 bytes
TSDB_DATA_TYPE_BINARY = 8, // string
TSDB_DATA_TYPE_TIMESTAMP = 9,// 8 bytes
TSDB_DATA_TYPE_NCHAR = 10, // unicode string
TSDB_DATA_TYPE_UTINYINT = 11,// 1 byte
TSDB_DATA_TYPE_USMALLINT = 12,// 2 bytes
TSDB_DATA_TYPE_UINT = 13, // 4 bytes
TSDB_DATA_TYPE_UBIGINT = 14 // 8 bytes
}
enum TDengineInitOption
{
TSDB_OPTION_LOCALE = 0,
TSDB_OPTION_CHARSET = 1,
TSDB_OPTION_TIMEZONE = 2,
TDDB_OPTION_CONFIGDIR = 3,
TDDB_OPTION_SHELL_ACTIVITY_TIMER = 4
}
enum TDengineSchemalessProtocol
{
TSDB_SML_UNKNOWN_PROTOCOL = 0,
TSDB_SML_LINE_PROTOCOL = 1,
TSDB_SML_TELNET_PROTOCOL = 2,
TSDB_SML_JSON_PROTOCOL = 3
}
enum TDengineSchemalessPrecision
{
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
}
class TDengineMeta
{
public string name;
public short size;
public byte type;
public string TypeName()
{
switch ((TDengineDataType)type)
{
case TDengineDataType.TSDB_DATA_TYPE_BOOL:
return "BOOL";
case TDengineDataType.TSDB_DATA_TYPE_TINYINT:
return "TINYINT";
case TDengineDataType.TSDB_DATA_TYPE_SMALLINT:
return "SMALLINT";
case TDengineDataType.TSDB_DATA_TYPE_INT:
return "INT";
case TDengineDataType.TSDB_DATA_TYPE_BIGINT:
return "BIGINT";
case TDengineDataType.TSDB_DATA_TYPE_UTINYINT:
return "TINYINT UNSIGNED";
case TDengineDataType.TSDB_DATA_TYPE_USMALLINT:
return "SMALLINT UNSIGNED";
case TDengineDataType.TSDB_DATA_TYPE_UINT:
return "INT UNSIGNED";
case TDengineDataType.TSDB_DATA_TYPE_UBIGINT:
return "BIGINT UNSIGNED";
case TDengineDataType.TSDB_DATA_TYPE_FLOAT:
return "FLOAT";
case TDengineDataType.TSDB_DATA_TYPE_DOUBLE:
return "DOUBLE";
case TDengineDataType.TSDB_DATA_TYPE_BINARY:
return "STRING";
case TDengineDataType.TSDB_DATA_TYPE_TIMESTAMP:
return "TIMESTAMP";
case TDengineDataType.TSDB_DATA_TYPE_NCHAR:
return "NCHAR";
default:
return "undefine";
}
}
}
class TDengine
{
public const int TSDB_CODE_SUCCESS = 0;
[DllImport("taos", EntryPoint = "taos_init", CallingConvention = CallingConvention.Cdecl)]
static extern public void Init();
[DllImport("taos", EntryPoint = "taos_cleanup", CallingConvention = CallingConvention.Cdecl)]
static extern public void Cleanup();
[DllImport("taos", EntryPoint = "taos_options", CallingConvention = CallingConvention.Cdecl)]
static extern public void Options(int option, string value);
[DllImport("taos", EntryPoint = "taos_connect", CallingConvention = CallingConvention.Cdecl)]
static extern public IntPtr Connect(string ip, string user, string password, string db, short port);
[DllImport("taos", EntryPoint = "taos_errstr", CallingConvention = CallingConvention.Cdecl)]
static extern private IntPtr taos_errstr(IntPtr res);
static public string Error(IntPtr res)
{
IntPtr errPtr = taos_errstr(res);
return Marshal.PtrToStringAnsi(errPtr);
}
[DllImport("taos", EntryPoint = "taos_errno", CallingConvention = CallingConvention.Cdecl)]
static extern public int ErrorNo(IntPtr res);
[DllImport("taos", EntryPoint = "taos_query", CallingConvention = CallingConvention.Cdecl)]
static extern public IntPtr Query(IntPtr conn, string sqlstr);
[DllImport("taos", EntryPoint = "taos_affected_rows", CallingConvention = CallingConvention.Cdecl)]
static extern public int AffectRows(IntPtr res);
[DllImport("taos", EntryPoint = "taos_field_count", CallingConvention = CallingConvention.Cdecl)]
static extern public int FieldCount(IntPtr res);
[DllImport("taos", EntryPoint = "taos_fetch_fields", CallingConvention = CallingConvention.Cdecl)]
static extern private IntPtr taos_fetch_fields(IntPtr res);
static public List<TDengineMeta> FetchFields(IntPtr res)
{
const int fieldSize = 68;
List<TDengineMeta> metas = new List<TDengineMeta>();
if (res == IntPtr.Zero)
{
return metas;
}
int fieldCount = FieldCount(res);
IntPtr fieldsPtr = taos_fetch_fields(res);
for (int i = 0; i < fieldCount; ++i)
{
int offset = i * fieldSize;
TDengineMeta meta = new TDengineMeta();
meta.name = Marshal.PtrToStringAnsi(fieldsPtr + offset);
meta.type = Marshal.ReadByte(fieldsPtr + offset + 65);
meta.size = Marshal.ReadInt16(fieldsPtr + offset + 66);
metas.Add(meta);
}
return metas;
}
[DllImport("taos", EntryPoint = "taos_fetch_row", CallingConvention = CallingConvention.Cdecl)]
static extern public IntPtr FetchRows(IntPtr res);
[DllImport("taos", EntryPoint = "taos_free_result", CallingConvention = CallingConvention.Cdecl)]
static extern public IntPtr FreeResult(IntPtr res);
[DllImport("taos", EntryPoint = "taos_close", CallingConvention = CallingConvention.Cdecl)]
static extern public int Close(IntPtr taos);
//get precision in restultset
[DllImport("taos", EntryPoint = "taos_result_precision", CallingConvention = CallingConvention.Cdecl)]
static extern public int ResultPrecision(IntPtr taos);
//schemaless API
[DllImport("taos",SetLastError = true, EntryPoint = "taos_schemaless_insert", CallingConvention = CallingConvention.Cdecl)]
static extern public IntPtr SchemalessInsert(IntPtr taos, string[] lines, int numLines, int protocol, int precision);
}
}
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="TDengine.Connector" Version="1.0.2" />
</ItemGroup>
</Project>
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Text;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Collections;
namespace TDengineDriver
{
class SchemalessSample
{
// connect parameters
private string host = "127.0.0.1";
private string configDir = "C:/TDengine/cfg";
private string user = "root";
private string passwd = "taosdata";
private short port = 0;
private IntPtr conn = IntPtr.Zero;
private string dbName = "csharp";
private string dbPrecision = "ms";
static void Main(string[] args)
{
string[] lines = {
"stg,t1=3i64,t2=4f64,t3=\"t3\" c1=3i64,c3=L\"passit\",c2=false,c4=4f64 1626006833639000000",
"stg,t1=4i64,t3=\"t4\",t2=5f64,t4=5f64 c1=3i64,c3=L\"passitagin\",c2=true,c4=5f64,c5=5f64 1626006833641000000"
};
string[] jsonStr = {
"{"
+"\"metric\": \"stb0_0\","
+"\"timestamp\": 1626006833,"
+"\"value\": 10,"
+"\"tags\": {"
+" \"t1\": true,"
+"\"t2\": false,"
+"\"t3\": 10,"
+"\"t4\": \"123_abc_.!@#$%^&*:;,./?|+-=()[]{}<>\""
+"}"
+"}"
};
SchemalessSample sample = new SchemalessSample();
sample.InitTDengine();
sample.ConnectTDengine();
sample.dropDatabase();
sample.createDatabase();
sample.useDatabase();
sample.schemalessInsert(lines, 2, (int)TDengineSchemalessProtocol.TSDB_SML_LINE_PROTOCOL, (int)TDengineSchemalessPrecision.TSDB_SML_TIMESTAMP_NANO_SECONDS);
sample.checkSelect("stg");
sample.schemalessInsert(jsonStr,1,(int)TDengineSchemalessProtocol.TSDB_SML_JSON_PROTOCOL,(int)TDengineSchemalessPrecision.TSDB_SML_TIMESTAMP_SECONDS);
sample.checkSelect("stb0_0");
sample.CloseConnection();
sample.cleanup();
}
public void InitTDengine()
{
TDengine.Options((int)TDengineInitOption.TDDB_OPTION_CONFIGDIR, this.configDir);
TDengine.Options((int)TDengineInitOption.TDDB_OPTION_SHELL_ACTIVITY_TIMER, "60");
Console.WriteLine("init...");
TDengine.Init();
Console.WriteLine("get connection starting...");
}
public void ConnectTDengine()
{
string db = "";
this.conn = TDengine.Connect(host, this.user, this.passwd, db, this.port);
if (this.conn == IntPtr.Zero)
{
Console.WriteLine("connection failed: " + this.host);
ExitProgram();
}
else
{
Console.WriteLine("[ OK ] Connection established.");
}
}
public void createDatabase()
{
StringBuilder sql = new StringBuilder();
sql.Append("create database if not exists ").Append(this.dbName).Append(" precision '").Append(this.dbPrecision).Append("'");
execute(sql.ToString());
}
public void useDatabase()
{
StringBuilder sql = new StringBuilder();
sql.Append("use ").Append(this.dbName);
execute(sql.ToString());
}
public void checkSelect(String tableName)
{
StringBuilder sql = new StringBuilder();
sql.Append("select * from ").Append(this.dbName).Append(".").Append(tableName);
ExecuteQuery(sql.ToString());
}
public void schemalessInsert(string[] sqlstr, int lineCnt, int protocol, int precision)
{
IntPtr res = TDengine.SchemalessInsert(this.conn, sqlstr, lineCnt, protocol, precision);
if (TDengine.ErrorNo(res) != 0)
{
Console.WriteLine("schemaless_insert failed:{0}", TDengine.Error(res));
Console.WriteLine("line string:{0}", sqlstr);
Console.WriteLine("");
ExitProgram();
}
else
{
Console.WriteLine("else");
Console.WriteLine("schemaless insert success:{0}", TDengine.ErrorNo(res));
}
DisplayRes(res);
}
public void dropDatabase()
{
StringBuilder sql = new StringBuilder();
sql.Append("drop database if exists ").Append(this.dbName);
execute(sql.ToString());
}
public void execute(string sql)
{
DateTime dt1 = DateTime.Now;
IntPtr res = TDengine.Query(this.conn, sql.ToString());
DateTime dt2 = DateTime.Now;
TimeSpan span = dt2 - dt1;
if ((res == IntPtr.Zero) || (TDengine.ErrorNo(res) != 0))
{
Console.Write(sql.ToString() + " failure, ");
if (res != IntPtr.Zero)
{
Console.Write("reason: " + TDengine.Error(res));
}
Console.WriteLine("");
ExitProgram();
}
else
{
Console.WriteLine(sql.ToString() + " success");
}
TDengine.FreeResult(res);
}
public void DisplayRes(IntPtr res)
{
long queryRows = 0;
int fieldCount = TDengine.FieldCount(res);
List<TDengineMeta> metas = TDengine.FetchFields(res);
for (int j = 0; j < metas.Count; j++)
{
TDengineMeta meta = (TDengineMeta)metas[j];
}
IntPtr rowdata;
StringBuilder builder = new StringBuilder();
while ((rowdata = TDengine.FetchRows(res)) != IntPtr.Zero)
{
queryRows++;
for (int fields = 0; fields < fieldCount; ++fields)
{
TDengineMeta meta = metas[fields];
int offset = IntPtr.Size * fields;
IntPtr data = Marshal.ReadIntPtr(rowdata, offset);
builder.Append("---");
if (data == IntPtr.Zero)
{
builder.Append("NULL");
continue;
}
switch ((TDengineDataType)meta.type)
{
case TDengineDataType.TSDB_DATA_TYPE_BOOL:
bool v1 = Marshal.ReadByte(data) == 0 ? false : true;
builder.Append(v1);
break;
case TDengineDataType.TSDB_DATA_TYPE_TINYINT:
byte v2 = Marshal.ReadByte(data);
builder.Append(v2);
break;
case TDengineDataType.TSDB_DATA_TYPE_SMALLINT:
short v3 = Marshal.ReadInt16(data);
builder.Append(v3);
break;
case TDengineDataType.TSDB_DATA_TYPE_INT:
int v4 = Marshal.ReadInt32(data);
builder.Append(v4);
break;
case TDengineDataType.TSDB_DATA_TYPE_BIGINT:
long v5 = Marshal.ReadInt64(data);
builder.Append(v5);
break;
case TDengineDataType.TSDB_DATA_TYPE_FLOAT:
float v6 = (float)Marshal.PtrToStructure(data, typeof(float));
builder.Append(v6);
break;
case TDengineDataType.TSDB_DATA_TYPE_DOUBLE:
double v7 = (double)Marshal.PtrToStructure(data, typeof(double));
builder.Append(v7);
break;
case TDengineDataType.TSDB_DATA_TYPE_BINARY:
string v8 = Marshal.PtrToStringAnsi(data);
builder.Append(v8);
break;
case TDengineDataType.TSDB_DATA_TYPE_TIMESTAMP:
long v9 = Marshal.ReadInt64(data);
builder.Append(v9);
break;
case TDengineDataType.TSDB_DATA_TYPE_NCHAR:
string v10 = Marshal.PtrToStringAnsi(data);
builder.Append(v10);
break;
}
}
builder.Append("---");
if (queryRows <= 10)
{
Console.WriteLine(builder.ToString());
}
builder.Clear();
}
if (TDengine.ErrorNo(res) != 0)
{
Console.Write("Query is not complete, Error {0:G}", TDengine.ErrorNo(res), TDengine.Error(res));
}
Console.WriteLine("");
TDengine.FreeResult(res);
}
public void ExecuteQuery(string sql)
{
DateTime dt1 = DateTime.Now;
IntPtr res = TDengine.Query(conn, sql);
DateTime dt2 = DateTime.Now;
TimeSpan span = dt2 - dt1;
if ((res == IntPtr.Zero) || (TDengine.ErrorNo(res) != 0))
{
Console.Write(sql.ToString() + " failure, ");
if (res != IntPtr.Zero)
{
Console.Write("reason: " + TDengine.Error(res));
}
Console.WriteLine("");
ExitProgram();
}
Console.WriteLine("[OK] time cost: " + span.ToString() + "ms, execute statement ====> " + sql.ToString());
DisplayRes(res);
}
public void CloseConnection()
{
if (this.conn != IntPtr.Zero)
{
TDengine.Close(this.conn);
Console.WriteLine("connection closed.");
}
}
static void ExitProgram()
{
System.Environment.Exit(0);
}
public void cleanup()
{
Console.WriteLine("clean up...");
System.Environment.Exit(0);
}
// method to get db precision
}
}
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Text;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Collections;
namespace TDengineDriver
{
public class StmtDemo
{
//connection parameters
private string host = "127.0.0.1";
private string configDir = "C:/TDengine/cfg";
private string user = "root";
private string passwd = "taosdata";
private short port = 0;
private IntPtr conn = IntPtr.Zero;
private IntPtr stmt = IntPtr.Zero;
static void Main(string[] args)
{
string dropDB = "drop database if exists csharp";
string createDB = "create database if not exists csharp keep 36500";
string selectDB = "use csharp";
string stmtSql = "insert into ? using stmtdemo tags(?,?,?,?,?,?,?,?,?,?,?,?,?) values(?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
string createTable = "create stable stmtdemo (ts timestamp "
+ ",b bool"
+ ",v1 tinyint"
+ ",v2 smallint"
+ ",v4 int"
+ ",v8 bigint"
+ ",f4 float"
+ ",f8 double"
+ ",u1 tinyint unsigned"
+ ",u2 smallint unsigned"
+ ",u4 int unsigned"
+ ",u8 bigint unsigned"
+ ",bin binary(200)"
+ ",blob nchar(200)"
+ ")tags("
+ "bo bool"
+ ",tt tinyint"
+ ",si smallint"
+ ",ii int"
+ ",bi bigint"
+ ",tu tinyint unsigned"
+ ",su smallint unsigned"
+ ",iu int unsigned"
+ ",bu bigint unsigned"
+ ",ff float "
+ ",dd double "
+ ",bb binary(200)"
+ ",nc nchar(200)"
+ ")";
string dropTable = "drop table if exists stmtdemo";
string tableName = "t1";
StmtDemo stmtDemo = new StmtDemo();
Console.WriteLine("---------------------------------------------------------------");
Console.WriteLine("Start StmtDemo insert Testing...");
Console.WriteLine("---------------------------------------------------------------");
stmtDemo.InitTDengine();
//TDengine connect
stmtDemo.ConnectTDengine();
//before stmt
stmtDemo.ExecuteQuery(dropDB);
stmtDemo.ExecuteQuery(createDB);
stmtDemo.ExecuteQuery(selectDB);
stmtDemo.ExecuteQuery(dropTable);
stmtDemo.ExecuteQuery(createTable);
stmtDemo.StmtInit();
// string[] tableList = { "stmtdemo" };
// stmtDemo.loadTableInfo(tableList);
stmtDemo.StmtPrepare(stmtSql);
TAOS_BIND[] binds = stmtDemo.InitBindArr();
TAOS_MULTI_BIND[] mbinds = stmtDemo.InitMultBindArr();
stmtDemo.SetTableNameTags(tableName, binds);
stmtDemo.BindParamBatch(mbinds);
stmtDemo.AddBatch();
stmtDemo.StmtExecute();
TaosBind.FreeTaosBind(binds);
TaosMultiBind.FreeTaosBind(mbinds);
stmtDemo.StmtClose();
Console.WriteLine("---------------------------------------------------------------");
Console.WriteLine("start StmtDemo select Testing...");
Console.WriteLine("---------------------------------------------------------------");
stmtDemo.StmtInit();
string selectSql = "SELECT * FROM stmtdemo WHERE v1 > ? AND v4 < ?";
stmtDemo.StmtPrepare(selectSql);
TAOS_BIND[] queryCondition = new TAOS_BIND[2];
queryCondition[0] = TaosBind.BindTinyInt(0);
queryCondition[1] = TaosBind.BindInt(1000);
Console.WriteLine(selectSql);
stmtDemo.BindParam(queryCondition);
stmtDemo.StmtExecute();
stmtDemo.StmtUseResult();
stmtDemo.StmtClose();
TaosBind.FreeTaosBind(queryCondition);
Console.WriteLine("---------------------------------------------------------------");
Console.WriteLine("Stop StmtDemo Testing...");
Console.WriteLine("---------------------------------------------------------------");
stmtDemo.CloseConnection();
}
public TAOS_BIND[] InitBindArr()
{
TAOS_BIND[] binds = new TAOS_BIND[13];
binds[0] = TaosBind.BindBool(true);
binds[1] = TaosBind.BindTinyInt(-2);
binds[2] = TaosBind.BindSmallInt(short.MaxValue);
binds[3] = TaosBind.BindInt(int.MaxValue);
binds[4] = TaosBind.BindBigInt(Int64.MaxValue);
binds[5] = TaosBind.BindUTinyInt(byte.MaxValue - 1);
binds[6] = TaosBind.BindUSmallInt(UInt16.MaxValue - 1);
binds[7] = TaosBind.BindUInt(uint.MinValue + 1);
binds[8] = TaosBind.BindUBigInt(UInt64.MinValue + 1);
binds[9] = TaosBind.BindFloat(11.11F);
binds[10] = TaosBind.BindDouble(22.22D);
binds[11] = TaosBind.BindBinary("qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM`1234567890-=+_)(*&^%$#@!~[];,./<>?:{}");
binds[12] = TaosBind.BindNchar("qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKZXCVBNM`1234567890-=+_)(*&^%$#@!~[];,./<>?:{}");
return binds;
}
public TAOS_MULTI_BIND[] InitMultBindArr()
{
TAOS_MULTI_BIND[] mBinds = new TAOS_MULTI_BIND[14];
long[] tsArr = new long[5] { 1637064040000, 1637064041000, 1637064042000, 1637064043000, 1637064044000 };
bool?[] boolArr = new bool?[5] { true, false, null, true, true };
sbyte?[] tinyIntArr = new sbyte?[5] { -127, 0, null, 8, 127 };
short?[] shortArr = new short?[5] { short.MinValue + 1, -200, null, 100, short.MaxValue };
int?[] intArr = new int?[5] { -200, -100, null, 0, 300 };
long?[] longArr = new long?[5] { long.MinValue + 1, -2000, null, 1000, long.MaxValue };
float?[] floatArr = new float?[5] { float.MinValue + 1, -12.1F, null, 0F, float.MaxValue };
double?[] doubleArr = new double?[5] { double.MinValue + 1, -19.112D, null, 0D, double.MaxValue };
byte?[] uTinyIntArr = new byte?[5] { byte.MinValue, 12, null, 89, byte.MaxValue - 1 };
ushort?[] uShortArr = new ushort?[5] { ushort.MinValue, 200, null, 400, ushort.MaxValue - 1 };
uint?[] uIntArr = new uint?[5] { uint.MinValue, 100, null, 2, uint.MaxValue - 1 };
ulong?[] uLongArr = new ulong?[5] { ulong.MinValue, 2000, null, 1000, long.MaxValue - 1 };
string[] binaryArr = new string[5] { "1234567890~!@#$%^&*()_+=-`[]{}:,./<>?", String.Empty, null, "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM", "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890~!@#$%^&*()_+=-`[]{}:,./<>?" };
string[] ncharArr = new string[5] { "1234567890~!@#$%^&*()_+=-`[]{}:,./<>?", null, "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM", "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890~!@#$%^&*()_+=-`[]{}:,./<>?", string.Empty };
mBinds[0] = TaosMultiBind.MultiBindTimestamp(tsArr);
mBinds[1] = TaosMultiBind.MultiBindBool(boolArr);
mBinds[2] = TaosMultiBind.MultiBindTinyInt(tinyIntArr);
mBinds[3] = TaosMultiBind.MultiBindSmallInt(shortArr);
mBinds[4] = TaosMultiBind.MultiBindInt(intArr);
mBinds[5] = TaosMultiBind.MultiBindBigint(longArr);
mBinds[6] = TaosMultiBind.MultiBindFloat(floatArr);
mBinds[7] = TaosMultiBind.MultiBindDouble(doubleArr);
mBinds[8] = TaosMultiBind.MultiBindUTinyInt(uTinyIntArr);
mBinds[9] = TaosMultiBind.MultiBindUSmallInt(uShortArr);
mBinds[10] = TaosMultiBind.MultiBindUInt(uIntArr);
mBinds[11] = TaosMultiBind.MultiBindUBigInt(uLongArr);
mBinds[12] = TaosMultiBind.MultiBindBinary(binaryArr);
mBinds[13] = TaosMultiBind.MultiBindNchar(ncharArr);
return mBinds;
}
public void loadTableInfo(string[] arr)
{
if (TDengine.LoadTableInfo(this.conn, arr) == 0)
{
Console.WriteLine("load table info success");
}
else
{
Console.WriteLine("load table info failed");
ExitProgram();
}
}
public void InitTDengine()
{
TDengine.Options((int)TDengineInitOption.TDDB_OPTION_CONFIGDIR, this.configDir);
TDengine.Options((int)TDengineInitOption.TDDB_OPTION_SHELL_ACTIVITY_TIMER, "60");
TDengine.Init();
Console.WriteLine("TDengine Initialization finished");
}
public void ConnectTDengine()
{
string db = "";
this.conn = TDengine.Connect(this.host, this.user, this.passwd, db, this.port);
if (this.conn == IntPtr.Zero)
{
Console.WriteLine("Connect to TDengine failed");
ExitProgram();
}
else
{
Console.WriteLine("Connect to TDengine success");
}
}
public void ExecuteQuery(String sql)
{
IntPtr res = TDengine.Query(conn, sql);
if ((res == IntPtr.Zero) || (TDengine.ErrorNo(res) != 0))
{
Console.Write(sql.ToString() + " failure, ");
if (res != IntPtr.Zero)
{
Console.Write("reason: " + TDengine.Error(res));
}
Console.WriteLine("");
ExitProgram();
}
else
{
Console.WriteLine(sql.ToString() + " success");
}
TDengine.FreeResult(res);
}
public void StmtInit()
{
this.stmt = TDengine.StmtInit(conn);
if (this.stmt == IntPtr.Zero)
{
Console.WriteLine("Init stmt failed");
ExitProgram();
}
else
{
Console.WriteLine("Init stmt success");
}
}
public void StmtPrepare(string sql)
{
int res = TDengine.StmtPrepare(this.stmt, sql);
if (res == 0)
{
Console.WriteLine("stmt prepare success");
}
else
{
Console.WriteLine("stmt prepare failed " + TDengine.StmtErrorStr(stmt));
ExitProgram();
}
}
public void SetTableName(String tableName)
{
int res = TDengine.StmtSetTbname(this.stmt, tableName);
Console.WriteLine("setTableName():" + res);
if (res == 0)
{
Console.WriteLine("set_tbname success");
}
else
{
Console.Write("set_tbname failed, " + TDengine.StmtErrorStr(stmt));
StmtClose();
ExitProgram();
}
}
public void SetTableNameTags(String tableName, TAOS_BIND[] tags)
{
int res = TDengine.StmtSetTbnameTags(this.stmt, tableName, tags);
if (res == 0)
{
Console.WriteLine("set tbname && tags success");
}
else
{
Console.Write("set tbname && tags failed, " + TDengine.StmtErrorStr(stmt));
StmtClose();
ExitProgram();
}
}
public void SetSubTableName(string name)
{
int res = TDengine.StmtSetSubTbname(this.stmt, name);
if (res == 0)
{
Console.WriteLine("set subtable name success");
}
else
{
Console.Write("set subtable name failed, " + TDengine.StmtErrorStr(stmt));
StmtClose();
ExitProgram();
}
}
public void BindParam(TAOS_BIND[] binds)
{
Console.WriteLine("in bindParam()");
int res = TDengine.StmtBindParam(this.stmt, binds);
if (res == 0)
{
Console.WriteLine("bind para success");
}
else
{
Console.Write("bind para failed, " + TDengine.StmtErrorStr(stmt));
StmtClose();
ExitProgram();
}
}
public void BindSingleParamBatch(TAOS_MULTI_BIND bind, int index)
{
int res = TDengine.StmtBindSingleParamBatch(this.stmt,ref bind, index);
if (res == 0)
{
Console.WriteLine("single bind batch success");
}
else
{
Console.Write("single bind batch failed: " + TDengine.StmtErrorStr(stmt));
StmtClose();
ExitProgram();
}
}
public void BindParamBatch(TAOS_MULTI_BIND[] bind)
{
int res = TDengine.StmtBindParamBatch(this.stmt, bind);
if (res == 0)
{
Console.WriteLine("bind parameter batch success");
}
else
{
Console.WriteLine("bind parameter batch failed, " + TDengine.StmtErrorStr(stmt));
StmtClose();
ExitProgram();
}
}
public void AddBatch()
{
int res = TDengine.StmtAddBatch(this.stmt);
if (res == 0)
{
Console.WriteLine("stmt add batch success");
}
else
{
Console.Write("stmt add batch failed,reason: " + TDengine.StmtErrorStr(stmt));
StmtClose();
ExitProgram();
}
}
public void StmtExecute()
{
int res = TDengine.StmtExecute(this.stmt);
if (res == 0)
{
Console.WriteLine("Execute stmt success");
}
else
{
Console.Write("Execute stmt failed,reason: " + TDengine.StmtErrorStr(stmt));
StmtClose();
ExitProgram();
}
}
public void StmtClose()
{
int res = TDengine.StmtClose(this.stmt);
if (res == 0)
{
Console.WriteLine("close stmt success");
}
else
{
Console.WriteLine("close stmt failed, " + TDengine.StmtErrorStr(stmt));
StmtClose();
ExitProgram();
}
}
public void CloseConnection()
{
if (this.conn != IntPtr.Zero)
{
if (TDengine.Close(this.conn) == 0)
{
Console.WriteLine("close connection sucess");
}
else
{
Console.WriteLine("close Connection failed");
}
}
}
//select only
public void StmtUseResult()
{
IntPtr res = TDengine.StmtUseResult(this.stmt);
if ((res == IntPtr.Zero) || (TDengine.ErrorNo(res) != 0))
{
if (res != IntPtr.Zero)
{
Console.Write("reason: " + TDengine.Error(res));
}
Console.WriteLine("");
StmtClose();
CloseConnection();
ExitProgram();
}
else
{
Console.WriteLine("{0},query success");
DisplayRes(res);
TDengine.FreeResult(res);
}
}
public void DisplayRes(IntPtr res)
{
long queryRows = 0;
if ((res == IntPtr.Zero) || (TDengine.ErrorNo(res) != 0))
{
if (res != IntPtr.Zero)
{
Console.Write("reason: " + TDengine.Error(res));
}
Console.WriteLine("");
ExitProgram();
}
int fieldCount = TDengine.FieldCount(res);
List<TDengineMeta> metas = TDengine.FetchFields(res);
for (int j = 0; j < metas.Count; j++)
{
TDengineMeta meta = (TDengineMeta)metas[j];
}
IntPtr rowdata;
StringBuilder builder = new StringBuilder();
while ((rowdata = TDengine.FetchRows(res)) != IntPtr.Zero)
{
queryRows++;
for (int fields = 0; fields < fieldCount; ++fields)
{
TDengineMeta meta = metas[fields];
int offset = IntPtr.Size * fields;
IntPtr data = Marshal.ReadIntPtr(rowdata, offset);
builder.Append("---");
if (data == IntPtr.Zero)
{
builder.Append("NULL");
continue;
}
switch ((TDengineDataType)meta.type)
{
case TDengineDataType.TSDB_DATA_TYPE_BOOL:
bool v1 = Marshal.ReadByte(data) == 0 ? false : true;
builder.Append(v1);
break;
case TDengineDataType.TSDB_DATA_TYPE_TINYINT:
byte v2 = Marshal.ReadByte(data);
builder.Append(v2);
break;
case TDengineDataType.TSDB_DATA_TYPE_SMALLINT:
short v3 = Marshal.ReadInt16(data);
builder.Append(v3);
break;
case TDengineDataType.TSDB_DATA_TYPE_INT:
int v4 = Marshal.ReadInt32(data);
builder.Append(v4);
break;
case TDengineDataType.TSDB_DATA_TYPE_BIGINT:
long v5 = Marshal.ReadInt64(data);
builder.Append(v5);
break;
case TDengineDataType.TSDB_DATA_TYPE_FLOAT:
float v6 = (float)Marshal.PtrToStructure(data, typeof(float));
builder.Append(v6);
break;
case TDengineDataType.TSDB_DATA_TYPE_DOUBLE:
double v7 = (double)Marshal.PtrToStructure(data, typeof(double));
builder.Append(v7);
break;
case TDengineDataType.TSDB_DATA_TYPE_BINARY:
string v8 = Marshal.PtrToStringAnsi(data);
builder.Append(v8);
break;
case TDengineDataType.TSDB_DATA_TYPE_TIMESTAMP:
long v9 = Marshal.ReadInt64(data);
builder.Append(v9);
break;
case TDengineDataType.TSDB_DATA_TYPE_NCHAR:
string v10 = Marshal.PtrToStringAnsi(data);
builder.Append(v10);
break;
}
}
builder.Append("---");
if (queryRows <= 10)
{
Console.WriteLine(builder.ToString());
}
builder.Clear();
}
if (TDengine.ErrorNo(res) != 0)
{
Console.Write("Query is not complete, Error {0:G}", TDengine.ErrorNo(res), TDengine.Error(res));
}
Console.WriteLine("");
}
public static void ExitProgram()
{
TDengine.Cleanup();
System.Environment.Exit(0);
}
}
}
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<PackageReference Include="TDengine.Connector" Version="1.0.3" />
</ItemGroup>
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
</Project>
FROM tdengine/tdengine-beta:latest
ENV DEBIAN_FRONTEND=noninteractive
ARG MIRROR=archive.ubuntu.com
RUN sed -Ei 's/\w+.ubuntu.com/'${MIRROR}'/' /etc/apt/sources.list && apt update && apt install mono-devel -y
RUN apt-get install wget -y \
&& wget https://packages.microsoft.com/config/ubuntu/18.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb \
&& dpkg -i packages-microsoft-prod.deb \
&& rm packages-microsoft-prod.deb \
&& apt-get update && apt-get install -y dotnet-sdk-5.0
COPY ./*.cs *.csproj /tmp/
WORKDIR /tmp/
RUN dotnet build -c Release && cp bin/Release/net5.0/taosdemo bin/Release/net5.0/taosdemo.* /usr/local/bin/ && rm -rf /tmp/*
FROM tdengine/tdengine-beta:latest
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install wget -y \
&& wget https://packages.microsoft.com/config/ubuntu/18.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb \
&& dpkg -i packages-microsoft-prod.deb \
&& rm packages-microsoft-prod.deb \
&& apt-get update && apt-get install -y dotnet-runtime-5.0
COPY --from=0 /usr/local/bin/taosdemo* /usr/local/bin/
CMD ["/usr/local/bin/taosdemo"]
# C# Taosdemo
## For Mono
install build environment
```sh
yum/apt install mono-complete
```
build C# version taosdemo.
```sh
mcs -out:taosdemo *.cs
./taosdemo --help
```
## For DotNet
install dotnet environment.
```sh
wget https://packages.microsoft.com/config/ubuntu/18.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb \
&& dpkg -i packages-microsoft-prod.deb \
&& rm packages-microsoft-prod.deb \
&& apt-get update && apt-get install -y dotnet-sdk-5.0
```
Build DotNet version taosdemo.
```sh
dotnet build -c Release
./bin/Release/net5.0/taosdemo --help
```
## Usage
```
Usage: mono taosdemo.exe [OPTION...]
--help Show usage.
-h <hostname> host, The host to connect to TDengine. Default is localhost.
-p <port> port, The TCP/IP port number to use for the connection. Default is 0.
-u <username> user, The user name to use when connecting to the server. Default is 'root'.
-P <password> password, The password to use when connecting to the server. Default is 'taosdata'.
-d <dbname> database, Destination database. Default is 'test'.
-a <replications> replica, Set the replica parameters of the database, Default 1, min: 1, max: 5.
-m <table prefix> table_prefix, Table prefix name. Default is 't'.
-M stable, Use super table.
-s <stable prefix> stable_prefix, STable prefix name. Default is 'st'
-Q <DEFAULT | command> query, Execute query command. set 'DEFAULT' means select * from each table
-T <number> num_of_threads, The number of threads. Default is 10.
-r <number> num_of_records_per_req, The number of records per request. Default is 1000.
-t <number> num_of_tables, The number of tables. Default is 1.
-n <number> num_of_records_per_table, The number of records per table. Default is 1.
-c <path> config_directory, Configuration directory. Default is '/etc/taos/'.
-x flag, Insert only flag.
-O order, Insert mode--0: In order, 1: Out of order. Default is in order.
-R <number> rate, Out of order data's rate--if order=1 Default 10, min: 0, max: 50.
-D <number> Delete data methods 0: don't delete, 1: delete by table, 2: delete by stable, 3: delete by database.
-v Print verbose output
-g Print debug output
-y Skip read key for continous test, default is not skip
```
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Text;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Collections;
using System.Threading;
using System.Diagnostics;
namespace TDengineDriver
{
class TDengineTest
{
//connect parameters
private string host = "127.0.0.1";
private string configDir = "C:/TDengine/cfg";
private string user = "root";
private string password = "taosdata";
private short port = 0;
//sql parameters
private string dbName = "db";
private string stablePrefix = "st";
private string tablePrefix = "t";
private bool isInsertOnly = false;
private string query = "NONE";
private short queryMode = 1;
private long recordsPerTable = 1;
private int recordsPerRequest = 1;
private int colsPerRecord = 3;
private long batchRows = 1000;
private long numOfTables = 1;
private short replica = 1;
private IntPtr conn = IntPtr.Zero;
// private long rowsInserted = 0;
private bool useStable = false;
private short methodOfDelete = 0;
private long numOfThreads = 1;
private short rateOfOutorder = 10;
private bool order = true;
private bool skipReadKey = false;
private bool verbose = false;
private bool debug = false;
static void HelpPrint(string arg, string desc)
{
string indent = " ";
Console.WriteLine("{0}{1}", indent, arg.PadRight(25) + desc);
}
static void PrintHelp(String[] argv)
{
for (int i = 0; i < argv.Length; ++i)
{
if ("--help" == argv[i])
{
Console.WriteLine("Usage: mono taosdemo.exe [OPTION...]");
Console.WriteLine("");
HelpPrint("--help", "Show usage.");
Console.WriteLine("");
HelpPrint("-h <hostname>", "host, The host to connect to TDengine. Default is localhost.");
HelpPrint("-p <port>", "port, The TCP/IP port number to use for the connection. Default is 0.");
HelpPrint("-u <username>", "user, The user name to use when connecting to the server. Default is 'root'.");
HelpPrint("-P <password>", "password, The password to use when connecting to the server. Default is 'taosdata'.");
HelpPrint("-d <dbname>", "database, Destination database. Default is 'test'.");
HelpPrint("-a <replications>", "replica, Set the replica parameters of the database, Default 1, min: 1, max: 5.");
HelpPrint("-m <table prefix>", "table_prefix, Table prefix name. Default is 't'.");
HelpPrint("-M", "stable, Use super table.");
HelpPrint("-s <stable prefix>", "stable_prefix, STable prefix name. Default is 'st'");
HelpPrint("-Q <DEFAULT | command>", "query, Execute query command. set 'DEFAULT' means select * from each table");
/* NOT SUPPORT SO FAR
HelpPrint("-o", "outputfile, Direct output to the named file. Default is './output.txt'.");
HelpPrint("-q", "query_mode, Query mode--0: SYNC, 1: ASYNC. Default is SYNC.");
HelpPrint("-b", "type_of_cols, data_type of columns: 'INT', 'TINYINT', 'SMALLINT', 'BIGINT', 'FLOAT', 'DOUBLE', 'BINARY'. Default is 'INT'.");
HelpPrint("-w", "length_of_binary, The length of data_type 'BINARY'. Only applicable when type of cols is 'BINARY'. Default is 8");
HelpPrint("-l", "num_of_cols_per_record, The number of columns per record. Default is 3.");
*/
HelpPrint("-T <number>", "num_of_threads, The number of threads. Default is 10.");
HelpPrint("-r <number>", "num_of_records_per_req, The number of records per request. Default is 1000.");
HelpPrint("-t <number>", "num_of_tables, The number of tables. Default is 1.");
HelpPrint("-n <number>", "num_of_records_per_table, The number of records per table. Default is 1.");
HelpPrint("-c <path>", "config_directory, Configuration directory. Default is '/etc/taos/'.");
HelpPrint("-x", "flag, Insert only flag.");
HelpPrint("-O", "order, Insert mode--0: In order, 1: Out of order. Default is in order.");
HelpPrint("-R <number>", "rate, Out of order data's rate--if order=1 Default 10, min: 0, max: 50.");
HelpPrint("-D <number>", "Delete data methods 0: don't delete, 1: delete by table, 2: delete by stable, 3: delete by database.");
HelpPrint("-v", "Print verbose output");
HelpPrint("-g", "Print debug output");
HelpPrint("-y", "Skip read key for continous test, default is not skip");
System.Environment.Exit(0);
}
}
}
public void ReadArgument(String[] argv)
{
host = this.GetArgumentAsString(argv, "-h", "127.0.0.1");
port = (short)this.GetArgumentAsLong(argv, "-p", 0, 65535, 6030);
user = this.GetArgumentAsString(argv, "-u", "root");
password = this.GetArgumentAsString(argv, "-P", "taosdata");
dbName = this.GetArgumentAsString(argv, "-d", "taosdemo_cs");
stablePrefix = this.GetArgumentAsString(argv, "-s", "st");
tablePrefix = this.GetArgumentAsString(argv, "-m", "t");
isInsertOnly = this.GetArgumentAsFlag(argv, "-x", true);
query = this.GetArgumentAsString(argv, "-Q", "NONE");
queryMode = (short)this.GetArgumentAsLong(argv, "-q", 0, 1, 0);
numOfTables = this.GetArgumentAsLong(argv, "-t", 1, 1000000000, 1);
batchRows = this.GetArgumentAsLong(argv, "-r", 1, 10000, 1000);
recordsPerTable = this.GetArgumentAsLong(argv, "-n", 1, 100000000000, 1);
recordsPerRequest = (int)this.GetArgumentAsLong(argv, "-r", 1, 10000, 1);
colsPerRecord = (int)this.GetArgumentAsLong(argv, "-l", 1, 1024, 3);
configDir = this.GetArgumentAsString(argv, "-c", "C:/TDengine/cfg");
useStable = this.GetArgumentAsFlag(argv, "-M", true);
replica = (short)this.GetArgumentAsLong(argv, "-a", 1, 5, 1);
methodOfDelete = (short)this.GetArgumentAsLong(argv, "-D", 0, 3, 0);
numOfThreads = (short)this.GetArgumentAsLong(argv, "-T", 1, 10000, 1);
order = this.GetArgumentAsFlag(argv, "-O", false);
rateOfOutorder = (short)this.GetArgumentAsLong(argv, "-R", 0, 50, 10);
skipReadKey = this.GetArgumentAsFlag(argv, "-y", true);
verbose = this.GetArgumentAsFlag(argv, "-v", true);
debug = this.GetArgumentAsFlag(argv, "-g", true);
VerbosePrint("###################################################################\n");
VerbosePrintFormat("# Server IP: {0}\n", host);
VerbosePrintFormat("# User: {0}\n", user);
VerbosePrintFormat("# Password: {0}\n", password);
VerbosePrintFormat("# Number of Columns per record: {0}\n", colsPerRecord);
VerbosePrintFormat("# Number of Threads: {0}\n", numOfThreads);
VerbosePrintFormat("# Number of Tables: {0}\n", numOfTables);
VerbosePrintFormat("# Number of records per Table: {0}\n", recordsPerTable);
VerbosePrintFormat("# Records/Request: {0}\n", recordsPerRequest);
VerbosePrintFormat("# Database name: {0}\n", dbName);
VerbosePrintFormat("# Replica: {0}\n", replica);
VerbosePrintFormat("# Use STable: {0}\n", useStable);
VerbosePrintFormat("# Table prefix: {0}\n", tablePrefix);
if (useStable == true)
{
VerbosePrintFormat("# STable prefix: {0}\n", stablePrefix);
}
VerbosePrintFormat("# Data order: {0}\n", order);
VerbosePrintFormat("# Data out of order rate: {0}\n", rateOfOutorder);
VerbosePrintFormat("# Delete method: {0}\n", methodOfDelete);
VerbosePrintFormat("# Query command: {0}\n", query);
VerbosePrintFormat("# Query Mode: {0}\n", queryMode);
VerbosePrintFormat("# Insert Only: {0}\n", isInsertOnly);
VerbosePrintFormat("# Verbose output {0}\n", verbose);
VerbosePrintFormat("# Test time: {0}\n", DateTime.Now.ToString("h:mm:ss tt"));
VerbosePrint("###################################################################\n");
if (skipReadKey == false)
{
Console.Write("Press any key to continue..\n");
Console.ReadKey();
}
}
public bool GetArgumentAsFlag(String[] argv, String argName, bool defaultValue)
{
int argc = argv.Length;
for (int i = 0; i < argc; ++i)
{
if (argName == argv[i])
{
return defaultValue;
}
}
return !defaultValue;
}
public long GetArgumentAsLong(String[] argv, String argName, int minVal, long maxVal, int defaultValue)
{
int argc = argv.Length;
for (int i = 0; i < argc; ++i)
{
if (argName != argv[i])
{
continue;
}
if (i < argc - 1)
{
String tmp = argv[i + 1];
if (tmp[0] == '-')
{
Console.WriteLine("option {0:G} requires an argument", argName);
ExitProgram(1);
}
long tmpVal = Convert.ToInt64(tmp);
if (tmpVal < minVal || tmpVal > maxVal)
{
Console.WriteLine("option {0:G} value should in range [{1:G}, {2:G}]", argName, minVal, maxVal);
ExitProgram(1);
}
return tmpVal;
}
}
return defaultValue;
}
public String GetArgumentAsString(String[] argv, String argName, String defaultValue)
{
int argc = argv.Length;
for (int i = 0; i < argc; ++i)
{
if (argName != argv[i])
{
continue;
}
if (i < argc - 1)
{
String tmp = argv[i + 1];
if (tmp[0] == '-')
{
Console.WriteLine("option {0:G} requires an argument", argName);
ExitProgram(1);
}
return tmp;
}
}
return defaultValue;
}
static void CleanAndExitProgram(int ret)
{
TDengine.Cleanup();
System.Environment.Exit(ret);
}
static void ExitProgram(int ret)
{
System.Environment.Exit(ret);
}
private void VerbosePrintFormat(string format, params object[] parameters)
{
if (verbose == true)
{
Console.Write(format, parameters);
}
}
private void VerbosePrint(string str)
{
if (verbose == true)
{
Console.Write(str);
}
}
private void DebugPrintFormat(string format, params object[] parameters)
{
if (debug == true)
{
Console.Write(format, parameters);
}
}
private void DebugPrint(string str)
{
if (debug == true)
{
Console.Write(str);
}
}
public void InitTDengine()
{
TDengine.Options((int)TDengineInitOption.TDDB_OPTION_CONFIGDIR, this.configDir);
TDengine.Options((int)TDengineInitOption.TDDB_OPTION_SHELL_ACTIVITY_TIMER, "60");
TDengine.Init();
VerbosePrint("TDengine Initialization finished\n");
}
public void ConnectTDengine()
{
string db = "";
VerbosePrintFormat("host:{0} user:{1}, pass:{2}; db:{3}, port:{4}\n",
this.host, this.user, this.password, db, this.port);
this.conn = TDengine.Connect(this.host, this.user, this.password, db, this.port);
if (this.conn == IntPtr.Zero)
{
Console.WriteLine("Connect to TDengine failed");
CleanAndExitProgram(1);
}
else
{
VerbosePrint("Connect to TDengine success\n");
}
}
public void CreateTablesByThreads()
{
Thread[] threadArr = new Thread[numOfThreads];
long quotition = numOfTables / numOfThreads;
if (quotition < 1)
{
numOfThreads = numOfTables;
quotition = 1;
}
long remainder = 0;
if (numOfThreads != 0)
{
remainder = numOfTables % numOfThreads;
}
long last = 0;
for (int i = 0; i < numOfThreads; i++)
{
CreateTableThread createTableThread = new CreateTableThread();
createTableThread.id = i;
createTableThread.verbose = verbose;
createTableThread.debug = debug;
createTableThread.dbName = this.dbName;
createTableThread.tablePrefix = this.tablePrefix;
createTableThread.useStable = useStable;
if (useStable)
{
createTableThread.stablePrefix = stablePrefix;
}
createTableThread.conn = conn;
createTableThread.start = last;
if (i < remainder)
{
createTableThread.end = last + quotition;
}
else
{
createTableThread.end = last + quotition - 1;
}
last = createTableThread.end + 1;
threadArr[i] = new Thread(createTableThread.ThreadMain);
threadArr[i].Start();
}
for (int j = 0; j < numOfThreads; j++)
{
threadArr[j].Join();
}
}
public void dropDatabase()
{
StringBuilder sql = new StringBuilder();
sql.Append("DROP DATABASE IF EXISTS ").Append(this.dbName);
IntPtr res = TDengine.Query(this.conn, sql.ToString());
if ((res == IntPtr.Zero) || (TDengine.ErrorNo(res) != 0))
{
Console.Write(sql.ToString() + " failure, ");
if (res != IntPtr.Zero) {
Console.Write("reason: " + TDengine.Error(res));
}
Console.WriteLine("");
CleanAndExitProgram(1);
}
else
{
VerbosePrint(sql.ToString() + " success\n");
}
}
public void CreateDb()
{
StringBuilder sql = new StringBuilder();
sql.Append("CREATE DATABASE IF NOT EXISTS ").Append(this.dbName).Append(" replica ").Append(this.replica).Append(" keep 36500");
IntPtr res = TDengine.Query(this.conn, sql.ToString());
if ((res == IntPtr.Zero) || (TDengine.ErrorNo(res) != 0))
{
Console.Write(sql.ToString() + " failure, ");
if (res != IntPtr.Zero) {
Console.Write("reason: " + TDengine.Error(res));
}
Console.WriteLine("");
CleanAndExitProgram(1);
}
else
{
VerbosePrint(sql.ToString() + " success\n");
}
TDengine.FreeResult(res);
}
public void CreateStable()
{
StringBuilder sql = new StringBuilder();
sql.Clear();
sql.Append("CREATE TABLE IF NOT EXISTS ").
Append(this.dbName).Append(".").Append(this.stablePrefix).
Append("(ts timestamp, v1 bool, v2 tinyint, v3 smallint, v4 int, v5 bigint, v6 float, v7 double, v8 binary(10), v9 nchar(10), v10 tinyint unsigned, v11 smallint unsigned, v12 int unsigned, v13 bigint unsigned) tags(t1 int)");
IntPtr res = TDengine.Query(this.conn, sql.ToString());
if ((res == IntPtr.Zero) || (TDengine.ErrorNo(res) != 0))
{
Console.Write(sql.ToString() + " failure, ");
if (res != IntPtr.Zero) {
Console.Write("reason: " + TDengine.Error(res));
}
Console.WriteLine("");
CleanAndExitProgram(1);
}
else
{
VerbosePrint(sql.ToString() + " success\n");
}
TDengine.FreeResult(res);
}
public void InsertByThreads()
{
Thread[] threadArr = new Thread[numOfThreads];
long quotition = numOfTables / numOfThreads;
if (quotition < 1)
{
numOfThreads = numOfTables;
quotition = 1;
}
long remainder = 0;
if (numOfThreads != 0)
{
remainder = numOfTables % numOfThreads;
}
long last = 0;
for (int i = 0; i < numOfThreads; i++)
{
InsertDataThread insertThread = new InsertDataThread();
insertThread.id = i;
insertThread.recordsPerTable = recordsPerTable;
insertThread.batchRows = batchRows;
insertThread.numOfTables = numOfTables;
insertThread.verbose = verbose;
insertThread.debug = debug;
insertThread.dbName = this.dbName;
insertThread.tablePrefix = this.tablePrefix;
insertThread.order = this.order;
insertThread.rateOfOutorder = this.rateOfOutorder;
if (useStable)
{
insertThread.stablePrefix = stablePrefix;
}
insertThread.conn = conn;
insertThread.start = last;
if (i < remainder)
{
insertThread.end = last + quotition;
}
else
{
insertThread.end = last + quotition - 1;
}
last = insertThread.end + 1;
threadArr[i] = new Thread(insertThread.ThreadMain);
threadArr[i].Start();
}
for (int j = 0; j < numOfThreads; j++)
{
threadArr[j].Join();
}
}
public void ExecuteQuery()
{
long queryRows = 0;
for (int i = 0; i < this.numOfTables; ++i)
{
string sql;
if (query == "DEFAULT")
{
sql = "select * from " + this.dbName + "." + tablePrefix + i;
}
else
{
sql = query;
}
DebugPrintFormat("query: {0}, sql:{1}\n", query, sql);
IntPtr res = TDengine.Query(conn, sql);
DebugPrintFormat("res: {0}\n", res);
if ((res == IntPtr.Zero) || (TDengine.ErrorNo(res) != 0))
{
Console.Write(sql.ToString() + " failure, ");
if (res != IntPtr.Zero) {
Console.Write("reason: " + TDengine.Error(res));
}
Console.WriteLine("");
CleanAndExitProgram(1);
}
int fieldCount = TDengine.FieldCount(res);
DebugPrint("field count: " + fieldCount + "\n");
List<TDengineMeta> metas = TDengine.FetchFields(res);
for (int j = 0; j < metas.Count; j++)
{
TDengineMeta meta = (TDengineMeta)metas[j];
DebugPrint("index:" + j + ", type:" + meta.type + ", typename:" + meta.TypeName() + ", name:" + meta.name + ", size:" + meta.size + "\n");
}
IntPtr rowdata;
StringBuilder builder = new StringBuilder();
while ((rowdata = TDengine.FetchRows(res)) != IntPtr.Zero)
{
queryRows++;
for (int fields = 0; fields < fieldCount; ++fields)
{
TDengineMeta meta = metas[fields];
int offset = IntPtr.Size * fields;
IntPtr data = Marshal.ReadIntPtr(rowdata, offset);
builder.Append(" | ");
if (data == IntPtr.Zero)
{
builder.Append("NULL");
continue;
}
switch ((TDengineDataType)meta.type)
{
case TDengineDataType.TSDB_DATA_TYPE_BOOL:
bool v1 = Marshal.ReadByte(data) == 0 ? false : true;
builder.Append(v1);
break;
case TDengineDataType.TSDB_DATA_TYPE_TINYINT:
sbyte v2 = (sbyte)Marshal.ReadByte(data);
builder.Append(v2);
break;
case TDengineDataType.TSDB_DATA_TYPE_SMALLINT:
short v3 = Marshal.ReadInt16(data);
builder.Append(v3);
break;
case TDengineDataType.TSDB_DATA_TYPE_INT:
int v4 = Marshal.ReadInt32(data);
builder.Append(v4);
break;
case TDengineDataType.TSDB_DATA_TYPE_BIGINT:
long v5 = Marshal.ReadInt64(data);
builder.Append(v5);
break;
case TDengineDataType.TSDB_DATA_TYPE_FLOAT:
float v6 = (float)Marshal.PtrToStructure(data, typeof(float));
builder.Append(v6);
break;
case TDengineDataType.TSDB_DATA_TYPE_DOUBLE:
double v7 = (double)Marshal.PtrToStructure(data, typeof(double));
builder.Append(v7);
break;
case TDengineDataType.TSDB_DATA_TYPE_BINARY:
string v8 = Marshal.PtrToStringAnsi(data);
builder.Append(v8);
break;
case TDengineDataType.TSDB_DATA_TYPE_TIMESTAMP:
long v9 = Marshal.ReadInt64(data);
builder.Append(v9);
break;
case TDengineDataType.TSDB_DATA_TYPE_NCHAR:
string v10 = Marshal.PtrToStringAnsi(data);
builder.Append(v10);
break;
case TDengineDataType.TSDB_DATA_TYPE_UTINYINT:
byte v11 = Marshal.ReadByte(data);
builder.Append(v11);
break;
case TDengineDataType.TSDB_DATA_TYPE_USMALLINT:
ushort v12 = (ushort)Marshal.ReadInt16(data);
builder.Append(v12);
break;
case TDengineDataType.TSDB_DATA_TYPE_UINT:
uint v13 = (uint)Marshal.ReadInt32(data);
builder.Append(v13);
break;
case TDengineDataType.TSDB_DATA_TYPE_UBIGINT:
ulong v14 = (ulong)Marshal.ReadInt64(data);
builder.Append(v14);
break;
}
}
builder.Append(" | ");
VerbosePrint(builder.ToString() + "\n");
builder.Clear();
}
if (TDengine.ErrorNo(res) != 0)
{
Console.Write("Query is not complete, Error {0:G}",
TDengine.ErrorNo(res), TDengine.Error(res));
}
TDengine.FreeResult(res);
}
}
public void CloseConnection()
{
if (this.conn != IntPtr.Zero)
{
TDengine.Close(this.conn);
}
}
// Main entry
static void Main(string[] args)
{
PrintHelp(args);
TDengineTest tester = new TDengineTest();
tester.ReadArgument(args);
tester.InitTDengine();
tester.ConnectTDengine();
if (tester.isInsertOnly == false)
{
tester.dropDatabase();
tester.CreateDb();
if (tester.useStable == true)
{
tester.CreateStable();
}
tester.CreateTablesByThreads();
}
Stopwatch watch = Stopwatch.StartNew();
tester.InsertByThreads();
watch.Stop();
double elapsedMs = watch.Elapsed.TotalMilliseconds;
Console.WriteLine("C# taosdemo: Spent {0} seconds to insert {1} records with {2} record(s) per request: {3} records/second",
elapsedMs / 1000,
tester.recordsPerTable * tester.numOfTables,
tester.batchRows,
(tester.recordsPerTable * tester.numOfTables * 1000) / elapsedMs);
tester.DebugPrintFormat("query command:{0}\n", tester.query);
if (tester.query != "NONE")
{
watch = Stopwatch.StartNew();
tester.ExecuteQuery();
watch.Stop();
elapsedMs = watch.Elapsed.TotalMilliseconds;
Console.WriteLine("C# taosdemo: Spent {0} seconds to query {1} records.\n",
elapsedMs / 1000,
tester.recordsPerTable * tester.numOfTables
);
}
tester.CloseConnection();
Console.WriteLine("End.");
CleanAndExitProgram(0);
}
public class InsertDataThread
{
public long id { set; get; }
public long start { set; get; }
public long end { set; get; }
public string dbName { set; get; }
public IntPtr conn { set; get; }
public string tablePrefix { set; get; }
public string stablePrefix { set; get; }
public long recordsPerTable { set; get; }
public long batchRows { set; get; }
public long numOfTables { set; get; }
public bool verbose { set; get; }
public bool debug { set; get; }
public bool order { set; get; }
public short rateOfOutorder { set; get; }
private void VerbosePrintFormat(string format, params object[] parameters)
{
if (verbose == true)
{
Console.Write(format, parameters);
}
}
private void VerbosePrint(string str)
{
if (verbose == true)
{
Console.Write(str);
}
}
private void DebugPrintFormat(string format, params object[] parameters)
{
if (debug == true)
{
Console.Write(format, parameters);
}
}
private void DebugPrint(string str)
{
if (debug == true)
{
Console.Write(str);
}
}
public void ThreadMain()
{
VerbosePrintFormat("InsertDataThread {0} from {1} to {2}\n", id, start, end);
StringBuilder sql = new StringBuilder();
DateTime now = DateTime.Now;
int h = now.Hour;
int m = now.Minute;
int s = now.Second;
long baseTimestamp = -16094340000; // 1969-06-29 01:21:00
VerbosePrintFormat("beginTime is {0} + {1}h:{2}m:{3}s\n", baseTimestamp, h, m, s);
long beginTimestamp = baseTimestamp + ((h * 60 + m) * 60 + s) * 1000;
Random random = new Random();
long rowsInserted = 0;
long i = 0;
while (i < recordsPerTable)
{
for (long table = start; table <= end; ++table)
{
long inserted = i;
sql.Clear();
sql.Append("INSERT INTO ").
Append(this.dbName).Append(".").Append(this.tablePrefix).Append(table).
Append(" VALUES");
if (recordsPerTable < batchRows)
{
batchRows = recordsPerTable;
}
for (int batch = 0; batch < batchRows; ++batch)
{
long writeTimeStamp = beginTimestamp + i + batch;
int rnd = 100;
if (this.order == false)
{
rnd = random.Next(1, 100);
if (rnd <= this.rateOfOutorder)
{
writeTimeStamp = writeTimeStamp + rnd * 10000;
DebugPrint("### ");
}
DebugPrintFormat("order:{0} rnd:{1} timestamp:{2}\n", this.order, rnd, writeTimeStamp);
}
else
{
DebugPrintFormat("order:{0} timestamp:{1}\n", this.order, writeTimeStamp);
}
sql.Append("(")
.Append(writeTimeStamp)
.Append(", 1, -2, -3,")
.Append(i + batch - 127)
.Append(", -5, -6, -7, 'abc', 'def', 254, 65534,")
.Append(4294967294 - (uint)i - (uint)batch)
.Append(",")
.Append(18446744073709551614 - (ulong)i - (ulong)batch)
.Append(")");
}
VerbosePrint(sql.ToString() + "\n");
IntPtr res = TDengine.Query(this.conn, sql.ToString());
if ((res == IntPtr.Zero) || (TDengine.ErrorNo(res) != 0))
{
Console.Write(sql.ToString() + " failure, ");
if (res != IntPtr.Zero) {
Console.Write("reason: " + TDengine.Error(res));
}
Console.WriteLine("");
}
inserted += this.batchRows;
int affectRows = TDengine.AffectRows(res);
rowsInserted += affectRows;
TDengine.FreeResult(res);
if (table == end)
{
i = inserted;
}
}
}
}
}
public class CreateTableThread
{
public long id { set; get; }
public long start { set; get; }
public long end { set; get; }
public string dbName { set; get; }
public IntPtr conn { set; get; }
public string tablePrefix { set; get; }
public string stablePrefix { set; get; }
public bool verbose { set; get; }
public bool debug { set; get; }
public bool useStable { set; get; }
private void VerbosePrintFormat(string format, params object[] parameters)
{
if (verbose == true)
{
Console.Write(format, parameters);
}
}
private void VerbosePrint(string str)
{
if (verbose == true)
{
Console.Write(str);
}
}
private void DebugPrintFormat(string format, params object[] parameters)
{
if (debug == true)
{
Console.Write(format, parameters);
}
}
public void ThreadMain()
{
VerbosePrintFormat("CreateTable {0} from {1} to {2}\n", id, start, end);
StringBuilder sql = new StringBuilder();
for (long tableId = start; tableId <= end; tableId++)
{
sql.Clear();
sql = sql.Append("CREATE TABLE IF NOT EXISTS ").
Append(this.dbName).Append(".").Append(this.tablePrefix).Append(tableId);
if (useStable == true)
{
sql = sql.Append(" USING ").Append(this.dbName).Append(".").Append(this.stablePrefix).
Append(" TAGS(").Append(tableId).Append(")");
}
else
{
sql = sql.Append("(ts timestamp, v1 bool, v2 tinyint, v3 smallint, v4 int, v5 bigint, v6 float, v7 double, v8 binary(10), v9 nchar(10), v10 tinyint unsigned, v11 smallint unsigned, v12 int unsigned, v13 bigint unsigned)");
}
IntPtr res = TDengine.Query(this.conn, sql.ToString());
if ((res == IntPtr.Zero) || (TDengine.ErrorNo(res) != 0))
{
Console.Write(sql.ToString() + " failure, ");
if (res != IntPtr.Zero) {
Console.Write("reason: " + TDengine.Error(res));
}
Console.WriteLine("");
CleanAndExitProgram(1);
}
else
{
VerbosePrint(sql.ToString() + " success\n");
}
TDengine.FreeResult(res);
}
}
}
}
}
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="TDengine.Connector" Version="1.0.2" />
</ItemGroup>
</Project>
# 如何在 windows环境下使用jdbc进行TDengine应用开发
本文以windows环境为例,介绍java如何进行TDengine开发应用
## 环境准备
(1)安装jdk
官网下载jdk-1.8,下载页面:https://www.oracle.com/java/technologies/javase/javase-jdk8-downloads.html
安装,配置环境变量,把jdk加入到环境变量里。
命令行内查看java的版本。
```shell
>java -version
java version "1.8.0_131"
Java(TM) SE Runtime Environment (build 1.8.0_131-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.131-b11, mixed mode)
```
(2)安装配置maven
官网下载maven,下载地址:http://maven.apache.org/download.cgi
配置环境变量MAVEN_HOME,将MAVEN_HOME/bin添加到PATH
命令行里查看maven的版本
```shell
>mvn --version
Apache Maven 3.5.0 (ff8f5e7444045639af65f6095c62210b5713f426; 2017-04-04T03:39:06+08:00)
Maven home: D:\apache-maven-3.5.0\bin\..
Java version: 1.8.0_131, vendor: Oracle Corporation
Java home: C:\Program Files\Java\jdk1.8.0_131\jre
Default locale: zh_CN, platform encoding: GBK
OS name: "windows 10", version: "10.0", arch: "amd64", family: "windows"
```
为了加快maven下载依赖的速度,可以为maven配置mirror,修改MAVEN_HOME\config\settings.xml文件
```xml
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
<!-- 配置本地maven仓库的路径 -->
<localRepository>D:\apache-maven-localRepository</localRepository>
<mirrors>
<!-- 配置阿里云Maven镜像仓库 -->
<mirror>
<id>alimaven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>
</mirrors>
<profiles>
<!-- 配置jdk,maven会默认使用java1.8 -->
<profile>
<id>jdk-1.8</id>
<activation>
<activeByDefault>true</activeByDefault>
<jdk>1.8</jdk>
</activation>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
</properties>
</profile>
</profiles>
</settings>
```
(3)在linux服务器上安装TDengine-server
在taosdata官网下载TDengine-server,下载地址:https://www.taosdata.com/cn/all-downloads/
在linux服务器上安装TDengine-server
```shell
# tar -zxvf package/TDengine-server-2.0.1.1-Linux-x64.tar.gz
# cd TDengine-server/
# ./install.sh
```
启动taosd
```shell
# systemctl start taosd
```
在server上用taos连接taosd
```shell
# taos
taos> show dnodes;
id | end_point | vnodes | cores | status | role | create_time |
==================================================================================================================
1 | td01:6030 | 2 | 4 | ready | any | 2020-08-19 18:40:25.045 |
Query OK, 1 row(s) in set (0.005765s)
```
如果可以正确连接到taosd实例,并打印出databases的信息,说明TDengine的server已经正确启动。这里查看server的hostname
```shell
# hostname -f
td01
```
注意,如果安装TDengine后,使用默认的taos.cfg配置文件,taosd会使用当前server的hostname创建dnode实例。之后,在client也需要使用这个hostname来连接taosd。
(4)在windows上安装TDengine-client
在taosdata官网下载taos客户端,下载地址:
https://www.taosdata.com/cn/all-downloads/
下载后,双击exe安装。
修改client的hosts文件(C:\Windows\System32\drivers\etc\hosts),将server的hostname和ip配置到client的hosts文件中
```
192.168.236.136 td01
```
配置完成后,在命令行内使用taos shell连接server端
```shell
C:\TDengine>taos -h td01
Welcome to the TDengine shell from Linux, Client Version:2.0.1.1
Copyright (c) 2017 by TAOS Data, Inc. All rights reserved.
taos> show databases;
name | created_time | ntables | vgroups | replica | quorum | days | keep0,keep1,keep(D) | cache(MB) | blocks | minrows | maxrows | wallevel | fsync | comp | precision | status |
===================================================================================================================================================================================================================================================================
test | 2020-08-19 18:43:50.731 | 1 | 1 | 1 | 1 | 2 | 3650,3650,3650 | 16 | 6 | 100 | 4096 | 1 | 3000 | 2 | ms | ready |
log | 2020-08-19 18:40:28.064 | 4 | 1 | 1 | 1 | 10 | 30,30,30 | 1 | 3 | 100 | 4096 | 1 | 3000 | 2 | us | ready |
Query OK, 2 row(s) in set (0.068000s)
```
如果windows上的client能够正常连接,并打印database信息,说明client可以正常连接server了。
## 应用开发
(1)新建maven工程,在pom.xml中引入taos-jdbcdriver依赖。
```xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.taosdata.demo</groupId>
<artifactId>JdbcDemo</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>com.taosdata.jdbc</groupId>
<artifactId>taos-jdbcdriver</artifactId>
<version>2.0.8</version>
</dependency>
</dependencies>
</project>
```
(2)使用jdbc查询TDengine数据库
下面是示例代码:
```java
public class JdbcDemo {
public static void main(String[] args) throws Exception {
Connection conn = getConn();
Statement stmt = conn.createStatement();
// create database
stmt.executeUpdate("create database if not exists db");
// use database
stmt.executeUpdate("use db");
// create table
stmt.executeUpdate("create table if not exists tb (ts timestamp, temperature int, humidity float)");
// insert data
int affectedRows = stmt.executeUpdate("insert into tb values(now, 23, 10.3) (now + 1s, 20, 9.3)");
System.out.println("insert " + affectedRows + " rows.");
// query data
ResultSet resultSet = stmt.executeQuery("select * from tb");
Timestamp ts = null;
int temperature = 0;
float humidity = 0;
while(resultSet.next()){
ts = resultSet.getTimestamp(1);
temperature = resultSet.getInt(2);
humidity = resultSet.getFloat("humidity");
System.out.printf("%s, %d, %s\n", ts, temperature, humidity);
}
}
public static Connection getConn() throws Exception{
Class.forName("com.taosdata.jdbc.TSDBDriver");
String jdbcUrl = "jdbc:TAOS://td01:0/log?user=root&password=taosdata";
Properties connProps = new Properties();
connProps.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
connProps.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8");
connProps.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8");
Connection conn = DriverManager.getConnection(jdbcUrl, connProps);
return conn;
}
}
```
(3)测试jdbc访问tdengine的sever实例
console输出:
```
insert 2 rows.
2020-08-26 00:06:34.575, 23, 10.3
2020-08-26 00:06:35.575, 20, 9.3
```
## 指南
(1)如何设置主机名和hosts
在server上查看hostname和fqdn
```shell
查看hostname
# hostname
taos-server
查看fqdn
# hostname -f
taos-server
```
windows下hosts文件位于:
C:\\Windows\System32\drivers\etc\hosts
修改hosts文件,添加server的ip和hostname
```s
192.168.56.101 node5
```
(2)什么是fqdn?
> 什么是FQDN?
>
> FQDN(Full qualified domain name)全限定域名,fqdn由2部分组成:hostname+domainname。
>
> 例如,一个邮件服务器的fqdn可能是:mymail.somecollege.edu,其中mymail是hostname(主机名),somcollege.edu是domainname(域名)。本例中,.edu是顶级域名,.somecollege是二级域名。
>
> 当连接服务器时,必须指定fqdn,然后,dns服务器通过查看dns表,将hostname解析为相应的ip地址。如果只指定hostname(不指定domainname),应用程序可能服务解析主机名。因为如果你试图访问不在本地的远程服务器时,本地的dns服务器和可能没有远程服务器的hostname列表。
>
> 参考:https://kb.iu.edu/d/aiuv
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.taosdata.jdbc</groupId>
<artifactId>JDBCDemo</artifactId>
<version>SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<project.assembly.dir>src/main/resources/assembly</project.assembly.dir>
</properties>
<dependencies>
<dependency>
<groupId>com.taosdata.jdbc</groupId>
<artifactId>taos-jdbcdriver</artifactId>
<version>2.0.36</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.3.0</version>
<executions>
<!-- jdbcDemo -->
<execution>
<id>JdbcDemo</id>
<configuration>
<finalName>JdbcDemo</finalName>
<archive>
<manifest>
<mainClass>com.taosdata.example.JdbcDemo</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
<execution>
<id>JdbcRestfulDemo</id>
<configuration>
<finalName>JdbcRestfulDemo</finalName>
<archive>
<manifest>
<mainClass>com.taosdata.example.JdbcRestfulDemo</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
<execution>
<id>SubscribeDemo</id>
<configuration>
<finalName>SubscribeDemo</finalName>
<archive>
<manifest>
<mainClass>com.taosdata.example.SubscribeDemo</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
</project>
# How to Run the JDBC Demo Code On Linux OS
TDengine's JDBC demo project is organized in a Maven way so that users can easily compile, package and run the project. If you don't have Maven on your server, you may install it using
```
sudo apt-get install maven
```
## Install TDengine Client
Make sure you have already installed a tdengine client on your current develop environment.
Download the tdengine package on our website: ``https://www.taosdata.com/cn/all-downloads/`` and install the client.
## Run jdbcDemo using mvn plugin
run command:
```
mvn clean compile exec:java -Dexec.mainClass="com.taosdata.example.JdbcDemo"
```
and run with your customed args
```
mvn clean compile exec:java -Dexec.mainClass="com.taosdata.example.JdbcDemo" -Dexec.args="-host [HOSTNAME]"
```
## Compile the Demo Code and Run It
To compile taos-jdbcdriver, go to the source directory ``TDengine/src/connector/jdbc`` and execute
```
mvn clean package -Dmaven.test.skip=true
```
To compile the demo project, go to the source directory ``TDengine/tests/examples/JDBC/JDBCDemo`` and execute
```
mvn clean package assembly:single
```
To run JDBCDemo.jar, go to ``TDengine/tests/examples/JDBC/JDBCDemo`` and execute
```
java -Djava.ext.dirs=../../../../src/connector/jdbc/target:$JAVA_HOME/jre/lib/ext -jar target/JDBCDemo-SNAPSHOT-jar-with-dependencies.jar -host [HOSTNAME]
```
package com.taosdata.example;
import java.sql.*;
import java.util.*;
public class BatchInsert {
private static final String host = "127.0.0.1";
private static final String user = "root";
private static final String password = "taosdata";
private static final String dbname = "test";
private static final String stbname = "stb";
private static final int tables= 100;
private static final int rows = 500;
private static final long ts = 1604877767000l;
private Connection conn;
private void init() {
// final String url = "jdbc:TAOS://" + host + ":6030/?user=" + user + "&password=" + password;
final String url = "jdbc:TAOS-RS://" + host + ":6041/?user=" + user + "&password=" + password;
// get connection
try {
Properties properties = new Properties();
properties.setProperty("charset", "UTF-8");
properties.setProperty("locale", "en_US.UTF-8");
properties.setProperty("timezone", "UTC-8");
System.out.println("get connection starting...");
conn = DriverManager.getConnection(url, properties);
if (conn != null){
System.out.println("[ OK ] Connection established.");
}
Statement stmt = conn.createStatement();
stmt.execute("drop database if exists " + dbname);
stmt.execute("create database if not exists " + dbname);
stmt.execute("use " + dbname);
stmt.execute("create table " + dbname + "." + stbname + "(ts timestamp, col int) tags(id int)");
} catch (SQLException e) {
e.printStackTrace();
}
}
private String generateSql() {
StringBuilder sb = new StringBuilder();
Random rand = new Random();
sb.append("insert into ");
for (int i = 0; i < tables; i++) {
sb.append(dbname + ".tb" + i + " using " + dbname + "." + stbname + " tags(" + i + ") values");
for (int j = 0; j < rows; j++) {
sb.append("(");
sb.append(ts + j);
sb.append(",");
sb.append(rand.nextInt(1000));
sb.append(") ");
}
}
return sb.toString();
}
private void executeQuery(String sql) {
try (Statement stmt = conn.createStatement()) {
long start = System.currentTimeMillis();
stmt.execute(sql);
long end = System.currentTimeMillis();
System.out.println("insert " + tables * rows + " records, cost " + (end - start)+ "ms");
} catch (SQLException ex) {
ex.printStackTrace();
}
}
public static void main(String[] args) {
BatchInsert bi = new BatchInsert();
String sql = bi.generateSql();
bi.init();
bi.executeQuery(sql);
}
}
package com.taosdata.example;
import com.taosdata.jdbc.TSDBDriver;
import java.sql.*;
import java.util.Properties;
public class ClientParameterSetting {
private static final String host = "127.0.0.1";
public static void main(String[] args) throws SQLException {
setParameterInJdbcUrl();
setParameterInProperties();
}
private static void setParameterInJdbcUrl() throws SQLException {
String jdbcUrl = "jdbc:TAOS://" + host + ":6030/?debugFlag=135&asyncLog=0";
Connection connection = DriverManager.getConnection(jdbcUrl, "root", "taosdata");
printDatabase(connection);
connection.close();
}
private static void setParameterInProperties() throws SQLException {
String jdbcUrl = "jdbc:TAOS://" + host + ":6030/";
Properties properties = new Properties();
properties.setProperty("user", "root");
properties.setProperty("password", "taosdata");
properties.setProperty("debugFlag", "135");
properties.setProperty("asyncLog", "0");
properties.setProperty("maxSQLLength", "1048576");
try (Connection conn = DriverManager.getConnection(jdbcUrl, properties)) {
printDatabase(conn);
}
}
private static void printDatabase(Connection connection) throws SQLException {
try (Statement stmt = connection.createStatement()) {
ResultSet rs = stmt.executeQuery("show databases");
ResultSetMetaData meta = rs.getMetaData();
while (rs.next()) {
for (int i = 1; i <= meta.getColumnCount(); i++) {
System.out.print(meta.getColumnLabel(i) + ": " + rs.getString(i) + "\t");
}
System.out.println();
}
}
}
}
package com.taosdata.example;
import java.sql.*;
import java.util.Properties;
public class JdbcDemo {
private static String host;
private static final String dbName = "test";
private static final String tbName = "weather";
private static final String user = "root";
private static final String password = "taosdata";
private Connection connection;
public static void main(String[] args) {
for (int i = 0; i < args.length; i++) {
if ("-host".equalsIgnoreCase(args[i]) && i < args.length - 1)
host = args[++i];
}
if (host == null) {
printHelp();
}
JdbcDemo demo = new JdbcDemo();
demo.init();
demo.createDatabase();
demo.useDatabase();
demo.dropTable();
demo.createTable();
demo.insert();
demo.select();
demo.dropTable();
demo.close();
}
private void init() {
final String url = "jdbc:TAOS://" + host + ":6030/?user=" + user + "&password=" + password;
// get connection
try {
Properties properties = new Properties();
properties.setProperty("charset", "UTF-8");
properties.setProperty("locale", "en_US.UTF-8");
properties.setProperty("timezone", "UTC-8");
System.out.println("get connection starting...");
connection = DriverManager.getConnection(url, properties);
if (connection != null)
System.out.println("[ OK ] Connection established.");
} catch (SQLException e) {
e.printStackTrace();
}
}
private void createDatabase() {
String sql = "create database if not exists " + dbName;
exuete(sql);
}
private void useDatabase() {
String sql = "use " + dbName;
exuete(sql);
}
private void dropTable() {
final String sql = "drop table if exists " + dbName + "." + tbName + "";
exuete(sql);
}
private void createTable() {
final String sql = "create table if not exists " + dbName + "." + tbName + " (ts timestamp, temperature float, humidity int)";
exuete(sql);
}
private void insert() {
final String sql = "insert into " + dbName + "." + tbName + " (ts, temperature, humidity) values(now, 20.5, 34)";
exuete(sql);
}
private void select() {
final String sql = "select * from " + dbName + "." + tbName;
executeQuery(sql);
}
private void close() {
try {
if (connection != null) {
this.connection.close();
System.out.println("connection closed.");
}
} catch (SQLException e) {
e.printStackTrace();
}
}
private void executeQuery(String sql) {
long start = System.currentTimeMillis();
try (Statement statement = connection.createStatement()) {
ResultSet resultSet = statement.executeQuery(sql);
long end = System.currentTimeMillis();
printSql(sql, true, (end - start));
printResult(resultSet);
} catch (SQLException e) {
long end = System.currentTimeMillis();
printSql(sql, false, (end - start));
e.printStackTrace();
}
}
private void printResult(ResultSet resultSet) throws SQLException {
ResultSetMetaData metaData = resultSet.getMetaData();
while (resultSet.next()) {
for (int i = 1; i <= metaData.getColumnCount(); i++) {
String columnLabel = metaData.getColumnLabel(i);
String value = resultSet.getString(i);
System.out.printf("%s: %s\t", columnLabel, value);
}
System.out.println();
}
}
private void printSql(String sql, boolean succeed, long cost) {
System.out.println("[ " + (succeed ? "OK" : "ERROR!") + " ] time cost: " + cost + " ms, execute statement ====> " + sql);
}
private void exuete(String sql) {
long start = System.currentTimeMillis();
try (Statement statement = connection.createStatement()) {
boolean execute = statement.execute(sql);
long end = System.currentTimeMillis();
printSql(sql, true, (end - start));
} catch (SQLException e) {
long end = System.currentTimeMillis();
printSql(sql, false, (end - start));
e.printStackTrace();
}
}
private static void printHelp() {
System.out.println("Usage: java -jar JDBCDemo.jar -host <hostname>");
System.exit(0);
}
}
package com.taosdata.example;
import java.sql.*;
import java.util.Properties;
public class JdbcRestfulDemo {
private static final String host = "localhost";
private static final String dbname = "test";
private static final String user = "root";
private static final String password = "taosdata";
public static void main(String[] args) {
try {
// use port 6041 in url when use JDBC-restful
String url = "jdbc:TAOS-RS://" + host + ":6041/?user=" + user + "&password=" + password;
Properties properties = new Properties();
properties.setProperty("charset", "UTF-8");
properties.setProperty("locale", "en_US.UTF-8");
properties.setProperty("timezone", "UTC-8");
Connection conn = DriverManager.getConnection(url, properties);
Statement stmt = conn.createStatement();
stmt.execute("drop database if exists " + dbname);
stmt.execute("create database if not exists " + dbname);
stmt.execute("use " + dbname);
stmt.execute("create table " + dbname + ".weather(ts timestamp, temperature float) tags(location nchar(64))");
stmt.executeUpdate("insert into t1 using " + dbname + ".weather tags('北京') values(now, 18.2)");
ResultSet rs = stmt.executeQuery("select * from " + dbname + ".weather");
ResultSetMetaData meta = rs.getMetaData();
while (rs.next()) {
for (int i = 1; i <= meta.getColumnCount(); i++) {
System.out.print(meta.getColumnLabel(i) + ": " + rs.getString(i) + "\t");
}
System.out.println();
}
rs.close();
stmt.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
package com.taosdata.example;
import com.taosdata.jdbc.TSDBPreparedStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Random;
public class ParameterBindingDemo {
private static final String host = "127.0.0.1";
private static final Random random = new Random(System.currentTimeMillis());
private static final int BINARY_COLUMN_SIZE = 20;
private static final String[] schemaList = {
"create table stable1(ts timestamp, f1 tinyint, f2 smallint, f3 int, f4 bigint) tags(t1 tinyint, t2 smallint, t3 int, t4 bigint)",
"create table stable2(ts timestamp, f1 float, f2 double) tags(t1 float, t2 double)",
"create table stable3(ts timestamp, f1 bool) tags(t1 bool)",
"create table stable4(ts timestamp, f1 binary(" + BINARY_COLUMN_SIZE + ")) tags(t1 binary(" + BINARY_COLUMN_SIZE + "))",
"create table stable5(ts timestamp, f1 nchar(" + BINARY_COLUMN_SIZE + ")) tags(t1 nchar(" + BINARY_COLUMN_SIZE + "))"
};
private static final int numOfSubTable = 10, numOfRow = 10;
public static void main(String[] args) throws SQLException {
String jdbcUrl = "jdbc:TAOS://" + host + ":6030/";
Connection conn = DriverManager.getConnection(jdbcUrl, "root", "taosdata");
init(conn);
bindInteger(conn);
bindFloat(conn);
bindBoolean(conn);
bindBytes(conn);
bindString(conn);
conn.close();
}
private static void init(Connection conn) throws SQLException {
try (Statement stmt = conn.createStatement()) {
stmt.execute("drop database if exists test_parabind");
stmt.execute("create database if not exists test_parabind");
stmt.execute("use test_parabind");
for (int i = 0; i < schemaList.length; i++) {
stmt.execute(schemaList[i]);
}
}
}
private static void bindInteger(Connection conn) throws SQLException {
String sql = "insert into ? using stable1 tags(?,?,?,?) values(?,?,?,?,?)";
try (TSDBPreparedStatement pstmt = conn.prepareStatement(sql).unwrap(TSDBPreparedStatement.class)) {
for (int i = 1; i <= numOfSubTable; i++) {
// set table name
pstmt.setTableName("t1_" + i);
// set tags
pstmt.setTagByte(0, Byte.parseByte(Integer.toString(random.nextInt(Byte.MAX_VALUE))));
pstmt.setTagShort(1, Short.parseShort(Integer.toString(random.nextInt(Short.MAX_VALUE))));
pstmt.setTagInt(2, random.nextInt(Integer.MAX_VALUE));
pstmt.setTagLong(3, random.nextLong());
// set columns
ArrayList<Long> tsList = new ArrayList<>();
long current = System.currentTimeMillis();
for (int j = 0; j < numOfRow; j++)
tsList.add(current + j);
pstmt.setTimestamp(0, tsList);
ArrayList<Byte> f1List = new ArrayList<>();
for (int j = 0; j < numOfRow; j++)
f1List.add(Byte.parseByte(Integer.toString(random.nextInt(Byte.MAX_VALUE))));
pstmt.setByte(1, f1List);
ArrayList<Short> f2List = new ArrayList<>();
for (int j = 0; j < numOfRow; j++)
f2List.add(Short.parseShort(Integer.toString(random.nextInt(Short.MAX_VALUE))));
pstmt.setShort(2, f2List);
ArrayList<Integer> f3List = new ArrayList<>();
for (int j = 0; j < numOfRow; j++)
f3List.add(random.nextInt(Integer.MAX_VALUE));
pstmt.setInt(3, f3List);
ArrayList<Long> f4List = new ArrayList<>();
for (int j = 0; j < numOfRow; j++)
f4List.add(random.nextLong());
pstmt.setLong(4, f4List);
// add column
pstmt.columnDataAddBatch();
}
// execute column
pstmt.columnDataExecuteBatch();
}
}
private static void bindFloat(Connection conn) throws SQLException {
String sql = "insert into ? using stable2 tags(?,?) values(?,?,?)";
TSDBPreparedStatement pstmt = conn.prepareStatement(sql).unwrap(TSDBPreparedStatement.class);
for (int i = 1; i <= numOfSubTable; i++) {
// set table name
pstmt.setTableName("t2_" + i);
// set tags
pstmt.setTagFloat(0, random.nextFloat());
pstmt.setTagDouble(1, random.nextDouble());
// set columns
ArrayList<Long> tsList = new ArrayList<>();
long current = System.currentTimeMillis();
for (int j = 0; j < numOfRow; j++)
tsList.add(current + j);
pstmt.setTimestamp(0, tsList);
ArrayList<Float> f1List = new ArrayList<>();
for (int j = 0; j < numOfRow; j++)
f1List.add(random.nextFloat());
pstmt.setFloat(1, f1List);
ArrayList<Double> f2List = new ArrayList<>();
for (int j = 0; j < numOfRow; j++)
f2List.add(random.nextDouble());
pstmt.setDouble(2, f2List);
// add column
pstmt.columnDataAddBatch();
}
// execute
pstmt.columnDataExecuteBatch();
// close if no try-with-catch statement is used
pstmt.close();
}
private static void bindBoolean(Connection conn) throws SQLException {
String sql = "insert into ? using stable3 tags(?) values(?,?)";
try (TSDBPreparedStatement pstmt = conn.prepareStatement(sql).unwrap(TSDBPreparedStatement.class)) {
for (int i = 1; i <= numOfSubTable; i++) {
// set table name
pstmt.setTableName("t3_" + i);
// set tags
pstmt.setTagBoolean(0, random.nextBoolean());
// set columns
ArrayList<Long> tsList = new ArrayList<>();
long current = System.currentTimeMillis();
for (int j = 0; j < numOfRow; j++)
tsList.add(current + j);
pstmt.setTimestamp(0, tsList);
ArrayList<Boolean> f1List = new ArrayList<>();
for (int j = 0; j < numOfRow; j++)
f1List.add(random.nextBoolean());
pstmt.setBoolean(1, f1List);
// add column
pstmt.columnDataAddBatch();
}
// execute
pstmt.columnDataExecuteBatch();
}
}
private static void bindBytes(Connection conn) throws SQLException {
String sql = "insert into ? using stable4 tags(?) values(?,?)";
try (TSDBPreparedStatement pstmt = conn.prepareStatement(sql).unwrap(TSDBPreparedStatement.class)) {
for (int i = 1; i <= numOfSubTable; i++) {
// set table name
pstmt.setTableName("t4_" + i);
// set tags
pstmt.setTagString(0, new String("abc"));
// set columns
ArrayList<Long> tsList = new ArrayList<>();
long current = System.currentTimeMillis();
for (int j = 0; j < numOfRow; j++)
tsList.add(current + j);
pstmt.setTimestamp(0, tsList);
ArrayList<String> f1List = new ArrayList<>();
for (int j = 0; j < numOfRow; j++) {
f1List.add(new String("abc"));
}
pstmt.setString(1, f1List, BINARY_COLUMN_SIZE);
// add column
pstmt.columnDataAddBatch();
}
// execute
pstmt.columnDataExecuteBatch();
}
}
private static void bindString(Connection conn) throws SQLException {
String sql = "insert into ? using stable5 tags(?) values(?,?)";
try (TSDBPreparedStatement pstmt = conn.prepareStatement(sql).unwrap(TSDBPreparedStatement.class)) {
for (int i = 1; i <= numOfSubTable; i++) {
// set table name
pstmt.setTableName("t5_" + i);
// set tags
pstmt.setTagNString(0, "北京-abc");
// set columns
ArrayList<Long> tsList = new ArrayList<>();
long current = System.currentTimeMillis();
for (int j = 0; j < numOfRow; j++)
tsList.add(current + j);
pstmt.setTimestamp(0, tsList);
ArrayList<String> f1List = new ArrayList<>();
for (int j = 0; j < numOfRow; j++) {
f1List.add("北京-abc");
}
pstmt.setNString(1, f1List, BINARY_COLUMN_SIZE);
// add column
pstmt.columnDataAddBatch();
}
// execute
pstmt.columnDataExecuteBatch();
}
}
}
package com.taosdata.example;
import com.taosdata.jdbc.TSDBConnection;
import com.taosdata.jdbc.TSDBDriver;
import com.taosdata.jdbc.TSDBResultSet;
import com.taosdata.jdbc.TSDBSubscribe;
import java.sql.DriverManager;
import java.sql.ResultSetMetaData;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
public class SubscribeDemo {
private static final String usage = "java -jar SubscribeDemo.jar -host <hostname> -database <database name> -topic <topic> -sql <sql>";
public static void main(String[] args) {
// parse args from command line
String host = "", database = "", topic = "", sql = "";
for (int i = 0; i < args.length; i++) {
if ("-host".equalsIgnoreCase(args[i]) && i < args.length - 1) {
host = args[++i];
}
if ("-database".equalsIgnoreCase(args[i]) && i < args.length - 1) {
database = args[++i];
}
if ("-topic".equalsIgnoreCase(args[i]) && i < args.length - 1) {
topic = args[++i];
}
if ("-sql".equalsIgnoreCase(args[i]) && i < args.length - 1) {
sql = args[++i];
}
}
if (host.isEmpty() || database.isEmpty() || topic.isEmpty() || sql.isEmpty()) {
System.out.println(usage);
return;
}
try {
Properties properties = new Properties();
properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
properties.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8");
properties.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8");
final String url = "jdbc:TAOS://" + host + ":6030/" + database + "?user=root&password=taosdata";
// get TSDBConnection
TSDBConnection connection = (TSDBConnection) DriverManager.getConnection(url, properties);
// create TSDBSubscribe
TSDBSubscribe sub = connection.subscribe(topic, sql, false);
int total = 0;
while (true) {
TSDBResultSet rs = sub.consume();
int count = 0;
ResultSetMetaData meta = rs.getMetaData();
while (rs.next()) {
for (int i = 1; i <= meta.getColumnCount(); i++) {
System.out.print(meta.getColumnLabel(i) + ": " + rs.getString(i) + "\t");
}
System.out.println();
count++;
}
total += count;
// System.out.printf("%d rows consumed, total %d\n", count, total);
if (total >= 10)
break;
TimeUnit.SECONDS.sleep(1);
}
sub.close(false);
connection.close();
} catch (Exception e) {
System.out.println("host: " + host + ", database: " + database + ", topic: " + topic + ", sql: " + sql);
e.printStackTrace();
}
}
}
\ No newline at end of file
HELP.md
target/
.mvn/
!**/src/main/**
!**/src/test/**
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
### VS Code ###
.vscode/
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.taosdata.jdbc</groupId>
<artifactId>SpringJdbcTemplate</artifactId>
<version>1.0-SNAPSHOT</version>
<name>SpringJdbcTemplate</name>
<url>http://www.taosdata.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.taosdata.jdbc</groupId>
<artifactId>taos-jdbcdriver</artifactId>
<version>2.0.18</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<archive>
<manifest>
<mainClass>com.taosdata.example.jdbcTemplate.App</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
## TDengine Spring JDBC Template Demo
`Spring JDBC Template` 简化了原生 JDBC Connection 获取释放等操作,使得操作数据库更加方便。
### 配置
修改 `src/main/resources/applicationContext.xml` 文件中 TDengine 的配置信息:
```xml
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.taosdata.jdbc.TSDBDriver"></property>
<property name="url" value="jdbc:TAOS://127.0.0.1:6030/log"></property>
<property name="username" value="root"></property>
<property name="password" value="taosdata"></property>
</bean>
<bean id = "jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate" >
<property name="dataSource" ref = "dataSource" ></property>
</bean>
```
### 打包运行
进入 `TDengine/tests/examples/JDBC/SpringJdbcTemplate` 目录下,执行以下命令可以生成可执行 jar 包。
```shell
mvn clean package
```
打包成功之后,进入 `target/` 目录下,执行以下命令就可运行测试:
```shell
java -jar SpringJdbcTemplate-1.0-SNAPSHOT-jar-with-dependencies.jar
```
\ No newline at end of file
package com.taosdata.example.jdbcTemplate;
import com.taosdata.example.jdbcTemplate.dao.ExecuteAsStatement;
import com.taosdata.example.jdbcTemplate.dao.WeatherDao;
import com.taosdata.example.jdbcTemplate.domain.Weather;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.sql.Timestamp;
import java.util.Date;
import java.util.List;
import java.util.Random;
public class App {
private static Random random = new Random(System.currentTimeMillis());
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
ExecuteAsStatement executor = ctx.getBean(ExecuteAsStatement.class);
// drop database
executor.doExecute("drop database if exists test");
// create database
executor.doExecute("create database if not exists test");
//use database
executor.doExecute("use test");
// create table
executor.doExecute("create table if not exists test.weather (ts timestamp, temperature int, humidity float)");
WeatherDao weatherDao = ctx.getBean(WeatherDao.class);
Weather weather = new Weather(new Timestamp(new Date().getTime()), random.nextFloat() * 50.0f, random.nextInt(100));
// insert rows
int affectedRows = weatherDao.add(weather);
System.out.println("insert success " + affectedRows + " rows.");
// query for list
int limit = 10, offset = 0;
List<Weather> weatherList = weatherDao.queryForList(limit, offset);
for (Weather w : weatherList) {
System.out.println(w);
}
}
}
package com.taosdata.example.jdbcTemplate.dao;
public interface ExecuteAsStatement{
void doExecute(String sql);
}
package com.taosdata.example.jdbcTemplate.dao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
@Repository
public class ExecuteAsStatementImpl implements ExecuteAsStatement {
@Autowired
private JdbcTemplate jdbcTemplate;
@Override
public void doExecute(String sql) {
jdbcTemplate.execute(sql);
}
}
package com.taosdata.example.jdbcTemplate.dao;
import com.taosdata.example.jdbcTemplate.domain.Weather;
import java.util.List;
public interface WeatherDao {
int add(Weather weather);
int[] batchInsert(List<Weather> weatherList);
List<Weather> queryForList(int limit, int offset);
int count();
}
package com.taosdata.example.jdbcTemplate.dao;
import com.taosdata.example.jdbcTemplate.domain.Weather;
import com.taosdata.example.jdbcTemplate.dao.WeatherDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.List;
@Repository
public class WeatherDaoImpl implements WeatherDao {
@Autowired
private JdbcTemplate jdbcTemplate;
@Override
public int add(Weather weather) {
return jdbcTemplate.update(
"insert into test.weather(ts, temperature, humidity) VALUES(?,?,?)",
weather.getTs(), weather.getTemperature(), weather.getHumidity()
);
}
@Override
public int[] batchInsert(List<Weather> weatherList) {
return jdbcTemplate.batchUpdate("insert into test.weather(ts, temperature, humidity) values( ?, ?, ?)", new BatchPreparedStatementSetter() {
@Override
public void setValues(PreparedStatement ps, int i) throws SQLException {
ps.setTimestamp(1, weatherList.get(i).getTs());
ps.setFloat(2, weatherList.get(i).getTemperature());
ps.setInt(3, weatherList.get(i).getHumidity());
}
@Override
public int getBatchSize() {
return weatherList.size();
}
});
}
@Override
public List<Weather> queryForList(int limit, int offset) {
return jdbcTemplate.query("select * from test.weather limit ? offset ?", (rs, rowNum) -> {
Timestamp ts = rs.getTimestamp("ts");
float temperature = rs.getFloat("temperature");
int humidity = rs.getInt("humidity");
return new Weather(ts, temperature, humidity);
}, limit, offset);
}
@Override
public int count() {
return jdbcTemplate.queryForObject("select count(*) from test.weather", Integer.class);
}
}
package com.taosdata.example.jdbcTemplate.domain;
import java.sql.Timestamp;
public class Weather {
private Timestamp ts;
private float temperature;
private int humidity;
public Weather() {
}
public Weather(Timestamp ts, float temperature, int humidity) {
this.ts = ts;
this.temperature = temperature;
this.humidity = humidity;
}
@Override
public String toString() {
return "Weather{" +
"ts=" + ts +
", temperature=" + temperature +
", humidity=" + humidity +
'}';
}
public Timestamp getTs() {
return ts;
}
public void setTs(Timestamp ts) {
this.ts = ts;
}
public float getTemperature() {
return temperature;
}
public void setTemperature(float temperature) {
this.temperature = temperature;
}
public int getHumidity() {
return humidity;
}
public void setHumidity(int humidity) {
this.humidity = humidity;
}
}
<?xml version="1.0" encoding="utf-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"
default-autowire="byName">
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.taosdata.jdbc.TSDBDriver"></property>
<property name="url" value="jdbc:TAOS://127.0.0.1:6030/"></property>
<property name="username" value="root"></property>
<property name="password" value="taosdata"></property>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<context:component-scan base-package="com.taosdata.example.jdbcTemplate"/>
</beans>
package com.taosdata.example.jdbcTemplate;
import com.taosdata.example.jdbcTemplate.dao.ExecuteAsStatement;
import com.taosdata.example.jdbcTemplate.dao.WeatherDao;
import com.taosdata.example.jdbcTemplate.domain.Weather;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import static org.junit.Assert.assertEquals;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath:applicationContext.xml"})
public class BatcherInsertTest {
@Autowired
private WeatherDao weatherDao;
@Autowired
private ExecuteAsStatement executor;
private static final int numOfRecordsPerTable = 1000;
private static long ts = 1496732686000l;
private static Random random = new Random(System.currentTimeMillis());
@Before
public void before() {
// drop database
executor.doExecute("drop database if exists test");
// create database
executor.doExecute("create database if not exists test");
//use database
executor.doExecute("use test");
// create table
executor.doExecute("create table if not exists test.weather (ts timestamp, temperature int, humidity float)");
}
@Test
public void batchInsert() {
List<Weather> weatherList = new ArrayList<>();
for (int i = 0; i < numOfRecordsPerTable; i++) {
ts += 1000;
Weather weather = new Weather(new Timestamp(ts), random.nextFloat() * 50.0f, random.nextInt(100));
weatherList.add(weather);
}
long start = System.currentTimeMillis();
weatherDao.batchInsert(weatherList);
long end = System.currentTimeMillis();
System.out.println("batch insert(" + numOfRecordsPerTable + " rows) time cost ==========> " + (end - start) + " ms");
int count = weatherDao.count();
assertEquals(count, numOfRecordsPerTable);
}
}
这个example中,我们适配了java常见的连接池:
* HikariCP(默认)
* druid
* dbcp
* c3p0
### 说明
ConnectionPoolDemo的程序逻辑:
1. 创建到host的connection连接池
2. 创建名称为pool_test的database,创建表超级weather,创建tableSize个子表
3. 总共插入totalNumber条数据。
### 如何运行这个例子:
```shell script
mvn clean package assembly:single
java -jar target/connectionPools-1.0-SNAPSHOT-jar-with-dependencies.jar -host 127.0.0.1
```
使用mvn运行ConnectionPoolDemo的main方法,可以指定参数
```shell script
Usage:
java -jar target/connectionPools-1.0-SNAPSHOT-jar-with-dependencies.jar
-host : hostname
-poolType <c3p0| dbcp| druid| hikari>
-poolSize <poolSize>
-tableSize <tableSize>
-batchSize : 每条Insert SQL中values的数量
-sleep : 每次插入任务提交后的
```
### 日志
使用log4j,将日志和错误分别输出到了debug.log和error.log中
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<groupId>com.taosdata.demo</groupId>
<artifactId>connectionPools</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<!-- taos -->
<dependency>
<groupId>com.taosdata.jdbc</groupId>
<artifactId>taos-jdbcdriver</artifactId>
<version>2.0.34</version>
</dependency>
<!-- druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.17</version>
</dependency>
<!-- HikariCP -->
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>3.2.0</version>
</dependency>
<!-- dbcp Connection Pool -->
<dependency>
<groupId>commons-pool</groupId>
<artifactId>commons-pool</artifactId>
<version>1.5.4</version>
</dependency>
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>
<!-- c3p0 -->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.4</version>
</dependency>
<!-- log4j -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.17.1</version>
</dependency>
<!-- proxool -->
<dependency>
<groupId>com.cloudhopper.proxool</groupId>
<artifactId>proxool</artifactId>
<version>0.9.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>ConnectionPoolDemo</id>
<configuration>
<finalName>ConnectionPoolDemo</finalName>
<archive>
<manifest>
<mainClass>com.taosdata.example.ConnectionPoolDemo</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
<execution>
<id>ProxoolDemo</id>
<configuration>
<finalName>ProxoolDemo</finalName>
<archive>
<manifest>
<mainClass>com.taosdata.example.ProxoolDemo</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
package com.taosdata.example;
import com.taosdata.example.common.InsertTask;
import com.taosdata.example.pool.C3p0Builder;
import com.taosdata.example.pool.DbcpBuilder;
import com.taosdata.example.pool.DruidPoolBuilder;
import com.taosdata.example.pool.HikariCpBuilder;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class ConnectionPoolDemo {
private static Logger logger = LogManager.getLogger(DruidPoolBuilder.class);
private static final String dbName = "pool_test";
private static String poolType = "hikari";
private static long totalSize = 1_000_000l;
private static long tableSize = 1;
private static long batchSize = 1;
private static int poolSize = 50;
private static int threadCount = 50;
private static int sleep = 0;
public static void main(String[] args) {
String host = null;
for (int i = 0; i < args.length; i++) {
if ("-host".equalsIgnoreCase(args[i]) && i < args.length - 1) {
host = args[++i];
}
if ("-poolType".equalsIgnoreCase(args[i]) && i < args.length - 1) {
poolType = args[++i];
}
if ("-recordNumber".equalsIgnoreCase(args[i]) && i < args.length - 1) {
totalSize = Long.parseLong(args[++i]);
}
if ("-tableNumber".equalsIgnoreCase(args[i]) && i < args.length - 1) {
tableSize = Long.parseLong(args[++i]);
}
if ("-batchNumber".equalsIgnoreCase(args[i]) && i < args.length - 1) {
batchSize = Long.parseLong(args[++i]);
}
}
if (host == null) {
System.out.println("Usage: java -jar XXX.jar -host <hostname> " +
"-poolType <c3p0| dbcp| druid| hikari>" +
"-recordNumber <number> " +
"-tableNumber <number> " +
"-batchNumber <number> " +
"-sleep <number> "
);
return;
}
DataSource dataSource;
switch (poolType) {
case "c3p0":
dataSource = C3p0Builder.getDataSource(host, poolSize);
break;
case "dbcp":
dataSource = DbcpBuilder.getDataSource(host, poolSize);
break;
case "druid":
dataSource = DruidPoolBuilder.getDataSource(host, poolSize);
break;
case "hikari":
default:
dataSource = HikariCpBuilder.getDataSource(host, poolSize);
poolType = "hikari";
}
logger.info(">>>>>>>>>>>>>> connection pool Type: " + poolType);
init(dataSource);
// try {
// Connection connection = dataSource.getConnection();
// Statement statement = connection.createStatement();
// String sql = "insert into " + dbName + ".t_1 values('2020-01-01 00:00:00.000',12.12,111)";
// int affectRows = statement.executeUpdate(sql);
// System.out.println("affectRows >>> " + affectRows);
// affectRows = statement.executeUpdate(sql);
// System.out.println("affectRows >>> " + affectRows);
// statement.close();
// connection.close();
// } catch (SQLException e) {
// e.printStackTrace();
// }
ExecutorService executor = Executors.newFixedThreadPool(threadCount);
for (long i = 0; i < totalSize / tableSize / batchSize; i++) {
executor.execute(new InsertTask(dataSource, dbName, tableSize, batchSize));
// sleep few seconds
try {
if (sleep > 0)
TimeUnit.MILLISECONDS.sleep(sleep);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
executor.shutdown();
}
private static void init(DataSource dataSource) {
try (Connection conn = dataSource.getConnection()) {
execute(conn, "drop database if exists " + dbName + "");
execute(conn, "create database if not exists " + dbName + "");
execute(conn, "use " + dbName + "");
execute(conn, "create table weather(ts timestamp, temperature float, humidity int) tags(location nchar(64), groupId int)");
for (int tb_ind = 1; tb_ind <= tableSize; tb_ind++) {
execute(conn, "create table t_" + tb_ind + " using weather tags('beijing'," + (tb_ind + 1) + ")");
}
logger.info(">>>>>>>>>>>>>>>>>>>>>>>>>>>> init finished.");
} catch (SQLException e) {
e.printStackTrace();
}
}
private static void execute(Connection con, String sql) {
try (Statement stmt = con.createStatement()) {
stmt.executeUpdate(sql);
logger.info("SQL >>> " + sql);
} catch (SQLException e) {
e.printStackTrace();
}
}
}
package com.taosdata.example;
import org.logicalcobwebs.proxool.ProxoolException;
import org.logicalcobwebs.proxool.configuration.JAXPConfigurator;
import java.sql.*;
public class ProxoolDemo {
public static void main(String[] args) {
String xml = parseConfigurationXml(args);
if (xml == null) {
printHelp();
System.exit(0);
}
try {
JAXPConfigurator.configure(xml, false);
Class.forName("org.logicalcobwebs.proxool.ProxoolDriver");
Connection connection = DriverManager.getConnection("proxool.ds");
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery("show databases");
ResultSetMetaData metaData = rs.getMetaData();
while (rs.next()) {
for (int i = 1; i <= metaData.getColumnCount(); i++) {
System.out.print(metaData.getColumnLabel(i) + ": " + rs.getString(i));
}
System.out.println();
}
stmt.close();
} catch (ClassNotFoundException | SQLException | ProxoolException e) {
e.printStackTrace();
}
}
private static String parseConfigurationXml(String[] args) {
String host = null;
for (int i = 0; i < args.length; i++) {
if ("--xml".equalsIgnoreCase(args[i]) && i < args.length - 1) {
host = args[++i];
}
}
return host;
}
private static void printHelp() {
System.out.println("Usage: java -jar ProxoolDemo.jar --xml [xml]");
}
}
package com.taosdata.example.common;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Random;
public class InsertTask implements Runnable {
private final Random random = new Random(System.currentTimeMillis());
private static final Logger logger = LogManager.getLogger(InsertTask.class);
private final DataSource ds;
private final String dbName;
private final long tableSize;
private final long batchSize;
public InsertTask(DataSource ds, String dbName, long tableSize, long batchSize) {
this.ds = ds;
this.dbName = dbName;
this.tableSize = tableSize;
this.batchSize = batchSize;
}
@Override
public void run() {
int affectedRows = 0;
long start = System.currentTimeMillis();
try (Connection conn = ds.getConnection(); Statement stmt = conn.createStatement()) {
for (int tb_index = 1; tb_index <= tableSize; tb_index++) {
StringBuilder sb = new StringBuilder();
sb.append("insert into ").append(dbName).append(".t_").append(tb_index).append("(ts, temperature, humidity) values ");
for (int i = 0; i < batchSize; i++) {
sb.append("(").append(start + i).append(", ").append(random.nextFloat() * 30).append(", ").append(random.nextInt(70)).append(") ");
}
logger.info("SQL >>> " + sb.toString());
affectedRows += stmt.executeUpdate(sb.toString());
}
} catch (SQLException e) {
e.printStackTrace();
}
logger.info(">>> affectedRows:" + affectedRows + " TimeCost:" + (System.currentTimeMillis() - start) + " ms");
}
}
package com.taosdata.example.pool;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import javax.sql.DataSource;
import java.beans.PropertyVetoException;
public class C3p0Builder {
public static DataSource getDataSource(String host, int poolSize) {
ComboPooledDataSource ds = new ComboPooledDataSource();
try {
ds.setDriverClass("com.taosdata.jdbc.TSDBDriver");
} catch (PropertyVetoException e) {
e.printStackTrace();
}
ds.setJdbcUrl("jdbc:TAOS://" + host + ":6030");
ds.setUser("root");
ds.setPassword("taosdata");
ds.setMinPoolSize(poolSize);
ds.setMaxPoolSize(poolSize);
ds.setAcquireIncrement(5);
return ds;
}
}
package com.taosdata.example.pool;
import org.apache.commons.dbcp.BasicDataSource;
import javax.sql.DataSource;
public class DbcpBuilder {
public static DataSource getDataSource(String host, int poolSize) {
BasicDataSource ds = new BasicDataSource();
ds.setDriverClassName("com.taosdata.jdbc.TSDBDriver");
ds.setUrl("jdbc:TAOS://" + host + ":6030");
ds.setUsername("root");
ds.setPassword("taosdata");
ds.setMaxActive(poolSize);
ds.setMinIdle(poolSize);
ds.setInitialSize(poolSize);
return ds;
}
}
package com.taosdata.example.pool;
import com.alibaba.druid.pool.DruidDataSource;
import javax.sql.DataSource;
public class DruidPoolBuilder {
public static DataSource getDataSource(String host, int poolSize) {
final String url = "jdbc:TAOS://" + host + ":6030";
DruidDataSource dataSource = new DruidDataSource();
// jdbc properties
dataSource.setDriverClassName("com.taosdata.jdbc.TSDBDriver");
dataSource.setUrl(url);
dataSource.setUsername("root");
dataSource.setPassword("taosdata");
// pool configurations
dataSource.setInitialSize(poolSize);
dataSource.setMinIdle(poolSize);
dataSource.setMaxActive(poolSize);
dataSource.setMaxWait(30000);
dataSource.setValidationQuery("select server_status()");
return dataSource;
}
}
package com.taosdata.example.pool;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import javax.sql.DataSource;
public class HikariCpBuilder {
public static DataSource getDataSource(String host, int poolSize) {
HikariConfig config = new HikariConfig();
// jdbc properties
config.setDriverClassName("com.taosdata.jdbc.TSDBDriver");
config.setJdbcUrl("jdbc:TAOS://" + host + ":6030");
config.setUsername("root");
config.setPassword("taosdata");
// pool configurations
config.setMinimumIdle(poolSize); //minimum number of idle connection
config.setMaximumPoolSize(poolSize); //maximum number of connection in the pool
config.setConnectionTimeout(30000); //maximum wait milliseconds for get connection from pool
config.setMaxLifetime(0); // maximum life time for each connection
config.setIdleTimeout(0); // max idle time for recycle idle connection
config.setConnectionTestQuery("select server_status()"); //validation query
HikariDataSource ds = new HikariDataSource(config);
return ds;
}
}
### 设置###
log4j.rootLogger=debug,stdout,DebugLog,ErrorLog
### 输出信息到控制抬 ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=[%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n
### 输出DEBUG 级别以上的日志到=logs/debug.log
log4j.appender.DebugLog=org.apache.log4j.DailyRollingFileAppender
log4j.appender.DebugLog.File=logs/debug.log
log4j.appender.DebugLog.Append=true
log4j.appender.DebugLog.Threshold=DEBUG
log4j.appender.DebugLog.layout=org.apache.log4j.PatternLayout
log4j.appender.DebugLog.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
### 输出ERROR 级别以上的日志到=logs/error.log
log4j.appender.ErrorLog=org.apache.log4j.DailyRollingFileAppender
log4j.appender.ErrorLog.File=logs/error.log
log4j.appender.ErrorLog.Append=true
log4j.appender.ErrorLog.Threshold=ERROR
log4j.appender.ErrorLog.layout=org.apache.log4j.PatternLayout
log4j.appender.ErrorLog.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<something-else-entirely>
<proxool>
<alias>ds</alias>
<!--数据源的别名-->
<driver-url>jdbc:TAOS-RS://127.0.0.1:6041/log</driver-url>
<!--url连接串-->
<driver-class>com.taosdata.jdbc.rs.RestfulDriver</driver-class>
<!--驱动类-->
<driver-properties>
<property name="user" value="root"/>
<property name="password" value="taosdata"/>
</driver-properties>
<!--最大连接数(默认5个),超过了这个连接数,再有请求时,就排在队列中等候,最大的等待请求数由maximum-new-connections决定 -->
<maximum-connection-count>100</maximum-connection-count>
<!-- 定义连接池中的最大连接数 -->
<maximum-active-time>100</maximum-active-time>
<!--最少保持的空闲连接数(默认2个)-->
<prototype-count>1</prototype-count>
<!--最小连接数(默认2个)-->
<minimum-connection-count>5</minimum-connection-count>
<!--proxool自动侦察各个连接状态的时间间隔(毫秒),侦察到空闲的连接就马上回收,超时的销毁 默认30秒-->
<house-keeping-sleep-time>30000</house-keeping-sleep-time>
<!--用于保持连接的测试语句 -->
<house-keeping-test-sql>select server_status()</house-keeping-test-sql>
</proxool>
</something-else-entirely>
\ No newline at end of file
README.md
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/
/*
* Copyright 2007-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.net.*;
import java.io.*;
import java.nio.channels.*;
import java.util.Properties;
public class MavenWrapperDownloader {
private static final String WRAPPER_VERSION = "0.5.6";
/**
* Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
*/
private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
+ WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
/**
* Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
* use instead of the default one.
*/
private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
".mvn/wrapper/maven-wrapper.properties";
/**
* Path where the maven-wrapper.jar will be saved to.
*/
private static final String MAVEN_WRAPPER_JAR_PATH =
".mvn/wrapper/maven-wrapper.jar";
/**
* Name of the property which should be used to override the default download url for the wrapper.
*/
private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
public static void main(String args[]) {
System.out.println("- Downloader started");
File baseDirectory = new File(args[0]);
System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
// If the maven-wrapper.properties exists, read it and check if it contains a custom
// wrapperUrl parameter.
File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
String url = DEFAULT_DOWNLOAD_URL;
if (mavenWrapperPropertyFile.exists()) {
FileInputStream mavenWrapperPropertyFileInputStream = null;
try {
mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
Properties mavenWrapperProperties = new Properties();
mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
} catch (IOException e) {
System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
} finally {
try {
if (mavenWrapperPropertyFileInputStream != null) {
mavenWrapperPropertyFileInputStream.close();
}
} catch (IOException e) {
// Ignore ...
}
}
}
System.out.println("- Downloading from: " + url);
File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
if (!outputFile.getParentFile().exists()) {
if (!outputFile.getParentFile().mkdirs()) {
System.out.println(
"- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
}
}
System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
try {
downloadFileFromURL(url, outputFile);
System.out.println("Done");
System.exit(0);
} catch (Throwable e) {
System.out.println("- Error downloading");
e.printStackTrace();
System.exit(1);
}
}
private static void downloadFileFromURL(String urlString, File destination) throws Exception {
if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
String username = System.getenv("MVNW_USERNAME");
char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
Authenticator.setDefault(new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
});
}
URL website = new URL(urlString);
ReadableByteChannel rbc;
rbc = Channels.newChannel(website.openStream());
FileOutputStream fos = new FileOutputStream(destination);
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
fos.close();
rbc.close();
}
}
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip
wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar
#!/bin/sh
# ----------------------------------------------------------------------------
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# ----------------------------------------------------------------------------
# ----------------------------------------------------------------------------
# Maven Start Up Batch script
#
# Required ENV vars:
# ------------------
# JAVA_HOME - location of a JDK home dir
#
# Optional ENV vars
# -----------------
# M2_HOME - location of maven2's installed home dir
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
# e.g. to debug Maven itself, use
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
# ----------------------------------------------------------------------------
if [ -z "$MAVEN_SKIP_RC" ]; then
if [ -f /etc/mavenrc ]; then
. /etc/mavenrc
fi
if [ -f "$HOME/.mavenrc" ]; then
. "$HOME/.mavenrc"
fi
fi
# OS specific support. $var _must_ be set to either true or false.
cygwin=false
darwin=false
mingw=false
case "$(uname)" in
CYGWIN*) cygwin=true ;;
MINGW*) mingw=true ;;
Darwin*)
darwin=true
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html
if [ -z "$JAVA_HOME" ]; then
if [ -x "/usr/libexec/java_home" ]; then
export JAVA_HOME="$(/usr/libexec/java_home)"
else
export JAVA_HOME="/Library/Java/Home"
fi
fi
;;
esac
if [ -z "$JAVA_HOME" ]; then
if [ -r /etc/gentoo-release ]; then
JAVA_HOME=$(java-config --jre-home)
fi
fi
if [ -z "$M2_HOME" ]; then
## resolve links - $0 may be a link to maven's home
PRG="$0"
# need this for relative symlinks
while [ -h "$PRG" ]; do
ls=$(ls -ld "$PRG")
link=$(expr "$ls" : '.*-> \(.*\)$')
if expr "$link" : '/.*' >/dev/null; then
PRG="$link"
else
PRG="$(dirname "$PRG")/$link"
fi
done
saveddir=$(pwd)
M2_HOME=$(dirname "$PRG")/..
# make it fully qualified
M2_HOME=$(cd "$M2_HOME" && pwd)
cd "$saveddir"
# echo Using m2 at $M2_HOME
fi
# For Cygwin, ensure paths are in UNIX format before anything is touched
if $cygwin; then
[ -n "$M2_HOME" ] &&
M2_HOME=$(cygpath --unix "$M2_HOME")
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=$(cygpath --unix "$JAVA_HOME")
[ -n "$CLASSPATH" ] &&
CLASSPATH=$(cygpath --path --unix "$CLASSPATH")
fi
# For Mingw, ensure paths are in UNIX format before anything is touched
if $mingw; then
[ -n "$M2_HOME" ] &&
M2_HOME="$( (
cd "$M2_HOME"
pwd
))"
[ -n "$JAVA_HOME" ] &&
JAVA_HOME="$( (
cd "$JAVA_HOME"
pwd
))"
fi
if [ -z "$JAVA_HOME" ]; then
javaExecutable="$(which javac)"
if [ -n "$javaExecutable" ] && ! [ "$(expr \"$javaExecutable\" : '\([^ ]*\)')" = "no" ]; then
# readlink(1) is not available as standard on Solaris 10.
readLink=$(which readlink)
if [ ! $(expr "$readLink" : '\([^ ]*\)') = "no" ]; then
if $darwin; then
javaHome="$(dirname \"$javaExecutable\")"
javaExecutable="$(cd \"$javaHome\" && pwd -P)/javac"
else
javaExecutable="$(readlink -f \"$javaExecutable\")"
fi
javaHome="$(dirname \"$javaExecutable\")"
javaHome=$(expr "$javaHome" : '\(.*\)/bin')
JAVA_HOME="$javaHome"
export JAVA_HOME
fi
fi
fi
if [ -z "$JAVACMD" ]; then
if [ -n "$JAVA_HOME" ]; then
if [ -x "$JAVA_HOME/jre/sh/java" ]; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
else
JAVACMD="$(which java)"
fi
fi
if [ ! -x "$JAVACMD" ]; then
echo "Error: JAVA_HOME is not defined correctly." >&2
echo " We cannot execute $JAVACMD" >&2
exit 1
fi
if [ -z "$JAVA_HOME" ]; then
echo "Warning: JAVA_HOME environment variable is not set."
fi
CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
# traverses directory structure from process work directory to filesystem root
# first directory with .mvn subdirectory is considered project base directory
find_maven_basedir() {
if [ -z "$1" ]; then
echo "Path not specified to find_maven_basedir"
return 1
fi
basedir="$1"
wdir="$1"
while [ "$wdir" != '/' ]; do
if [ -d "$wdir"/.mvn ]; then
basedir=$wdir
break
fi
# workaround for JBEAP-8937 (on Solaris 10/Sparc)
if [ -d "${wdir}" ]; then
wdir=$(
cd "$wdir/.."
pwd
)
fi
# end of workaround
done
echo "${basedir}"
}
# concatenates all lines of a file
concat_lines() {
if [ -f "$1" ]; then
echo "$(tr -s '\n' ' ' <"$1")"
fi
}
BASE_DIR=$(find_maven_basedir "$(pwd)")
if [ -z "$BASE_DIR" ]; then
exit 1
fi
##########################################################################################
# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
# This allows using the maven wrapper in projects that prohibit checking in binary data.
##########################################################################################
if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found .mvn/wrapper/maven-wrapper.jar"
fi
else
if [ "$MVNW_VERBOSE" = true ]; then
echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
fi
if [ -n "$MVNW_REPOURL" ]; then
jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
else
jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
fi
while IFS="=" read key value; do
case "$key" in wrapperUrl)
jarUrl="$value"
break
;;
esac
done <"$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
if [ "$MVNW_VERBOSE" = true ]; then
echo "Downloading from: $jarUrl"
fi
wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
if $cygwin; then
wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath")
fi
if command -v wget >/dev/null; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found wget ... using wget"
fi
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
wget "$jarUrl" -O "$wrapperJarPath"
else
wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath"
fi
elif command -v curl >/dev/null; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found curl ... using curl"
fi
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
curl -o "$wrapperJarPath" "$jarUrl" -f
else
curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
fi
else
if [ "$MVNW_VERBOSE" = true ]; then
echo "Falling back to using Java to download"
fi
javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
# For Cygwin, switch paths to Windows format before running javac
if $cygwin; then
javaClass=$(cygpath --path --windows "$javaClass")
fi
if [ -e "$javaClass" ]; then
if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
if [ "$MVNW_VERBOSE" = true ]; then
echo " - Compiling MavenWrapperDownloader.java ..."
fi
# Compiling the Java class
("$JAVA_HOME/bin/javac" "$javaClass")
fi
if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
# Running the downloader
if [ "$MVNW_VERBOSE" = true ]; then
echo " - Running MavenWrapperDownloader.java ..."
fi
("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
fi
fi
fi
fi
##########################################################################################
# End of extension
##########################################################################################
export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
if [ "$MVNW_VERBOSE" = true ]; then
echo $MAVEN_PROJECTBASEDIR
fi
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
# For Cygwin, switch paths to Windows format before running java
if $cygwin; then
[ -n "$M2_HOME" ] &&
M2_HOME=$(cygpath --path --windows "$M2_HOME")
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME")
[ -n "$CLASSPATH" ] &&
CLASSPATH=$(cygpath --path --windows "$CLASSPATH")
[ -n "$MAVEN_PROJECTBASEDIR" ] &&
MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR")
fi
# Provide a "standardized" way to retrieve the CLI args that will
# work with both Windows and non-Windows executions.
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
export MAVEN_CMD_LINE_ARGS
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
exec "$JAVACMD" \
$MAVEN_OPTS \
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
"-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
@REM ----------------------------------------------------------------------------
@REM Licensed to the Apache Software Foundation (ASF) under one
@REM or more contributor license agreements. See the NOTICE file
@REM distributed with this work for additional information
@REM regarding copyright ownership. The ASF licenses this file
@REM to you under the Apache License, Version 2.0 (the
@REM "License"); you may not use this file except in compliance
@REM with the License. You may obtain a copy of the License at
@REM
@REM https://www.apache.org/licenses/LICENSE-2.0
@REM
@REM Unless required by applicable law or agreed to in writing,
@REM software distributed under the License is distributed on an
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@REM KIND, either express or implied. See the License for the
@REM specific language governing permissions and limitations
@REM under the License.
@REM ----------------------------------------------------------------------------
@REM ----------------------------------------------------------------------------
@REM Maven Start Up Batch script
@REM
@REM Required ENV vars:
@REM JAVA_HOME - location of a JDK home dir
@REM
@REM Optional ENV vars
@REM M2_HOME - location of maven2's installed home dir
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
@REM e.g. to debug Maven itself, use
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
@REM ----------------------------------------------------------------------------
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
@echo off
@REM set title of command window
title %0
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
@REM set %HOME% to equivalent of $HOME
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
@REM Execute a user defined script before this one
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
:skipRcPre
@setlocal
set ERROR_CODE=0
@REM To isolate internal variables from possible post scripts, we use another setlocal
@setlocal
@REM ==== START VALIDATION ====
if not "%JAVA_HOME%" == "" goto OkJHome
echo.
echo Error: JAVA_HOME not found in your environment. >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
:OkJHome
if exist "%JAVA_HOME%\bin\java.exe" goto init
echo.
echo Error: JAVA_HOME is set to an invalid directory. >&2
echo JAVA_HOME = "%JAVA_HOME%" >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
@REM ==== END VALIDATION ====
:init
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
@REM Fallback to current working directory if not found.
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
set EXEC_DIR=%CD%
set WDIR=%EXEC_DIR%
:findBaseDir
IF EXIST "%WDIR%"\.mvn goto baseDirFound
cd ..
IF "%WDIR%"=="%CD%" goto baseDirNotFound
set WDIR=%CD%
goto findBaseDir
:baseDirFound
set MAVEN_PROJECTBASEDIR=%WDIR%
cd "%EXEC_DIR%"
goto endDetectBaseDir
:baseDirNotFound
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
cd "%EXEC_DIR%"
:endDetectBaseDir
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
@setlocal EnableExtensions EnableDelayedExpansion
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
:endReadAdditionalConfig
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
)
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
if exist %WRAPPER_JAR% (
if "%MVNW_VERBOSE%" == "true" (
echo Found %WRAPPER_JAR%
)
) else (
if not "%MVNW_REPOURL%" == "" (
SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
)
if "%MVNW_VERBOSE%" == "true" (
echo Couldn't find %WRAPPER_JAR%, downloading it ...
echo Downloading from: %DOWNLOAD_URL%
)
powershell -Command "&{"^
"$webclient = new-object System.Net.WebClient;"^
"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
"}"^
"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
"}"
if "%MVNW_VERBOSE%" == "true" (
echo Finished downloading %WRAPPER_JAR%
)
)
@REM End of extension
@REM Provide a "standardized" way to retrieve the CLI args that will
@REM work with both Windows and non-Windows executions.
set MAVEN_CMD_LINE_ARGS=%*
%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
if ERRORLEVEL 1 goto error
goto end
:error
set ERROR_CODE=1
:end
@endlocal & set ERROR_CODE=%ERROR_CODE%
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
@REM check for post script, once with legacy .bat ending and once with .cmd ending
if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
:skipRcPost
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
if "%MAVEN_BATCH_PAUSE%" == "on" pause
if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
exit /B %ERROR_CODE%
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.taosdata.example</groupId>
<artifactId>mybatisplus-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>mybatisplus-demo</name>
<description>Demo project for tdengine</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.1.2</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.17</version>
</dependency>
<dependency>
<groupId>com.taosdata.jdbc</groupId>
<artifactId>taos-jdbcdriver</artifactId>
<version>2.0.18</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.17</version>
<configuration>
<includes>
<include>**/*Test.java</include>
</includes>
<excludes>
<exclude>**/Abstract*.java</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
package com.taosdata.example.mybatisplusdemo;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScan("com.taosdata.example.mybatisplusdemo.mapper")
public class MybatisplusDemoApplication {
public static void main(String[] args) {
SpringApplication.run(MybatisplusDemoApplication.class, args);
}
}
\ No newline at end of file
package com.taosdata.example.mybatisplusdemo.config;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MybatisPlusConfig {
/** mybatis 3.4.1 pagination config start ***/
// @Bean
// public MybatisPlusInterceptor mybatisPlusInterceptor() {
// MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
// return interceptor;
// }
// @Bean
// public ConfigurationCustomizer configurationCustomizer() {
// return configuration -> configuration.setUseDeprecatedExecutor(false);
// }
@Bean
public PaginationInterceptor paginationInterceptor() {
// return new PaginationInterceptor();
PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
//TODO: mybatis-plus do not support TDengine, use postgresql Dialect
paginationInterceptor.setDialectType("postgresql");
return paginationInterceptor;
}
}
package com.taosdata.example.mybatisplusdemo.domain;
import lombok.Data;
import java.sql.Timestamp;
@Data
public class Temperature {
private Timestamp ts;
private float temperature;
private String location;
private int tbIndex;
}
package com.taosdata.example.mybatisplusdemo.domain;
import lombok.Data;
import java.sql.Timestamp;
@Data
public class Weather {
private Timestamp ts;
private float temperature;
private int humidity;
private String location;
}
package com.taosdata.example.mybatisplusdemo.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.taosdata.example.mybatisplusdemo.domain.Temperature;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Update;
public interface TemperatureMapper extends BaseMapper<Temperature> {
@Update("CREATE TABLE if not exists temperature(ts timestamp, temperature float) tags(location nchar(64), tbIndex int)")
int createSuperTable();
@Update("create table #{tbName} using temperature tags( #{location}, #{tbindex})")
int createTable(@Param("tbName") String tbName, @Param("location") String location, @Param("tbindex") int tbindex);
@Update("drop table if exists temperature")
void dropSuperTable();
@Insert("insert into t${tbIndex}(ts, temperature) values(#{ts}, #{temperature})")
int insertOne(Temperature one);
}
package com.taosdata.example.mybatisplusdemo.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.taosdata.example.mybatisplusdemo.domain.Weather;
public interface WeatherMapper extends BaseMapper<Weather> {
}
spring:
datasource:
driver-class-name: com.taosdata.jdbc.TSDBDriver
url: jdbc:TAOS://localhost:6030/mp_test?charset=UTF-8&locale=en_US.UTF-8&timezone=UTC-8
user: root
password: taosdata
druid:
initial-size: 5
min-idle: 5
max-active: 5
mybatis-plus:
configuration:
map-underscore-to-camel-case: false
logging:
level:
com:
taosdata:
example:
mybatisplusdemo:
mapper: debug
package com.taosdata.example.mybatisplusdemo.mapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.taosdata.example.mybatisplusdemo.domain.Temperature;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.sql.Timestamp;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class TemperatureMapperTest {
private static Random random = new Random(System.currentTimeMillis());
private static String[] locations = {"北京", "上海", "深圳", "广州", "杭州"};
@Before
public void before() {
mapper.dropSuperTable();
// create table temperature
mapper.createSuperTable();
// create table t_X using temperature
for (int i = 0; i < 10; i++) {
mapper.createTable("t" + i, locations[random.nextInt(locations.length)], i);
}
// insert into table
int affectRows = 0;
// insert 10 tables
for (int i = 0; i < 10; i++) {
// each table insert 5 rows
for (int j = 0; j < 5; j++) {
Temperature one = new Temperature();
one.setTs(new Timestamp(1605024000000l));
one.setTemperature(random.nextFloat() * 50);
one.setLocation("望京");
one.setTbIndex(i);
affectRows += mapper.insertOne(one);
}
}
Assert.assertEquals(50, affectRows);
}
@After
public void after() {
mapper.dropSuperTable();
}
@Autowired
private TemperatureMapper mapper;
/***
* test SelectList
* **/
@Test
public void testSelectList() {
List<Temperature> temperatureList = mapper.selectList(null);
temperatureList.forEach(System.out::println);
}
/***
* test InsertOne which is a custom metheod
* ***/
@Test
public void testInsert() {
Temperature one = new Temperature();
one.setTs(new Timestamp(1605024000000l));
one.setTemperature(random.nextFloat() * 50);
one.setLocation("望京");
int affectRows = mapper.insertOne(one);
Assert.assertEquals(1, affectRows);
}
/***
* test SelectOne
* **/
@Test
public void testSelectOne() {
QueryWrapper<Temperature> wrapper = new QueryWrapper<>();
wrapper.eq("location", "beijing");
Temperature one = mapper.selectOne(wrapper);
System.out.println(one);
Assert.assertNotNull(one);
}
/***
* test select By map
* ***/
@Test
public void testSelectByMap() {
Map<String, Object> map = new HashMap<>();
map.put("location", "beijing");
List<Temperature> temperatures = mapper.selectByMap(map);
Assert.assertEquals(1, temperatures.size());
}
/***
* test selectObjs
* **/
@Test
public void testSelectObjs() {
List<Object> ts = mapper.selectObjs(null);
System.out.println(ts);
}
/**
* test selectC ount
* **/
@Test
public void testSelectCount() {
int count = mapper.selectCount(null);
Assert.assertEquals(5, count);
}
/****
* 分页
*/
@Test
public void testSelectPage() {
IPage page = new Page(1, 2);
IPage<Temperature> temperatureIPage = mapper.selectPage(page, null);
System.out.println("total : " + temperatureIPage.getTotal());
System.out.println("pages : " + temperatureIPage.getPages());
for (Temperature temperature : temperatureIPage.getRecords()) {
System.out.println(temperature);
}
}
}
\ No newline at end of file
package com.taosdata.example.mybatisplusdemo.mapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.taosdata.example.mybatisplusdemo.domain.Weather;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.sql.Timestamp;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class WeatherMapperTest {
private static Random random = new Random(System.currentTimeMillis());
@Autowired
private WeatherMapper mapper;
@Test
public void testSelectList() {
List<Weather> weathers = mapper.selectList(null);
weathers.forEach(System.out::println);
}
@Test
public void testInsert() {
Weather one = new Weather();
one.setTs(new Timestamp(1605024000000l));
one.setTemperature(random.nextFloat() * 50);
one.setHumidity(random.nextInt(100));
one.setLocation("望京");
int affectRows = mapper.insert(one);
Assert.assertEquals(1, affectRows);
}
@Test
public void testSelectOne() {
QueryWrapper<Weather> wrapper = new QueryWrapper<>();
wrapper.eq("location", "beijing");
Weather one = mapper.selectOne(wrapper);
System.out.println(one);
Assert.assertEquals(12.22f, one.getTemperature(), 0.00f);
Assert.assertEquals("beijing", one.getLocation());
}
@Test
public void testSelectByMap() {
Map<String, Object> map = new HashMap<>();
map.put("location", "beijing");
List<Weather> weathers = mapper.selectByMap(map);
Assert.assertEquals(1, weathers.size());
}
@Test
public void testSelectObjs() {
List<Object> ts = mapper.selectObjs(null);
System.out.println(ts);
}
@Test
public void testSelectCount() {
int count = mapper.selectCount(null);
// Assert.assertEquals(5, count);
System.out.println(count);
}
@Test
public void testSelectPage() {
IPage page = new Page(1, 2);
IPage<Weather> weatherIPage = mapper.selectPage(page, null);
System.out.println("total : " + weatherIPage.getTotal());
System.out.println("pages : " + weatherIPage.getPages());
for (Weather weather : weatherIPage.getRecords()) {
System.out.println(weather);
}
}
}
\ No newline at end of file
# TDengine examples
| No. | Name | Describe |
| :--: | :----------------: | ------------------------------------------------------------ |
| 1 | JDBCDemo | Example codes for JDBC-JNI, JDBC-RESTful, Subscribe |
| 2 | connectionPools | Example codes for HikariCP, Druid, dbcp, c3p0 connection pools |
| 3 | SpringJdbcTemplate | Example codes for spring jdbcTemplate |
| 4 | mybatisplus-demo | Example codes for mybatis |
| 5 | springbootdemo | Example codes for springboot |
| 6 | taosdemo | This is an internal tool for testing Our JDBC-JNI, JDBC-RESTful, RESTful interfaces |
more detail: https://www.taosdata.com/cn/documentation20/connector/java
.mvn/
target/
!**/src/main/**
!**/src/test/**
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
### VS Code ###
.vscode/
#!/bin/sh
# ----------------------------------------------------------------------------
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# ----------------------------------------------------------------------------
# ----------------------------------------------------------------------------
# Maven2 Start Up Batch script
#
# Required ENV vars:
# ------------------
# JAVA_HOME - location of a JDK home dir
#
# Optional ENV vars
# -----------------
# M2_HOME - location of maven2's installed home dir
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
# e.g. to debug Maven itself, use
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
# ----------------------------------------------------------------------------
if [ -z "$MAVEN_SKIP_RC" ] ; then
if [ -f /etc/mavenrc ] ; then
. /etc/mavenrc
fi
if [ -f "$HOME/.mavenrc" ] ; then
. "$HOME/.mavenrc"
fi
fi
# OS specific support. $var _must_ be set to either true or false.
cygwin=false;
darwin=false;
mingw=false
case "`uname`" in
CYGWIN*) cygwin=true ;;
MINGW*) mingw=true;;
Darwin*) darwin=true
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html
if [ -z "$JAVA_HOME" ]; then
if [ -x "/usr/libexec/java_home" ]; then
export JAVA_HOME="`/usr/libexec/java_home`"
else
export JAVA_HOME="/Library/Java/Home"
fi
fi
;;
esac
if [ -z "$JAVA_HOME" ] ; then
if [ -r /etc/gentoo-release ] ; then
JAVA_HOME=`java-config --jre-home`
fi
fi
if [ -z "$M2_HOME" ] ; then
## resolve links - $0 may be a link to maven's home
PRG="$0"
# need this for relative symlinks
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG="`dirname "$PRG"`/$link"
fi
done
saveddir=`pwd`
M2_HOME=`dirname "$PRG"`/..
# make it fully qualified
M2_HOME=`cd "$M2_HOME" && pwd`
cd "$saveddir"
# echo Using m2 at $M2_HOME
fi
# For Cygwin, ensure paths are in UNIX format before anything is touched
if $cygwin ; then
[ -n "$M2_HOME" ] &&
M2_HOME=`cygpath --unix "$M2_HOME"`
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
[ -n "$CLASSPATH" ] &&
CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
fi
# For Mingw, ensure paths are in UNIX format before anything is touched
if $mingw ; then
[ -n "$M2_HOME" ] &&
M2_HOME="`(cd "$M2_HOME"; pwd)`"
[ -n "$JAVA_HOME" ] &&
JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
fi
if [ -z "$JAVA_HOME" ]; then
javaExecutable="`which javac`"
if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
# readlink(1) is not available as standard on Solaris 10.
readLink=`which readlink`
if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
if $darwin ; then
javaHome="`dirname \"$javaExecutable\"`"
javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
else
javaExecutable="`readlink -f \"$javaExecutable\"`"
fi
javaHome="`dirname \"$javaExecutable\"`"
javaHome=`expr "$javaHome" : '\(.*\)/bin'`
JAVA_HOME="$javaHome"
export JAVA_HOME
fi
fi
fi
if [ -z "$JAVACMD" ] ; then
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
else
JAVACMD="`which java`"
fi
fi
if [ ! -x "$JAVACMD" ] ; then
echo "Error: JAVA_HOME is not defined correctly." >&2
echo " We cannot execute $JAVACMD" >&2
exit 1
fi
if [ -z "$JAVA_HOME" ] ; then
echo "Warning: JAVA_HOME environment variable is not set."
fi
CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
# traverses directory structure from process work directory to filesystem root
# first directory with .mvn subdirectory is considered project base directory
find_maven_basedir() {
if [ -z "$1" ]
then
echo "Path not specified to find_maven_basedir"
return 1
fi
basedir="$1"
wdir="$1"
while [ "$wdir" != '/' ] ; do
if [ -d "$wdir"/.mvn ] ; then
basedir=$wdir
break
fi
# workaround for JBEAP-8937 (on Solaris 10/Sparc)
if [ -d "${wdir}" ]; then
wdir=`cd "$wdir/.."; pwd`
fi
# end of workaround
done
echo "${basedir}"
}
# concatenates all lines of a file
concat_lines() {
if [ -f "$1" ]; then
echo "$(tr -s '\n' ' ' < "$1")"
fi
}
BASE_DIR=`find_maven_basedir "$(pwd)"`
if [ -z "$BASE_DIR" ]; then
exit 1;
fi
##########################################################################################
# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
# This allows using the maven wrapper in projects that prohibit checking in binary data.
##########################################################################################
if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found .mvn/wrapper/maven-wrapper.jar"
fi
else
if [ "$MVNW_VERBOSE" = true ]; then
echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
fi
if [ -n "$MVNW_REPOURL" ]; then
jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar"
else
jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar"
fi
while IFS="=" read key value; do
case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
esac
done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
if [ "$MVNW_VERBOSE" = true ]; then
echo "Downloading from: $jarUrl"
fi
wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
if $cygwin; then
wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
fi
if command -v wget > /dev/null; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found wget ... using wget"
fi
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
wget "$jarUrl" -O "$wrapperJarPath"
else
wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath"
fi
elif command -v curl > /dev/null; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found curl ... using curl"
fi
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
curl -o "$wrapperJarPath" "$jarUrl" -f
else
curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
fi
else
if [ "$MVNW_VERBOSE" = true ]; then
echo "Falling back to using Java to download"
fi
javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
# For Cygwin, switch paths to Windows format before running javac
if $cygwin; then
javaClass=`cygpath --path --windows "$javaClass"`
fi
if [ -e "$javaClass" ]; then
if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
if [ "$MVNW_VERBOSE" = true ]; then
echo " - Compiling MavenWrapperDownloader.java ..."
fi
# Compiling the Java class
("$JAVA_HOME/bin/javac" "$javaClass")
fi
if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
# Running the downloader
if [ "$MVNW_VERBOSE" = true ]; then
echo " - Running MavenWrapperDownloader.java ..."
fi
("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
fi
fi
fi
fi
##########################################################################################
# End of extension
##########################################################################################
export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
if [ "$MVNW_VERBOSE" = true ]; then
echo $MAVEN_PROJECTBASEDIR
fi
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
# For Cygwin, switch paths to Windows format before running java
if $cygwin; then
[ -n "$M2_HOME" ] &&
M2_HOME=`cygpath --path --windows "$M2_HOME"`
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
[ -n "$CLASSPATH" ] &&
CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
[ -n "$MAVEN_PROJECTBASEDIR" ] &&
MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
fi
# Provide a "standardized" way to retrieve the CLI args that will
# work with both Windows and non-Windows executions.
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
export MAVEN_CMD_LINE_ARGS
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
exec "$JAVACMD" \
$MAVEN_OPTS \
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
"-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
@REM ----------------------------------------------------------------------------
@REM Licensed to the Apache Software Foundation (ASF) under one
@REM or more contributor license agreements. See the NOTICE file
@REM distributed with this work for additional information
@REM regarding copyright ownership. The ASF licenses this file
@REM to you under the Apache License, Version 2.0 (the
@REM "License"); you may not use this file except in compliance
@REM with the License. You may obtain a copy of the License at
@REM
@REM https://www.apache.org/licenses/LICENSE-2.0
@REM
@REM Unless required by applicable law or agreed to in writing,
@REM software distributed under the License is distributed on an
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@REM KIND, either express or implied. See the License for the
@REM specific language governing permissions and limitations
@REM under the License.
@REM ----------------------------------------------------------------------------
@REM ----------------------------------------------------------------------------
@REM Maven2 Start Up Batch script
@REM
@REM Required ENV vars:
@REM JAVA_HOME - location of a JDK home dir
@REM
@REM Optional ENV vars
@REM M2_HOME - location of maven2's installed home dir
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
@REM e.g. to debug Maven itself, use
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
@REM ----------------------------------------------------------------------------
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
@echo off
@REM set title of command window
title %0
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
@REM set %HOME% to equivalent of $HOME
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
@REM Execute a user defined script before this one
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
:skipRcPre
@setlocal
set ERROR_CODE=0
@REM To isolate internal variables from possible post scripts, we use another setlocal
@setlocal
@REM ==== START VALIDATION ====
if not "%JAVA_HOME%" == "" goto OkJHome
echo.
echo Error: JAVA_HOME not found in your environment. >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
:OkJHome
if exist "%JAVA_HOME%\bin\java.exe" goto init
echo.
echo Error: JAVA_HOME is set to an invalid directory. >&2
echo JAVA_HOME = "%JAVA_HOME%" >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
@REM ==== END VALIDATION ====
:init
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
@REM Fallback to current working directory if not found.
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
set EXEC_DIR=%CD%
set WDIR=%EXEC_DIR%
:findBaseDir
IF EXIST "%WDIR%"\.mvn goto baseDirFound
cd ..
IF "%WDIR%"=="%CD%" goto baseDirNotFound
set WDIR=%CD%
goto findBaseDir
:baseDirFound
set MAVEN_PROJECTBASEDIR=%WDIR%
cd "%EXEC_DIR%"
goto endDetectBaseDir
:baseDirNotFound
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
cd "%EXEC_DIR%"
:endDetectBaseDir
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
@setlocal EnableExtensions EnableDelayedExpansion
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
:endReadAdditionalConfig
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar"
FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
)
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
if exist %WRAPPER_JAR% (
if "%MVNW_VERBOSE%" == "true" (
echo Found %WRAPPER_JAR%
)
) else (
if not "%MVNW_REPOURL%" == "" (
SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar"
)
if "%MVNW_VERBOSE%" == "true" (
echo Couldn't find %WRAPPER_JAR%, downloading it ...
echo Downloading from: %DOWNLOAD_URL%
)
powershell -Command "&{"^
"$webclient = new-object System.Net.WebClient;"^
"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
"}"^
"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
"}"
if "%MVNW_VERBOSE%" == "true" (
echo Finished downloading %WRAPPER_JAR%
)
)
@REM End of extension
@REM Provide a "standardized" way to retrieve the CLI args that will
@REM work with both Windows and non-Windows executions.
set MAVEN_CMD_LINE_ARGS=%*
%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
if ERRORLEVEL 1 goto error
goto end
:error
set ERROR_CODE=1
:end
@endlocal & set ERROR_CODE=%ERROR_CODE%
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
@REM check for post script, once with legacy .bat ending and once with .cmd ending
if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
:skipRcPost
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
if "%MAVEN_BATCH_PAUSE%" == "on" pause
if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
exit /B %ERROR_CODE%
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.taosdata.example</groupId>
<artifactId>springbootdemo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springbootdemo</name>
<description>Demo project for using tdengine with Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>com.taosdata.jdbc</groupId>
<artifactId>taos-jdbcdriver</artifactId>
<version>2.0.34</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.17</version>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
## TDengine SpringBoot + Mybatis Demo
### 配置 application.properties
```properties
# datasource config
spring.datasource.driver-class-name=com.taosdata.jdbc.TSDBDriver
spring.datasource.url=jdbc:TAOS://127.0.0.1:6030/log
spring.datasource.username=root
spring.datasource.password=taosdata
spring.datasource.druid.initial-size=5
spring.datasource.druid.min-idle=5
spring.datasource.druid.max-active=5
# max wait time for get connection, ms
spring.datasource.druid.max-wait=60000
spring.datasource.druid.validation-query=select server_status();
spring.datasource.druid.validation-query-timeout=5000
spring.datasource.druid.test-on-borrow=false
spring.datasource.druid.test-on-return=false
spring.datasource.druid.test-while-idle=true
spring.datasource.druid.time-between-eviction-runs-millis=60000
spring.datasource.druid.min-evictable-idle-time-millis=600000
spring.datasource.druid.max-evictable-idle-time-millis=900000
# mybatis
mybatis.mapper-locations=classpath:mapper/*.xml
# log
logging.level.com.taosdata.jdbc.springbootdemo.dao=debug
```
### 主要功能
* 创建数据库和表
```xml
<!-- weatherMapper.xml -->
<update id="createDB" >
create database if not exists test;
</update>
<update id="createTable" >
create table if not exists test.weather(ts timestamp, temperature int, humidity float);
</update>
```
* 插入单条记录
```xml
<!-- weatherMapper.xml -->
<insert id="insert" parameterType="Weather" >
insert into test.weather (ts, temperature, humidity) values (now, #{temperature,jdbcType=INTEGER}, #{humidity,jdbcType=FLOAT})
</insert>
```
* 插入多条记录
```xml
<!-- weatherMapper.xml -->
<insert id="batchInsert" parameterType="java.util.List" >
insert into test.weather (ts, temperature, humidity) values
<foreach separator=" " collection="list" item="weather" index="index" >
(now + #{index}a, #{weather.temperature}, #{weather.humidity})
</foreach>
</insert>
```
* 分页查询
```xml
<!-- weatherMapper.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="WeatherMapper">
<resultMap id="BaseResultMap" type="Weather">
<id column="ts" jdbcType="TIMESTAMP" property="ts" />
<result column="temperature" jdbcType="INTEGER" property="temperature" />
<result column="humidity" jdbcType="FLOAT" property="humidity" />
</resultMap>
<sql id="Base_Column_List">
ts, temperature, humidity
</sql>
<select id="select" resultMap="BaseResultMap">
select
<include refid="Base_Column_List" />
from test.weather
order by ts desc
<if test="limit != null">
limit #{limit,jdbcType=BIGINT}
</if>
<if test="offset != null">
offset #{offset,jdbcType=BIGINT}
</if>
</select>
</mapper>
```
package com.taosdata.example.springbootdemo;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@MapperScan(basePackages = {"com.taosdata.example.springbootdemo"})
@SpringBootApplication
public class SpringbootdemoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootdemoApplication.class, args);
}
}
\ No newline at end of file
package com.taosdata.example.springbootdemo.controller;
import com.taosdata.example.springbootdemo.domain.Weather;
import com.taosdata.example.springbootdemo.service.WeatherService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
@RequestMapping("/weather")
@RestController
public class WeatherController {
@Autowired
private WeatherService weatherService;
@GetMapping("/lastOne")
public Weather lastOne() {
return weatherService.lastOne();
}
@GetMapping("/init")
public int init() {
return weatherService.init();
}
@GetMapping("/{limit}/{offset}")
public List<Weather> queryWeather(@PathVariable Long limit, @PathVariable Long offset) {
return weatherService.query(limit, offset);
}
@PostMapping("/{temperature}/{humidity}")
public int saveWeather(@PathVariable float temperature, @PathVariable float humidity) {
return weatherService.save(temperature, humidity);
}
@GetMapping("/count")
public int count() {
return weatherService.count();
}
@GetMapping("/subTables")
public List<String> getSubTables() {
return weatherService.getSubTables();
}
@GetMapping("/avg")
public List<Weather> avg() {
return weatherService.avg();
}
}
package com.taosdata.example.springbootdemo.dao;
import com.taosdata.example.springbootdemo.domain.Weather;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Map;
public interface WeatherMapper {
Map<String, Object> lastOne();
void dropDB();
void createDB();
void createSuperTable();
void createTable(Weather weather);
List<Weather> select(@Param("limit") Long limit, @Param("offset") Long offset);
int insert(Weather weather);
int count();
List<String> getSubTables();
List<Weather> avg();
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.taosdata.example.springbootdemo.dao.WeatherMapper">
<resultMap id="BaseResultMap" type="com.taosdata.example.springbootdemo.domain.Weather">
<id column="ts" jdbcType="TIMESTAMP" property="ts"/>
<result column="temperature" jdbcType="FLOAT" property="temperature"/>
<result column="humidity" jdbcType="FLOAT" property="humidity"/>
</resultMap>
<select id="lastOne" resultType="java.util.Map">
select last_row(*), location, groupid
from test.weather
</select>
<update id="dropDB">
drop
database if exists test
</update>
<update id="createDB">
create
database if not exists test
</update>
<update id="createSuperTable">
create table if not exists test.weather
(
ts
timestamp,
temperature
float,
humidity
float,
note
binary
(
64
)) tags
(
location nchar
(
64
), groupId int)
</update>
<update id="createTable" parameterType="com.taosdata.example.springbootdemo.domain.Weather">
create table if not exists test.t#{groupId} using test.weather tags
(
#{location},
#{groupId}
)
</update>
<select id="select" resultMap="BaseResultMap">
select * from test.weather order by ts desc
<if test="limit != null">
limit #{limit,jdbcType=BIGINT}
</if>
<if test="offset != null">
offset #{offset,jdbcType=BIGINT}
</if>
</select>
<insert id="insert" parameterType="com.taosdata.example.springbootdemo.domain.Weather">
insert into test.t#{groupId} (ts, temperature, humidity, note)
values (#{ts}, ${temperature}, ${humidity}, #{note})
</insert>
<select id="getSubTables" resultType="String">
select tbname
from test.weather
</select>
<select id="count" resultType="int">
select count(*)
from test.weather
</select>
<resultMap id="avgResultSet" type="com.taosdata.example.springbootdemo.domain.Weather">
<id column="ts" jdbcType="TIMESTAMP" property="ts"/>
<result column="avg(temperature)" jdbcType="FLOAT" property="temperature"/>
<result column="avg(humidity)" jdbcType="FLOAT" property="humidity"/>
</resultMap>
<select id="avg" resultMap="avgResultSet">
select avg(temperature), avg(humidity)
from test.weather interval(1m)
</select>
</mapper>
\ No newline at end of file
package com.taosdata.example.springbootdemo.domain;
import com.fasterxml.jackson.annotation.JsonFormat;
import java.sql.Timestamp;
public class Weather {
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSS", timezone = "GMT+8")
private Timestamp ts;
private Float temperature;
private Float humidity;
private String location;
private String note;
private int groupId;
public Weather() {
}
public Weather(Timestamp ts, float temperature, float humidity) {
this.ts = ts;
this.temperature = temperature;
this.humidity = humidity;
}
public Timestamp getTs() {
return ts;
}
public void setTs(Timestamp ts) {
this.ts = ts;
}
public Float getTemperature() {
return temperature;
}
public void setTemperature(Float temperature) {
this.temperature = temperature;
}
public Float getHumidity() {
return humidity;
}
public void setHumidity(Float humidity) {
this.humidity = humidity;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public int getGroupId() {
return groupId;
}
public void setGroupId(int groupId) {
this.groupId = groupId;
}
public String getNote() {
return note;
}
public void setNote(String note) {
this.note = note;
}
}
package com.taosdata.example.springbootdemo.service;
import com.taosdata.example.springbootdemo.dao.WeatherMapper;
import com.taosdata.example.springbootdemo.domain.Weather;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.sql.Timestamp;
import java.util.List;
import java.util.Map;
import java.util.Random;
@Service
public class WeatherService {
@Autowired
private WeatherMapper weatherMapper;
private Random random = new Random(System.currentTimeMillis());
private String[] locations = {"北京", "上海", "广州", "深圳", "天津"};
public int init() {
weatherMapper.dropDB();
weatherMapper.createDB();
weatherMapper.createSuperTable();
long ts = System.currentTimeMillis();
long thirtySec = 1000 * 30;
int count = 0;
for (int i = 0; i < 20; i++) {
Weather weather = new Weather(new Timestamp(ts + (thirtySec * i)), 30 * random.nextFloat(), random.nextInt(100));
weather.setLocation(locations[random.nextInt(locations.length)]);
weather.setGroupId(i % locations.length);
weather.setNote("note-" + i);
weatherMapper.createTable(weather);
count += weatherMapper.insert(weather);
}
return count;
}
public List<Weather> query(Long limit, Long offset) {
return weatherMapper.select(limit, offset);
}
public int save(float temperature, float humidity) {
Weather weather = new Weather();
weather.setTemperature(temperature);
weather.setHumidity(humidity);
return weatherMapper.insert(weather);
}
public int count() {
return weatherMapper.count();
}
public List<String> getSubTables() {
return weatherMapper.getSubTables();
}
public List<Weather> avg() {
return weatherMapper.avg();
}
public Weather lastOne() {
Map<String, Object> result = weatherMapper.lastOne();
long ts = (long) result.get("ts");
float temperature = (float) result.get("temperature");
float humidity = (float) result.get("humidity");
String note = (String) result.get("note");
int groupId = (int) result.get("groupid");
String location = (String) result.get("location");
Weather weather = new Weather(new Timestamp(ts), temperature, humidity);
weather.setNote(note);
weather.setGroupId(groupId);
weather.setLocation(location);
return weather;
}
}
package com.taosdata.example.springbootdemo.util;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import java.sql.Timestamp;
import java.util.Map;
@Aspect
@Component
public class TaosAspect {
@Around("execution(java.util.Map<String,Object> com.taosdata.example.springbootdemo.dao.*.*(..))")
public Object handleType(ProceedingJoinPoint joinPoint) {
Map<String, Object> result = null;
try {
result = (Map<String, Object>) joinPoint.proceed();
for (String key : result.keySet()) {
Object obj = result.get(key);
if (obj instanceof byte[]) {
obj = new String((byte[]) obj);
result.put(key, obj);
}
if (obj instanceof Timestamp) {
obj = ((Timestamp) obj).getTime();
result.put(key, obj);
}
}
} catch (Throwable e) {
e.printStackTrace();
}
return result;
}
}
# datasource config - JDBC-JNI
#spring.datasource.driver-class-name=com.taosdata.jdbc.TSDBDriver
#spring.datasource.url=jdbc:TAOS://localhost:6030/?timezone=UTC-8&charset=UTF-8&locale=en_US.UTF-8
#spring.datasource.username=root
#spring.datasource.password=taosdata
# datasource config - JDBC-RESTful
spring.datasource.driver-class-name=com.taosdata.jdbc.rs.RestfulDriver
spring.datasource.url=jdbc:TAOS-RS://localhsot:6041/test?timezone=UTC-8&charset=UTF-8&locale=en_US.UTF-8
spring.datasource.username=root
spring.datasource.password=taosdata
spring.datasource.druid.initial-size=5
spring.datasource.druid.min-idle=5
spring.datasource.druid.max-active=5
spring.datasource.druid.max-wait=30000
spring.datasource.druid.validation-query=select server_status();
spring.aop.auto=true
spring.aop.proxy-target-class=true
#mybatis
mybatis.mapper-locations=classpath:mapper/*.xml
logging.level.com.taosdata.jdbc.springbootdemo.dao=debug
HELP.md
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/
/*
* Copyright 2007-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.net.*;
import java.io.*;
import java.nio.channels.*;
import java.util.Properties;
public class MavenWrapperDownloader {
private static final String WRAPPER_VERSION = "0.5.6";
/**
* Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
*/
private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
+ WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
/**
* Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
* use instead of the default one.
*/
private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
".mvn/wrapper/maven-wrapper.properties";
/**
* Path where the maven-wrapper.jar will be saved to.
*/
private static final String MAVEN_WRAPPER_JAR_PATH =
".mvn/wrapper/maven-wrapper.jar";
/**
* Name of the property which should be used to override the default download url for the wrapper.
*/
private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
public static void main(String args[]) {
System.out.println("- Downloader started");
File baseDirectory = new File(args[0]);
System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
// If the maven-wrapper.properties exists, read it and check if it contains a custom
// wrapperUrl parameter.
File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
String url = DEFAULT_DOWNLOAD_URL;
if (mavenWrapperPropertyFile.exists()) {
FileInputStream mavenWrapperPropertyFileInputStream = null;
try {
mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
Properties mavenWrapperProperties = new Properties();
mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
} catch (IOException e) {
System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
} finally {
try {
if (mavenWrapperPropertyFileInputStream != null) {
mavenWrapperPropertyFileInputStream.close();
}
} catch (IOException e) {
// Ignore ...
}
}
}
System.out.println("- Downloading from: " + url);
File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
if (!outputFile.getParentFile().exists()) {
if (!outputFile.getParentFile().mkdirs()) {
System.out.println(
"- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
}
}
System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
try {
downloadFileFromURL(url, outputFile);
System.out.println("Done");
System.exit(0);
} catch (Throwable e) {
System.out.println("- Error downloading");
e.printStackTrace();
System.exit(1);
}
}
private static void downloadFileFromURL(String urlString, File destination) throws Exception {
if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
String username = System.getenv("MVNW_USERNAME");
char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
Authenticator.setDefault(new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
});
}
URL website = new URL(urlString);
ReadableByteChannel rbc;
rbc = Channels.newChannel(website.openStream());
FileOutputStream fos = new FileOutputStream(destination);
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
fos.close();
rbc.close();
}
}
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip
wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar
#!/bin/sh
# ----------------------------------------------------------------------------
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# ----------------------------------------------------------------------------
# ----------------------------------------------------------------------------
# Maven Start Up Batch script
#
# Required ENV vars:
# ------------------
# JAVA_HOME - location of a JDK home dir
#
# Optional ENV vars
# -----------------
# M2_HOME - location of maven2's installed home dir
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
# e.g. to debug Maven itself, use
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
# ----------------------------------------------------------------------------
if [ -z "$MAVEN_SKIP_RC" ]; then
if [ -f /etc/mavenrc ]; then
. /etc/mavenrc
fi
if [ -f "$HOME/.mavenrc" ]; then
. "$HOME/.mavenrc"
fi
fi
# OS specific support. $var _must_ be set to either true or false.
cygwin=false
darwin=false
mingw=false
case "$(uname)" in
CYGWIN*) cygwin=true ;;
MINGW*) mingw=true ;;
Darwin*)
darwin=true
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html
if [ -z "$JAVA_HOME" ]; then
if [ -x "/usr/libexec/java_home" ]; then
export JAVA_HOME="$(/usr/libexec/java_home)"
else
export JAVA_HOME="/Library/Java/Home"
fi
fi
;;
esac
if [ -z "$JAVA_HOME" ]; then
if [ -r /etc/gentoo-release ]; then
JAVA_HOME=$(java-config --jre-home)
fi
fi
if [ -z "$M2_HOME" ]; then
## resolve links - $0 may be a link to maven's home
PRG="$0"
# need this for relative symlinks
while [ -h "$PRG" ]; do
ls=$(ls -ld "$PRG")
link=$(expr "$ls" : '.*-> \(.*\)$')
if expr "$link" : '/.*' >/dev/null; then
PRG="$link"
else
PRG="$(dirname "$PRG")/$link"
fi
done
saveddir=$(pwd)
M2_HOME=$(dirname "$PRG")/..
# make it fully qualified
M2_HOME=$(cd "$M2_HOME" && pwd)
cd "$saveddir"
# echo Using m2 at $M2_HOME
fi
# For Cygwin, ensure paths are in UNIX format before anything is touched
if $cygwin; then
[ -n "$M2_HOME" ] &&
M2_HOME=$(cygpath --unix "$M2_HOME")
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=$(cygpath --unix "$JAVA_HOME")
[ -n "$CLASSPATH" ] &&
CLASSPATH=$(cygpath --path --unix "$CLASSPATH")
fi
# For Mingw, ensure paths are in UNIX format before anything is touched
if $mingw; then
[ -n "$M2_HOME" ] &&
M2_HOME="$( (
cd "$M2_HOME"
pwd
))"
[ -n "$JAVA_HOME" ] &&
JAVA_HOME="$( (
cd "$JAVA_HOME"
pwd
))"
fi
if [ -z "$JAVA_HOME" ]; then
javaExecutable="$(which javac)"
if [ -n "$javaExecutable" ] && ! [ "$(expr \"$javaExecutable\" : '\([^ ]*\)')" = "no" ]; then
# readlink(1) is not available as standard on Solaris 10.
readLink=$(which readlink)
if [ ! $(expr "$readLink" : '\([^ ]*\)') = "no" ]; then
if $darwin; then
javaHome="$(dirname \"$javaExecutable\")"
javaExecutable="$(cd \"$javaHome\" && pwd -P)/javac"
else
javaExecutable="$(readlink -f \"$javaExecutable\")"
fi
javaHome="$(dirname \"$javaExecutable\")"
javaHome=$(expr "$javaHome" : '\(.*\)/bin')
JAVA_HOME="$javaHome"
export JAVA_HOME
fi
fi
fi
if [ -z "$JAVACMD" ]; then
if [ -n "$JAVA_HOME" ]; then
if [ -x "$JAVA_HOME/jre/sh/java" ]; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
else
JAVACMD="$(which java)"
fi
fi
if [ ! -x "$JAVACMD" ]; then
echo "Error: JAVA_HOME is not defined correctly." >&2
echo " We cannot execute $JAVACMD" >&2
exit 1
fi
if [ -z "$JAVA_HOME" ]; then
echo "Warning: JAVA_HOME environment variable is not set."
fi
CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
# traverses directory structure from process work directory to filesystem root
# first directory with .mvn subdirectory is considered project base directory
find_maven_basedir() {
if [ -z "$1" ]; then
echo "Path not specified to find_maven_basedir"
return 1
fi
basedir="$1"
wdir="$1"
while [ "$wdir" != '/' ]; do
if [ -d "$wdir"/.mvn ]; then
basedir=$wdir
break
fi
# workaround for JBEAP-8937 (on Solaris 10/Sparc)
if [ -d "${wdir}" ]; then
wdir=$(
cd "$wdir/.."
pwd
)
fi
# end of workaround
done
echo "${basedir}"
}
# concatenates all lines of a file
concat_lines() {
if [ -f "$1" ]; then
echo "$(tr -s '\n' ' ' <"$1")"
fi
}
BASE_DIR=$(find_maven_basedir "$(pwd)")
if [ -z "$BASE_DIR" ]; then
exit 1
fi
##########################################################################################
# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
# This allows using the maven wrapper in projects that prohibit checking in binary data.
##########################################################################################
if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found .mvn/wrapper/maven-wrapper.jar"
fi
else
if [ "$MVNW_VERBOSE" = true ]; then
echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
fi
if [ -n "$MVNW_REPOURL" ]; then
jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
else
jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
fi
while IFS="=" read key value; do
case "$key" in wrapperUrl)
jarUrl="$value"
break
;;
esac
done <"$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
if [ "$MVNW_VERBOSE" = true ]; then
echo "Downloading from: $jarUrl"
fi
wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
if $cygwin; then
wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath")
fi
if command -v wget >/dev/null; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found wget ... using wget"
fi
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
wget "$jarUrl" -O "$wrapperJarPath"
else
wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath"
fi
elif command -v curl >/dev/null; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found curl ... using curl"
fi
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
curl -o "$wrapperJarPath" "$jarUrl" -f
else
curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
fi
else
if [ "$MVNW_VERBOSE" = true ]; then
echo "Falling back to using Java to download"
fi
javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
# For Cygwin, switch paths to Windows format before running javac
if $cygwin; then
javaClass=$(cygpath --path --windows "$javaClass")
fi
if [ -e "$javaClass" ]; then
if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
if [ "$MVNW_VERBOSE" = true ]; then
echo " - Compiling MavenWrapperDownloader.java ..."
fi
# Compiling the Java class
("$JAVA_HOME/bin/javac" "$javaClass")
fi
if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
# Running the downloader
if [ "$MVNW_VERBOSE" = true ]; then
echo " - Running MavenWrapperDownloader.java ..."
fi
("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
fi
fi
fi
fi
##########################################################################################
# End of extension
##########################################################################################
export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
if [ "$MVNW_VERBOSE" = true ]; then
echo $MAVEN_PROJECTBASEDIR
fi
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
# For Cygwin, switch paths to Windows format before running java
if $cygwin; then
[ -n "$M2_HOME" ] &&
M2_HOME=$(cygpath --path --windows "$M2_HOME")
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME")
[ -n "$CLASSPATH" ] &&
CLASSPATH=$(cygpath --path --windows "$CLASSPATH")
[ -n "$MAVEN_PROJECTBASEDIR" ] &&
MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR")
fi
# Provide a "standardized" way to retrieve the CLI args that will
# work with both Windows and non-Windows executions.
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
export MAVEN_CMD_LINE_ARGS
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
exec "$JAVACMD" \
$MAVEN_OPTS \
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
"-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
@REM ----------------------------------------------------------------------------
@REM Licensed to the Apache Software Foundation (ASF) under one
@REM or more contributor license agreements. See the NOTICE file
@REM distributed with this work for additional information
@REM regarding copyright ownership. The ASF licenses this file
@REM to you under the Apache License, Version 2.0 (the
@REM "License"); you may not use this file except in compliance
@REM with the License. You may obtain a copy of the License at
@REM
@REM https://www.apache.org/licenses/LICENSE-2.0
@REM
@REM Unless required by applicable law or agreed to in writing,
@REM software distributed under the License is distributed on an
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@REM KIND, either express or implied. See the License for the
@REM specific language governing permissions and limitations
@REM under the License.
@REM ----------------------------------------------------------------------------
@REM ----------------------------------------------------------------------------
@REM Maven Start Up Batch script
@REM
@REM Required ENV vars:
@REM JAVA_HOME - location of a JDK home dir
@REM
@REM Optional ENV vars
@REM M2_HOME - location of maven2's installed home dir
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
@REM e.g. to debug Maven itself, use
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
@REM ----------------------------------------------------------------------------
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
@echo off
@REM set title of command window
title %0
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
@REM set %HOME% to equivalent of $HOME
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
@REM Execute a user defined script before this one
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
:skipRcPre
@setlocal
set ERROR_CODE=0
@REM To isolate internal variables from possible post scripts, we use another setlocal
@setlocal
@REM ==== START VALIDATION ====
if not "%JAVA_HOME%" == "" goto OkJHome
echo.
echo Error: JAVA_HOME not found in your environment. >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
:OkJHome
if exist "%JAVA_HOME%\bin\java.exe" goto init
echo.
echo Error: JAVA_HOME is set to an invalid directory. >&2
echo JAVA_HOME = "%JAVA_HOME%" >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
@REM ==== END VALIDATION ====
:init
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
@REM Fallback to current working directory if not found.
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
set EXEC_DIR=%CD%
set WDIR=%EXEC_DIR%
:findBaseDir
IF EXIST "%WDIR%"\.mvn goto baseDirFound
cd ..
IF "%WDIR%"=="%CD%" goto baseDirNotFound
set WDIR=%CD%
goto findBaseDir
:baseDirFound
set MAVEN_PROJECTBASEDIR=%WDIR%
cd "%EXEC_DIR%"
goto endDetectBaseDir
:baseDirNotFound
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
cd "%EXEC_DIR%"
:endDetectBaseDir
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
@setlocal EnableExtensions EnableDelayedExpansion
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
:endReadAdditionalConfig
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
)
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
if exist %WRAPPER_JAR% (
if "%MVNW_VERBOSE%" == "true" (
echo Found %WRAPPER_JAR%
)
) else (
if not "%MVNW_REPOURL%" == "" (
SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
)
if "%MVNW_VERBOSE%" == "true" (
echo Couldn't find %WRAPPER_JAR%, downloading it ...
echo Downloading from: %DOWNLOAD_URL%
)
powershell -Command "&{"^
"$webclient = new-object System.Net.WebClient;"^
"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
"}"^
"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
"}"
if "%MVNW_VERBOSE%" == "true" (
echo Finished downloading %WRAPPER_JAR%
)
)
@REM End of extension
@REM Provide a "standardized" way to retrieve the CLI args that will
@REM work with both Windows and non-Windows executions.
set MAVEN_CMD_LINE_ARGS=%*
%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
if ERRORLEVEL 1 goto error
goto end
:error
set ERROR_CODE=1
:end
@endlocal & set ERROR_CODE=%ERROR_CODE%
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
@REM check for post script, once with legacy .bat ending and once with .cmd ending
if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
:skipRcPost
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
if "%MAVEN_BATCH_PAUSE%" == "on" pause
if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
exit /B %ERROR_CODE%
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.taosdata</groupId>
<artifactId>taosdemo</artifactId>
<version>2.0.1</version>
<name>taosdemo</name>
<packaging>jar</packaging>
<description>Demo project for TDengine</description>
<properties>
<spring.version>5.3.14</spring.version>
</properties>
<dependencies>
<!-- spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- HikariCP -->
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>3.4.5</version>
</dependency>
<!-- taos jdbc -->
<dependency>
<groupId>com.taosdata.jdbc</groupId>
<artifactId>taos-jdbcdriver</artifactId>
<version>2.0.20</version>
<!-- <scope>system</scope>-->
<!-- <systemPath>${project.basedir}/src/main/resources/lib/taos-jdbcdriver-2.0.15-dist.jar</systemPath>-->
</dependency>
<!-- fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.75</version>
</dependency>
<!-- mysql: just for test -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.16</version>
<scope>test</scope>
</dependency>
<!-- log4j -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.17.1</version>
</dependency>
<!-- junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.1</version>
<scope>test</scope>
</dependency>
<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.16</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
<include>**/*.jar</include>
</includes>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<archive>
<manifest>
<!-- 指定JdbcChecker为mainClass -->
<mainClass>com.taosdata.taosdemo.TaosDemoApplication</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
```
cd tests/examples/JDBC/taosdemo
mvn clean package -Dmaven.test.skip=true
# 先建表,再插入的
java -jar target/taosdemo-2.0-jar-with-dependencies.jar -host [hostname] -database [database] -doCreateTable true -superTableSQL "create table weather(ts timestamp, f1 int) tags(t1 nchar(4))" -numOfTables 1000 -numOfRowsPerTable 100000000 -numOfThreadsForInsert 10 -numOfTablesPerSQL 10 -numOfValuesPerSQL 100
# 不建表,直接插入的
java -jar target/taosdemo-2.0-jar-with-dependencies.jar -host [hostname] -database [database] -doCreateTable false -superTableSQL "create table weather(ts timestamp, f1 int) tags(t1 nchar(4))" -numOfTables 1000 -numOfRowsPerTable 100000000 -numOfThreadsForInsert 10 -numOfTablesPerSQL 10 -numOfValuesPerSQL 100
```
需求:
1. 可以读lowa的配置文件
2. 支持JDBC-JNI和JDBC-restful
3. 读取配置文件,持续执行查询
\ No newline at end of file
package com.taosdata.taosdemo;
import com.taosdata.taosdemo.components.DataSourceFactory;
import com.taosdata.taosdemo.components.JdbcTaosdemoConfig;
import com.taosdata.taosdemo.domain.SuperTableMeta;
import com.taosdata.taosdemo.service.DatabaseService;
import com.taosdata.taosdemo.service.SqlExecuteTask;
import com.taosdata.taosdemo.service.SubTableService;
import com.taosdata.taosdemo.service.SuperTableService;
import com.taosdata.taosdemo.service.data.SuperTableMetaGenerator;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import javax.sql.DataSource;
import java.io.IOException;
import java.time.Duration;
import java.time.Instant;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
public class TaosDemoApplication {
private static final Logger logger = LogManager.getLogger(TaosDemoApplication.class);
public static void main(String[] args) throws IOException {
// 读配置参数
JdbcTaosdemoConfig config = new JdbcTaosdemoConfig(args);
boolean isHelp = Arrays.asList(args).contains("--help");
if (isHelp || config.host == null || config.host.isEmpty()) {
JdbcTaosdemoConfig.printHelp();
System.exit(0);
}
// 初始化
final DataSource dataSource = DataSourceFactory.getInstance(config.host, config.port, config.user, config.password);
if (config.executeSql != null && !config.executeSql.isEmpty() && !config.executeSql.replaceAll("\\s", "").isEmpty()) {
Thread task = new Thread(new SqlExecuteTask(dataSource, config.executeSql));
task.start();
try {
task.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
return;
}
final DatabaseService databaseService = new DatabaseService(dataSource);
final SuperTableService superTableService = new SuperTableService(dataSource);
final SubTableService subTableService = new SubTableService(dataSource);
// 创建数据库
long start = System.currentTimeMillis();
Map<String, String> databaseParam = new HashMap<>();
databaseParam.put("database", config.database);
databaseParam.put("keep", Integer.toString(config.keep));
databaseParam.put("days", Integer.toString(config.days));
databaseParam.put("replica", Integer.toString(config.replica));
//TODO: other database parameters
databaseService.createDatabase(databaseParam);
databaseService.useDatabase(config.database);
long end = System.currentTimeMillis();
logger.info(">>> create database time cost : " + (end - start) + " ms.");
/**********************************************************************************/
// 构造超级表的meta
SuperTableMeta superTableMeta;
// create super table
if (config.superTableSQL != null) {
// use a sql to create super table
superTableMeta = SuperTableMetaGenerator.generate(config.superTableSQL);
if (config.database != null && !config.database.isEmpty())
superTableMeta.setDatabase(config.database);
} else if (config.numOfFields == 0) {
String sql = "create table " + config.database + "." + config.superTable + " (ts timestamp, temperature float, humidity int) tags(location nchar(64), groupId int)";
superTableMeta = SuperTableMetaGenerator.generate(sql);
} else {
// create super table with specified field size and tag size
superTableMeta = SuperTableMetaGenerator.generate(config.database, config.superTable, config.numOfFields, config.prefixOfFields, config.numOfTags, config.prefixOfTags);
}
/**********************************************************************************/
// 建表
start = System.currentTimeMillis();
if (config.doCreateTable) {
superTableService.drop(superTableMeta.getDatabase(), superTableMeta.getName());
superTableService.create(superTableMeta);
if (!config.autoCreateTable) {
// 批量建子表
subTableService.createSubTable(superTableMeta, config.numOfTables, config.prefixOfTable, config.numOfThreadsForCreate);
}
}
end = System.currentTimeMillis();
logger.info(">>> create table time cost : " + (end - start) + " ms.");
/**********************************************************************************/
// 插入
long tableSize = config.numOfTables;
int threadSize = config.numOfThreadsForInsert;
long startTime = getProperStartTime(config.startTime, config.keep);
if (tableSize < threadSize)
threadSize = (int) tableSize;
long gap = (long) Math.ceil((0.0d + tableSize) / threadSize);
start = System.currentTimeMillis();
// multi threads to insert
int affectedRows = subTableService.insertMultiThreads(superTableMeta, threadSize, tableSize, startTime, gap, config);
end = System.currentTimeMillis();
logger.info("insert " + affectedRows + " rows, time cost: " + (end - start) + " ms");
/**********************************************************************************/
// 查询
/**********************************************************************************/
// 删除表
if (config.dropTable) {
superTableService.drop(config.database, config.superTable);
}
System.exit(0);
}
private static long getProperStartTime(long startTime, int keep) {
Instant now = Instant.now();
long earliest = now.minus(Duration.ofDays(keep - 1)).toEpochMilli();
if (startTime == 0 || startTime < earliest) {
startTime = earliest;
}
return startTime;
}
}
package com.taosdata.taosdemo.components;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.stereotype.Component;
import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
@Component
public class DataSourceFactory {
private static DataSource instance;
public static DataSource getInstance(String host, int port, String user, String password) throws IOException {
if (instance == null) {
synchronized (DataSourceFactory.class) {
if (instance == null) {
InputStream is = DataSourceFactory.class.getClassLoader().getResourceAsStream("application.properties");
Properties properties = new Properties();
properties.load(is);
HikariConfig config = new HikariConfig();
if (properties.containsKey("jdbc.driver")) {
// String driverName = properties.getProperty("jdbc.driver");
// System.out.println(">>> load driver : " + driverName);
// try {
// Class.forName(driverName);
// } catch (ClassNotFoundException e) {
// e.printStackTrace();
// }
config.setDriverClassName(properties.getProperty("jdbc.driver"));
} else {
config.setDriverClassName("com.taosdata.jdbc.TSDBDriver");
}
if ("com.taosdata.jdbc.rs.RestfulDriver".equalsIgnoreCase(properties.getProperty("jdbc.driver")))
config.setJdbcUrl("jdbc:TAOS-RS://" + host + ":6041/?charset=UTF-8&locale=en_US.UTF-8&timezone=UTC-8");
else
config.setJdbcUrl("jdbc:TAOS://" + host + ":" + port + "/?charset=UTF-8&locale=en_US.UTF-8&timezone=UTC-8");
config.setUsername(user);
config.setPassword(password);
// maximum-pool-size
if (properties.containsKey("hikari.maximum-pool-size"))
config.setMaximumPoolSize(Integer.parseInt(properties.getProperty("hikari.maximum-pool-size")));
else
config.setMaximumPoolSize(500);
// minimum-idle
if (properties.containsKey("hikari.minimum-idle"))
config.setMinimumIdle(Integer.parseInt(properties.getProperty("hikari.minimum-idle")));
else
config.setMinimumIdle(100);
config.setMaxLifetime(0);
instance = new HikariDataSource(config);
}
}
}
return instance;
}
}
package com.taosdata.taosdemo.components;
import com.taosdata.taosdemo.utils.TimeStampUtil;
public final class JdbcTaosdemoConfig {
// instance
public String host; //host
public int port = 6030; //port
public String user = "root"; //user
public String password = "taosdata"; //password
// database
public String database = "jdbcdb"; //database
public int keep = 3650; //keep
public int days = 30; //days
public int replica = 1; //replica
public int blocks = 16;
public int cache = 8;
public String precision = "ms";
//super table
public boolean doCreateTable = true;
public String superTable = "weather"; //super table name
public String prefixOfFields = "col";
public int numOfFields;
public String prefixOfTags = "tag";
public int numOfTags;
public String superTableSQL;
//sub table
public String prefixOfTable = "t";
// insert task
public boolean autoCreateTable;
public long numOfTables = 10;
public long numOfRowsPerTable = 10;
public int numOfTablesPerSQL = 1;
public int numOfValuesPerSQL = 1;
public int numOfThreadsForCreate = 1;
public int numOfThreadsForInsert = 1;
public long startTime;
public long timeGap = 1;
public int frequency;
public int order;
public int rate = 10;
public long range = 1000l;
// select task
public String executeSql;
// drop task
public boolean dropTable = false;
public static void printHelp() {
System.out.println("Usage: java -jar jdbc-taosdemo-2.0.jar [OPTION...]");
// instance
System.out.println("-host The host to connect to TDengine which you must specify");
System.out.println("-port The TCP/IP port number to use for the connection. Default is 6030");
System.out.println("-user The TDengine user name to use when connecting to the server. Default is 'root'");
System.out.println("-password The password to use when connecting to the server.Default is 'taosdata'");
// database
System.out.println("-database Destination database. Default is 'jdbcdb'");
System.out.println("-keep database keep parameter. Default is 3650");
System.out.println("-days database days parameter. Default is 30");
System.out.println("-replica database replica parameter. Default 1, min: 1, max: 3");
System.out.println("-blocks database blocks parameter. Default is 16");
System.out.println("-cache database cache parameter. Default is 8");
System.out.println("-precision database precision parameter. Default is ms");
// super table
System.out.println("-doCreateTable do create super table and sub table, true or false, Default true");
System.out.println("-superTable super table name. Default 'weather'");
System.out.println("-prefixOfFields The prefix of field in super table. Default is 'col'");
System.out.println("-numOfFields The number of field in super table. Default is (ts timestamp, temperature float, humidity int).");
System.out.println("-prefixOfTags The prefix of tag in super table. Default is 'tag'");
System.out.println("-numOfTags The number of tag in super table. Default is (location nchar(64), groupId int).");
System.out.println("-superTableSQL specify a sql statement for the super table.\n" +
" Default is 'create table weather(ts timestamp, temperature float, humidity int) tags(location nchar(64), groupId int). \n" +
" if you use this parameter, the numOfFields and numOfTags will be invalid'");
// sub table
System.out.println("-prefixOfTable The prefix of sub tables. Default is 't'");
System.out.println("-numOfTables The number of tables. Default is 1");
System.out.println("-numOfThreadsForCreate The number of thread during create sub table. Default is 1");
// insert task
System.out.println("-autoCreateTable Use auto Create sub tables SQL. Default is false");
System.out.println("-numOfRowsPerTable The number of records per table. Default is 1");
System.out.println("-numOfThreadsForInsert The number of threads during insert row. Default is 1");
System.out.println("-numOfTablesPerSQL The number of table per SQL. Default is 1");
System.out.println("-numOfValuesPerSQL The number of value per SQL. Default is 1");
System.out.println("-startTime start time for insert task, The format is \"yyyy-MM-dd HH:mm:ss.SSS\".");
System.out.println("-timeGap the number of time gap. Default is 1000 ms");
System.out.println("-frequency the number of records per second inserted into one table. default is 0, do not control frequency");
System.out.println("-order Insert mode--0: In order, 1: Out of order. Default is in order");
System.out.println("-rate The proportion of data out of order. effective only if order is 1. min 0, max 100, default is 10");
System.out.println("-range The range of data out of order. effective only if order is 1. default is 1000 ms");
// query task
System.out.println("-executeSql execute a specific sql.");
// drop task
System.out.println("-dropTable Drop data before quit. Default is false");
System.out.println("--help Give this help list");
}
/**
* parse args from command line
*
* @param args command line args
* @return JdbcTaosdemoConfig
*/
public JdbcTaosdemoConfig(String[] args) {
for (int i = 0; i < args.length; i++) {
// instance
if ("-host".equals(args[i]) && i < args.length - 1) {
host = args[++i];
}
if ("-port".equals(args[i]) && i < args.length - 1) {
port = Integer.parseInt(args[++i]);
}
if ("-user".equals(args[i]) && i < args.length - 1) {
user = args[++i];
}
if ("-password".equals(args[i]) && i < args.length - 1) {
password = args[++i];
}
// database
if ("-database".equals(args[i]) && i < args.length - 1) {
database = args[++i];
}
if ("-keep".equals(args[i]) && i < args.length - 1) {
keep = Integer.parseInt(args[++i]);
}
if ("-days".equals(args[i]) && i < args.length - 1) {
days = Integer.parseInt(args[++i]);
}
if ("-replica".equals(args[i]) && i < args.length - 1) {
replica = Integer.parseInt(args[++i]);
}
if ("-blocks".equals(args[i]) && i < args.length - 1) {
blocks = Integer.parseInt(args[++i]);
}
if ("-cache".equals(args[i]) && i < args.length - 1) {
cache = Integer.parseInt(args[++i]);
}
if ("-precision".equals(args[i]) && i < args.length - 1) {
precision = args[++i];
}
// super table
if ("-doCreateTable".equals(args[i]) && i < args.length - 1) {
doCreateTable = Boolean.parseBoolean(args[++i]);
}
if ("-superTable".equals(args[i]) && i < args.length - 1) {
superTable = args[++i];
}
if ("-prefixOfFields".equals(args[i]) && i < args.length - 1) {
prefixOfFields = args[++i];
}
if ("-numOfFields".equals(args[i]) && i < args.length - 1) {
numOfFields = Integer.parseInt(args[++i]);
}
if ("-prefixOfTags".equals(args[i]) && i < args.length - 1) {
prefixOfTags = args[++i];
}
if ("-numOfTags".equals(args[i]) && i < args.length - 1) {
numOfTags = Integer.parseInt(args[++i]);
}
if ("-superTableSQL".equals(args[i]) && i < args.length - 1) {
superTableSQL = args[++i];
}
// sub table
if ("-prefixOfTable".equals(args[i]) && i < args.length - 1) {
prefixOfTable = args[++i];
}
if ("-numOfTables".equals(args[i]) && i < args.length - 1) {
numOfTables = Long.parseLong(args[++i]);
}
if ("-autoCreateTable".equals(args[i]) && i < args.length - 1) {
autoCreateTable = Boolean.parseBoolean(args[++i]);
}
if ("-numOfThreadsForCreate".equals(args[i]) && i < args.length - 1) {
numOfThreadsForCreate = Integer.parseInt(args[++i]);
}
// insert task
if ("-numOfRowsPerTable".equals(args[i]) && i < args.length - 1) {
numOfRowsPerTable = Long.parseLong(args[++i]);
}
if ("-numOfThreadsForInsert".equals(args[i]) && i < args.length - 1) {
numOfThreadsForInsert = Integer.parseInt(args[++i]);
}
if ("-numOfTablesPerSQL".equals(args[i]) && i < args.length - 1) {
numOfTablesPerSQL = Integer.parseInt(args[++i]);
}
if ("-numOfValuesPerSQL".equals(args[i]) && i < args.length - 1) {
numOfValuesPerSQL = Integer.parseInt(args[++i]);
}
if ("-startTime".equals(args[i]) && i < args.length - 1) {
startTime = TimeStampUtil.datetimeToLong(args[++i]);
}
if ("-timeGap".equals(args[i]) && i < args.length - 1) {
timeGap = Long.parseLong(args[++i]);
}
if ("-frequency".equals(args[i]) && i < args.length - 1) {
frequency = Integer.parseInt(args[++i]);
}
if ("-order".equals(args[i]) && i < args.length - 1) {
order = Integer.parseInt(args[++i]);
}
if ("-rate".equals(args[i]) && i < args.length - 1) {
rate = Integer.parseInt(args[++i]);
if (rate < 0 || rate > 100)
throw new IllegalArgumentException("rate must between 0 and 100");
}
if ("-range".equals(args[i]) && i < args.length - 1) {
range = Integer.parseInt(args[++i]);
}
// select task
if ("-executeSql".equals(args[i]) && i < args.length - 1) {
executeSql = args[++i];
}
// drop task
if ("-dropTable".equals(args[i]) && i < args.length - 1) {
dropTable = Boolean.parseBoolean(args[++i]);
}
}
}
}
package com.taosdata.taosdemo.components;
import com.alibaba.fastjson.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class JsonConfig {
public static void main(String[] args) {
JsonConfig config = new JsonConfig();
String str = config.read("insert.json");
JSONObject jsonObject = JSONObject.parseObject(str);
System.out.println(jsonObject);
}
private String read(String fileName) {
try {
BufferedReader reader = new BufferedReader(
new InputStreamReader(JsonConfig.class.getClassLoader().getResourceAsStream(fileName))
);
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line);
}
return sb.toString();
} catch (IOException e) {
e.printStackTrace();
}
return fileName;
}
}
\ No newline at end of file
package com.taosdata.taosdemo.dao;
import java.util.Map;
public interface DatabaseMapper {
// create database if not exists XXX
void createDatabase(String dbname);
// drop database if exists XXX
void dropDatabase(String dbname);
// create database if not exists XXX keep XX days XX replica XX
void createDatabaseWithParameters(Map<String, String> map);
// use XXX
void useDatabase(String dbname);
//TODO: alter database
//TODO: show database
}
package com.taosdata.taosdemo.dao;
import com.taosdata.taosdemo.utils.SqlSpeller;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import org.springframework.jdbc.core.JdbcTemplate;
import javax.sql.DataSource;
import java.util.Map;
public class DatabaseMapperImpl implements DatabaseMapper {
private static final Logger logger = LogManager.getLogger(DatabaseMapperImpl.class);
private final JdbcTemplate jdbcTemplate;
public DatabaseMapperImpl(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
@Override
public void createDatabase(String dbname) {
String sql = "create database if not exists " + dbname;
jdbcTemplate.execute(sql);
logger.debug("SQL >>> " + sql);
}
@Override
public void dropDatabase(String dbname) {
String sql = "drop database if exists " + dbname;
jdbcTemplate.update(sql);
logger.debug("SQL >>> " + sql);
}
@Override
public void createDatabaseWithParameters(Map<String, String> map) {
String sql = SqlSpeller.createDatabase(map);
jdbcTemplate.execute(sql);
logger.debug("SQL >>> " + sql);
}
@Override
public void useDatabase(String dbname) {
String sql = "use " + dbname;
jdbcTemplate.execute(sql);
logger.debug("SQL >>> " + sql);
}
}
package com.taosdata.taosdemo.dao;
import com.taosdata.taosdemo.domain.SubTableMeta;
import com.taosdata.taosdemo.domain.SubTableValue;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface SubTableMapper {
// 创建:子表
void createUsingSuperTable(SubTableMeta subTableMeta);
// 插入:一张子表多个values
int insertOneTableMultiValues(SubTableValue subTableValue);
// 插入:一张子表多个values, 自动建表
int insertOneTableMultiValuesUsingSuperTable(SubTableValue subTableValue);
// 插入:多张表多个values
int insertMultiTableMultiValues(List<SubTableValue> tables);
// 插入:多张表多个values,自动建表
int insertMultiTableMultiValuesUsingSuperTable(List<SubTableValue> tables);
//<!-- TODO:修改子表标签值 alter table ${tablename} set tag tagName=newTagValue-->
}
\ No newline at end of file
package com.taosdata.taosdemo.dao;
import com.taosdata.taosdemo.domain.SubTableMeta;
import com.taosdata.taosdemo.domain.SubTableValue;
import com.taosdata.taosdemo.utils.SqlSpeller;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import org.springframework.jdbc.core.JdbcTemplate;
import javax.sql.DataSource;
import java.util.List;
public class SubTableMapperImpl implements SubTableMapper {
private static final Logger logger = LogManager.getLogger(SubTableMapperImpl.class);
private final JdbcTemplate jdbcTemplate;
public SubTableMapperImpl(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
@Override
public void createUsingSuperTable(SubTableMeta subTableMeta) {
String sql = SqlSpeller.createTableUsingSuperTable(subTableMeta);
logger.debug("SQL >>> " + sql);
jdbcTemplate.execute(sql);
}
@Override
public int insertOneTableMultiValues(SubTableValue subTableValue) {
String sql = SqlSpeller.insertOneTableMultiValues(subTableValue);
logger.debug("SQL >>> " + sql);
int affectRows = 0;
try {
affectRows = jdbcTemplate.update(sql);
} catch (Exception e) {
e.printStackTrace();
}
return affectRows;
}
@Override
public int insertOneTableMultiValuesUsingSuperTable(SubTableValue subTableValue) {
String sql = SqlSpeller.insertOneTableMultiValuesUsingSuperTable(subTableValue);
logger.debug("SQL >>> " + sql);
int affectRows = 0;
try {
affectRows = jdbcTemplate.update(sql);
} catch (Exception e) {
e.printStackTrace();
}
return affectRows;
}
@Override
public int insertMultiTableMultiValues(List<SubTableValue> tables) {
String sql = SqlSpeller.insertMultiSubTableMultiValues(tables);
logger.debug("SQL >>> " + sql);
int affectRows = 0;
try {
affectRows = jdbcTemplate.update(sql);
} catch (Exception e) {
e.printStackTrace();
}
return affectRows;
}
@Override
public int insertMultiTableMultiValuesUsingSuperTable(List<SubTableValue> tables) {
String sql = SqlSpeller.insertMultiTableMultiValuesUsingSuperTable(tables);
logger.debug("SQL >>> " + sql);
int affectRows = 0;
try {
affectRows = jdbcTemplate.update(sql);
} catch (Exception e) {
e.printStackTrace();
}
return affectRows;
}
}
package com.taosdata.taosdemo.dao;
import com.taosdata.taosdemo.domain.SuperTableMeta;
import org.springframework.stereotype.Repository;
@Repository
public interface SuperTableMapper {
// 创建超级表 create table if not exists xxx.xxx (f1 type1, f2 type2, ... ) tags( t1 type1, t2 type2 ...)
void createSuperTable(SuperTableMeta tableMetadata);
// 删除超级表 drop table if exists xxx;
void dropSuperTable(String database, String name);
//<!-- TODO:查询所有超级表信息 show stables -->
//<!-- TODO:查询表结构 describe stable -->
//<!-- TODO:增加列 alter table ${tablename} add column fieldName dataType -->
//<!-- TODO:删除列 alter table ${tablename} drop column fieldName -->
//<!-- TODO:添加标签 alter table ${tablename} add tag new_tagName tag_type -->
//<!-- TODO:删除标签 alter table ${tablename} drop tag_name -->
//<!-- TODO:修改标签名 alter table ${tablename} change tag old_tagName new_tagName -->
}
package com.taosdata.taosdemo.dao;
import com.taosdata.taosdemo.domain.SuperTableMeta;
import com.taosdata.taosdemo.utils.SqlSpeller;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import org.springframework.jdbc.core.JdbcTemplate;
import javax.sql.DataSource;
public class SuperTableMapperImpl implements SuperTableMapper {
private static final Logger logger = LogManager.getLogger(SuperTableMapperImpl.class);
private JdbcTemplate jdbcTemplate;
public SuperTableMapperImpl(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
@Override
public void createSuperTable(SuperTableMeta tableMetadata) {
String sql = SqlSpeller.createSuperTable(tableMetadata);
logger.debug("SQL >>> " + sql);
jdbcTemplate.execute(sql);
}
@Override
public void dropSuperTable(String database, String name) {
String sql = "drop table if exists " + database + "." + name;
logger.debug("SQL >>> " + sql);
jdbcTemplate.execute(sql);
}
}
package com.taosdata.taosdemo.dao;
import com.taosdata.taosdemo.domain.TableMeta;
import com.taosdata.taosdemo.domain.TableValue;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface TableMapper {
// 创建:普通表
void create(TableMeta tableMeta);
// 插入:一张表多个value
int insertOneTableMultiValues(TableValue values);
// 插入: 一张表多个value,指定的列
int insertOneTableMultiValuesWithColumns(TableValue values);
// 插入:多个表多个value
int insertMultiTableMultiValues(List<TableValue> tables);
// 插入:多个表多个value, 指定的列
int insertMultiTableMultiValuesWithColumns(List<TableValue> tables);
}
\ No newline at end of file
package com.taosdata.taosdemo.dao;
import com.taosdata.taosdemo.domain.TableMeta;
import com.taosdata.taosdemo.domain.TableValue;
import com.taosdata.taosdemo.utils.SqlSpeller;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import org.springframework.jdbc.core.JdbcTemplate;
import java.util.List;
public class TableMapperImpl implements TableMapper {
private static final Logger logger = LogManager.getLogger(TableMapperImpl.class);
private JdbcTemplate template;
@Override
public void create(TableMeta tableMeta) {
String sql = SqlSpeller.createTable(tableMeta);
logger.debug("SQL >>> " + sql);
template.execute(sql);
}
@Override
public int insertOneTableMultiValues(TableValue values) {
String sql = SqlSpeller.insertOneTableMultiValues(values);
logger.debug("SQL >>> " + sql);
return template.update(sql);
}
@Override
public int insertOneTableMultiValuesWithColumns(TableValue values) {
String sql = SqlSpeller.insertOneTableMultiValuesWithColumns(values);
logger.debug("SQL >>> " + sql);
return template.update(sql);
}
@Override
public int insertMultiTableMultiValues(List<TableValue> tables) {
String sql = SqlSpeller.insertMultiTableMultiValues(tables);
logger.debug("SQL >>> " + sql);
return template.update(sql);
}
@Override
public int insertMultiTableMultiValuesWithColumns(List<TableValue> tables) {
String sql = SqlSpeller.insertMultiTableMultiValuesWithColumns(tables);
logger.debug("SQL >>> " + sql);
return template.update(sql);
}
}
package com.taosdata.taosdemo.domain;
import lombok.Data;
@Data
public class FieldMeta {
private String name;
private String type;
public FieldMeta() {
}
public FieldMeta(String name, String type) {
this.name = name;
this.type = type;
}
}
\ No newline at end of file
package com.taosdata.taosdemo.domain;
import lombok.Data;
@Data
public class FieldValue<T> {
private String name;
private T value;
public FieldValue() {
}
public FieldValue(String name, T value) {
this.name = name;
this.value = value;
}
}
package com.taosdata.taosdemo.domain;
import lombok.Data;
import java.util.List;
@Data
public class RowValue {
private List<FieldValue> fields;
public RowValue(List<FieldValue> fields) {
this.fields = fields;
}
}
\ No newline at end of file
package com.taosdata.taosdemo.domain;
import lombok.Data;
import java.util.List;
@Data
public class SubTableMeta {
private String database;
private String supertable;
private String name;
private List<TagValue> tags;
private List<FieldMeta> fields;
}
package com.taosdata.taosdemo.domain;
import lombok.Data;
import java.util.List;
@Data
public class SubTableValue {
private String database;
private String supertable;
private String name;
private List<TagValue> tags;
private List<RowValue> values;
}
package com.taosdata.taosdemo.domain;
import lombok.Data;
import java.util.List;
@Data
public class SuperTableMeta {
private String database;
private String name;
private List<FieldMeta> fields;
private List<TagMeta> tags;
}
\ No newline at end of file
package com.taosdata.taosdemo.domain;
import lombok.Data;
import java.util.List;
@Data
public class TableMeta {
private String database;
private String name;
private List<FieldMeta> fields;
}
package com.taosdata.taosdemo.domain;
import lombok.Data;
import java.util.List;
@Data
public class TableValue {
private String database;
private String name;
private List<FieldMeta> columns;
private List<RowValue> values;
}
package com.taosdata.taosdemo.domain;
import lombok.Data;
@Data
public class TagMeta {
private String name;
private String type;
public TagMeta() {
}
public TagMeta(String name, String type) {
this.name = name;
this.type = type;
}
}
package com.taosdata.taosdemo.domain;
import lombok.Data;
@Data
public class TagValue<T> {
private String name;
private T value;
public TagValue() {
}
public TagValue(String name, T value) {
this.name = name;
this.value = value;
}
}
package com.taosdata.taosdemo.service;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
public class AbstractService {
protected int getAffectRows(List<Future<Integer>> futureList) {
int count = 0;
for (Future<Integer> future : futureList) {
try {
count += future.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
return count;
}
protected int getAffectRows(Future<Integer> future) {
int count = 0;
try {
count += future.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
return count;
}
}
package com.taosdata.taosdemo.service;
import com.taosdata.taosdemo.dao.DatabaseMapper;
import com.taosdata.taosdemo.dao.DatabaseMapperImpl;
import javax.sql.DataSource;
import java.util.Map;
public class DatabaseService {
private final DatabaseMapper databaseMapper;
public DatabaseService(DataSource dataSource) {
this.databaseMapper = new DatabaseMapperImpl(dataSource);
}
// 建库,指定 name
public void createDatabase(String database) {
databaseMapper.createDatabase(database);
}
// 建库,指定参数 keep,days,replica等
public void createDatabase(Map<String, String> map) {
if (map.isEmpty())
return;
if (map.containsKey("database") && map.size() == 1) {
createDatabase(map.get("database"));
return;
}
databaseMapper.createDatabaseWithParameters(map);
}
// drop database
public void dropDatabase(String dbname) {
databaseMapper.dropDatabase(dbname);
}
// use database
public void useDatabase(String dbname) {
databaseMapper.useDatabase(dbname);
}
}
package com.taosdata.taosdemo.service;
import com.taosdata.jdbc.utils.SqlSyntaxValidator;
import javax.sql.DataSource;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class QueryService {
private final DataSource dataSource;
public QueryService(DataSource dataSource) {
this.dataSource = dataSource;
}
/* only select or show SQL Statement is valid for executeQuery */
public Boolean[] areValidQueries(String[] sqls) {
Boolean[] ret = new Boolean[sqls.length];
for (int i = 0; i < sqls.length; i++) {
ret[i] = true;
if (!SqlSyntaxValidator.isValidForExecuteQuery(sqls[i])) {
ret[i] = false;
continue;
}
try (Connection conn = dataSource.getConnection(); Statement stmt = conn.createStatement()) {
stmt.executeQuery(sqls[i]);
} catch (SQLException e) {
ret[i] = false;
continue;
}
}
return ret;
}
public String[] generateSuperTableQueries(String dbName) {
List<String> sqls = new ArrayList<>();
try (Connection conn = dataSource.getConnection(); Statement stmt = conn.createStatement()) {
stmt.execute("use " + dbName);
ResultSet rs = stmt.executeQuery("show stables");
while (rs.next()) {
String name = rs.getString("name");
sqls.add("select count(*) from " + dbName + "." + name);
sqls.add("select first(*) from " + dbName + "." + name);
sqls.add("select last(*) from " + dbName + "." + name);
sqls.add("select last_row(*) from " + dbName + "." + name);
}
} catch (SQLException e) {
e.printStackTrace();
}
String[] sqlArr = new String[sqls.size()];
return sqls.toArray(sqlArr);
}
public void querySuperTable(String[] sqls, int interval, int threadCount, long queryTimes) {
List<Thread> threads = IntStream.range(0, threadCount).mapToObj(i -> new Thread(() -> {
// do query
try (Connection conn = dataSource.getConnection(); Statement stmt = conn.createStatement()) {
long count = queryTimes;
if (count == 0)
count = Long.MAX_VALUE;
while (count > 0) {
for (String sql : sqls) {
long start = System.currentTimeMillis();
ResultSet rs = stmt.executeQuery(sql);
printResultSet(rs);
long end = System.currentTimeMillis();
long timecost = end - start;
if (interval - timecost > 0) {
TimeUnit.MILLISECONDS.sleep(interval - timecost);
}
}
count--;
}
} catch (SQLException | InterruptedException e) {
e.printStackTrace();
}
})).collect(Collectors.toList());
threads.stream().forEach(Thread::start);
for (Thread thread : threads) {
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private void printResultSet(ResultSet rs) throws SQLException {
ResultSetMetaData meta = rs.getMetaData();
while (rs.next()) {
for (int i = 1; i <= meta.getColumnCount(); i++) {
System.out.print(meta.getColumnLabel(i) + ": " + rs.getString(i) + "\t");
}
System.out.println();
}
}
}
package com.taosdata.taosdemo.service;
import com.taosdata.taosdemo.utils.Printer;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class SqlExecuteTask implements Runnable {
private final DataSource dataSource;
private final String sql;
public SqlExecuteTask(DataSource dataSource, String sql) {
this.dataSource = dataSource;
this.sql = sql;
}
@Override
public void run() {
try (Connection conn = dataSource.getConnection(); Statement stmt = conn.createStatement()) {
long start = System.currentTimeMillis();
boolean execute = stmt.execute(sql);
long end = System.currentTimeMillis();
if (execute) {
ResultSet rs = stmt.getResultSet();
Printer.printResult(rs);
} else {
Printer.printSql(sql, true, (end - start));
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
package com.taosdata.taosdemo.service;
import com.taosdata.taosdemo.components.JdbcTaosdemoConfig;
import com.taosdata.taosdemo.dao.SubTableMapper;
import com.taosdata.taosdemo.dao.SubTableMapperImpl;
import com.taosdata.taosdemo.domain.SubTableMeta;
import com.taosdata.taosdemo.domain.SubTableValue;
import com.taosdata.taosdemo.domain.SuperTableMeta;
import com.taosdata.taosdemo.service.data.SubTableMetaGenerator;
import com.taosdata.taosdemo.service.data.SubTableValueGenerator;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import javax.sql.DataSource;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class SubTableService extends AbstractService {
private SubTableMapper mapper;
private static final Logger logger = LogManager.getLogger(SubTableService.class);
public SubTableService(DataSource datasource) {
this.mapper = new SubTableMapperImpl(datasource);
}
public void createSubTable(SuperTableMeta superTableMeta, long numOfTables, String prefixOfTable, int numOfThreadsForCreate) {
ExecutorService executor = Executors.newFixedThreadPool(numOfThreadsForCreate);
for (long i = 0; i < numOfTables; i++) {
long tableIndex = i;
executor.execute(() -> createSubTable(superTableMeta, prefixOfTable + (tableIndex + 1)));
}
executor.shutdown();
try {
executor.awaitTermination(Long.MAX_VALUE,TimeUnit.NANOSECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void createSubTable(SuperTableMeta superTableMeta, String tableName) {
// 构造数据
SubTableMeta meta = SubTableMetaGenerator.generate(superTableMeta, tableName);
createSubTable(meta);
}
// 创建一张子表,可以指定database,supertable,tablename,tag值
public void createSubTable(SubTableMeta subTableMeta) {
mapper.createUsingSuperTable(subTableMeta);
}
/*************************************************************************************************************************/
// 插入:多线程,多表
public int insert(List<SubTableValue> subTableValues, int threadSize, int frequency) {
ExecutorService executor = Executors.newFixedThreadPool(threadSize);
Future<Integer> future = executor.submit(() -> insert(subTableValues));
executor.shutdown();
//TODO:frequency
return getAffectRows(future);
}
// 插入:单表,insert into xxx values(),()...
public int insert(SubTableValue subTableValue) {
return mapper.insertOneTableMultiValues(subTableValue);
}
// 插入: 多表,insert into xxx values(),()... xxx values(),()...
public int insert(List<SubTableValue> subTableValues) {
return mapper.insertMultiTableMultiValues(subTableValues);
}
// 插入:单表,自动建表, insert into xxx using xxx tags(...) values(),()...
public int insertAutoCreateTable(SubTableValue subTableValue) {
return mapper.insertOneTableMultiValuesUsingSuperTable(subTableValue);
}
// 插入:多表,自动建表, insert into xxx using XXX tags(...) values(),()... xxx using XXX tags(...) values(),()...
public int insertAutoCreateTable(List<SubTableValue> subTableValues) {
return mapper.insertMultiTableMultiValuesUsingSuperTable(subTableValues);
}
public int insertMultiThreads(SuperTableMeta superTableMeta, int threadSize, long tableSize, long startTime, long gap, JdbcTaosdemoConfig config) {
List<FutureTask> taskList = new ArrayList<>();
List<Thread> threads = IntStream.range(0, threadSize)
.mapToObj(i -> {
long startInd = i * gap;
long endInd = (i + 1) * gap < tableSize ? (i + 1) * gap : tableSize;
FutureTask<Integer> task = new FutureTask<>(
new InsertTask(superTableMeta,
startInd, endInd,
startTime, config.timeGap,
config.numOfRowsPerTable, config.numOfTablesPerSQL, config.numOfValuesPerSQL,
config.order, config.rate, config.range,
config.prefixOfTable, config.autoCreateTable)
);
taskList.add(task);
return new Thread(task, "InsertThread-" + i);
}).collect(Collectors.toList());
threads.stream().forEach(Thread::start);
for (Thread thread : threads) {
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
int affectedRows = 0;
for (FutureTask<Integer> task : taskList) {
try {
affectedRows += task.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
return affectedRows;
}
private class InsertTask implements Callable<Integer> {
private final long startTableInd; // included
private final long endTableInd; // excluded
private final long startTime;
private final long timeGap;
private final long numOfRowsPerTable;
private long numOfTablesPerSQL;
private long numOfValuesPerSQL;
private final SuperTableMeta superTableMeta;
private final int order;
private final int rate;
private final long range;
private final String prefixOfTable;
private final boolean autoCreateTable;
public InsertTask(SuperTableMeta superTableMeta, long startTableInd, long endTableInd,
long startTime, long timeGap,
long numOfRowsPerTable, long numOfTablesPerSQL, long numOfValuesPerSQL,
int order, int rate, long range,
String prefixOfTable, boolean autoCreateTable) {
this.superTableMeta = superTableMeta;
this.startTableInd = startTableInd;
this.endTableInd = endTableInd;
this.startTime = startTime;
this.timeGap = timeGap;
this.numOfRowsPerTable = numOfRowsPerTable;
this.numOfTablesPerSQL = numOfTablesPerSQL;
this.numOfValuesPerSQL = numOfValuesPerSQL;
this.order = order;
this.rate = rate;
this.range = range;
this.prefixOfTable = prefixOfTable;
this.autoCreateTable = autoCreateTable;
}
@Override
public Integer call() {
long numOfTables = endTableInd - startTableInd;
if (numOfRowsPerTable < numOfValuesPerSQL)
numOfValuesPerSQL = (int) numOfRowsPerTable;
if (numOfTables < numOfTablesPerSQL)
numOfTablesPerSQL = (int) numOfTables;
int affectRows = 0;
// row
for (long rowCnt = 0; rowCnt < numOfRowsPerTable; ) {
long rowSize = numOfValuesPerSQL;
if (rowCnt + rowSize > numOfRowsPerTable) {
rowSize = numOfRowsPerTable - rowCnt;
}
//table
for (long tableCnt = startTableInd; tableCnt < endTableInd; ) {
long tableSize = numOfTablesPerSQL;
if (tableCnt + tableSize > endTableInd) {
tableSize = endTableInd - tableCnt;
}
long startTime = this.startTime + rowCnt * timeGap;
// System.out.println(Thread.currentThread().getName() + " >>> " + "rowCnt: " + rowCnt + ", rowSize: " + rowSize + ", " + "tableCnt: " + tableCnt + ",tableSize: " + tableSize + ", " + "startTime: " + startTime + ",timeGap: " + timeGap + "");
/***********************************************/
// 生成数据
List<SubTableValue> data = SubTableValueGenerator.generate(superTableMeta, prefixOfTable, tableCnt, tableSize, rowSize, startTime, timeGap);
// 乱序
if (order != 0)
SubTableValueGenerator.disrupt(data, rate, range);
// insert
if (autoCreateTable)
affectRows += insertAutoCreateTable(data);
else
affectRows += insert(data);
/***********************************************/
tableCnt += tableSize;
}
rowCnt += rowSize;
}
return affectRows;
}
}
}
package com.taosdata.taosdemo.service;
import com.taosdata.taosdemo.dao.SuperTableMapper;
import com.taosdata.taosdemo.dao.SuperTableMapperImpl;
import com.taosdata.taosdemo.domain.SuperTableMeta;
import javax.sql.DataSource;
public class SuperTableService {
private SuperTableMapper superTableMapper;
public SuperTableService(DataSource dataSource) {
this.superTableMapper = new SuperTableMapperImpl(dataSource);
}
// 创建超级表,指定每个field的名称和类型,每个tag的名称和类型
public void create(SuperTableMeta superTableMeta) {
superTableMapper.createSuperTable(superTableMeta);
}
public void drop(String database, String name) {
superTableMapper.dropSuperTable(database, name);
}
}
package com.taosdata.taosdemo.service;
import com.taosdata.taosdemo.dao.TableMapper;
import com.taosdata.taosdemo.domain.TableMeta;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class TableService extends AbstractService {
private TableMapper tableMapper;
//创建一张表
public void create(TableMeta tableMeta) {
tableMapper.create(tableMeta);
}
//创建多张表
public void create(List<TableMeta> tables) {
tables.stream().forEach(this::create);
}
}
package com.taosdata.taosdemo.service.data;
import com.taosdata.taosdemo.domain.FieldMeta;
import com.taosdata.taosdemo.domain.FieldValue;
import com.taosdata.taosdemo.domain.RowValue;
import com.taosdata.taosdemo.utils.DataGenerator;
import java.util.*;
public class FieldValueGenerator {
public static Random random = new Random(System.currentTimeMillis());
// 生成start到end的时间序列,时间戳为顺序,不含有乱序,field的value为随机生成
public static List<RowValue> generate(long start, long end, long timeGap, List<FieldMeta> fieldMetaList) {
List<RowValue> values = new ArrayList<>();
for (long ts = start; ts < end; ts += timeGap) {
List<FieldValue> fieldValues = new ArrayList<>();
// timestamp
fieldValues.add(new FieldValue(fieldMetaList.get(0).getName(), ts));
// other values
for (int fieldInd = 1; fieldInd < fieldMetaList.size(); fieldInd++) {
FieldMeta fieldMeta = fieldMetaList.get(fieldInd);
fieldValues.add(new FieldValue(fieldMeta.getName(), DataGenerator.randomValue(fieldMeta.getType())));
}
values.add(new RowValue(fieldValues));
}
return values;
}
// 生成start到end的时间序列,时间戳为顺序,含有乱序,rate为乱序的比例,range为乱序前跳范围,field的value为随机生成
public static List<RowValue> disrupt(List<RowValue> values, int rate, long range) {
long timeGap = (long) (values.get(1).getFields().get(0).getValue()) - (long) (values.get(0).getFields().get(0).getValue());
int bugSize = values.size() * rate / 100;
Set<Integer> bugIndSet = new HashSet<>();
while (bugIndSet.size() < bugSize) {
bugIndSet.add(random.nextInt(values.size()));
}
for (Integer bugInd : bugIndSet) {
Long timestamp = (Long) values.get(bugInd).getFields().get(0).getValue();
Long newTimestamp = timestamp - timeGap - random.nextInt((int) range);
values.get(bugInd).getFields().get(0).setValue(newTimestamp);
}
return values;
}
}
package com.taosdata.taosdemo.service.data;
import com.taosdata.taosdemo.domain.SubTableMeta;
import com.taosdata.taosdemo.domain.SuperTableMeta;
import com.taosdata.taosdemo.domain.TagValue;
import java.util.ArrayList;
import java.util.List;
public class SubTableMetaGenerator {
// 创建tableSize张子表,使用tablePrefix作为子表名的前缀,使用superTableMeta的元数据
// create table xxx using XXX tags(XXX)
public static List<SubTableMeta> generate(SuperTableMeta superTableMeta, int tableSize, String tablePrefix) {
List<SubTableMeta> subTableMetaList = new ArrayList<>();
for (int i = 1; i <= tableSize; i++) {
SubTableMeta subTableMeta = new SubTableMeta();
// create table xxx.xxx using xxx tags(...)
subTableMeta.setDatabase(superTableMeta.getDatabase());
subTableMeta.setName(tablePrefix + i);
subTableMeta.setSupertable(superTableMeta.getName());
subTableMeta.setFields(superTableMeta.getFields());
List<TagValue> tagValues = TagValueGenerator.generate(superTableMeta.getTags());
subTableMeta.setTags(tagValues);
subTableMetaList.add(subTableMeta);
}
return subTableMetaList;
}
public static SubTableMeta generate(SuperTableMeta superTableMeta, String tableName) {
SubTableMeta subTableMeta = new SubTableMeta();
// create table xxx.xxx using xxx tags(...)
subTableMeta.setDatabase(superTableMeta.getDatabase());
subTableMeta.setName(tableName);
subTableMeta.setSupertable(superTableMeta.getName());
subTableMeta.setFields(superTableMeta.getFields());
List<TagValue> tagValues = TagValueGenerator.generate(superTableMeta.getTags());
subTableMeta.setTags(tagValues);
return subTableMeta;
}
}
package com.taosdata.taosdemo.service.data;
import com.taosdata.taosdemo.domain.*;
import com.taosdata.taosdemo.utils.TimeStampUtil;
import org.springframework.beans.BeanUtils;
import java.util.ArrayList;
import java.util.List;
public class SubTableValueGenerator {
public static List<SubTableValue> generate(SuperTableMeta superTableMeta, String prefixOfTables, long tableIndex, long tableSize, long valueSize, long startTime, long timeGap) {
List<SubTableValue> subTableValues = new ArrayList<>();
for (int i = 1; i <= tableSize; i++) {
SubTableValue subTableValue = new SubTableValue();
subTableValue.setDatabase(superTableMeta.getDatabase());
subTableValue.setName(prefixOfTables + (tableIndex + i));
subTableValue.setSupertable(superTableMeta.getName());
TimeStampUtil.TimeTuple tuple = TimeStampUtil.range(startTime, timeGap, valueSize);
List<TagValue> tags = TagValueGenerator.generate(superTableMeta.getTags());
subTableValue.setTags(tags);
List<RowValue> values = FieldValueGenerator.generate(tuple.start, tuple.end, tuple.timeGap, superTableMeta.getFields());
subTableValue.setValues(values);
subTableValues.add(subTableValue);
}
return subTableValues;
}
public static List<SubTableValue> generate(List<SubTableMeta> subTableMetaList, int numOfRowsPerTable, long start, long timeGap) {
return generate(subTableMetaList, 0, subTableMetaList.size(), numOfRowsPerTable, start, timeGap);
}
public static void disrupt(List<SubTableValue> subTableValueList, int rate, long range) {
subTableValueList.stream().forEach((tableValue) -> {
List<RowValue> values = tableValue.getValues();
FieldValueGenerator.disrupt(values, rate, range);
});
}
public static List<List<SubTableValue>> split(List<SubTableValue> subTableValueList, int numOfTables, int numOfTablesPerSQL, int numOfRowsPerTable, int numOfValuesPerSQL) {
List<List<SubTableValue>> dataList = new ArrayList<>();
if (numOfRowsPerTable < numOfValuesPerSQL)
numOfValuesPerSQL = numOfRowsPerTable;
if (numOfTables < numOfTablesPerSQL)
numOfTablesPerSQL = numOfTables;
//table
for (int tableCnt = 0; tableCnt < numOfTables; ) {
int tableSize = numOfTablesPerSQL;
if (tableCnt + tableSize > numOfTables) {
tableSize = numOfTables - tableCnt;
}
// row
for (int rowCnt = 0; rowCnt < numOfRowsPerTable; ) {
int rowSize = numOfValuesPerSQL;
if (rowCnt + rowSize > numOfRowsPerTable) {
rowSize = numOfRowsPerTable - rowCnt;
}
// System.out.println("rowCnt: " + rowCnt + ", rowSize: " + rowSize + ", tableCnt: " + tableCnt + ", tableSize: " + tableSize);
// split
List<SubTableValue> blocks = subTableValueList.subList(tableCnt, tableCnt + tableSize);
List<SubTableValue> newBlocks = new ArrayList<>();
for (int i = 0; i < blocks.size(); i++) {
SubTableValue subTableValue = blocks.get(i);
SubTableValue newSubTableValue = new SubTableValue();
BeanUtils.copyProperties(subTableValue, newSubTableValue);
List<RowValue> values = subTableValue.getValues().subList(rowCnt, rowCnt + rowSize);
newSubTableValue.setValues(values);
newBlocks.add(newSubTableValue);
}
dataList.add(newBlocks);
rowCnt += rowSize;
}
tableCnt += tableSize;
}
return dataList;
}
public static void main(String[] args) {
split(null, 99, 10, 99, 10);
}
public static List<SubTableValue> generate(List<SubTableMeta> subTableMetaList, int tableCnt, int tableSize, int rowSize, long startTime, long timeGap) {
List<SubTableValue> subTableValueList = new ArrayList<>();
for (int i = 0; i < tableSize; i++) {
SubTableMeta subTableMeta = subTableMetaList.get(tableCnt + i);
SubTableValue subTableValue = new SubTableValue();
subTableValue.setDatabase(subTableMeta.getDatabase());
subTableValue.setName(subTableMeta.getName());
subTableValue.setSupertable(subTableMeta.getSupertable());
subTableValue.setTags(subTableMeta.getTags());
TimeStampUtil.TimeTuple tuple = TimeStampUtil.range(startTime, timeGap, rowSize);
List<RowValue> values = FieldValueGenerator.generate(tuple.start, tuple.end, tuple.timeGap, subTableMeta.getFields());
subTableValue.setValues(values);
subTableValueList.add(subTableValue);
}
return subTableValueList;
}
}
package com.taosdata.taosdemo.service.data;
import com.taosdata.taosdemo.domain.FieldMeta;
import com.taosdata.taosdemo.domain.SuperTableMeta;
import com.taosdata.taosdemo.domain.TagMeta;
import com.taosdata.taosdemo.utils.TaosConstants;
import java.util.ArrayList;
import java.util.List;
public class SuperTableMetaGenerator {
// 创建超级表,使用指定SQL语句
public static SuperTableMeta generate(String superTableSQL) {
SuperTableMeta tableMeta = new SuperTableMeta();
// for example : create table superTable (ts timestamp, temperature float, humidity int) tags(location nchar(64), groupId int)
superTableSQL = superTableSQL.trim().toLowerCase();
if (!superTableSQL.startsWith("create"))
throw new RuntimeException("invalid create super table SQL");
if (superTableSQL.contains("tags")) {
String tagSQL = superTableSQL.substring(superTableSQL.indexOf("tags") + 4).trim();
tagSQL = tagSQL.substring(tagSQL.indexOf("(") + 1, tagSQL.lastIndexOf(")"));
String[] tagPairs = tagSQL.split(",");
List<TagMeta> tagMetaList = new ArrayList<>();
for (String tagPair : tagPairs) {
String name = tagPair.trim().split("\\s+")[0];
String type = tagPair.trim().split("\\s+")[1];
tagMetaList.add(new TagMeta(name, type));
}
tableMeta.setTags(tagMetaList);
superTableSQL = superTableSQL.substring(0, superTableSQL.indexOf("tags"));
}
if (superTableSQL.contains("(")) {
String fieldSQL = superTableSQL.substring(superTableSQL.indexOf("(") + 1, superTableSQL.indexOf(")"));
String[] fieldPairs = fieldSQL.split(",");
List<FieldMeta> fieldList = new ArrayList<>();
for (String fieldPair : fieldPairs) {
String name = fieldPair.trim().split("\\s+")[0];
String type = fieldPair.trim().split("\\s+")[1];
fieldList.add(new FieldMeta(name, type));
}
tableMeta.setFields(fieldList);
superTableSQL = superTableSQL.substring(0, superTableSQL.indexOf("("));
}
superTableSQL = superTableSQL.substring(superTableSQL.indexOf("table") + 5).trim();
if (superTableSQL.contains(".")) {
String database = superTableSQL.split("\\.")[0];
tableMeta.setDatabase(database);
superTableSQL = superTableSQL.substring(superTableSQL.indexOf(".") + 1);
}
tableMeta.setName(superTableSQL.trim());
return tableMeta;
}
// 创建超级表,指定field和tag的个数
public static SuperTableMeta generate(String database, String name, int fieldSize, String fieldPrefix, int tagSize, String tagPrefix) {
if (fieldSize < 2 || tagSize < 1) {
throw new RuntimeException("create super table but fieldSize less than 2 or tagSize less than 1");
}
SuperTableMeta tableMetadata = new SuperTableMeta();
tableMetadata.setDatabase(database);
tableMetadata.setName(name);
// fields
List<FieldMeta> fields = new ArrayList<>();
fields.add(new FieldMeta("ts", "timestamp"));
for (int i = 1; i <= fieldSize; i++) {
fields.add(new FieldMeta(fieldPrefix + "" + i, TaosConstants.DATA_TYPES[i % TaosConstants.DATA_TYPES.length]));
}
tableMetadata.setFields(fields);
// tags
List<TagMeta> tags = new ArrayList<>();
for (int i = 1; i <= tagSize; i++) {
tags.add(new TagMeta(tagPrefix + "" + i, TaosConstants.DATA_TYPES[i % TaosConstants.DATA_TYPES.length]));
}
tableMetadata.setTags(tags);
return tableMetadata;
}
}
package com.taosdata.taosdemo.service.data;
import com.taosdata.taosdemo.domain.TagMeta;
import com.taosdata.taosdemo.domain.TagValue;
import com.taosdata.taosdemo.utils.DataGenerator;
import java.util.ArrayList;
import java.util.List;
public class TagValueGenerator {
// 创建标签值:使用tagMetas
public static List<TagValue> generate(List<TagMeta> tagMetas) {
List<TagValue> tagValues = new ArrayList<>();
for (int i = 0; i < tagMetas.size(); i++) {
TagMeta tagMeta = tagMetas.get(i);
TagValue tagValue = new TagValue();
tagValue.setName(tagMeta.getName());
tagValue.setValue(DataGenerator.randomValue(tagMeta.getType()));
tagValues.add(tagValue);
}
return tagValues;
}
}
package com.taosdata.taosdemo.utils;
import java.util.Random;
public class DataGenerator {
private static Random random = new Random(System.currentTimeMillis());
private static final String alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
// "timestamp", "int", "bigint", "float", "double", "binary(64)", "smallint", "tinyint", "bool", "nchar(64)",
public static Object randomValue(String type) {
int length = 64;
if (type.contains("(")) {
length = Integer.parseInt(type.substring(type.indexOf("(") + 1, type.indexOf(")")));
type = type.substring(0, type.indexOf("("));
}
switch (type.trim().toLowerCase()) {
case "timestamp":
return randomTimestamp();
case "int":
return randomInt();
case "bigint":
return randomBigint();
case "float":
return randomFloat();
case "double":
return randomDouble();
case "binary":
return randomBinary(length);
case "smallint":
return randomSmallint();
case "tinyint":
return randomTinyint();
case "bool":
return randomBoolean();
case "nchar":
return randomNchar(length);
default:
throw new IllegalArgumentException("Unexpected value: " + type);
}
}
public static Long randomTimestamp() {
long start = System.currentTimeMillis();
return randomTimestamp(start, start + 60l * 60l * 1000l);
}
public static Long randomTimestamp(Long start, Long end) {
return start + (long) random.nextInt((int) (end - start));
}
public static String randomNchar(int length) {
return randomChinese(length);
}
public static Boolean randomBoolean() {
return random.nextBoolean();
}
public static Integer randomTinyint() {
return randomInt(-127, 127);
}
public static Integer randomSmallint() {
return randomInt(-32767, 32767);
}
public static String randomBinary(int length) {
return randomString(length);
}
public static String randomString(int length) {
String zh_en = "";
for (int i = 0; i < length; i++) {
zh_en += alphabet.charAt(random.nextInt(alphabet.length()));
}
return zh_en;
}
public static String randomChinese(int length) {
String zh_cn = "";
int bottom = Integer.parseInt("4e00", 16);
int top = Integer.parseInt("9fa5", 16);
for (int i = 0; i < length; i++) {
char c = (char) (random.nextInt(top - bottom + 1) + bottom);
zh_cn += new String(new char[]{c});
}
return zh_cn;
}
public static Double randomDouble() {
return randomDouble(0, 100);
}
public static Double randomDouble(double bottom, double top) {
return bottom + (top - bottom) * random.nextDouble();
}
public static Float randomFloat() {
return randomFloat(0, 100);
}
public static Float randomFloat(float bottom, float top) {
return bottom + (top - bottom) * random.nextFloat();
}
public static Long randomBigint() {
return random.nextLong();
}
public static Integer randomInt(int bottom, int top) {
return bottom + random.nextInt((top - bottom));
}
public static Integer randomInt() {
return randomInt(0, 100);
}
}
package com.taosdata.taosdemo.utils;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
public class Printer {
public static void printResult(ResultSet resultSet) throws SQLException {
ResultSetMetaData metaData = resultSet.getMetaData();
while (resultSet.next()) {
for (int i = 1; i <= metaData.getColumnCount(); i++) {
String columnLabel = metaData.getColumnLabel(i);
String value = resultSet.getString(i);
System.out.printf("%s: %s\t", columnLabel, value);
}
System.out.println();
}
}
public static void printSql(String sql, boolean succeed, long cost) {
System.out.println("[ " + (succeed ? "OK" : "ERROR!") + " ] time cost: " + cost + " ms, execute statement ====> " + sql);
}
private Printer() {
}
}
package com.taosdata.taosdemo.utils;
import com.taosdata.taosdemo.domain.*;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class SqlSpeller {
// create database if not exists xxx keep xx days xx replica xx cache xx...
public static String createDatabase(Map<String, String> map) {
StringBuilder sb = new StringBuilder();
sb.append("create database if not exists ").append(map.get("database")).append(" ");
if (map.containsKey("keep"))
sb.append("keep ").append(map.get("keep")).append(" ");
if (map.containsKey("days"))
sb.append("days ").append(map.get("days")).append(" ");
if (map.containsKey("replica"))
sb.append("replica ").append(map.get("replica")).append(" ");
if (map.containsKey("cache"))
sb.append("cache ").append(map.get("cache")).append(" ");
if (map.containsKey("blocks"))
sb.append("blocks ").append(map.get("blocks")).append(" ");
if (map.containsKey("minrows"))
sb.append("minrows ").append(map.get("minrows")).append(" ");
if (map.containsKey("maxrows"))
sb.append("maxrows ").append(map.get("maxrows")).append(" ");
if (map.containsKey("precision"))
sb.append("precision ").append(map.get("precision")).append(" ");
if (map.containsKey("comp"))
sb.append("comp ").append(map.get("comp")).append(" ");
if (map.containsKey("walLevel"))
sb.append("walLevel ").append(map.get("walLevel")).append(" ");
if (map.containsKey("quorum"))
sb.append("quorum ").append(map.get("quorum")).append(" ");
if (map.containsKey("fsync"))
sb.append("fsync ").append(map.get("fsync")).append(" ");
if (map.containsKey("update"))
sb.append("update ").append(map.get("update")).append(" ");
return sb.toString();
}
// create table if not exists xx.xx using xx.xx tags(x,x,x)
public static String createTableUsingSuperTable(SubTableMeta subTableMeta) {
StringBuilder sb = new StringBuilder();
sb.append("create table if not exists ").append(subTableMeta.getDatabase()).append(".").append(subTableMeta.getName()).append(" ");
sb.append("using ").append(subTableMeta.getDatabase()).append(".").append(subTableMeta.getSupertable()).append(" ");
// String tagStr = subTableMeta.getTags().stream().filter(Objects::nonNull)
// .map(tagValue -> tagValue.getName() + " '" + tagValue.getValue() + "' ")
// .collect(Collectors.joining(",", "(", ")"));
sb.append("tags ").append(tagValues(subTableMeta.getTags()));
return sb.toString();
}
// insert into xx.xxx values(x,x,x),(x,x,x)...
public static String insertOneTableMultiValues(SubTableValue subTableValue) {
StringBuilder sb = new StringBuilder();
sb.append("insert into ").append(subTableValue.getDatabase()).append(".").append(subTableValue.getName() + " ");
sb.append("values").append(rowValues(subTableValue.getValues()));
return sb.toString();
}
//f1, f2, f3
private static String fieldValues(List<FieldValue> fields) {
return IntStream.range(0, fields.size()).mapToObj(i -> {
if (i == 0) {
return "" + fields.get(i).getValue() + "";
} else {
return "'" + fields.get(i).getValue() + "'";
}
}).collect(Collectors.joining(",", "(", ")"));
// return fields.stream()
// .filter(Objects::nonNull)
// .map(fieldValue -> "'" + fieldValue.getValue() + "'")
// .collect(Collectors.joining(",", "(", ")"));
}
//(f1, f2, f3),(f1, f2, f3)
private static String rowValues(List<RowValue> rowValues) {
return rowValues.stream().filter(Objects::nonNull)
.map(rowValue -> fieldValues(rowValue.getFields()))
.collect(Collectors.joining(",", "", ""));
}
// insert into xx.xxx using xx.xx tags(x,x,x) values(x,x,x),(x,x,x)...
public static String insertOneTableMultiValuesUsingSuperTable(SubTableValue subTableValue) {
StringBuilder sb = new StringBuilder();
sb.append("insert into ").append(subTableValue.getDatabase()).append(".").append(subTableValue.getName()).append(" ");
sb.append("using ").append(subTableValue.getDatabase()).append(".").append(subTableValue.getSupertable()).append(" ");
sb.append("tags ").append(tagValues(subTableValue.getTags()) + " ");
sb.append("values ").append(rowValues(subTableValue.getValues()));
return sb.toString();
}
// (t1,t2,t3...)
private static String tagValues(List<TagValue> tags) {
return tags.stream().filter(Objects::nonNull)
.map(tagValue -> "'" + tagValue.getValue() + "'")
.collect(Collectors.joining(",", "(", ")"));
}
// insert into xx.xx values(),(),()... xx.xx values(),()...
public static String insertMultiSubTableMultiValues(List<SubTableValue> tables) {
return "insert into " + tables.stream().filter(Objects::nonNull)
.map(table -> table.getDatabase() + "." + table.getName() + " values " + rowValues(table.getValues()))
.collect(Collectors.joining(" ", "", ""));
}
// insert into xx.xx using xx.xx tags(xx,xx) values(),()...
public static String insertMultiTableMultiValuesUsingSuperTable(List<SubTableValue> tables) {
return "insert into " + tables.stream().filter(Objects::nonNull)
.map(table -> {
StringBuilder sb = new StringBuilder();
sb.append(table.getDatabase()).append(".").append(table.getName());
sb.append(" using ").append(table.getDatabase()).append(".").append(table.getSupertable());
sb.append(" tags ").append(tagValues(table.getTags()));
sb.append(" values ").append(rowValues(table.getValues()));
return sb.toString();
}).collect(Collectors.joining(" "));
}
// create table if not exists xx.xx (f1 xx,f2 xx...) tags(t1 xx, t2 xx...)
public static String createSuperTable(SuperTableMeta tableMetadata) {
StringBuilder sb = new StringBuilder();
sb.append("create table if not exists ").append(tableMetadata.getDatabase()).append(".").append(tableMetadata.getName());
String fields = tableMetadata.getFields().stream()
.filter(Objects::nonNull).map(field -> field.getName() + " " + field.getType() + " ")
.collect(Collectors.joining(",", "(", ")"));
sb.append(fields);
sb.append(" tags ");
String tags = tableMetadata.getTags().stream().filter(Objects::nonNull)
.map(tag -> tag.getName() + " " + tag.getType() + " ")
.collect(Collectors.joining(",", "(", ")"));
sb.append(tags);
return sb.toString();
}
public static String createTable(TableMeta tableMeta) {
StringBuilder sb = new StringBuilder();
sb.append("create table if not exists ").append(tableMeta.getDatabase()).append(".").append(tableMeta.getName()).append(" ");
String fields = tableMeta.getFields().stream()
.filter(Objects::nonNull).map(field -> field.getName() + " " + field.getType() + " ")
.collect(Collectors.joining(",", "(", ")"));
sb.append(fields);
return sb.toString();
}
// insert into xx.xx values()
public static String insertOneTableMultiValues(TableValue table) {
StringBuilder sb = new StringBuilder();
sb.append("insert into ").append(table.getDatabase()).append(".").append(table.getName() + " ");
sb.append("values").append(rowValues(table.getValues()));
return sb.toString();
}
// insert into xx.xx (f1, f2, f3...) values(xx,xx,xx),(xx,xx,xx)...
public static String insertOneTableMultiValuesWithColumns(TableValue table) {
StringBuilder sb = new StringBuilder();
sb.append("insert into ").append(table.getDatabase()).append(".").append(table.getName()).append(" ");
sb.append(columnNames(table.getColumns()));
sb.append(" values ").append(rowValues(table.getValues()));
return sb.toString();
}
// (f1, f2, f3...)
private static String columnNames(List<FieldMeta> fields) {
return fields.stream()
.filter(Objects::nonNull)
.map(column -> column.getName() + " ")
.collect(Collectors.joining(",", "(", ")"));
}
public static String insertMultiTableMultiValuesWithColumns(List<TableValue> tables) {
StringBuilder sb = new StringBuilder();
sb.append("insert into ").append(tables.stream().filter(Objects::nonNull)
.map(table -> table.getDatabase() + "." + table.getName() + " " + columnNames(table.getColumns()) + " values " + rowValues(table.getValues()))
.collect(Collectors.joining(" ")));
return sb.toString();
}
public static String insertMultiTableMultiValues(List<TableValue> tables) {
StringBuilder sb = new StringBuilder();
sb.append("insert into ").append(tables.stream().filter(Objects::nonNull).map(table ->
table.getDatabase() + "." + table.getName() + " values " + rowValues(table.getValues())
).collect(Collectors.joining(" ")));
return sb.toString();
}
}
package com.taosdata.taosdemo.utils;
public class TaosConstants {
public static final String[] DATA_TYPES = {
"timestamp", "int", "bigint", "float", "double",
"binary(64)", "smallint", "tinyint", "bool", "nchar(64)",
};
}
package com.taosdata.taosdemo.utils;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class TimeStampUtil {
private static final String datetimeFormat = "yyyy-MM-dd HH:mm:ss.SSS";
public static long datetimeToLong(String dateTime) {
SimpleDateFormat sdf = new SimpleDateFormat(datetimeFormat);
try {
return sdf.parse(dateTime).getTime();
} catch (ParseException e) {
throw new IllegalArgumentException("invalid datetime string >>> " + dateTime);
}
}
public static String longToDatetime(long time) {
SimpleDateFormat sdf = new SimpleDateFormat(datetimeFormat);
return sdf.format(new Date(time));
}
public static class TimeTuple {
public Long start;
public Long end;
public Long timeGap;
TimeTuple(long start, long end, long timeGap) {
this.start = start;
this.end = end;
this.timeGap = timeGap;
}
}
public static TimeTuple range(long start, long timeGap, long size) {
long now = System.currentTimeMillis();
if (timeGap < 1)
timeGap = 1;
if (start == 0)
start = now - size * timeGap;
// 如果size小于1异常
if (size < 1)
throw new IllegalArgumentException("size less than 1.");
// 如果timeGap为1,已经超长,需要前移start
if (start + size > now) {
start = now - size;
return new TimeTuple(start, now, 1);
}
long end = start + (long) (timeGap * size);
if (end > now) {
//压缩timeGap
end = now;
double gap = (end - start) / (size * 1.0f);
if (gap < 1.0f) {
timeGap = 1;
start = end - size;
} else {
timeGap = (long) gap;
end = start + (long) (timeGap * size);
}
}
return new TimeTuple(start, end, timeGap);
}
}
jdbc.driver=com.taosdata.jdbc.rs.RestfulDriver
#jdbc.driver=com.taosdata.jdbc.TSDBDriver
hikari.maximum-pool-size=20
hikari.minimum-idle=20
hikari.max-lifetime=0
\ No newline at end of file
{
"filetype": "insert",
"cfgdir": "/etc/taos",
"host": "127.0.0.1",
"port": 6030,
"user": "root",
"password": "taosdata",
"thread_count": 2,
"databases": [
{
"dbinfo": {
"name": "db04",
"drop": "no",
"replica": 1,
"days": 2,
"cache": 16,
"blocks": 8,
"precision": "ms",
"keep": 36500,
"minRows": 100,
"maxRows": 4096,
"comp": 2,
"walLevel": 1,
"quorum": 1,
"fsync": 3000,
"update": 0
},
"super_tables": [
{
"name": "stb04",
"child_table_exists": "no",
"childtable_count": 10,
"childtable_prefix": "stb01_",
"auto_create_table": "no",
"data_source": "rand",
"insert_mode": "taosc",
"insert_rate": 0,
"insert_rows": 100,
"interlace_rows": 3,
"max_sql_len": 1024,
"disorder_ratio": 0,
"disorder_range": 1000,
"timestamp_step": 10,
"start_timestamp": "2020-10-01 00:00:00.000",
"sample_format": "csv",
"sample_file": "./sample.csv",
"tags_file": "",
"columns": [
{
"type": "TINYINT"
},
{
"type": "SMALLINT"
},
{
"type": "INT"
},
{
"type": "BIGINT"
},
{
"type": "BOOL"
},
{
"type": "FLOAT"
},
{
"type": "DOUBLE"
},
{
"type": "TIMESTAMP"
},
{
"type": "BINARY",
"len": 16
},
{
"type": "NCHAR",
"len": 4
}
],
"tags": [
{
"type": "TINYINT"
},
{
"type": "SMALLINT"
},
{
"type": "INT"
},
{
"type": "BIGINT"
},
{
"type": "BOOL"
},
{
"type": "FLOAT"
},
{
"type": "DOUBLE"
},
{
"type": "BINARY",
"len": 16
},
{
"type": "NCHAR",
"len": 4
}
]
}
]
}
]
}
### 设置###
log4j.rootLogger=info,stdout
### 输出信息到控制抬 ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=[%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n
### 输出DEBUG 级别以上的日志到=logs/debug.log
log4j.appender.DebugLog=org.apache.log4j.DailyRollingFileAppender
log4j.appender.DebugLog.File=logs/debug.log
log4j.appender.DebugLog.Append=true
log4j.appender.DebugLog.Threshold=DEBUG
log4j.appender.DebugLog.layout=org.apache.log4j.PatternLayout
log4j.appender.DebugLog.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
### 输出ERROR 级别以上的日志到=logs/error.log
log4j.appender.ErrorLog=org.apache.log4j.DailyRollingFileAppender
log4j.appender.ErrorLog.File=logs/error.log
log4j.appender.ErrorLog.Append=true
log4j.appender.ErrorLog.Threshold=ERROR
log4j.appender.ErrorLog.layout=org.apache.log4j.PatternLayout
log4j.appender.ErrorLog.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
\ No newline at end of file
{
"filetype":"query",
"cfgdir": "/etc/taos",
"host": "127.0.0.1",
"port": 6030,
"user": "root",
"password": "taosdata",
"databases": "db01",
"super_table_query":
{"rate":1, "concurrent":1,"time":10000,
"sqls": [{"sql": "select count(*) from stb01", "result": "./query_res0.txt"}]
},
"sub_table_query":
{"stblname": "stb01", "rate":1, "threads":1,
"sqls": [{"sql": "select count(*) from xxxx", "result": "./query_res1.txt"}]
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Index</title>
</head>
<body>
<h1>Developing~~~</h1>
</body>
</html>
\ No newline at end of file
package com.taosdata.taosdemo.service;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
public class DatabaseServiceTest {
private DatabaseService service;
@Test
public void testCreateDatabase1() {
service.createDatabase("testXXXX");
}
@Test
public void dropDatabase() {
service.dropDatabase("testXXXX");
}
@Test
public void useDatabase() {
service.useDatabase("test");
}
}
\ No newline at end of file
package com.taosdata.taosdemo.service;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.junit.BeforeClass;
import org.junit.Test;
public class QueryServiceTest {
private static QueryService queryService;
@Test
public void areValidQueries() {
}
@Test
public void generateSuperTableQueries() {
String[] sqls = queryService.generateSuperTableQueries("restful_test");
for (String sql : sqls) {
System.out.println(sql);
}
}
@Test
public void querySuperTable() {
String[] sqls = queryService.generateSuperTableQueries("restful_test");
queryService.querySuperTable(sqls, 1000, 10, 10);
}
@BeforeClass
public static void beforeClass() throws ClassNotFoundException {
Class.forName("com.taosdata.jdbc.TSDBDriver");
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:TAOS://127.0.0.1:6030/?charset=UTF-8&locale=en_US.UTF-8&timezone=UTC-8");
config.setUsername("root");
config.setPassword("taosdata");
HikariDataSource dataSource = new HikariDataSource(config);
queryService = new QueryService(dataSource);
}
}
\ No newline at end of file
package com.taosdata.taosdemo.service;
import com.taosdata.taosdemo.domain.SubTableMeta;
import com.taosdata.taosdemo.domain.TagValue;
import org.junit.Before;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
public class SubTableServiceTest {
private SubTableService service;
private List<SubTableMeta> subTables;
@Before
public void before() {
subTables = new ArrayList<>();
for (int i = 1; i <= 1; i++) {
SubTableMeta subTableMeta = new SubTableMeta();
subTableMeta.setDatabase("test");
subTableMeta.setSupertable("weather");
subTableMeta.setName("t" + i);
List<TagValue> tags = new ArrayList<>();
tags.add(new TagValue("location", "beijing"));
tags.add(new TagValue("groupId", i));
subTableMeta.setTags(tags);
subTables.add(subTableMeta);
}
}
@Test
public void testCreateSubTable() {
}
@Test
public void testCreateSubTableList() {
}
}
\ No newline at end of file
package com.taosdata.taosdemo.service;
import com.taosdata.taosdemo.domain.FieldMeta;
import com.taosdata.taosdemo.domain.SuperTableMeta;
import com.taosdata.taosdemo.domain.TagMeta;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
public class SuperTableServiceTest {
private SuperTableService service;
@Test
public void testCreate() {
SuperTableMeta superTableMeta = new SuperTableMeta();
superTableMeta.setDatabase("test");
superTableMeta.setName("weather");
List<FieldMeta> fields = new ArrayList<>();
fields.add(new FieldMeta("ts", "timestamp"));
fields.add(new FieldMeta("temperature", "float"));
fields.add(new FieldMeta("humidity", "int"));
superTableMeta.setFields(fields);
List<TagMeta> tags = new ArrayList<>();
tags.add(new TagMeta("location", "nchar(64)"));
tags.add(new TagMeta("groupId", "int"));
superTableMeta.setTags(tags);
service.create(superTableMeta);
}
}
\ No newline at end of file
package com.taosdata.taosdemo.service;
import com.taosdata.taosdemo.domain.TableMeta;
import org.junit.Before;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
public class TableServiceTest {
private TableService tableService;
private List<TableMeta> tables;
@Before
public void before() {
tables = new ArrayList<>();
for (int i = 0; i < 1; i++) {
TableMeta tableMeta = new TableMeta();
tableMeta.setDatabase("test");
tableMeta.setName("weather" + (i + 1));
tables.add(tableMeta);
}
}
@Test
public void testCreate() {
tableService.create(tables);
}
}
\ No newline at end of file
package com.taosdata.taosdemo.service.data;
import com.taosdata.taosdemo.domain.FieldMeta;
import com.taosdata.taosdemo.domain.RowValue;
import com.taosdata.taosdemo.utils.TimeStampUtil;
import org.junit.After;
import org.junit.Assert;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
public class FieldValueGeneratorTest {
private List<RowValue> rowValues;
@Test
public void generate() {
List<FieldMeta> fieldMetas = new ArrayList<>();
fieldMetas.add(new FieldMeta("ts", "timestamp"));
fieldMetas.add(new FieldMeta("temperature", "float"));
fieldMetas.add(new FieldMeta("humidity", "int"));
long start = TimeStampUtil.datetimeToLong("2020-01-01 00:00:00.000");
long end = TimeStampUtil.datetimeToLong("2020-01-01 10:00:00.000");
rowValues = FieldValueGenerator.generate(start, end, 1000l * 3600, fieldMetas);
Assert.assertEquals(10, rowValues.size());
}
@Test
public void disrupt() {
List<FieldMeta> fieldMetas = new ArrayList<>();
fieldMetas.add(new FieldMeta("ts", "timestamp"));
fieldMetas.add(new FieldMeta("temperature", "float"));
fieldMetas.add(new FieldMeta("humidity", "int"));
long start = TimeStampUtil.datetimeToLong("2020-01-01 00:00:00.000");
long end = TimeStampUtil.datetimeToLong("2020-01-01 10:00:00.000");
rowValues = FieldValueGenerator.generate(start, end, 1000l * 3600l, fieldMetas);
FieldValueGenerator.disrupt(rowValues, 20, 1000);
Assert.assertEquals(10, rowValues.size());
}
@After
public void after() {
for (RowValue row : rowValues) {
row.getFields().stream().forEach(field -> {
if (field.getName().equals("ts")) {
System.out.print(TimeStampUtil.longToDatetime((Long) field.getValue()));
} else
System.out.print(" ," + field.getValue());
});
System.out.println();
}
}
}
\ No newline at end of file
package com.taosdata.taosdemo.service.data;
import com.taosdata.taosdemo.domain.FieldMeta;
import com.taosdata.taosdemo.domain.SubTableMeta;
import com.taosdata.taosdemo.domain.SuperTableMeta;
import com.taosdata.taosdemo.domain.TagMeta;
import org.junit.After;
import org.junit.Assert;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
public class SubTableMetaGeneratorTest {
List<SubTableMeta> subTableMetas;
@Test
public void generate() {
SuperTableMeta superTableMeta = new SuperTableMeta();
superTableMeta.setDatabase("test");
superTableMeta.setName("weather");
List<FieldMeta> fields = new ArrayList<>();
fields.add(new FieldMeta("ts", "timestamp"));
fields.add(new FieldMeta("temperature", "float"));
fields.add(new FieldMeta("humidity", "int"));
superTableMeta.setFields(fields);
List<TagMeta> tags = new ArrayList<>();
tags.add(new TagMeta("location", "nchar(64)"));
tags.add(new TagMeta("groupId", "int"));
superTableMeta.setTags(tags);
subTableMetas = SubTableMetaGenerator.generate(superTableMeta, 10, "t");
Assert.assertEquals(10, subTableMetas.size());
Assert.assertEquals("t1", subTableMetas.get(0).getName());
Assert.assertEquals("t2", subTableMetas.get(1).getName());
Assert.assertEquals("t3", subTableMetas.get(2).getName());
Assert.assertEquals("t4", subTableMetas.get(3).getName());
Assert.assertEquals("t5", subTableMetas.get(4).getName());
Assert.assertEquals("t6", subTableMetas.get(5).getName());
Assert.assertEquals("t7", subTableMetas.get(6).getName());
Assert.assertEquals("t8", subTableMetas.get(7).getName());
Assert.assertEquals("t9", subTableMetas.get(8).getName());
Assert.assertEquals("t10", subTableMetas.get(9).getName());
}
@After
public void after() {
for (SubTableMeta subTableMeta : subTableMetas) {
System.out.println(subTableMeta);
}
}
}
\ No newline at end of file
package com.taosdata.taosdemo.service.data;
import com.taosdata.taosdemo.domain.FieldMeta;
import com.taosdata.taosdemo.domain.SuperTableMeta;
import com.taosdata.taosdemo.domain.TagMeta;
import org.junit.After;
import org.junit.Assert;
import org.junit.Test;
public class SuperTableMetaGeneratorImplTest {
private SuperTableMeta meta;
@Test
public void generate() {
String sql = "create table test.weather (ts timestamp, temperature float, humidity int) tags(location nchar(64), groupId int)";
meta = SuperTableMetaGenerator.generate(sql);
Assert.assertEquals("test", meta.getDatabase());
Assert.assertEquals("weather", meta.getName());
Assert.assertEquals(3, meta.getFields().size());
Assert.assertEquals("ts", meta.getFields().get(0).getName());
Assert.assertEquals("timestamp", meta.getFields().get(0).getType());
Assert.assertEquals("temperature", meta.getFields().get(1).getName());
Assert.assertEquals("float", meta.getFields().get(1).getType());
Assert.assertEquals("humidity", meta.getFields().get(2).getName());
Assert.assertEquals("int", meta.getFields().get(2).getType());
Assert.assertEquals("location", meta.getTags().get(0).getName());
Assert.assertEquals("nchar(64)", meta.getTags().get(0).getType());
Assert.assertEquals("groupid", meta.getTags().get(1).getName());
Assert.assertEquals("int", meta.getTags().get(1).getType());
}
@Test
public void generate2() {
meta = SuperTableMetaGenerator.generate("test", "weather", 10, "col", 10, "tag");
Assert.assertEquals("test", meta.getDatabase());
Assert.assertEquals("weather", meta.getName());
Assert.assertEquals(11, meta.getFields().size());
for (FieldMeta fieldMeta : meta.getFields()) {
Assert.assertNotNull(fieldMeta.getName());
Assert.assertNotNull(fieldMeta.getType());
}
for (TagMeta tagMeta : meta.getTags()) {
Assert.assertNotNull(tagMeta.getName());
Assert.assertNotNull(tagMeta.getType());
}
}
@After
public void after() {
System.out.println(meta.getDatabase());
System.out.println(meta.getName());
for (FieldMeta fieldMeta : meta.getFields()) {
System.out.println(fieldMeta);
}
for (TagMeta tagMeta : meta.getTags()) {
System.out.println(tagMeta);
}
}
}
\ No newline at end of file
package com.taosdata.taosdemo.service.data;
import com.taosdata.taosdemo.domain.TagMeta;
import com.taosdata.taosdemo.domain.TagValue;
import org.junit.After;
import org.junit.Assert;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
public class TagValueGeneratorTest {
List<TagValue> tagvalues;
@Test
public void generate() {
List<TagMeta> tagMetaList = new ArrayList<>();
tagMetaList.add(new TagMeta("location", "nchar(10)"));
tagMetaList.add(new TagMeta("groupId", "int"));
tagMetaList.add(new TagMeta("ts", "timestamp"));
tagMetaList.add(new TagMeta("temperature", "float"));
tagMetaList.add(new TagMeta("humidity", "double"));
tagMetaList.add(new TagMeta("text", "binary(10)"));
tagvalues = TagValueGenerator.generate(tagMetaList);
Assert.assertEquals("location", tagvalues.get(0).getName());
Assert.assertEquals("groupId", tagvalues.get(1).getName());
Assert.assertEquals("ts", tagvalues.get(2).getName());
Assert.assertEquals("temperature", tagvalues.get(3).getName());
Assert.assertEquals("humidity", tagvalues.get(4).getName());
Assert.assertEquals("text", tagvalues.get(5).getName());
}
@After
public void after() {
tagvalues.stream().forEach(System.out::println);
}
}
\ No newline at end of file
package com.taosdata.taosdemo.utils;
import org.junit.Assert;
import org.junit.Test;
public class DataGeneratorTest {
@Test
public void randomValue() {
for (int i = 0; i < TaosConstants.DATA_TYPES.length; i++) {
System.out.println(TaosConstants.DATA_TYPES[i] + " >>> " + DataGenerator.randomValue(TaosConstants.DATA_TYPES[i]));
}
}
@Test
public void randomNchar() {
String s = DataGenerator.randomNchar(10);
Assert.assertEquals(10, s.length());
}
}
\ No newline at end of file
package com.taosdata.taosdemo.utils;
import com.taosdata.taosdemo.domain.*;
import org.junit.Before;
import org.junit.Test;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class SqlSpellerTest {
@Test
public void createDatabase() {
HashMap<String, String> map = new HashMap<>();
map.put("database", "jdbcdb");
map.put("keep", "3650");
map.put("days", "30");
map.put("replica", "1");
map.put("minRows", "100");
map.put("maxRows", "1000");
map.put("cache", "16");
map.put("blocks", "8");
map.put("precision", "ms");
map.put("comp", "2");
map.put("walLevel", "1");
map.put("quorum", "1");
map.put("fsync", "3000");
map.put("update", "0");
String sql = SqlSpeller.createDatabase(map);
System.out.println(sql);
}
@Test
public void createTableUsingSuperTable() {
SubTableMeta subTableMeta = new SubTableMeta();
subTableMeta.setDatabase("test");
subTableMeta.setSupertable("weather");
subTableMeta.setName("t1");
List<TagValue> tags = new ArrayList<>();
for (int i = 0; i < 3; i++) {
tags.add(new TagValue("tag" + (i + 1), "nchar(64)"));
}
subTableMeta.setTags(tags);
String sql = SqlSpeller.createTableUsingSuperTable(subTableMeta);
System.out.println(sql);
}
@Test
public void insertOneTableMultiValues() {
String sql = SqlSpeller.insertOneTableMultiValues(tables.get(0));
System.out.println(sql);
}
@Test
public void insertOneTableMultiValuesUsingSuperTable() {
String sql = SqlSpeller.insertOneTableMultiValuesUsingSuperTable(tables.get(0));
System.out.println(sql);
}
@Test
public void insertMultiTableMultiValues() {
String sql = SqlSpeller.insertMultiSubTableMultiValues(tables);
System.out.println(sql);
}
@Test
public void insertMultiTableMultiValuesUsingSuperTable() {
String sql = SqlSpeller.insertMultiTableMultiValuesUsingSuperTable(tables);
System.out.println(sql);
}
private List<SubTableValue> tables;
@Before
public void before() {
tables = new ArrayList<>();
for (int ind = 0; ind < 3; ind++) {
SubTableValue table = new SubTableValue();
table.setDatabase("test");
// supertable
table.setSupertable("weather");
table.setName("t" + (ind + 1));
// tags
List<TagValue> tags = new ArrayList<>();
for (int i = 0; i < 3; i++) {
tags.add(new TagValue("tag" + (i + 1), "beijing"));
}
table.setTags(tags);
// values
List<RowValue> values = new ArrayList<>();
for (int i = 0; i < 2; i++) {
List<FieldValue> fields = new ArrayList<>();
for (int j = 0; j < 4; j++) {
fields.add(new FieldValue("f" + (j + 1), (j + 1) * 10));
}
values.add(new RowValue(fields));
}
table.setValues(values);
tables.add(table);
}
}
@Test
public void createSuperTable() {
SuperTableMeta superTableMeta = new SuperTableMeta();
superTableMeta.setDatabase("test");
superTableMeta.setName("weather");
List<FieldMeta> fields = new ArrayList<>();
for (int i = 0; i < 5; i++) {
fields.add(new FieldMeta("f" + (i + 1), "int"));
}
superTableMeta.setFields(fields);
List<TagMeta> tags = new ArrayList<>();
for (int i = 0; i < 3; i++) {
tags.add(new TagMeta("t" + (i + 1), "nchar(64)"));
}
superTableMeta.setTags(tags);
String sql = SqlSpeller.createSuperTable(superTableMeta);
System.out.println(sql);
}
@Test
public void createTable() {
TableMeta table = new TableMeta();
table.setDatabase("test");
table.setName("t1");
List<FieldMeta> fields = new ArrayList<>();
for (int i = 0; i < 3; i++) {
FieldMeta field = new FieldMeta();
field.setName("f" + (i + 1));
field.setType("nchar(64)");
fields.add(field);
}
table.setFields(fields);
String sql = SqlSpeller.createTable(table);
System.out.println(sql);
}
@Test
public void testInsertOneTableMultiValues() {
TableValue table = new TableValue();
table.setDatabase("test");
table.setName("t1");
List<RowValue> values = new ArrayList<>();
for (int j = 0; j < 5; j++) {
List<FieldValue> fields = new ArrayList<>();
for (int k = 0; k < 2; k++) {
FieldValue field = new FieldValue<>();
field.setValue((k + 1) * 100);
fields.add(field);
}
values.add(new RowValue(fields));
}
table.setValues(values);
String sql = SqlSpeller.insertOneTableMultiValues(table);
System.out.println(sql);
}
@Test
public void insertOneTableMultiValuesWithColumns() {
TableValue tableValue = new TableValue();
tableValue.setDatabase("test");
tableValue.setName("weather");
// columns
List<FieldMeta> columns = new ArrayList<>();
for (int i = 0; i < 3; i++) {
FieldMeta field = new FieldMeta();
field.setName("f" + (i + 1));
columns.add(field);
}
tableValue.setColumns(columns);
// values
List<RowValue> values = new ArrayList<>();
for (int i = 0; i < 3; i++) {
List<FieldValue> fields = new ArrayList<>();
for (int j = 0; j < 3; j++) {
FieldValue field = new FieldValue();
field.setValue(j);
fields.add(field);
}
values.add(new RowValue(fields));
}
tableValue.setValues(values);
String sql = SqlSpeller.insertOneTableMultiValuesWithColumns(tableValue);
System.out.println(sql);
}
@Test
public void insertMultiTableMultiValuesWithColumns() {
List<TableValue> tables = new ArrayList<>();
for (int i = 0; i < 3; i++) {
TableValue table = new TableValue();
table.setDatabase("test");
table.setName("t" + (i + 1));
// columns
List<FieldMeta> columns = new ArrayList<>();
for (int j = 0; j < 3; j++) {
FieldMeta field = new FieldMeta();
field.setName("f" + (j + 1));
columns.add(field);
}
table.setColumns(columns);
// values
List<RowValue> values = new ArrayList<>();
for (int j = 0; j < 5; j++) {
List<FieldValue> fields = new ArrayList<>();
for (int k = 0; k < columns.size(); k++) {
FieldValue field = new FieldValue<>();
field.setValue((k + 1) * 10);
fields.add(field);
}
values.add(new RowValue(fields));
}
table.setValues(values);
tables.add(table);
}
String sql = SqlSpeller.insertMultiTableMultiValuesWithColumns(tables);
System.out.println(sql);
}
@Test
public void testInsertMultiTableMultiValues() {
List<TableValue> tables = new ArrayList<>();
for (int i = 0; i < 3; i++) {
TableValue table = new TableValue();
table.setDatabase("test");
table.setName("t" + (i + 1));
List<RowValue> values = new ArrayList<>();
for (int j = 0; j < 5; j++) {
List<FieldValue> fields = new ArrayList<>();
for (int k = 0; k < 2; k++) {
FieldValue field = new FieldValue<>();
field.setValue((k + 1) * 10);
fields.add(field);
}
values.add(new RowValue(fields));
}
table.setValues(values);
tables.add(table);
}
String sql = SqlSpeller.insertMultiTableMultiValues(tables);
System.out.println(sql);
}
}
\ No newline at end of file
package com.taosdata.taosdemo.utils;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class TimeStampUtilTest {
@Test
public void datetimeToLong() {
final String startTime = "2005-01-01 00:00:00.000";
long start = TimeStampUtil.datetimeToLong(startTime);
assertEquals(1104508800000l, start);
String dateTimeStr = TimeStampUtil.longToDatetime(start);
assertEquals("2005-01-01 00:00:00.000", dateTimeStr);
}
@Test
public void longToDatetime() {
System.out.println(TimeStampUtil.longToDatetime(1293334499006l));
String datetime = TimeStampUtil.longToDatetime(1510000000000L);
assertEquals("2017-11-07 04:26:40.000", datetime);
long timestamp = TimeStampUtil.datetimeToLong(datetime);
assertEquals(1510000000000L, timestamp);
}
@Test
public void range() {
long start = TimeStampUtil.datetimeToLong("2020-10-01 00:00:00.000");
long timeGap = 1000;
long numOfRowsPerTable = 1000l * 3600l * 24l * 90l;
TimeStampUtil.TimeTuple timeTuple = TimeStampUtil.range(start, timeGap, numOfRowsPerTable);
System.out.println(TimeStampUtil.longToDatetime(timeTuple.start));
System.out.println(TimeStampUtil.longToDatetime(timeTuple.end));
System.out.println(timeTuple.timeGap);
}
}
\ No newline at end of file
# Linux Platform
install.packages('rJDBC', repos='http://cran.us.r-project.org')
# Loading RJDBC packages
library('RJDBC')
# Set up working path and JDBC driver storage location
setwd('C:/TDengine')
# Load JDBC Driver for TDengine
drv<-JDBC("com.taosdata.jdbc.TSDBDriver","JDBCDriver-1.0.0-dist.jar", identifier.quote="\"")
# Connect to the database
conn<-dbConnect(drv,"jdbc:TSDB://192.168.1.114:0/?user=root&password=taosdata","root","taosdata")
# Get connection information
dbGetInfo(conn)
# Using database test
dbSendUpdate(conn, "use test")
# Insert data
dbSendUpdate(conn, "insert into t1 values(now, 99)")
# View all tables
table1<-dbGetQuery(conn,"show tables")
# Functional support for RJDBC
# List all tables
dbListTables(conn)
# Is there table iris
dbExistsTable(conn,”iris”)
# Connect summary information
summary(conn)
dbGetInfo(conn)
# Read all the data from the T1 table
dbReadTable(conn, "t1")
# Delete table t1
dbRemoveTable(conn,"t1")
# Execute any non-query SQL statements
dbSendUpdate(conn, "create table t1(a timestamp, b int, c nchar(12))");
# Write data
dbWriteTable(conn, "t1", t_demo_n, overwrite=FALSE, append=TRUE)
# Extracting data on demand using SQL statements
dbGetQuery(conn, "select k from tu")
# Close the connection
dbDisconnect(conn)
1503851026421, 220, 1.10
1503851026422, 221, 1.20
1503851026423, 219, 1.09
1503851026424, 222, 1.11
1503851026425, 220, 1.08
'2019-07-22 10:00:01.000', 219, 1.06
'2019-07-22 10:00:02.000', 218, 1.04
'2019-07-22 10:01:02.000', 220, 1.12
'2019-07-22 11:01:02.000', 221, 1.11
'2019-07-23 11:01:02.000', 220, 1.09
PROJECT(TDengine)
IF (TD_LINUX)
INCLUDE_DIRECTORIES(. ${TD_COMMUNITY_DIR}/src/inc ${TD_COMMUNITY_DIR}/src/client/inc ${TD_COMMUNITY_DIR}/inc)
AUX_SOURCE_DIRECTORY(. SRC)
ADD_EXECUTABLE(demo apitest.c)
TARGET_LINK_LIBRARIES(demo taos_static trpc tutil pthread )
ADD_EXECUTABLE(sml schemaless.c)
TARGET_LINK_LIBRARIES(sml taos_static trpc tutil pthread )
ADD_EXECUTABLE(sqlperf sqlperf.c)
TARGET_LINK_LIBRARIES(sqlperf taos_static trpc tutil pthread )
ADD_EXECUTABLE(subscribe subscribe.c)
TARGET_LINK_LIBRARIES(subscribe taos_static trpc tutil pthread )
ADD_EXECUTABLE(epoll epoll.c)
TARGET_LINK_LIBRARIES(epoll taos_static trpc tutil pthread ${LINK_LUA})
ENDIF ()
IF (TD_DARWIN)
INCLUDE_DIRECTORIES(. ${TD_COMMUNITY_DIR}/src/inc ${TD_COMMUNITY_DIR}/src/client/inc ${TD_COMMUNITY_DIR}/inc)
AUX_SOURCE_DIRECTORY(. SRC)
ADD_EXECUTABLE(demo demo.c)
TARGET_LINK_LIBRARIES(demo taos_static trpc tutil pthread ${LINK_LUA})
ADD_EXECUTABLE(epoll epoll.c)
TARGET_LINK_LIBRARIES(epoll taos_static trpc tutil pthread ${LINK_LUA})
ADD_EXECUTABLE(parameter-binding parameter-binding.c)
TARGET_LINK_LIBRARIES(parameter-binding taos)
ENDIF ()
// sample code to verify all TDengine API
// to compile: gcc -o apitest apitest.c -ltaos
#include "taoserror.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <taos.h>
#include <unistd.h>
static void prepare_data(TAOS* taos) {
TAOS_RES* result;
result = taos_query(taos, "drop database if exists test;");
taos_free_result(result);
usleep(100000);
result = taos_query(taos, "create database test precision 'ns';");
taos_free_result(result);
usleep(100000);
taos_select_db(taos, "test");
result = taos_query(taos, "create table meters(ts timestamp, a int) tags(area int);");
taos_free_result(result);
result = taos_query(taos, "create table t0 using meters tags(0);");
taos_free_result(result);
result = taos_query(taos, "create table t1 using meters tags(1);");
taos_free_result(result);
result = taos_query(taos, "create table t2 using meters tags(2);");
taos_free_result(result);
result = taos_query(taos, "create table t3 using meters tags(3);");
taos_free_result(result);
result = taos_query(taos, "create table t4 using meters tags(4);");
taos_free_result(result);
result = taos_query(taos, "create table t5 using meters tags(5);");
taos_free_result(result);
result = taos_query(taos, "create table t6 using meters tags(6);");
taos_free_result(result);
result = taos_query(taos, "create table t7 using meters tags(7);");
taos_free_result(result);
result = taos_query(taos, "create table t8 using meters tags(8);");
taos_free_result(result);
result = taos_query(taos, "create table t9 using meters tags(9);");
taos_free_result(result);
result = taos_query(taos,
"insert into t0 values('2020-01-01 00:00:00.000', 0)"
" ('2020-01-01 00:01:00.000', 0)"
" ('2020-01-01 00:02:00.000', 0)"
" t1 values('2020-01-01 00:00:00.000', 0)"
" ('2020-01-01 00:01:00.000', 0)"
" ('2020-01-01 00:02:00.000', 0)"
" ('2020-01-01 00:03:00.000', 0)"
" t2 values('2020-01-01 00:00:00.000', 0)"
" ('2020-01-01 00:01:00.000', 0)"
" ('2020-01-01 00:01:01.000', 0)"
" ('2020-01-01 00:01:02.000', 0)"
" t3 values('2020-01-01 00:01:02.000', 0)"
" t4 values('2020-01-01 00:01:02.000', 0)"
" t5 values('2020-01-01 00:01:02.000', 0)"
" t6 values('2020-01-01 00:01:02.000', 0)"
" t7 values('2020-01-01 00:01:02.000', 0)"
" t8 values('2020-01-01 00:01:02.000', 0)"
" t9 values('2020-01-01 00:01:02.000', 0)");
int affected = taos_affected_rows(result);
if (affected != 18) {
printf("\033[31m%d rows affected by last insert statement, but it should be 18\033[0m\n", affected);
}
taos_free_result(result);
// super tables subscription
usleep(1000000);
}
static int print_result(TAOS_RES* res, int blockFetch) {
TAOS_ROW row = NULL;
int num_fields = taos_num_fields(res);
TAOS_FIELD* fields = taos_fetch_fields(res);
int nRows = 0;
if (blockFetch) {
int rows = 0;
while ((rows = taos_fetch_block(res, &row))) {
// for (int i = 0; i < rows; i++) {
// char temp[256];
// taos_print_row(temp, row + i, fields, num_fields);
// puts(temp);
//}
nRows += rows;
}
} else {
while ((row = taos_fetch_row(res))) {
char temp[256] = {0};
taos_print_row(temp, row, fields, num_fields);
puts(temp);
nRows++;
}
}
printf("%d rows consumed.\n", nRows);
return nRows;
}
static void check_row_count(int line, TAOS_RES* res, int expected) {
int actual = print_result(res, expected % 2);
if (actual != expected) {
printf("\033[31mline %d: row count mismatch, expected: %d, actual: %d\033[0m\n", line, expected, actual);
} else {
printf("line %d: %d rows consumed as expected\n", line, actual);
}
}
static void verify_query(TAOS* taos) {
prepare_data(taos);
int code = taos_load_table_info(taos, "t0,t1,t2,t3,t4,t5,t6,t7,t8,t9");
if (code != 0) {
printf("\033[31mfailed to load table info: 0x%08x\033[0m\n", code);
}
code = taos_validate_sql(taos, "select * from nonexisttable");
if (code == 0) {
printf("\033[31mimpossible, the table does not exists\033[0m\n");
}
code = taos_validate_sql(taos, "select * from meters");
if (code != 0) {
printf("\033[31mimpossible, the table does exists: 0x%08x\033[0m\n", code);
}
TAOS_RES* res = taos_query(taos, "select * from meters");
check_row_count(__LINE__, res, 18);
printf("result precision is: %d\n", taos_result_precision(res));
int c = taos_field_count(res);
printf("field count is: %d\n", c);
int* lengths = taos_fetch_lengths(res);
for (int i = 0; i < c; i++) {
printf("length of column %d is %d\n", i, lengths[i]);
}
taos_free_result(res);
res = taos_query(taos, "select * from t0");
check_row_count(__LINE__, res, 3);
taos_free_result(res);
res = taos_query(taos, "select * from nonexisttable");
code = taos_errno(res);
printf("code=%d, error msg=%s\n", code, taos_errstr(res));
taos_free_result(res);
res = taos_query(taos, "select * from meters");
taos_stop_query(res);
taos_free_result(res);
}
void subscribe_callback(TAOS_SUB* tsub, TAOS_RES* res, void* param, int code) {
int rows = print_result(res, *(int*)param);
printf("%d rows consumed in subscribe_callback\n", rows);
}
static void verify_subscribe(TAOS* taos) {
prepare_data(taos);
TAOS_SUB* tsub = taos_subscribe(taos, 0, "test", "select * from meters;", NULL, NULL, 0);
TAOS_RES* res = taos_consume(tsub);
check_row_count(__LINE__, res, 18);
res = taos_consume(tsub);
check_row_count(__LINE__, res, 0);
TAOS_RES* result;
result = taos_query(taos, "insert into t0 values('2020-01-01 00:02:00.001', 0);");
taos_free_result(result);
result = taos_query(taos, "insert into t8 values('2020-01-01 00:01:03.000', 0);");
taos_free_result(result);
res = taos_consume(tsub);
check_row_count(__LINE__, res, 2);
result = taos_query(taos, "insert into t2 values('2020-01-01 00:01:02.001', 0);");
taos_free_result(result);
result = taos_query(taos, "insert into t1 values('2020-01-01 00:03:00.001', 0);");
taos_free_result(result);
res = taos_consume(tsub);
check_row_count(__LINE__, res, 2);
result = taos_query(taos, "insert into t1 values('2020-01-01 00:03:00.002', 0);");
taos_free_result(result);
res = taos_consume(tsub);
check_row_count(__LINE__, res, 1);
// keep progress information and restart subscription
taos_unsubscribe(tsub, 1);
result = taos_query(taos, "insert into t0 values('2020-01-01 00:04:00.000', 0);");
taos_free_result(result);
tsub = taos_subscribe(taos, 1, "test", "select * from meters;", NULL, NULL, 0);
res = taos_consume(tsub);
check_row_count(__LINE__, res, 24);
// keep progress information and continue previous subscription
taos_unsubscribe(tsub, 1);
tsub = taos_subscribe(taos, 0, "test", "select * from meters;", NULL, NULL, 0);
res = taos_consume(tsub);
check_row_count(__LINE__, res, 0);
// don't keep progress information and continue previous subscription
taos_unsubscribe(tsub, 0);
tsub = taos_subscribe(taos, 0, "test", "select * from meters;", NULL, NULL, 0);
res = taos_consume(tsub);
check_row_count(__LINE__, res, 24);
// single meter subscription
taos_unsubscribe(tsub, 0);
tsub = taos_subscribe(taos, 0, "test", "select * from t0;", NULL, NULL, 0);
res = taos_consume(tsub);
check_row_count(__LINE__, res, 5);
res = taos_consume(tsub);
check_row_count(__LINE__, res, 0);
result = taos_query(taos, "insert into t0 values('2020-01-01 00:04:00.001', 0);");
taos_free_result(result);
res = taos_consume(tsub);
check_row_count(__LINE__, res, 1);
taos_unsubscribe(tsub, 0);
int blockFetch = 0;
tsub = taos_subscribe(taos, 1, "test", "select * from meters;", subscribe_callback, &blockFetch, 1000);
usleep(2000000);
result = taos_query(taos, "insert into t0 values('2020-01-01 00:05:00.001', 0);");
taos_free_result(result);
usleep(2000000);
taos_unsubscribe(tsub, 0);
}
void retrieve_callback(void* param, TAOS_RES* tres, int numOfRows) {
if (numOfRows > 0) {
printf("%d rows async retrieved\n", numOfRows);
taos_fetch_rows_a(tres, retrieve_callback, param);
} else {
if (numOfRows < 0) {
printf("\033[31masync retrieve failed, code: %d\033[0m\n", numOfRows);
} else {
printf("async retrieve completed\n");
}
taos_free_result(tres);
}
}
void select_callback(void* param, TAOS_RES* tres, int code) {
if (code == 0 && tres) {
taos_fetch_rows_a(tres, retrieve_callback, param);
} else {
printf("\033[31masync select failed, code: %d\033[0m\n", code);
}
}
void verify_async(TAOS* taos) {
prepare_data(taos);
taos_query_a(taos, "select * from meters", select_callback, NULL);
usleep(1000000);
}
void stream_callback(void* param, TAOS_RES* res, TAOS_ROW row) {
if (res == NULL || row == NULL) {
return;
}
int num_fields = taos_num_fields(res);
TAOS_FIELD* fields = taos_fetch_fields(res);
printf("got one row from stream_callback\n");
char temp[256] = {0};
taos_print_row(temp, row, fields, num_fields);
puts(temp);
}
void verify_stream(TAOS* taos) {
prepare_data(taos);
TAOS_STREAM* strm =
taos_open_stream(taos, "select count(*) from meters interval(1m)", stream_callback, 0, NULL, NULL);
printf("waiting for stream data\n");
usleep(100000);
TAOS_RES* result = taos_query(taos, "insert into t0 values(now, 0)(now+5s,1)(now+10s, 2);");
taos_free_result(result);
usleep(200000000);
taos_close_stream(strm);
}
void verify_schema_less(TAOS* taos) {
TAOS_RES* result;
result = taos_query(taos, "drop database if exists test;");
taos_free_result(result);
usleep(100000);
result = taos_query(taos, "create database test precision 'ns' update 1 keep 36500;");
taos_free_result(result);
usleep(100000);
taos_select_db(taos, "test");
result = taos_query(taos, "create stable ste(ts timestamp, f int) tags(t1 bigint)");
taos_free_result(result);
usleep(100000);
int code = 0, affected_rows = 0;
char* lines[] = {
"st,t1=3i64,t2=4f64,t3=\"t3\" c1=3i64,c3=L\"passit\",c2=false,c4=4f64 1626006833639000000",
"st,t1=4i64,t3=\"t4\",t2=5f64,t4=5f64 c1=3i64,c3=L\"passitagin\",c2=true,c4=5f64,c5=5f64 1626006833640000000",
"ste,t2=5f64,t3=L\"ste\" c1=true,c2=4i64,c3=\"iam\" 1626056811823316532",
"st,t1=4i64,t2=5f64,t3=\"t4\" c1=3i64,c3=L\"passitagain\",c2=true,c4=5f64 1626006833642000000",
"ste,t2=5f64,t3=L\"ste2\" c3=\"iamszhou\",c4=false 1626056811843316532",
"ste,t2=5f64,t3=L\"ste2\" c3=\"iamszhou\",c4=false,c5=32i8,c6=64i16,c7=32i32,c8=88.88f32 1626056812843316532",
"st,t1=4i64,t3=\"t4\",t2=5f64,t4=5f64 c1=3i64,c3=L\"passitagin\",c2=true,c4=5f64,c5=5f64,c6=7u64 1626006933640000000",
"stf,t1=4i64,t3=\"t4\",t2=5f64,t4=5f64 c1=3i64,c3=L\"passitagin\",c2=true,c4=5f64,c5=5f64,c6=7u64 1626006933640000000",
"stf,t1=4i64,t3=\"t4\",t2=5f64,t4=5f64 c1=3i64,c3=L\"passitagin_stf\",c2=false,c5=5f64,c6=7u64 1626006933641000000"
};
result = taos_schemaless_insert(taos, lines , sizeof(lines)/sizeof(char*), TSDB_SML_LINE_PROTOCOL, TSDB_SML_TIMESTAMP_NANO_SECONDS);
code = taos_errno(result);
if (code != TSDB_CODE_SUCCESS) {
affected_rows = taos_affected_rows(result);
printf("\033[31m [lines1]taos_schemaless_insert failed, code: %d,%s, affected rows:%d \033[0m\n", code, taos_errstr(result), affected_rows);
}
taos_free_result(result);
char* lines2[] = {
"stg,t1=3i64,t2=4f64,t3=\"t3\" c1=3i64,c3=L\"passit\",c2=false,c4=4f64 1626006833639000000",
"stg,t1=4i64,t3=\"t4\",t2=5f64,t4=5f64 c1=3i64,c3=L\"passitagin\",c2=true,c4=5f64,c5=5f64 1626006833641000000"
};
result = taos_schemaless_insert(taos, &lines2[0], 1, TSDB_SML_LINE_PROTOCOL, TSDB_SML_TIMESTAMP_NANO_SECONDS);
code = taos_errno(result);
if (code != TSDB_CODE_SUCCESS) {
affected_rows = taos_affected_rows(result);
printf("\033[31m [lines2_0]taos_schemaless_insert failed, code: %d,%s, affected rows:%d \033[0m\n", code, taos_errstr(result), affected_rows);
}
taos_free_result(result);
result = taos_schemaless_insert(taos, &lines2[1], 1, TSDB_SML_LINE_PROTOCOL, TSDB_SML_TIMESTAMP_NANO_SECONDS);
code = taos_errno(result);
if (code != TSDB_CODE_SUCCESS) {
affected_rows = taos_affected_rows(result);
printf("\033[31m [lines2_1]taos_schemaless_insert failed, code: %d,%s, affected rows:%d \033[0m\n", code, taos_errstr(result), affected_rows);
}
taos_free_result(result);
char* lines3[] = {
"sth,t1=4i64,t2=5f64,t4=5f64,ID=childTable c1=3i64,c3=L\"passitagin_stf\",c2=false,c5=5f64,c6=7u64 1626006933641",
"sth,t1=4i64,t2=5f64,t4=5f64 c1=3i64,c3=L\"passitagin_stf\",c2=false,c5=5f64,c6=7u64 1626006933654"
};
result = taos_schemaless_insert(taos, lines3, 2, TSDB_SML_LINE_PROTOCOL, TSDB_SML_TIMESTAMP_MILLI_SECONDS);
code = taos_errno(result);
if (code != TSDB_CODE_SUCCESS) {
affected_rows = taos_affected_rows(result);
printf("\033[31m [lines3]taos_schemaless_insert failed, code: %d,%s, affected rows:%d \033[0m\n", code, taos_errstr(result), affected_rows);
}
taos_free_result(result);
char* lines4[] = {
"st123456,t1=3i64,t2=4f64,t3=\"t3\" c1=3i64,c3=L\"passit\",c2=false,c4=4f64 1626006833639000000",
"dgtyqodr,t2=5f64,t3=L\"ste\" c1=tRue,c2=4i64,c3=\"iam\" 1626056811823316532"
};
result = taos_schemaless_insert(taos, lines4, 2, TSDB_SML_LINE_PROTOCOL, TSDB_SML_TIMESTAMP_NANO_SECONDS);
code = taos_errno(result);
if (code != TSDB_CODE_SUCCESS) {
affected_rows = taos_affected_rows(result);
printf("\033[31m [lines4]taos_schemaless_insert failed, code: %d,%s, affected rows:%d \033[0m\n", code, taos_errstr(result), affected_rows);
}
taos_free_result(result);
char* lines5[] = {
"zqlbgs,id=zqlbgs_39302_21680,t0=f,t1=127i8,t2=32767i16,t3=2147483647i32,t4=9223372036854775807i64,t5=11.12345f32,t6=22.123456789f64,t7=\"binaryTagValue\",t8=L\"ncharTagValue\" c0=f,c1=127i8,c2=32767i16,c3=2147483647i32,c4=9223372036854775807i64,c5=11.12345f32,c6=22.123456789f64,c7=\"binaryColValue\",c8=L\"ncharColValue\",c9=7u64 1626006833639000000",
"zqlbgs,t9=f,id=zqlbgs_39302_21680,t0=f,t1=127i8,t11=127i8,t2=32767i16,t3=2147483647i32,t4=9223372036854775807i64,t5=11.12345f32,t6=22.123456789f64,t7=\"binaryTagValue\",t8=L\"ncharTagValue\",t10=L\"ncharTagValue\" c10=f,c0=f,c1=127i8,c12=127i8,c2=32767i16,c3=2147483647i32,c4=9223372036854775807i64,c5=11.12345f32,c6=22.123456789f64,c7=\"binaryColValue\",c8=L\"ncharColValue\",c9=7u64,c11=L\"ncharColValue\" 1626006833639000000"
};
result = taos_schemaless_insert(taos, &lines5[0], 1, TSDB_SML_LINE_PROTOCOL, TSDB_SML_TIMESTAMP_NANO_SECONDS);
code = taos_errno(result);
if (code != TSDB_CODE_SUCCESS) {
affected_rows = taos_affected_rows(result);
printf("\033[31m [lines5_0]taos_schemaless_insert failed, code: %d,%s, affected rows:%d \033[0m\n", code, taos_errstr(result), affected_rows);
}
taos_free_result(result);
result = taos_schemaless_insert(taos, &lines5[1], 1, TSDB_SML_LINE_PROTOCOL, TSDB_SML_TIMESTAMP_NANO_SECONDS);
code = taos_errno(result);
if (code != TSDB_CODE_SUCCESS) {
affected_rows = taos_affected_rows(result);
printf("\033[31m [lines5_1]taos_schemaless_insert failed, code: %d,%s, affected rows:%d \033[0m\n", code, taos_errstr(result), affected_rows);
}
taos_free_result(result);
char* lines6[] = {
"st123456,t1=3i64,t2=4f64,t3=\"t3\" c1=3i64,c3=L\"passit\",c2=false,c4=4f64 1626006833639000000",
"dgtyqodr,t2=5f64,t3=L\"ste\" c1=tRue,c2=4i64,c3=\"iam\" 1626056811823316532"
};
result = taos_schemaless_insert(taos, lines6, 2, TSDB_SML_LINE_PROTOCOL, TSDB_SML_TIMESTAMP_NANO_SECONDS);
code = taos_errno(result);
if (code != TSDB_CODE_SUCCESS) {
affected_rows = taos_affected_rows(result);
printf("\033[31m [lines6]taos_schemaless_insert failed, code: %d,%s, affected rows:%d \033[0m\n", code, taos_errstr(result), affected_rows);
}
taos_free_result(result);
//Test timestamp precision
char* lines7[] = {
"stts,t1=10i64,t2=4f64,t3=\"t3\" c1=3i64,c3=L\"passit\",c2=false,c4=4f64 1",
};
for (int precision = TSDB_SML_TIMESTAMP_HOURS; precision <= TSDB_SML_TIMESTAMP_NANO_SECONDS; ++precision) {
result = taos_schemaless_insert(taos, lines7, 1, TSDB_SML_LINE_PROTOCOL, precision);
code = taos_errno(result);
if (code != TSDB_CODE_SUCCESS) {
affected_rows = taos_affected_rows(result);
printf("\033[31m [lines7_%d]taos_schemaless_insert failed, code: %d,%s, affected rows:%d \033[0m\n", precision, code, taos_errstr(result), affected_rows);
}
taos_free_result(result);
}
}
int main(int argc, char* argv[]) {
const char* host = "127.0.0.1";
const char* user = "root";
const char* passwd = "taosdata";
taos_options(TSDB_OPTION_TIMEZONE, "GMT-8");
TAOS* taos = taos_connect(host, user, passwd, "", 0);
if (taos == NULL) {
printf("\033[31mfailed to connect to db, reason:%s\033[0m\n", taos_errstr(taos));
exit(1);
}
char* info = taos_get_server_info(taos);
printf("server info: %s\n", info);
info = taos_get_client_info(taos);
printf("client info: %s\n", info);
printf("************ verify schema-less *************\n");
verify_schema_less(taos);
printf("************ verify query *************\n");
verify_query(taos);
printf("********* verify async query **********\n");
verify_async(taos);
printf("*********** verify subscribe ************\n");
verify_subscribe(taos);
printf("************ verify stream *************\n");
// verify_stream(taos);
printf("done\n");
taos_close(taos);
taos_cleanup();
}
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// TAOS asynchronous API example
// this example opens multiple tables, insert/retrieve multiple tables
// it is used by TAOS internally for one performance testing
// to compiple: gcc -o asyncdemo asyncdemo.c -ltaos
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <unistd.h>
#include <taos.h>
int points = 5;
int numOfTables = 3;
int tablesInsertProcessed = 0;
int tablesSelectProcessed = 0;
int64_t st, et;
typedef struct {
int id;
TAOS * taos;
char name[16];
time_t timeStamp;
int value;
int rowsInserted;
int rowsTried;
int rowsRetrieved;
} STable;
void taos_insert_call_back(void *param, TAOS_RES *tres, int code);
void taos_select_call_back(void *param, TAOS_RES *tres, int code);
void taos_error(TAOS *taos);
static void queryDB(TAOS *taos, char *command) {
int i;
TAOS_RES *pSql = NULL;
int32_t code = -1;
for (i = 0; i < 5; i++) {
if (NULL != pSql) {
taos_free_result(pSql);
pSql = NULL;
}
pSql = taos_query(taos, command);
code = taos_errno(pSql);
if (0 == code) {
break;
}
}
if (code != 0) {
fprintf(stderr, "Failed to run %s, reason: %s\n", command, taos_errstr(pSql));
taos_free_result(pSql);
taos_close(taos);
taos_cleanup();
exit(EXIT_FAILURE);
}
taos_free_result(pSql);
}
int main(int argc, char *argv[]) {
TAOS * taos;
struct timeval systemTime;
int i;
char sql[1024] = {0};
char prefix[20] = {0};
char db[128] = {0};
STable * tableList;
if (argc != 5) {
printf("usage: %s server-ip dbname rowsPerTable numOfTables\n", argv[0]);
exit(0);
}
// a simple way to parse input parameters
if (argc >= 3) strcpy(db, argv[2]);
if (argc >= 4) points = atoi(argv[3]);
if (argc >= 5) numOfTables = atoi(argv[4]);
size_t size = sizeof(STable) * (size_t)numOfTables;
tableList = (STable *)malloc(size);
memset(tableList, 0, size);
taos = taos_connect(argv[1], "root", "taosdata", NULL, 0);
if (taos == NULL) taos_error(taos);
printf("success to connect to server\n");
sprintf(sql, "drop database if exists %s", db);
queryDB(taos, sql);
sprintf(sql, "create database %s", db);
queryDB(taos, sql);
sprintf(sql, "use %s", db);
queryDB(taos, sql);
strcpy(prefix, "asytbl_");
for (i = 0; i < numOfTables; ++i) {
tableList[i].id = i;
tableList[i].taos = taos;
sprintf(tableList[i].name, "%s%d", prefix, i);
sprintf(sql, "create table %s%d (ts timestamp, volume bigint)", prefix, i);
queryDB(taos, sql);
}
gettimeofday(&systemTime, NULL);
for (i = 0; i < numOfTables; ++i)
tableList[i].timeStamp = (time_t)(systemTime.tv_sec) * 1000 + systemTime.tv_usec / 1000;
printf("success to create tables, press any key to insert\n");
getchar();
printf("start to insert...\n");
gettimeofday(&systemTime, NULL);
st = systemTime.tv_sec * 1000000 + systemTime.tv_usec;
tablesInsertProcessed = 0;
tablesSelectProcessed = 0;
for (i = 0; i < numOfTables; ++i) {
// insert records in asynchronous API
sprintf(sql, "insert into %s values(%ld, 0)", tableList[i].name, 1546300800000 + i);
taos_query_a(taos, sql, taos_insert_call_back, (void *)(tableList + i));
}
printf("once insert finished, presse any key to query\n");
getchar();
while (1) {
if (tablesInsertProcessed < numOfTables) {
printf("wait for process finished\n");
sleep(1);
continue;
}
break;
}
printf("start to query...\n");
gettimeofday(&systemTime, NULL);
st = systemTime.tv_sec * 1000000 + systemTime.tv_usec;
for (i = 0; i < numOfTables; ++i) {
// select records in asynchronous API
sprintf(sql, "select * from %s", tableList[i].name);
taos_query_a(taos, sql, taos_select_call_back, (void *)(tableList + i));
}
printf("\nonce finished, press any key to exit\n");
getchar();
while (1) {
if (tablesSelectProcessed < numOfTables) {
printf("wait for process finished\n");
sleep(1);
continue;
}
break;
}
for (i = 0; i < numOfTables; ++i) {
printf("%s inserted:%d retrieved:%d\n", tableList[i].name, tableList[i].rowsInserted, tableList[i].rowsRetrieved);
}
taos_close(taos);
free(tableList);
printf("==== async demo end====\n");
printf("\n");
return 0;
}
void taos_error(TAOS *con) {
fprintf(stderr, "TDengine error: %s\n", taos_errstr(con));
taos_close(con);
taos_cleanup();
exit(1);
}
void taos_insert_call_back(void *param, TAOS_RES *tres, int code) {
STable * pTable = (STable *)param;
struct timeval systemTime;
char sql[128];
pTable->rowsTried++;
if (code < 0) {
printf("%s insert failed, code:%d, rows:%d\n", pTable->name, code, pTable->rowsTried);
} else if (code == 0) {
printf("%s not inserted\n", pTable->name);
} else {
pTable->rowsInserted++;
}
if (pTable->rowsTried < points) {
// for this demo, insert another record
sprintf(sql, "insert into %s values(%ld, %d)", pTable->name, 1546300800000 + pTable->rowsTried * 1000,
pTable->rowsTried);
taos_query_a(pTable->taos, sql, taos_insert_call_back, (void *)pTable);
} else {
printf("%d rows data are inserted into %s\n", points, pTable->name);
tablesInsertProcessed++;
if (tablesInsertProcessed >= numOfTables) {
gettimeofday(&systemTime, NULL);
et = systemTime.tv_sec * 1000000 + systemTime.tv_usec;
printf("%lld mseconds to insert %d data points\n", (et - st) / 1000, points * numOfTables);
}
}
taos_free_result(tres);
}
void taos_retrieve_call_back(void *param, TAOS_RES *tres, int numOfRows) {
STable * pTable = (STable *)param;
struct timeval systemTime;
if (numOfRows > 0) {
for (int i = 0; i < numOfRows; ++i) {
// synchronous API to retrieve a row from batch of records
/*TAOS_ROW row = */ (void)taos_fetch_row(tres);
// process row
}
pTable->rowsRetrieved += numOfRows;
// retrieve next batch of rows
taos_fetch_rows_a(tres, taos_retrieve_call_back, pTable);
} else {
if (numOfRows < 0) printf("%s retrieve failed, code:%d\n", pTable->name, numOfRows);
// taos_free_result(tres);
printf("%d rows data retrieved from %s\n", pTable->rowsRetrieved, pTable->name);
tablesSelectProcessed++;
if (tablesSelectProcessed >= numOfTables) {
gettimeofday(&systemTime, NULL);
et = systemTime.tv_sec * 1000000 + systemTime.tv_usec;
printf("%lld mseconds to query %d data rows\n", (et - st) / 1000, points * numOfTables);
}
taos_free_result(tres);
}
}
void taos_select_call_back(void *param, TAOS_RES *tres, int code) {
STable *pTable = (STable *)param;
if (code == 0 && tres) {
// asynchronous API to fetch a batch of records
taos_fetch_rows_a(tres, taos_retrieve_call_back, pTable);
} else {
printf("%s select failed, code:%d\n", pTable->name, code);
taos_free_result(tres);
taos_cleanup();
exit(1);
}
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include <taos.h>
#include "os.h"
#include "taosdef.h"
#include "taoserror.h"
#include "tconfig.h"
#include "tglobal.h"
#include "tulog.h"
#include "tsocket.h"
#include "tutil.h"
extern SGlobalCfg *taosGetConfigOption(const char *option) ;
int main( int argc, char *argv[]){
printf("start to test\n");
//case1:
//Test config to wrong type
const char config1[128] = "{\"cache\":\"4\"}";//input the parameter which want to be configured
taos_set_config(config1); //configure the parameter
SGlobalCfg *cfg1 ;
cfg1 = taosGetConfigOption("cache");//check the option result
if(cfg1->cfgStatus == 3) //If cfgStatus is 3,it means configure is success
printf("config cache to '4'success!\n");
else
printf("config cache failure!\n");
return 0 ;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include <taos.h>
#include "os.h"
#include "taosdef.h"
#include "taoserror.h"
#include "tconfig.h"
#include "tglobal.h"
#include "tulog.h"
#include "tsocket.h"
#include "tutil.h"
extern SGlobalCfg *taosGetConfigOption(const char *option) ;
int main( int argc, char *argv[]){
printf("start to test\n");
//case1:
//Test config with wrong JSON
//The result is failure
const char config1[128] = "{\"firstEp\":\"BCC-2:6030\",\"debugFlag\":\135\"}";//input the parameter which want to be configured
taos_set_config(config1); //configure the parameter
SGlobalCfg *cfg1 ;
cfg1 = taosGetConfigOption("firstEp");//check the option result
if(cfg1->cfgStatus == 3) //If cfgStatus is 3,it means configure is success
printf("config firstEp 'BCC-2:6030'success!\n");
else
printf("config firstEp failure!\n");
SGlobalCfg *cfg2 ;
cfg2 = taosGetConfigOption("debugFlag");//check the option result
if(cfg1->cfgStatus == 3) //If cfgStatus is 3,it means configure is success
printf("config debugFlag '135'success!\n");
else
printf("config debugFlag failure!\n");
//case2:
//repair the JSON and try again
//The result is success
const char config2[128] = "{\"firstEp\":\"BCC-2:6030\",\"debugFlag\":\"135\"}";//input the parameter which want to be configured
taos_set_config(config2); //configure the parameter
SGlobalCfg *cfg3 ;
cfg3 = taosGetConfigOption("firstEp");//check the option result
if(cfg3->cfgStatus == 3) //If cfgStatus is 3,it means configure is success
printf("config firstEp 'BCC-2:6030'success!\n");
else
printf("config firstEp failure!\n");
SGlobalCfg *cfg4 ;
cfg4 = taosGetConfigOption("debugFlag");//check the option result
if(cfg4->cfgStatus == 3) //If cfgStatus is 3,it means configure is success
printf("config debugFlag '135'success!\n");
else
printf("config debugFlag failure!\n");
return 0 ;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include <taos.h>
#include "os.h"
#include "taosdef.h"
#include "taoserror.h"
#include "tconfig.h"
#include "tglobal.h"
#include "tulog.h"
#include "tsocket.h"
#include "tutil.h"
extern SGlobalCfg *taosGetConfigOption(const char *option) ;
int main( int argc, char *argv[]){
printf("start to test\n");
//case1:
//Test config to wrong type
//The result is failure
const char config1[128] = "{\"debugFlag\":\"9999999999999999999999999\"}";//input the parameter which want to be configured
taos_set_config(config1); //configure the parameter
SGlobalCfg *cfg1 ;
cfg1 = taosGetConfigOption("debugFlag");//check the option result
if(cfg1->cfgStatus == 3) //If cfgStatus is 3,it means configure is success
printf("config debugFlag '9999999999999999999999999\n");
else
printf("config debugFlag failure!\n");
//case2:
//Try again with right parameter
//The result is failure
const char config2[128] = "{\"debugFlag\":\"135\"}";//input the parameter which want to be configured
taos_set_config(config2); //configure the parameter
SGlobalCfg *cfg2 ;
cfg2 = taosGetConfigOption("debugFlag");//check the option result
if(cfg2->cfgStatus == 3) //If cfgStatus is 3,it means configure is success
printf("config debugflag '135'success!\n");
else
printf("config debugflag failure!\n");
return 0 ;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include <taos.h>
#include "os.h"
#include "taosdef.h"
#include "taoserror.h"
#include "tconfig.h"
#include "tglobal.h"
#include "tulog.h"
#include "tsocket.h"
#include "tutil.h"
extern SGlobalCfg *taosGetConfigOption(const char *option) ;
int main( int argc, char *argv[]){
printf("start to test\n");
//case1:
//Test config to wrong type
const char config1[128] = "{\"rpcTimer\":\"0\"}";//input the parameter which want to be configured
taos_set_config(config1); //configure the parameter
SGlobalCfg *cfg1 ;
cfg1 = taosGetConfigOption("rpcTimer");//check the option result
if(cfg1->cfgStatus == 3) //If cfgStatus is 3,it means configure is success
printf("config rpcTimer to '0'success!\n");
else
printf("config rpcTimer failure!\n");
//case2:
//Try again with right parameter
const char config2[128] = "{\"rpcTimer\":\"400\"}";//input the parameter which want to be configured
taos_set_config(config2); //configure the parameter
SGlobalCfg *cfg2 ;
cfg2 = taosGetConfigOption("rpcTimer");//check the option result
if(cfg2->cfgStatus == 3) //If cfgStatus is 3,it means configure is success
printf("config rpcTimer '400'success!\n");
else
printf("config rpcTimer failure!\n");
return 0 ;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include <taos.h>
#include "os.h"
#include "taosdef.h"
#include "taoserror.h"
#include "tconfig.h"
#include "tglobal.h"
#include "tulog.h"
#include "tsocket.h"
#include "tutil.h"
extern SGlobalCfg *taosGetConfigOption(const char *option) ;
int main( int argc, char *argv[]){
printf("start to test\n");
//case1:
//Test config firstEp success
const char config1[128] = "{\"firstEp\":\"BCC-2:6030\",\"debugFlag\":\"135\"}";//input the parameter which want to be configured
taos_set_config(config1); //configure the parameter
SGlobalCfg *cfg1 ;
cfg1 = taosGetConfigOption("firstEp");//check the option result
if(cfg1->cfgStatus == 3) //If cfgStatus is 3,it means configure is success
printf("config firstEp 'BCC-2:6030'success!\n");
else
printf("config firstEp failure!\n");
SGlobalCfg *cfg2 ;
cfg2 = taosGetConfigOption("debugFlag");//check the option result
if(cfg2->cfgStatus == 3) //If cfgStatus is 3,it means configure is success
printf("config debugFlag '135' success!\n");
else
printf("config debugFlag failure!\n");
//case2:
//Test config only useful at the first time
//The result is failure
const char config2[128] = "{\"fqdn\":\"BCC-3\"}";//input the parameter which want to be configured
taos_set_config(config2); //configure the parameter
SGlobalCfg *cfg3 ;
cfg2 = taosGetConfigOption("fqdn");//check the option result
if(cfg2->cfgStatus == 3) //If cfgStatus is 3,it means configure is success
printf("config fqdn to 'BCC-3'success!\n");
else
printf("config fqdn failure!\n");
return 0 ;
}
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include "taos.h"
int numOfThreads = 1;
void* connectClusterAndDeal(void *arg) {
int port = *(int *)arg;
const char *host = "127.0.0.1";
const char *user = "root";
const char *passwd = "taosdata";
TAOS* taos1 = taos_connect(host, user, passwd, "", port);
TAOS* taos2 = taos_connect(host, user, passwd, "", port + 1000);
if (NULL == taos1 || NULL == taos2) {
printf("connect to (%d/%d) failed \n", port, port + 1000);
return NULL;
}
TAOS_RES *result = NULL;
result = taos_query(taos1, "drop database if exists db");
if (0 != taos_errno(result)) {
printf("failed %s\n", taos_errstr(result));
}
taos_free_result(result);
taos_query(taos2, "drop database if exists db");
if (0 != taos_errno(result)) {
printf("failed %s\n", taos_errstr(result));
}
taos_free_result(result);
// ========= build database
{
result = taos_query(taos1, "create database db");
if (0 != taos_errno(result)) {
printf("failed %s\n", taos_errstr(result));
}
taos_free_result(result);
}
{
result = taos_query(taos2, "create database db");
if (0 != taos_errno(result)) {
printf("failed %s\n", taos_errstr(result));
}
taos_free_result(result);
}
//======== create table
{
result = taos_query(taos1, "create stable db.stest (ts timestamp, port int) tags(tport int)");
if (0 != taos_errno(result)) {
printf("failed %s\n", taos_errstr(result));
}
taos_free_result(result);
}
{
result = taos_query(taos2, "create stable db.stest (ts timestamp, port int) tags(tport int)");
if (0 != taos_errno(result)) {
printf("failed %s\n", taos_errstr(result));
}
taos_free_result(result);
}
//======== create table
{
result = taos_query(taos1, "use db");
if (0 != taos_errno(result)) {
printf("failed %s\n", taos_errstr(result));
}
taos_free_result(result);
}
{
result = taos_query(taos2, "use db");
if (0 != taos_errno(result)) {
printf("failed %s\n", taos_errstr(result));
}
taos_free_result(result);
}
{
char buf[1024] = {0};
sprintf(buf, "insert into db.t1 using stest tags(%d) values(now, %d)", port, port);
for (int i = 0; i < 100000; i++) {
//printf("error here\t");
result = taos_query(taos1, buf);
if (0 != taos_errno(result)) {
printf("failed %s\n", taos_errstr(result));
}
taos_free_result(result);
//sleep(1);
}
}
{
char buf[1024] = {0};
sprintf(buf, "insert into db.t1 using stest tags(%d) values(now, %d)", port + 1000, port + 1000);
for (int i = 0; i < 100000; i++) {
result = taos_query(taos2, buf);
if (0 != taos_errno(result)) {
printf("failed %s\n", taos_errstr(result));
}
taos_free_result(result);
//sleep(1);
}
}
// query result
{
result = taos_query(taos1, "select * from stest");
if (result == NULL || taos_errno(result) != 0) {
printf("query failed %s\n", taos_errstr(result));
taos_free_result(result);
}
TAOS_ROW row;
int rows = 0;
int num_fields = taos_field_count(result);
TAOS_FIELD *fields = taos_fetch_fields(result);
while ((row = taos_fetch_row(result))) {
char temp[1024] = {0};
rows++;
taos_print_row(temp, row, fields , num_fields);
printf("%s\n", temp);
}
taos_free_result(result);
}
// query result
{
result = taos_query(taos2, "select * from stest");
if (result == NULL || taos_errno(result) != 0) {
printf("query failed %s\n", taos_errstr(result));
taos_free_result(result);
}
TAOS_ROW row;
int rows = 0;
int num_fields = taos_field_count(result);
TAOS_FIELD *fields = taos_fetch_fields(result);
while ((row = taos_fetch_row(result))) {
char temp[1024] = {0};
rows++;
taos_print_row(temp, row, fields , num_fields);
printf("%s\n", temp);
}
taos_free_result(result);
}
taos_close(taos1);
taos_close(taos2);
return NULL;
}
int main(int argc, char* argv[]) {
pthread_t *pthreads = malloc(sizeof(pthread_t) * numOfThreads);
int *port = malloc(sizeof(int) * numOfThreads);
port[0] = 6030;
for (int i = 0; i < numOfThreads; i++) {
pthread_create(&pthreads[i], NULL, connectClusterAndDeal, (void *)&port[i]);
}
for (int i = 0; i < numOfThreads; i++) {
pthread_join(pthreads[i], NULL);
}
free(port);
}
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// TAOS standard API example. The same syntax as MySQL, but only a subset
// to compile: gcc -o demo demo.c -ltaos
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <taos.h> // TAOS header file
static void queryDB(TAOS *taos, char *command) {
int i;
TAOS_RES *pSql = NULL;
int32_t code = -1;
for (i = 0; i < 5; i++) {
if (NULL != pSql) {
taos_free_result(pSql);
pSql = NULL;
}
pSql = taos_query(taos, command);
code = taos_errno(pSql);
if (0 == code) {
break;
}
}
if (code != 0) {
fprintf(stderr, "Failed to run %s, reason: %s\n", command, taos_errstr(pSql));
taos_free_result(pSql);
taos_close(taos);
exit(EXIT_FAILURE);
}
taos_free_result(pSql);
}
void Test(TAOS *taos, char *qstr, int i);
int main(int argc, char *argv[]) {
char qstr[1024];
// connect to server
if (argc < 2) {
printf("please input server-ip \n");
return 0;
}
TAOS *taos = taos_connect(argv[1], "root", "taosdata", NULL, 0);
if (taos == NULL) {
printf("failed to connect to server, reason:%s\n", "null taos" /*taos_errstr(taos)*/);
exit(1);
}
for (int i = 0; i < 100; i++) {
Test(taos, qstr, i);
}
taos_close(taos);
taos_cleanup();
}
void Test(TAOS *taos, char *qstr, int index) {
printf("==================test at %d\n================================", index);
queryDB(taos, "drop database if exists demo");
queryDB(taos, "create database demo");
TAOS_RES *result;
queryDB(taos, "use demo");
queryDB(taos,
"create table m1 (ts timestamp, ti tinyint, si smallint, i int, bi bigint, f float, d double, b binary(10))");
printf("success to create table\n");
int i = 0;
for (i = 0; i < 10; ++i) {
sprintf(qstr, "insert into m1 values (%" PRId64 ", %d, %d, %d, %d, %f, %lf, '%s')",
(uint64_t)(1546300800000 + i * 1000), i, i, i, i * 10000000, i * 1.0, i * 2.0, "hello");
printf("qstr: %s\n", qstr);
// note: how do you wanna do if taos_query returns non-NULL
// if (taos_query(taos, qstr)) {
// printf("insert row: %i, reason:%s\n", i, taos_errstr(taos));
// }
TAOS_RES *result1 = taos_query(taos, qstr);
if (result1 == NULL || taos_errno(result1) != 0) {
printf("failed to insert row, reason:%s\n", taos_errstr(result1));
taos_free_result(result1);
exit(1);
} else {
printf("insert row: %i\n", i);
}
taos_free_result(result1);
}
printf("success to insert rows, total %d rows\n", i);
// query the records
sprintf(qstr, "SELECT * FROM m1");
result = taos_query(taos, qstr);
if (result == NULL || taos_errno(result) != 0) {
printf("failed to select, reason:%s\n", taos_errstr(result));
taos_free_result(result);
exit(1);
}
TAOS_ROW row;
int rows = 0;
int num_fields = taos_field_count(result);
TAOS_FIELD *fields = taos_fetch_fields(result);
printf("num_fields = %d\n", num_fields);
printf("select * from table, result:\n");
// fetch the records row by row
while ((row = taos_fetch_row(result))) {
char temp[1024] = {0};
rows++;
taos_print_row(temp, row, fields, num_fields);
printf("%s\n", temp);
}
taos_free_result(result);
printf("====demo end====\n\n");
}
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// how to use to do a pressure-test upon eok
// tester: cat /dev/urandom | nc -c <ip> <port>
// testee: ./debug/build/bin/epoll -l <port> > /dev/null
// compare against: nc -l <port> > /dev/null
// monitor and compare : glances
#ifdef __APPLE__
#include "osEok.h"
#else // __APPLE__
#include <sys/epoll.h>
#endif // __APPLE__
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#include <libgen.h>
#include <locale.h>
#include <netdb.h>
#include <netinet/in.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#define D(fmt, ...) fprintf(stderr, "%s[%d]%s(): " fmt "\n", basename(__FILE__), __LINE__, __func__, ##__VA_ARGS__)
#define A(statement, fmt, ...) \
do { \
if (statement) break; \
fprintf(stderr, "%s[%d]%s(): assert [%s] failed: %d[%s]: " fmt "\n", basename(__FILE__), __LINE__, __func__, \
#statement, errno, strerror(errno), ##__VA_ARGS__); \
abort(); \
} while (0)
#define E(fmt, ...) \
do { \
fprintf(stderr, "%s[%d]%s(): %d[%s]: " fmt "\n", basename(__FILE__), __LINE__, __func__, errno, strerror(errno), \
##__VA_ARGS__); \
} while (0)
#include "os.h"
typedef struct ep_s ep_t;
struct ep_s {
int ep;
pthread_mutex_t lock;
int sv[2]; // 0 for read, 1 for write;
pthread_t thread;
volatile unsigned int stopping : 1;
volatile unsigned int waiting : 1;
volatile unsigned int wakenup : 1;
};
static int ep_dummy = 0;
static ep_t *ep_create(void);
static void ep_destroy(ep_t *ep);
static void *routine(void *arg);
static int open_listen(unsigned short port);
typedef struct fde_s fde_t;
struct fde_s {
int skt;
void (*on_event)(ep_t *ep, struct epoll_event *events, fde_t *client);
};
static void listen_event(ep_t *ep, struct epoll_event *ev, fde_t *client);
static void null_event(ep_t *ep, struct epoll_event *ev, fde_t *client);
#define usage(arg0, fmt, ...) \
do { \
if (fmt[0]) { \
fprintf(stderr, "" fmt "\n", ##__VA_ARGS__); \
} \
fprintf(stderr, "usage:\n"); \
fprintf(stderr, " %s -l <port> : specify listening port\n", arg0); \
} while (0)
int main(int argc, char *argv[]) {
char *prg = basename(argv[0]);
if (argc == 1) {
usage(prg, "");
return 0;
}
ep_t *ep = ep_create();
A(ep, "failed");
for (int i = 1; i < argc; ++i) {
const char *arg = argv[i];
if (0 == strcmp(arg, "-l")) {
++i;
if (i >= argc) {
usage(prg, "expecting <port> after -l, but got nothing");
return 1; // confirmed potential leakage
}
arg = argv[i];
int port = atoi(arg);
int skt = open_listen(port);
if (skt == -1) continue;
fde_t *client = (fde_t *)calloc(1, sizeof(*client));
if (!client) {
E("out of memory");
close(skt);
continue;
}
client->skt = skt;
client->on_event = listen_event;
struct epoll_event ev = {0};
ev.events = EPOLLIN | EPOLLERR | EPOLLHUP | EPOLLRDHUP;
ev.data.ptr = client;
A(0 == epoll_ctl(ep->ep, EPOLL_CTL_ADD, skt, &ev), "");
continue;
}
usage(prg, "unknown argument: [%s]", arg);
return 1;
}
char * line = NULL;
size_t linecap = 0;
ssize_t linelen;
while ((linelen = getline(&line, &linecap, stdin)) > 0) {
line[strlen(line) - 1] = '\0';
if (0 == strcmp(line, "exit")) break;
if (0 == strcmp(line, "quit")) break;
if (line == strstr(line, "close")) {
int fd = 0;
sscanf(line, "close %d", &fd);
if (fd <= 2) {
fprintf(stderr, "fd [%d] invalid\n", fd);
continue;
}
A(0 == epoll_ctl(ep->ep, EPOLL_CTL_DEL, fd, NULL), "");
continue;
}
if (strlen(line) == 0) continue;
fprintf(stderr, "unknown cmd:[%s]\n", line);
}
ep_destroy(ep);
D("");
return 0;
}
ep_t *ep_create(void) {
ep_t *ep = (ep_t *)calloc(1, sizeof(*ep));
A(ep, "out of memory");
A(-1 != (ep->ep = epoll_create(1)), "");
ep->sv[0] = -1;
ep->sv[1] = -1;
A(0 == socketpair(AF_LOCAL, SOCK_STREAM, 0, ep->sv), "");
A(0 == pthread_mutex_init(&ep->lock, NULL), "");
A(0 == pthread_mutex_lock(&ep->lock), "");
struct epoll_event ev = {0};
ev.events = EPOLLIN;
ev.data.ptr = &ep_dummy;
A(0 == epoll_ctl(ep->ep, EPOLL_CTL_ADD, ep->sv[0], &ev), "");
A(0 == pthread_create(&ep->thread, NULL, routine, ep), "");
A(0 == pthread_mutex_unlock(&ep->lock), "");
return ep;
}
static void ep_destroy(ep_t *ep) {
A(ep, "invalid argument");
ep->stopping = 1;
A(1 == send(ep->sv[1], "1", 1, 0), "");
A(0 == pthread_join(ep->thread, NULL), "");
A(0 == pthread_mutex_destroy(&ep->lock), "");
A(0 == close(ep->sv[0]), "");
A(0 == close(ep->sv[1]), "");
A(0 == close(ep->ep), "");
free(ep);
}
static void *routine(void *arg) {
A(arg, "invalid argument");
ep_t *ep = (ep_t *)arg;
while (!ep->stopping) {
struct epoll_event evs[10];
memset(evs, 0, sizeof(evs));
A(0 == pthread_mutex_lock(&ep->lock), "");
A(ep->waiting == 0, "internal logic error");
ep->waiting = 1;
A(0 == pthread_mutex_unlock(&ep->lock), "");
int r = epoll_wait(ep->ep, evs, sizeof(evs) / sizeof(evs[0]), -1);
A(r > 0, "indefinite epoll_wait shall not timeout:[%d]", r);
A(0 == pthread_mutex_lock(&ep->lock), "");
A(ep->waiting == 1, "internal logic error");
ep->waiting = 0;
A(0 == pthread_mutex_unlock(&ep->lock), "");
for (int i = 0; i < r; ++i) {
struct epoll_event *ev = evs + i;
if (ev->data.ptr == &ep_dummy) {
char c = '\0';
A(1 == recv(ep->sv[0], &c, 1, 0), "internal logic error");
A(0 == pthread_mutex_lock(&ep->lock), "");
ep->wakenup = 0;
A(0 == pthread_mutex_unlock(&ep->lock), "");
continue;
}
A(ev->data.ptr, "internal logic error");
fde_t *client = (fde_t *)ev->data.ptr;
client->on_event(ep, ev, client);
continue;
}
}
return NULL;
}
static int open_listen(unsigned short port) {
int r = 0;
int skt = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (skt == -1) {
E("socket() failed");
return -1;
}
do {
struct sockaddr_in si = {0};
si.sin_family = AF_INET;
si.sin_addr.s_addr = inet_addr("0.0.0.0");
si.sin_port = htons(port);
r = bind(skt, (struct sockaddr *)&si, sizeof(si));
if (r) {
E("bind(%u) failed", port);
break;
}
r = listen(skt, 100);
if (r) {
E("listen() failed");
break;
}
memset(&si, 0, sizeof(si));
socklen_t len = sizeof(si);
r = getsockname(skt, (struct sockaddr *)&si, &len);
if (r) {
E("getsockname() failed");
}
A(len == sizeof(si), "internal logic error");
D("listening at: %d", ntohs(si.sin_port));
return skt;
} while (0);
close(skt);
return -1;
}
static void listen_event(ep_t *ep, struct epoll_event *ev, fde_t *client) {
A(ev->events & EPOLLIN, "internal logic error");
struct sockaddr_in si = {0};
socklen_t silen = sizeof(si);
int skt = accept(client->skt, (struct sockaddr *)&si, &silen);
A(skt != -1, "internal logic error");
fde_t *server = (fde_t *)calloc(1, sizeof(*server));
if (!server) {
close(skt);
return;
}
server->skt = skt;
server->on_event = null_event;
struct epoll_event ee = {0};
ee.events = EPOLLIN | EPOLLERR | EPOLLHUP | EPOLLRDHUP;
ee.data.ptr = server;
A(0 == epoll_ctl(ep->ep, EPOLL_CTL_ADD, skt, &ee), "");
}
static void null_event(ep_t *ep, struct epoll_event *ev, fde_t *client) {
if (ev->events & EPOLLIN) {
char buf[8192];
int n = recv(client->skt, buf, sizeof(buf), 0);
A(n >= 0 && n <= sizeof(buf), "internal logic error:[%d]", n);
A(n == fwrite(buf, 1, n, stdout), "internal logic error");
}
if (ev->events & (EPOLLERR | EPOLLHUP | EPOLLRDHUP)) {
A(0 == pthread_mutex_lock(&ep->lock), "");
A(0 == epoll_ctl(ep->ep, EPOLL_CTL_DEL, client->skt, NULL), "");
A(0 == pthread_mutex_unlock(&ep->lock), "");
close(client->skt);
client->skt = -1;
client->on_event = NULL;
free(client);
}
}
# Copyright (c) 2017 by TAOS Technologies, Inc.
# todo: library dependency, header file dependency
ROOT=./
TARGET=exe
LFLAGS = '-Wl,-rpath,/usr/local/taos/driver/' -ltaos -lpthread -lm -lrt
CFLAGS = -O3 -g -Wall -Wno-deprecated -fPIC -Wno-unused-result -Wconversion \
-Wno-char-subscripts -D_REENTRANT -Wno-format -D_REENTRANT -DLINUX \
-Wno-unused-function -D_M_X64 -I/usr/local/taos/include -std=gnu99 \
-I../../../deps/cJson/inc \
-Wno-unused-function -D_M_X64 -I/usr/local/taos/include -std=gnu99 \
-fsanitize=address -fsanitize=undefined -fno-sanitize-recover=all -fsanitize=float-divide-by-zero -fsanitize=float-cast-overflow -fno-sanitize=null -fno-sanitize=alignment
all: $(TARGET)
exe:
gcc $(CFLAGS) ./asyncdemo.c -o $(ROOT)asyncdemo $(LFLAGS)
gcc $(CFLAGS) ./demo.c -o $(ROOT)demo $(LFLAGS)
gcc $(CFLAGS) ./prepare.c -o $(ROOT)prepare $(LFLAGS)
gcc $(CFLAGS) ./stream.c -o $(ROOT)stream $(LFLAGS)
gcc $(CFLAGS) ./subscribe.c -o $(ROOT)subscribe $(LFLAGS)
gcc $(CFLAGS) ./apitest.c -o $(ROOT)apitest $(LFLAGS)
clean:
rm $(ROOT)asyncdemo
rm $(ROOT)demo
rm $(ROOT)prepare
rm $(ROOT)stream
rm $(ROOT)subscribe
rm $(ROOT)apitest
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <taos.h>
#include <time.h>
bool isPrint = true;
void one_batch_one_table_1(TAOS *conn, long totalRows, long batchRows);
void one_batch_one_table_2(TAOS *conn, long totalRows, long batchRows);
void one_batch_one_table_3(TAOS *conn, long totalRows, long batchRows);
void one_batch_one_table_4(TAOS *conn, long totalRows, long batchRows);
void one_batch_one_table_5(TAOS *conn, long totalRows, long batchRows);
void one_batch_one_table_6(TAOS *conn, long totalRows, long batchRows);
void one_batch_one_table_7(TAOS *conn, long totalRows, long batchRows);
void one_batch_multi_table_1(TAOS *conn, long totalRows, long batchRows, int tables);
void one_batch_multi_table_2(TAOS *conn, long totalRows, long batchRows, int tables);
void one_batch_multi_table_3(TAOS *conn, long totalRows, long batchRows, int tables);
void execute(TAOS *conn, char *sql);
void prepare_normal_table(TAOS *conn);
void prepare_super_and_sub_table(TAOS *conn, int subTables);
void prepare_super_table(TAOS *conn, int subTables);
int64_t getCurrentTimeMill();
TAOS_STMT *A(TAOS *);
void B(TAOS_STMT *stmt, char sql[]);
void C(TAOS_STMT *stmt, char sql[]);
void D(TAOS_STMT *stmt, char sql[], int tag);
void E(TAOS_STMT *stmt);
void F(TAOS_STMT *stmt, int64_t ts_start);
void G1(TAOS_STMT *stmt, int64_t ts_start, int rows);
void G2(TAOS_STMT *stmt, int rows);
void H(TAOS_STMT *stmt, int64_t ts_start, int rows);
void I(TAOS_STMT *stmt);
void J(TAOS_STMT *stmt);
void L(TAOS_STMT *stmt);
int main() {
char host[] = "192.168.56.105";
srand(time(NULL));
// connect
TAOS *conn = taos_connect(host, "root", "taosdata", NULL, 0);
if (conn == NULL) {
printf("failed to connect to:%s, reason:%s\n", host, "null taos");
exit(-1);
}
execute(conn, "drop database if exists test");
execute(conn, "create database if not exists test");
execute(conn, "use test");
long totalRows = 1000000;
long batchRows = 32767;
int tables = 10;
prepare_super_table(conn, 1);
// A -> B -> D -> [F -> I]... -> J -> L
// one_batch_one_table_1(conn, totalRows, batchRows);
// A -> B -> [D -> [F -> I]... -> J]... -> L
// one_batch_one_table_2(conn, totalRows, batchRows);
// A -> B -> D -> [F... -> I -> J]... -> L
// one_batch_one_table_3(conn, totalRows, batchRows);
// A -> B -> D -> [H -> I -> J]... -> L
// one_batch_one_table_4(conn, totalRows, batchRows);
// A -> B -> [D -> H -> I -> J]... -> L
// one_batch_one_table_5(conn, totalRows, batchRows);
// A -> B -> [D -> H -> I -> J]... -> L
// one_batch_one_table_6(conn, totalRows, batchRows);
// A -> B -> [D -> H -> I -> J]... -> L
// one_batch_one_table_7(conn, totalRows, batchRows);
// A -> B -> [D -> [F -> I]... -> J]... -> L
// one_batch_multi_table_1(conn, totalRows, batchRows, tables);
// A -> B -> [D -> H -> I -> J]... -> L
// one_batch_multi_table_2(conn, totalRows, batchRows, tables);
// A -> B -> [D -> G1 -> G2 -> I -> J]... -> L
one_batch_multi_table_3(conn, totalRows, batchRows, tables);
// close
taos_close(conn);
taos_cleanup();
exit(0);
}
// A -> B -> D -> [F -> I]... -> J -> L
void one_batch_one_table_1(TAOS *conn, long totalRows, long batchRows) {
// given
time_t current;
time(&current);
current -= totalRows;
int64_t start = getCurrentTimeMill();
// when
TAOS_STMT *stmt = A(conn);
B(stmt, "insert into ? using weather tags(?) (ts, f1) values(?, ?)");
D(stmt, "t1", 1);
for (int i = 1; i <= totalRows; ++i) {
F(stmt, (current + i - 1) * 1000);
I(stmt);
if (i % batchRows == 0 || i == totalRows) {
J(stmt);
}
}
L(stmt);
int64_t end = getCurrentTimeMill();
printf("totalRows: %ld, batchRows: %ld, time cost: %lld ms\n", totalRows, batchRows, (end - start));
}
// A -> B -> D -> [F -> I]... -> J -> L
void one_batch_one_table_2(TAOS *conn, long totalRows, long batchRows) {
// given
time_t current;
time(&current);
current -= totalRows;
int64_t start = getCurrentTimeMill();
// when
TAOS_STMT *stmt = A(conn);
B(stmt, "insert into ? using weather tags(?) (ts, f1) values(?, ?)");
for (int i = 1; i <= totalRows; ++i) {
if (i % batchRows == 1) {
D(stmt, "t1", 1);
}
F(stmt, (current + i - 1) * 1000);
I(stmt);
if (i % batchRows == 0 || i == totalRows) {
J(stmt);
}
}
L(stmt);
int64_t end = getCurrentTimeMill();
printf("totalRows: %ld, batchRows: %ld, time cost: %lld ms\n", totalRows, batchRows, (end - start));
}
void one_batch_one_table_3(TAOS *conn, long totalRows, long batchRows) {
// given
time_t current;
time(&current);
current -= totalRows;
int64_t start = getCurrentTimeMill();
// when
TAOS_STMT *stmt = A(conn);
B(stmt, "insert into ? using weather tags(?) (ts, f1) values(?, ?)");
D(stmt, "t1", 1);
for (int i = 1; i <= totalRows; ++i) {
F(stmt, (current + i - 1) * 1000);
if (i % batchRows == 0 || i == totalRows) {
I(stmt);
J(stmt);
}
}
L(stmt);
int64_t end = getCurrentTimeMill();
printf("totalRows: %ld, batchRows: %ld, time cost: %lld ms\n", totalRows, batchRows, (end - start));
}
void one_batch_one_table_4(TAOS *conn, long totalRows, long batchRows) {
// given
time_t current;
time(&current);
current -= totalRows;
int64_t start = getCurrentTimeMill();
// when
TAOS_STMT *stmt = A(conn);
B(stmt, "insert into ? using weather tags(?) values(?,?)");
D(stmt, "t1", 1);
for (int i = 1; i <= totalRows; i += batchRows) {
int rows = (i + batchRows) > totalRows ? (totalRows + 1 - i) : batchRows;
H(stmt, (current + i) * 1000, rows);
I(stmt);
J(stmt);
}
L(stmt);
int64_t end = getCurrentTimeMill();
printf("totalRows: %ld, batchRows: %ld, time cost: %lld ms\n", totalRows, batchRows, (end - start));
}
void one_batch_one_table_5(TAOS *conn, long totalRows, long batchRows) {
// given
time_t current;
time(&current);
current -= totalRows;
int64_t start = getCurrentTimeMill();
// when
TAOS_STMT *stmt = A(conn);
B(stmt, "insert into ? using weather tags(?) values(?,?)");
for (int i = 1; i <= totalRows; i += batchRows) {
D(stmt, "t1", 1);
int rows = (i + batchRows) > totalRows ? (totalRows + 1 - i) : batchRows;
H(stmt, (current + i) * 1000, rows);
I(stmt);
J(stmt);
}
L(stmt);
int64_t end = getCurrentTimeMill();
printf("totalRows: %ld, batchRows: %ld, time cost: %lld ms\n", totalRows, batchRows, (end - start));
}
void one_batch_one_table_6(TAOS *conn, long totalRows, long batchRows) {
// given
time_t current;
time(&current);
current -= totalRows;
int64_t start = getCurrentTimeMill();
// when
TAOS_STMT *stmt = A(conn);
B(stmt, "insert into ? using weather tags(?) values(?,?)");
D(stmt, "t1", 1);
for (int i = 1; i <= totalRows; i += batchRows) {
int rows = (i + batchRows) > totalRows ? (totalRows + 1 - i) : batchRows;
G1(stmt, (current + i) * 1000, rows);
G2(stmt, rows);
I(stmt);
J(stmt);
}
L(stmt);
int64_t end = getCurrentTimeMill();
printf("totalRows: %ld, batchRows: %ld, time cost: %lld ms\n", totalRows, batchRows, (end - start));
}
void one_batch_one_table_7(TAOS *conn, long totalRows, long batchRows) {
// given
time_t current;
time(&current);
current -= totalRows;
int64_t start = getCurrentTimeMill();
// when
TAOS_STMT *stmt = A(conn);
B(stmt, "insert into ? using weather tags(?) values(?,?)");
for (int i = 1; i <= totalRows; i += batchRows) {
if (i % batchRows == 1) {
D(stmt, "t1", 1);
}
int rows = (i + batchRows) > totalRows ? (totalRows + 1 - i) : batchRows;
G1(stmt, (current + i) * 1000, rows);
G2(stmt, rows);
I(stmt);
J(stmt);
}
L(stmt);
int64_t end = getCurrentTimeMill();
printf("totalRows: %ld, batchRows: %ld, time cost: %lld ms\n", totalRows, batchRows, (end - start));
}
void one_batch_multi_table_1(TAOS *conn, long totalRows, long batchRows, int tables) {
// given
time_t current;
time(&current);
long eachTable = (totalRows - 1) / tables + 1;
current -= eachTable;
int64_t start = getCurrentTimeMill();
// when
TAOS_STMT *stmt = A(conn);
B(stmt, "insert into ? using weather tags(?) values(?, ?)");
for (int tbIndex = 0; tbIndex < tables; ++tbIndex) {
char tbname[10];
sprintf(tbname, "t%d", tbIndex);
eachTable = ((tbIndex + 1) * eachTable > totalRows) ? (totalRows - tbIndex * eachTable) : eachTable;
for (int rowIndex = 1; rowIndex <= eachTable; ++rowIndex) {
if (rowIndex % batchRows == 1) {
D(stmt, tbname, tbIndex);
if (isPrint)
printf("\ntbIndex: %d, table_rows: %ld, rowIndex: %d, batch_rows: %ld\n", tbIndex, eachTable, rowIndex,
batchRows);
}
F(stmt, (current + rowIndex - 1) * 1000);
I(stmt);
if (rowIndex % batchRows == 0 || rowIndex == eachTable) {
J(stmt);
}
}
}
L(stmt);
int64_t end = getCurrentTimeMill();
printf("totalRows: %ld, batchRows: %ld, table: %d, eachTableRows: %ld, time cost: %lld ms\n", totalRows, batchRows,
tables, eachTable, (end - start));
}
void one_batch_multi_table_2(TAOS *conn, long totalRows, long batchRows, int tables) {
// given
time_t current;
time(&current);
long eachTable = (totalRows - 1) / tables + 1;
current -= eachTable;
int64_t start = getCurrentTimeMill();
// when
TAOS_STMT *stmt = A(conn);
B(stmt, "insert into ? using weather tags(?) values(?,?)");
for (int tbIndex = 0; tbIndex < tables; ++tbIndex) {
char tbname[10];
sprintf(tbname, "t%d", tbIndex);
eachTable = ((tbIndex + 1) * eachTable > totalRows) ? (totalRows - tbIndex * eachTable) : eachTable;
for (int rowIndex = 1; rowIndex <= eachTable; rowIndex += batchRows) {
int rows = (rowIndex + batchRows) > eachTable ? (eachTable + 1 - rowIndex) : batchRows;
if (rowIndex % batchRows == 1) {
D(stmt, tbname, tbIndex);
if (isPrint)
printf("\ntbIndex: %d, table_rows: %ld, rowIndex: %d, batch_rows: %d\n", tbIndex, eachTable, rowIndex, rows);
}
H(stmt, (current + rowIndex) * 1000, rows);
I(stmt);
J(stmt);
}
}
L(stmt);
int64_t end = getCurrentTimeMill();
printf("totalRows: %ld, batchRows: %ld, table: %d, eachTableRows: %ld, time cost: %lld ms\n", totalRows, batchRows,
tables, eachTable, (end - start));
}
void one_batch_multi_table_3(TAOS *conn, long totalRows, long batchRows, int tables) {
// given
time_t current;
time(&current);
long eachTable = (totalRows - 1) / tables + 1;
current -= eachTable;
int64_t start = getCurrentTimeMill();
// when
TAOS_STMT *stmt = A(conn);
B(stmt, "insert into ? using weather tags(?) values(?, ?)");
for (int tbIndex = 0; tbIndex < tables; ++tbIndex) {
char tbname[10];
sprintf(tbname, "t%d", tbIndex);
eachTable = ((tbIndex + 1) * eachTable > totalRows) ? (totalRows - tbIndex * eachTable) : eachTable;
for (int rowIndex = 1; rowIndex <= eachTable; rowIndex += batchRows) {
int rows = (rowIndex + batchRows) > eachTable ? (eachTable + 1 - rowIndex) : batchRows;
if (rowIndex % batchRows == 1) {
D(stmt, tbname, tbIndex);
if (isPrint)
printf("\ntbIndex: %d, table_rows: %ld, rowIndex: %d, batch_rows: %d\n", tbIndex, eachTable, rowIndex, rows);
}
G1(stmt, (current + rowIndex) * 1000, rows);
G2(stmt, rows);
I(stmt);
J(stmt);
}
}
L(stmt);
int64_t end = getCurrentTimeMill();
printf("totalRows: %ld, batchRows: %ld, table: %d, eachTableRows: %ld, time cost: %lld ms\n", totalRows, batchRows,
tables, eachTable, (end - start));
}
void execute(TAOS *conn, char *sql) {
TAOS_RES *psql = taos_query(conn, sql);
if (psql == NULL) {
printf("failed to execute: %s, reason: %s\n", sql, taos_errstr(psql));
taos_free_result(psql);
taos_close(conn);
exit(-1);
}
taos_free_result(psql);
}
TAOS_STMT *A(TAOS *conn) {
if (isPrint) printf("A -> ");
return taos_stmt_init(conn);
}
void B(TAOS_STMT *stmt, char sql[]) {
if (isPrint) printf("B -> ");
int code = taos_stmt_prepare(stmt, sql, 0);
if (code != 0) {
printf("failed to prepare stmt: %s, reason: %s\n", sql, taos_stmt_errstr(stmt));
return;
}
}
void C(TAOS_STMT *stmt, char tbname[]) {
if (isPrint) printf("C -> ");
int code = taos_stmt_set_tbname(stmt, tbname);
if (code != 0) printf("failed to set_tbname_tags, reason: %s\n", taos_stmt_errstr(stmt));
}
void D(TAOS_STMT *stmt, char tbname[], int tag) {
if (isPrint) printf("D -> ");
TAOS_BIND tags[1];
tags[0].buffer_type = TSDB_DATA_TYPE_INT;
int tag_value = tag >= 0 ? tag : rand() % 100;
tags[0].buffer = &tag_value;
tags[0].buffer_length = sizeof(tag_value);
tags[0].length = &tags[0].buffer_length;
tags[0].is_null = NULL;
// set_tbname_tags
int code = taos_stmt_set_tbname_tags(stmt, tbname, tags);
if (code != 0) printf("failed to set_tbname_tags, reason: %s\n", taos_stmt_errstr(stmt));
}
void E(TAOS_STMT *stmt) {
// TODO
}
void F(TAOS_STMT *stmt, int64_t ts) {
if (isPrint) printf("F -> ");
TAOS_BIND params[2];
// timestamp
params[0].buffer_type = TSDB_DATA_TYPE_TIMESTAMP;
params[0].buffer = &ts;
params[0].buffer_length = sizeof(ts);
params[0].length = &params[0].buffer_length;
params[0].is_null = NULL;
// int
int value = rand() % 100;
params[1].buffer_type = TSDB_DATA_TYPE_INT;
params[1].buffer = &value;
params[1].buffer_length = sizeof(value);
params[1].length = &params[1].buffer_length;
params[1].is_null = NULL;
// bind
int code = taos_stmt_bind_param(stmt, params);
if (0 != code) printf("failed to bind_param, reason: %s\n", taos_stmt_errstr(stmt));
}
void H(TAOS_STMT *stmt, int64_t ts_start, int rows) {
if (isPrint) printf("H -> ");
TAOS_MULTI_BIND params[2];
// timestamp
int64_t ts[rows];
for (int i = 0; i < rows; ++i) {
ts[i] = ts_start + i * 1000;
}
params[0].buffer_type = TSDB_DATA_TYPE_TIMESTAMP;
params[0].buffer = ts;
params[0].buffer_length = sizeof(ts[0]);
params[0].length = malloc(sizeof(int64_t) * rows);
char is_null[rows];
for (int i = 0; i < rows; i++) {
is_null[i] = 0;
}
params[0].is_null = is_null;
params[0].num = rows;
// f1
int32_t values[rows];
for (int i = 0; i < rows; ++i) {
values[i] = rand() % 100;
}
params[1].buffer_type = TSDB_DATA_TYPE_INT;
params[1].buffer = values;
params[1].buffer_length = sizeof(int32_t);
params[1].length = malloc(sizeof(int32_t) * rows);
params[1].is_null = is_null;
params[1].num = rows;
int code = taos_stmt_bind_param_batch(stmt, params);
if (code != 0) {
printf("failed to bind_param_batch, reason: %s\n", taos_stmt_errstr(stmt));
return;
}
}
void G1(TAOS_STMT *stmt, int64_t ts_start, int rows) {
if (isPrint) printf("G1 -> ");
// timestamp
TAOS_MULTI_BIND param0[1];
int64_t ts[rows];
for (int i = 0; i < rows; ++i) {
ts[i] = ts_start + i * 1000;
}
param0[0].buffer_type = TSDB_DATA_TYPE_TIMESTAMP;
param0[0].buffer = ts;
param0[0].buffer_length = sizeof(ts[0]);
param0[0].length = malloc(sizeof(int64_t) * rows);
char is_null[rows];
for (int i = 0; i < rows; i++) {
is_null[i] = 0;
}
param0[0].is_null = is_null;
param0[0].num = rows;
int code = taos_stmt_bind_single_param_batch(stmt, param0, 0);
if (code != 0) {
printf("failed to bind_single_param_batch, reason: %s\n", taos_stmt_errstr(stmt));
return;
}
}
void G2(TAOS_STMT *stmt, int rows) {
if (isPrint) printf("G2 -> ");
// f1
TAOS_MULTI_BIND param1[1];
int32_t values[rows];
for (int i = 0; i < rows; ++i) {
values[i] = rand() % 100;
}
param1[0].buffer_type = TSDB_DATA_TYPE_INT;
param1[0].buffer = values;
param1[0].buffer_length = sizeof(int32_t);
param1[0].length = malloc(sizeof(int32_t) * rows);
char is_null[rows];
for (int i = 0; i < rows; i++) {
is_null[i] = 0;
}
param1[0].is_null = is_null;
param1[0].num = rows;
int code = taos_stmt_bind_single_param_batch(stmt, param1, 1);
if (code != 0) {
printf("failed to bind_single_param_batch, reason: %s\n", taos_stmt_errstr(stmt));
return;
}
}
void I(TAOS_STMT *stmt) {
if (isPrint) printf("I -> ");
int code = taos_stmt_add_batch(stmt);
if (code != 0) {
printf("failed to add_batch, reason: %s\n", taos_stmt_errstr(stmt));
return;
}
}
void J(TAOS_STMT *stmt) {
if (isPrint) printf("J -> ");
int code = taos_stmt_execute(stmt);
if (code != 0) {
printf("failed to execute, reason: %s\n", taos_stmt_errstr(stmt));
return;
}
}
void L(TAOS_STMT *stmt) {
if (isPrint) printf("L\n");
taos_stmt_close(stmt);
}
void prepare_super_table(TAOS *conn, int subTables) {
char sql[100] = "drop table weather";
execute(conn, sql);
if (isPrint) printf("sql>>> %s\n", sql);
sprintf(sql, "create table weather(ts timestamp, f1 int) tags(t1 int)");
execute(conn, sql);
if (isPrint) printf("sql>>> %s\n", sql);
for (int i = 0; i < subTables; i++) {
sprintf(sql, "drop table t%d", i);
if (isPrint) printf("sql>>> %s\n", sql);
execute(conn, sql);
}
}
void prepare_normal_table(TAOS *conn) {
execute(conn, "drop table weather");
execute(conn, "create table weather(ts timestamp, f1 int) tags(t1 int)");
}
void prepare_super_and_sub_table(TAOS *conn, int subTables) {
execute(conn, "drop table weather");
execute(conn, "create table weather(ts timestamp, f1 int) tags(t1 int)");
for (int i = 0; i < subTables; i++) {
char sql[100];
sprintf(sql, "drop table t%d", i);
if (isPrint) printf("sql>>> %s\n", sql);
execute(conn, sql);
sprintf(sql, "create table t%d using weather tags(%d)", i, i);
if (isPrint) printf("sql>>> %s\n", sql);
execute(conn, sql);
}
}
int64_t getCurrentTimeMill() {
struct timeval tv;
gettimeofday(&tv, NULL);
return ((unsigned long long)tv.tv_sec * 1000 + (unsigned long long)tv.tv_usec / 1000);
}
\ No newline at end of file
// TAOS standard API example. The same syntax as MySQL, but only a subet
// to compile: gcc -o prepare prepare.c -ltaos
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <taos.h>
#include <unistd.h>
void taosMsleep(int mseconds);
void verify_prepare(TAOS* taos) {
TAOS_RES* result = taos_query(taos, "drop database if exists test;");
taos_free_result(result);
usleep(100000);
result = taos_query(taos, "create database test;");
int code = taos_errno(result);
if (code != 0) {
printf("\033[31mfailed to create database, reason:%s\033[0m\n", taos_errstr(result));
taos_free_result(result);
exit(EXIT_FAILURE);
}
taos_free_result(result);
usleep(100000);
taos_select_db(taos, "test");
// create table
const char* sql =
"create table m1 (ts timestamp, b bool, v1 tinyint, v2 smallint, v4 int, v8 bigint, f4 float, f8 double, bin "
"binary(40), blob nchar(10), u1 tinyint unsigned, u2 smallint unsigned, u4 int unsigned, u8 bigint unsigned)";
result = taos_query(taos, sql);
code = taos_errno(result);
if (code != 0) {
printf("\033[31mfailed to create table, reason:%s\033[0m\n", taos_errstr(result));
taos_free_result(result);
exit(EXIT_FAILURE);
}
taos_free_result(result);
// insert 10 records
struct {
int64_t ts;
int8_t b;
int8_t v1;
int16_t v2;
int32_t v4;
int64_t v8;
float f4;
double f8;
char bin[40];
char blob[80];
uint8_t u1;
uint16_t u2;
uint32_t u4;
uint64_t u8;
} v = {0};
TAOS_STMT* stmt = taos_stmt_init(taos);
TAOS_BIND params[14];
params[0].buffer_type = TSDB_DATA_TYPE_TIMESTAMP;
params[0].buffer_length = sizeof(v.ts);
params[0].buffer = &v.ts;
params[0].length = &params[0].buffer_length;
params[0].is_null = NULL;
params[1].buffer_type = TSDB_DATA_TYPE_BOOL;
params[1].buffer_length = sizeof(v.b);
params[1].buffer = &v.b;
params[1].length = &params[1].buffer_length;
params[1].is_null = NULL;
params[2].buffer_type = TSDB_DATA_TYPE_TINYINT;
params[2].buffer_length = sizeof(v.v1);
params[2].buffer = &v.v1;
params[2].length = &params[2].buffer_length;
params[2].is_null = NULL;
params[3].buffer_type = TSDB_DATA_TYPE_SMALLINT;
params[3].buffer_length = sizeof(v.v2);
params[3].buffer = &v.v2;
params[3].length = &params[3].buffer_length;
params[3].is_null = NULL;
params[4].buffer_type = TSDB_DATA_TYPE_INT;
params[4].buffer_length = sizeof(v.v4);
params[4].buffer = &v.v4;
params[4].length = &params[4].buffer_length;
params[4].is_null = NULL;
params[5].buffer_type = TSDB_DATA_TYPE_BIGINT;
params[5].buffer_length = sizeof(v.v8);
params[5].buffer = &v.v8;
params[5].length = &params[5].buffer_length;
params[5].is_null = NULL;
params[6].buffer_type = TSDB_DATA_TYPE_FLOAT;
params[6].buffer_length = sizeof(v.f4);
params[6].buffer = &v.f4;
params[6].length = &params[6].buffer_length;
params[6].is_null = NULL;
params[7].buffer_type = TSDB_DATA_TYPE_DOUBLE;
params[7].buffer_length = sizeof(v.f8);
params[7].buffer = &v.f8;
params[7].length = &params[7].buffer_length;
params[7].is_null = NULL;
params[8].buffer_type = TSDB_DATA_TYPE_BINARY;
params[8].buffer_length = sizeof(v.bin);
params[8].buffer = v.bin;
params[8].length = &params[8].buffer_length;
params[8].is_null = NULL;
strcpy(v.blob, "一二三四五六七八九十");
params[9].buffer_type = TSDB_DATA_TYPE_NCHAR;
params[9].buffer_length = strlen(v.blob);
params[9].buffer = v.blob;
params[9].length = &params[9].buffer_length;
params[9].is_null = NULL;
params[10].buffer_type = TSDB_DATA_TYPE_UTINYINT;
params[10].buffer_length = sizeof(v.u1);
params[10].buffer = &v.u1;
params[10].length = &params[10].buffer_length;
params[10].is_null = NULL;
params[11].buffer_type = TSDB_DATA_TYPE_USMALLINT;
params[11].buffer_length = sizeof(v.u2);
params[11].buffer = &v.u2;
params[11].length = &params[11].buffer_length;
params[11].is_null = NULL;
params[12].buffer_type = TSDB_DATA_TYPE_UINT;
params[12].buffer_length = sizeof(v.u4);
params[12].buffer = &v.u4;
params[12].length = &params[12].buffer_length;
params[12].is_null = NULL;
params[13].buffer_type = TSDB_DATA_TYPE_UBIGINT;
params[13].buffer_length = sizeof(v.u8);
params[13].buffer = &v.u8;
params[13].length = &params[13].buffer_length;
params[13].is_null = NULL;
int is_null = 1;
sql = "insert into m1 values(?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
code = taos_stmt_prepare(stmt, sql, 0);
if (code != 0) {
printf("\033[31mfailed to execute taos_stmt_prepare. error:%s\033[0m\n", taos_stmt_errstr(stmt));
taos_stmt_close(stmt);
exit(EXIT_FAILURE);
}
v.ts = 1591060628000;
for (int i = 0; i < 10; ++i) {
v.ts += 1;
for (int j = 1; j < 10; ++j) {
params[j].is_null = ((i == j) ? &is_null : 0);
}
v.b = (int8_t)i % 2;
v.v1 = (int8_t)i;
v.v2 = (int16_t)(i * 2);
v.v4 = (int32_t)(i * 4);
v.v8 = (int64_t)(i * 8);
v.f4 = (float)(i * 40);
v.f8 = (double)(i * 80);
for (int j = 0; j < sizeof(v.bin); ++j) {
v.bin[j] = (char)(i + '0');
}
v.u1 = (uint8_t)i;
v.u2 = (uint16_t)(i * 2);
v.u4 = (uint32_t)(i * 4);
v.u8 = (uint64_t)(i * 8);
taos_stmt_bind_param(stmt, params);
taos_stmt_add_batch(stmt);
}
if (taos_stmt_execute(stmt) != 0) {
printf("\033[31mfailed to execute insert statement.error:%s\033[0m\n", taos_stmt_errstr(stmt));
taos_stmt_close(stmt);
exit(EXIT_FAILURE);
}
int affectedRows = taos_stmt_affected_rows(stmt);
printf("sucessfully inserted %d rows\n", affectedRows);
taos_stmt_close(stmt);
// query the records
stmt = taos_stmt_init(taos);
taos_stmt_prepare(stmt, "SELECT * FROM m1 WHERE v1 > ? AND v2 < ?", 0);
v.v1 = 5;
v.v2 = 15;
taos_stmt_bind_param(stmt, params + 2);
if (taos_stmt_execute(stmt) != 0) {
printf("\033[31mfailed to execute select statement.error:%s\033[0m\n", taos_stmt_errstr(stmt));
taos_stmt_close(stmt);
exit(EXIT_FAILURE);
}
result = taos_stmt_use_result(stmt);
TAOS_ROW row;
int rows = 0;
int num_fields = taos_num_fields(result);
TAOS_FIELD* fields = taos_fetch_fields(result);
// fetch the records row by row
while ((row = taos_fetch_row(result))) {
char temp[256] = {0};
rows++;
taos_print_row(temp, row, fields, num_fields);
printf("%s\n", temp);
}
taos_free_result(result);
taos_stmt_close(stmt);
}
void verify_prepare2(TAOS* taos) {
TAOS_RES* result = taos_query(taos, "drop database if exists test;");
taos_free_result(result);
usleep(100000);
result = taos_query(taos, "create database test;");
int code = taos_errno(result);
if (code != 0) {
printf("\033[31mfailed to create database, reason:%s\033[0m\n", taos_errstr(result));
taos_free_result(result);
exit(EXIT_FAILURE);
}
taos_free_result(result);
usleep(100000);
taos_select_db(taos, "test");
// create table
const char* sql =
"create table m1 (ts timestamp, b bool, v1 tinyint, v2 smallint, v4 int, v8 bigint, f4 float, f8 double, bin "
"binary(40), blob nchar(10), u1 tinyint unsigned, u2 smallint unsigned, u4 int unsigned, u8 bigint unsigned)";
result = taos_query(taos, sql);
code = taos_errno(result);
if (code != 0) {
printf("\033[31mfailed to create table, reason:%s\033[0m\n", taos_errstr(result));
taos_free_result(result);
exit(EXIT_FAILURE);
}
taos_free_result(result);
// insert 10 records
struct {
int64_t ts;
int8_t b;
int8_t v1;
int16_t v2;
int32_t v4;
int64_t v8;
float f4;
double f8;
char bin[40];
char blob[80];
uint8_t u1;
uint16_t u2;
uint32_t u4;
uint64_t u8;
} v = {0};
TAOS_STMT* stmt = taos_stmt_init(taos);
TAOS_BIND params[14];
params[0].buffer_type = TSDB_DATA_TYPE_TIMESTAMP;
params[0].buffer_length = sizeof(v.ts);
params[0].buffer = &v.ts;
params[0].length = &params[0].buffer_length;
params[0].is_null = NULL;
params[1].buffer_type = TSDB_DATA_TYPE_BOOL;
params[1].buffer_length = sizeof(v.b);
params[1].buffer = &v.b;
params[1].length = &params[1].buffer_length;
params[1].is_null = NULL;
params[2].buffer_type = TSDB_DATA_TYPE_TINYINT;
params[2].buffer_length = sizeof(v.v1);
params[2].buffer = &v.v1;
params[2].length = &params[2].buffer_length;
params[2].is_null = NULL;
params[3].buffer_type = TSDB_DATA_TYPE_SMALLINT;
params[3].buffer_length = sizeof(v.v2);
params[3].buffer = &v.v2;
params[3].length = &params[3].buffer_length;
params[3].is_null = NULL;
params[4].buffer_type = TSDB_DATA_TYPE_INT;
params[4].buffer_length = sizeof(v.v4);
params[4].buffer = &v.v4;
params[4].length = &params[4].buffer_length;
params[4].is_null = NULL;
params[5].buffer_type = TSDB_DATA_TYPE_BIGINT;
params[5].buffer_length = sizeof(v.v8);
params[5].buffer = &v.v8;
params[5].length = &params[5].buffer_length;
params[5].is_null = NULL;
params[6].buffer_type = TSDB_DATA_TYPE_FLOAT;
params[6].buffer_length = sizeof(v.f4);
params[6].buffer = &v.f4;
params[6].length = &params[6].buffer_length;
params[6].is_null = NULL;
params[7].buffer_type = TSDB_DATA_TYPE_DOUBLE;
params[7].buffer_length = sizeof(v.f8);
params[7].buffer = &v.f8;
params[7].length = &params[7].buffer_length;
params[7].is_null = NULL;
params[8].buffer_type = TSDB_DATA_TYPE_BINARY;
params[8].buffer_length = sizeof(v.bin);
params[8].buffer = v.bin;
params[8].length = &params[8].buffer_length;
params[8].is_null = NULL;
strcpy(v.blob, "一二三四五六七八九十");
params[9].buffer_type = TSDB_DATA_TYPE_NCHAR;
params[9].buffer_length = strlen(v.blob);
params[9].buffer = v.blob;
params[9].length = &params[9].buffer_length;
params[9].is_null = NULL;
params[10].buffer_type = TSDB_DATA_TYPE_UTINYINT;
params[10].buffer_length = sizeof(v.u1);
params[10].buffer = &v.u1;
params[10].length = &params[10].buffer_length;
params[10].is_null = NULL;
params[11].buffer_type = TSDB_DATA_TYPE_USMALLINT;
params[11].buffer_length = sizeof(v.u2);
params[11].buffer = &v.u2;
params[11].length = &params[11].buffer_length;
params[11].is_null = NULL;
params[12].buffer_type = TSDB_DATA_TYPE_UINT;
params[12].buffer_length = sizeof(v.u4);
params[12].buffer = &v.u4;
params[12].length = &params[12].buffer_length;
params[12].is_null = NULL;
params[13].buffer_type = TSDB_DATA_TYPE_UBIGINT;
params[13].buffer_length = sizeof(v.u8);
params[13].buffer = &v.u8;
params[13].length = &params[13].buffer_length;
params[13].is_null = NULL;
sql = "insert into ? values(?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
code = taos_stmt_prepare(stmt, sql, 0);
if (code != 0) {
printf("\033[31mfailed to execute taos_stmt_prepare. error:%s\033[0m\n", taos_stmt_errstr(stmt));
taos_stmt_close(stmt);
exit(EXIT_FAILURE);
}
code = taos_stmt_set_tbname(stmt, "m1");
if (code != 0) {
printf("\033[31mfailed to execute taos_stmt_prepare. error:%s\033[0m\n", taos_stmt_errstr(stmt));
taos_stmt_close(stmt);
exit(EXIT_FAILURE);
}
int is_null = 1;
v.ts = 1591060628000;
for (int i = 0; i < 10; ++i) {
v.ts += 1;
for (int j = 1; j < 10; ++j) {
params[j].is_null = ((i == j) ? &is_null : 0);
}
v.b = (int8_t)i % 2;
v.v1 = (int8_t)i;
v.v2 = (int16_t)(i * 2);
v.v4 = (int32_t)(i * 4);
v.v8 = (int64_t)(i * 8);
v.f4 = (float)(i * 40);
v.f8 = (double)(i * 80);
for (int j = 0; j < sizeof(v.bin); ++j) {
v.bin[j] = (char)(i + '0');
}
v.u1 = (uint8_t)i;
v.u2 = (uint16_t)(i * 2);
v.u4 = (uint32_t)(i * 4);
v.u8 = (uint64_t)(i * 8);
taos_stmt_bind_param(stmt, params);
taos_stmt_add_batch(stmt);
}
if (taos_stmt_execute(stmt) != 0) {
printf("\033[31mfailed to execute insert statement.error:%s\033[0m\n", taos_stmt_errstr(stmt));
taos_stmt_close(stmt);
exit(EXIT_FAILURE);
}
int affectedRows = taos_stmt_affected_rows(stmt);
printf("sucessfully inserted %d rows\n", affectedRows);
taos_stmt_close(stmt);
// query the records
stmt = taos_stmt_init(taos);
taos_stmt_prepare(stmt, "SELECT * FROM m1 WHERE v1 > ? AND v2 < ?", 0);
TAOS_BIND qparams[2];
int8_t v1 = 5;
int16_t v2 = 15;
qparams[0].buffer_type = TSDB_DATA_TYPE_TINYINT;
qparams[0].buffer_length = sizeof(v1);
qparams[0].buffer = &v1;
qparams[0].length = &qparams[0].buffer_length;
qparams[0].is_null = NULL;
qparams[1].buffer_type = TSDB_DATA_TYPE_SMALLINT;
qparams[1].buffer_length = sizeof(v2);
qparams[1].buffer = &v2;
qparams[1].length = &qparams[1].buffer_length;
qparams[1].is_null = NULL;
taos_stmt_bind_param(stmt, qparams);
if (taos_stmt_execute(stmt) != 0) {
printf("\033[31mfailed to execute select statement.error:%s\033[0m\n", taos_stmt_errstr(stmt));
taos_stmt_close(stmt);
exit(EXIT_FAILURE);
}
result = taos_stmt_use_result(stmt);
TAOS_ROW row;
int rows = 0;
int num_fields = taos_num_fields(result);
TAOS_FIELD* fields = taos_fetch_fields(result);
// fetch the records row by row
while ((row = taos_fetch_row(result))) {
char temp[256] = {0};
rows++;
taos_print_row(temp, row, fields, num_fields);
printf("%s\n", temp);
}
taos_free_result(result);
taos_stmt_close(stmt);
}
void verify_prepare3(TAOS* taos) {
TAOS_RES* result = taos_query(taos, "drop database if exists test;");
taos_free_result(result);
usleep(100000);
result = taos_query(taos, "create database test;");
int code = taos_errno(result);
if (code != 0) {
printf("\033[31mfailed to create database, reason:%s\033[0m\n", taos_errstr(result));
taos_free_result(result);
exit(EXIT_FAILURE);
}
taos_free_result(result);
usleep(100000);
taos_select_db(taos, "test");
// create table
const char* sql =
"create stable st1 (ts timestamp, b bool, v1 tinyint, v2 smallint, v4 int, v8 bigint, f4 float, f8 double, bin "
"binary(40), blob nchar(10), u1 tinyint unsigned, u2 smallint unsigned, u4 int unsigned, u8 bigint unsigned) "
"tags "
"(b_tag bool, v1_tag tinyint, v2_tag smallint, v4_tag int, v8_tag bigint, f4_tag float, f8_tag double, bin_tag "
"binary(40), blob_tag nchar(10), u1_tag tinyint unsigned, u2_tag smallint unsigned, u4_tag int unsigned, u8_tag "
"bigint "
"unsigned)";
result = taos_query(taos, sql);
code = taos_errno(result);
if (code != 0) {
printf("\033[31mfailed to create table, reason:%s\033[0m\n", taos_errstr(result));
taos_free_result(result);
exit(EXIT_FAILURE);
}
taos_free_result(result);
TAOS_BIND tags[13];
struct {
int8_t b;
int8_t v1;
int16_t v2;
int32_t v4;
int64_t v8;
float f4;
double f8;
char bin[40];
char blob[80];
uint8_t u1;
uint16_t u2;
uint32_t u4;
uint64_t u8;
} id = {0};
id.b = (int8_t)1;
id.v1 = (int8_t)1;
id.v2 = (int16_t)2;
id.v4 = (int32_t)4;
id.v8 = (int64_t)8;
id.f4 = (float)40;
id.f8 = (double)80;
for (int j = 0; j < sizeof(id.bin); ++j) {
id.bin[j] = (char)('1' + '0');
}
strcpy(id.blob, "一二三四五六七八九十");
id.u1 = (uint8_t)1;
id.u2 = (uint16_t)2;
id.u4 = (uint32_t)4;
id.u8 = (uint64_t)8;
tags[0].buffer_type = TSDB_DATA_TYPE_BOOL;
tags[0].buffer_length = sizeof(id.b);
tags[0].buffer = &id.b;
tags[0].length = &tags[0].buffer_length;
tags[0].is_null = NULL;
tags[1].buffer_type = TSDB_DATA_TYPE_TINYINT;
tags[1].buffer_length = sizeof(id.v1);
tags[1].buffer = &id.v1;
tags[1].length = &tags[1].buffer_length;
tags[1].is_null = NULL;
tags[2].buffer_type = TSDB_DATA_TYPE_SMALLINT;
tags[2].buffer_length = sizeof(id.v2);
tags[2].buffer = &id.v2;
tags[2].length = &tags[2].buffer_length;
tags[2].is_null = NULL;
tags[3].buffer_type = TSDB_DATA_TYPE_INT;
tags[3].buffer_length = sizeof(id.v4);
tags[3].buffer = &id.v4;
tags[3].length = &tags[3].buffer_length;
tags[3].is_null = NULL;
tags[4].buffer_type = TSDB_DATA_TYPE_BIGINT;
tags[4].buffer_length = sizeof(id.v8);
tags[4].buffer = &id.v8;
tags[4].length = &tags[4].buffer_length;
tags[4].is_null = NULL;
tags[5].buffer_type = TSDB_DATA_TYPE_FLOAT;
tags[5].buffer_length = sizeof(id.f4);
tags[5].buffer = &id.f4;
tags[5].length = &tags[5].buffer_length;
tags[5].is_null = NULL;
tags[6].buffer_type = TSDB_DATA_TYPE_DOUBLE;
tags[6].buffer_length = sizeof(id.f8);
tags[6].buffer = &id.f8;
tags[6].length = &tags[6].buffer_length;
tags[6].is_null = NULL;
tags[7].buffer_type = TSDB_DATA_TYPE_BINARY;
tags[7].buffer_length = sizeof(id.bin);
tags[7].buffer = &id.bin;
tags[7].length = &tags[7].buffer_length;
tags[7].is_null = NULL;
tags[8].buffer_type = TSDB_DATA_TYPE_NCHAR;
tags[8].buffer_length = strlen(id.blob);
tags[8].buffer = &id.blob;
tags[8].length = &tags[8].buffer_length;
tags[8].is_null = NULL;
tags[9].buffer_type = TSDB_DATA_TYPE_UTINYINT;
tags[9].buffer_length = sizeof(id.u1);
tags[9].buffer = &id.u1;
tags[9].length = &tags[9].buffer_length;
tags[9].is_null = NULL;
tags[10].buffer_type = TSDB_DATA_TYPE_USMALLINT;
tags[10].buffer_length = sizeof(id.u2);
tags[10].buffer = &id.u2;
tags[10].length = &tags[10].buffer_length;
tags[10].is_null = NULL;
tags[11].buffer_type = TSDB_DATA_TYPE_UINT;
tags[11].buffer_length = sizeof(id.u4);
tags[11].buffer = &id.u4;
tags[11].length = &tags[11].buffer_length;
tags[11].is_null = NULL;
tags[12].buffer_type = TSDB_DATA_TYPE_UBIGINT;
tags[12].buffer_length = sizeof(id.u8);
tags[12].buffer = &id.u8;
tags[12].length = &tags[12].buffer_length;
tags[12].is_null = NULL;
// insert 10 records
struct {
int64_t ts[10];
int8_t b[10];
int8_t v1[10];
int16_t v2[10];
int32_t v4[10];
int64_t v8[10];
float f4[10];
double f8[10];
char bin[10][40];
char blob[10][80];
uint8_t u1[10];
uint16_t u2[10];
uint32_t u4[10];
uint64_t u8[10];
} v;
int32_t* t8_len = malloc(sizeof(int32_t) * 10);
int32_t* t16_len = malloc(sizeof(int32_t) * 10);
int32_t* t32_len = malloc(sizeof(int32_t) * 10);
int32_t* t64_len = malloc(sizeof(int32_t) * 10);
int32_t* float_len = malloc(sizeof(int32_t) * 10);
int32_t* double_len = malloc(sizeof(int32_t) * 10);
int32_t* bin_len = malloc(sizeof(int32_t) * 10);
int32_t* blob_len = malloc(sizeof(int32_t) * 10);
int32_t* u8_len = malloc(sizeof(int32_t) * 10);
int32_t* u16_len = malloc(sizeof(int32_t) * 10);
int32_t* u32_len = malloc(sizeof(int32_t) * 10);
int32_t* u64_len = malloc(sizeof(int32_t) * 10);
TAOS_STMT* stmt = taos_stmt_init(taos);
TAOS_MULTI_BIND params[14];
char is_null[10] = {0};
params[0].buffer_type = TSDB_DATA_TYPE_TIMESTAMP;
params[0].buffer_length = sizeof(v.ts[0]);
params[0].buffer = v.ts;
params[0].length = t64_len;
params[0].is_null = is_null;
params[0].num = 10;
params[1].buffer_type = TSDB_DATA_TYPE_BOOL;
params[1].buffer_length = sizeof(v.b[0]);
params[1].buffer = v.b;
params[1].length = t8_len;
params[1].is_null = is_null;
params[1].num = 10;
params[2].buffer_type = TSDB_DATA_TYPE_TINYINT;
params[2].buffer_length = sizeof(v.v1[0]);
params[2].buffer = v.v1;
params[2].length = t8_len;
params[2].is_null = is_null;
params[2].num = 10;
params[3].buffer_type = TSDB_DATA_TYPE_SMALLINT;
params[3].buffer_length = sizeof(v.v2[0]);
params[3].buffer = v.v2;
params[3].length = t16_len;
params[3].is_null = is_null;
params[3].num = 10;
params[4].buffer_type = TSDB_DATA_TYPE_INT;
params[4].buffer_length = sizeof(v.v4[0]);
params[4].buffer = v.v4;
params[4].length = t32_len;
params[4].is_null = is_null;
params[4].num = 10;
params[5].buffer_type = TSDB_DATA_TYPE_BIGINT;
params[5].buffer_length = sizeof(v.v8[0]);
params[5].buffer = v.v8;
params[5].length = t64_len;
params[5].is_null = is_null;
params[5].num = 10;
params[6].buffer_type = TSDB_DATA_TYPE_FLOAT;
params[6].buffer_length = sizeof(v.f4[0]);
params[6].buffer = v.f4;
params[6].length = float_len;
params[6].is_null = is_null;
params[6].num = 10;
params[7].buffer_type = TSDB_DATA_TYPE_DOUBLE;
params[7].buffer_length = sizeof(v.f8[0]);
params[7].buffer = v.f8;
params[7].length = double_len;
params[7].is_null = is_null;
params[7].num = 10;
params[8].buffer_type = TSDB_DATA_TYPE_BINARY;
params[8].buffer_length = sizeof(v.bin[0]);
params[8].buffer = v.bin;
params[8].length = bin_len;
params[8].is_null = is_null;
params[8].num = 10;
params[9].buffer_type = TSDB_DATA_TYPE_NCHAR;
params[9].buffer_length = sizeof(v.blob[0]);
params[9].buffer = v.blob;
params[9].length = blob_len;
params[9].is_null = is_null;
params[9].num = 10;
params[10].buffer_type = TSDB_DATA_TYPE_UTINYINT;
params[10].buffer_length = sizeof(v.u1[0]);
params[10].buffer = v.u1;
params[10].length = u8_len;
params[10].is_null = is_null;
params[10].num = 10;
params[11].buffer_type = TSDB_DATA_TYPE_USMALLINT;
params[11].buffer_length = sizeof(v.u2[0]);
params[11].buffer = v.u2;
params[11].length = u16_len;
params[11].is_null = is_null;
params[11].num = 10;
params[12].buffer_type = TSDB_DATA_TYPE_UINT;
params[12].buffer_length = sizeof(v.u4[0]);
params[12].buffer = v.u4;
params[12].length = u32_len;
params[12].is_null = is_null;
params[12].num = 10;
params[13].buffer_type = TSDB_DATA_TYPE_UBIGINT;
params[13].buffer_length = sizeof(v.u8[0]);
params[13].buffer = v.u8;
params[13].length = u64_len;
params[13].is_null = is_null;
params[13].num = 10;
sql = "insert into ? using st1 tags(?,?,?,?,?,?,?,?,?,?,?,?,?) values(?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
code = taos_stmt_prepare(stmt, sql, 0);
if (code != 0) {
printf("\033[31mfailed to execute taos_stmt_prepare. error:%s\033[0m\n", taos_stmt_errstr(stmt));
taos_stmt_close(stmt);
exit(EXIT_FAILURE);
}
code = taos_stmt_set_tbname_tags(stmt, "m1", tags);
if (code != 0) {
printf("\033[31mfailed to execute taos_stmt_set_tbname_tags. error:%s\033[0m\n", taos_stmt_errstr(stmt));
taos_stmt_close(stmt);
exit(EXIT_FAILURE);
}
int64_t ts = 1591060628000;
for (int i = 0; i < 10; ++i) {
v.ts[i] = ts++;
is_null[i] = 0;
v.b[i] = (int8_t)i % 2;
v.v1[i] = (int8_t)i;
v.v2[i] = (int16_t)(i * 2);
v.v4[i] = (int32_t)(i * 4);
v.v8[i] = (int64_t)(i * 8);
v.f4[i] = (float)(i * 40);
v.f8[i] = (double)(i * 80);
for (int j = 0; j < sizeof(v.bin[0]); ++j) {
v.bin[i][j] = (char)(i + '0');
}
strcpy(v.blob[i], "一二三四五六七八九十");
v.u1[i] = (uint8_t)i;
v.u2[i] = (uint16_t)(i * 2);
v.u4[i] = (uint32_t)(i * 4);
v.u8[i] = (uint64_t)(i * 8);
t8_len[i] = sizeof(int8_t);
t16_len[i] = sizeof(int16_t);
t32_len[i] = sizeof(int32_t);
t64_len[i] = sizeof(int64_t);
float_len[i] = sizeof(float);
double_len[i] = sizeof(double);
bin_len[i] = sizeof(v.bin[0]);
blob_len[i] = (int32_t)strlen(v.blob[i]);
u8_len[i] = sizeof(uint8_t);
u16_len[i] = sizeof(uint16_t);
u32_len[i] = sizeof(uint32_t);
u64_len[i] = sizeof(uint64_t);
}
taos_stmt_bind_param_batch(stmt, params);
taos_stmt_add_batch(stmt);
if (taos_stmt_execute(stmt) != 0) {
printf("\033[31mfailed to execute insert statement.error:%s\033[0m\n", taos_stmt_errstr(stmt));
taos_stmt_close(stmt);
exit(EXIT_FAILURE);
}
int affectedRows = taos_stmt_affected_rows(stmt);
printf("successfully inserted %d rows\n", affectedRows);
taos_stmt_close(stmt);
// query the records
stmt = taos_stmt_init(taos);
taos_stmt_prepare(stmt, "SELECT * FROM m1 WHERE v1 > ? AND v2 < ?", 0);
TAOS_BIND qparams[2];
int8_t v1 = 5;
int16_t v2 = 15;
qparams[0].buffer_type = TSDB_DATA_TYPE_TINYINT;
qparams[0].buffer_length = sizeof(v1);
qparams[0].buffer = &v1;
qparams[0].length = &qparams[0].buffer_length;
qparams[0].is_null = NULL;
qparams[1].buffer_type = TSDB_DATA_TYPE_SMALLINT;
qparams[1].buffer_length = sizeof(v2);
qparams[1].buffer = &v2;
qparams[1].length = &qparams[1].buffer_length;
qparams[1].is_null = NULL;
taos_stmt_bind_param(stmt, qparams);
if (taos_stmt_execute(stmt) != 0) {
printf("\033[31mfailed to execute select statement.error:%s\033[0m\n", taos_stmt_errstr(stmt));
taos_stmt_close(stmt);
exit(EXIT_FAILURE);
}
result = taos_stmt_use_result(stmt);
TAOS_ROW row;
int rows = 0;
int num_fields = taos_num_fields(result);
TAOS_FIELD* fields = taos_fetch_fields(result);
// fetch the records row by row
while ((row = taos_fetch_row(result))) {
char temp[256] = {0};
rows++;
taos_print_row(temp, row, fields, num_fields);
printf("%s\n", temp);
}
taos_free_result(result);
taos_stmt_close(stmt);
free(t8_len);
free(t16_len);
free(t32_len);
free(t64_len);
free(float_len);
free(double_len);
free(bin_len);
free(blob_len);
free(u8_len);
free(u16_len);
free(u32_len);
free(u64_len);
}
/**
* @brief Verify the upper/lower case of tableName for create(by setTableName)/query/show/describe/drop.
* https://jira.taosdata.com:18080/browse/TS-904
* https://jira.taosdata.com:18090/pages/viewpage.action?pageId=129140555
* @param taos
*/
void verify_prepare4(TAOS* taos) {
printf("Verify the upper/lower case of tableName for create(by setTableName)/query/show/describe/drop etc.\n");
TAOS_RES* result = taos_query(taos, "drop database if exists test;");
taos_free_result(result);
usleep(100000);
result = taos_query(taos, "create database test;");
int code = taos_errno(result);
if (code != 0) {
printf("\033[31mfailed to create database, reason:%s\033[0m\n", taos_errstr(result));
taos_free_result(result);
exit(EXIT_FAILURE);
}
taos_free_result(result);
usleep(100000);
taos_select_db(taos, "test");
// create table
const char* sql =
"create stable st1 (ts timestamp, b bool, v1 tinyint, v2 smallint, v4 int, v8 bigint, f4 float, f8 double, bin "
"binary(40), blob nchar(10), u1 tinyint unsigned, u2 smallint unsigned, u4 int unsigned, u8 bigint unsigned) "
"tags "
"(b_tag bool, v1_tag tinyint, v2_tag smallint, v4_tag int, v8_tag bigint, f4_tag float, f8_tag double, bin_tag "
"binary(40), blob_tag nchar(10), u1_tag tinyint unsigned, u2_tag smallint unsigned, u4_tag int unsigned, u8_tag "
"bigint "
"unsigned)";
result = taos_query(taos, sql);
code = taos_errno(result);
if (code != 0) {
printf("\033[31mfailed to create table, reason:%s\033[0m\n", taos_errstr(result));
taos_free_result(result);
exit(EXIT_FAILURE);
}
taos_free_result(result);
TAOS_BIND tags[13];
struct {
int8_t b;
int8_t v1;
int16_t v2;
int32_t v4;
int64_t v8;
float f4;
double f8;
char bin[40];
char blob[80];
uint8_t u1;
uint16_t u2;
uint32_t u4;
uint64_t u8;
} id = {0};
id.b = (int8_t)1;
id.v1 = (int8_t)1;
id.v2 = (int16_t)2;
id.v4 = (int32_t)4;
id.v8 = (int64_t)8;
id.f4 = (float)40;
id.f8 = (double)80;
for (int j = 0; j < sizeof(id.bin); ++j) {
id.bin[j] = (char)('1' + '0');
}
strcpy(id.blob, "一二三四五六七八九十");
id.u1 = (uint8_t)1;
id.u2 = (uint16_t)2;
id.u4 = (uint32_t)4;
id.u8 = (uint64_t)8;
tags[0].buffer_type = TSDB_DATA_TYPE_BOOL;
tags[0].buffer_length = sizeof(id.b);
tags[0].buffer = &id.b;
tags[0].length = &tags[0].buffer_length;
tags[0].is_null = NULL;
tags[1].buffer_type = TSDB_DATA_TYPE_TINYINT;
tags[1].buffer_length = sizeof(id.v1);
tags[1].buffer = &id.v1;
tags[1].length = &tags[1].buffer_length;
tags[1].is_null = NULL;
tags[2].buffer_type = TSDB_DATA_TYPE_SMALLINT;
tags[2].buffer_length = sizeof(id.v2);
tags[2].buffer = &id.v2;
tags[2].length = &tags[2].buffer_length;
tags[2].is_null = NULL;
tags[3].buffer_type = TSDB_DATA_TYPE_INT;
tags[3].buffer_length = sizeof(id.v4);
tags[3].buffer = &id.v4;
tags[3].length = &tags[3].buffer_length;
tags[3].is_null = NULL;
tags[4].buffer_type = TSDB_DATA_TYPE_BIGINT;
tags[4].buffer_length = sizeof(id.v8);
tags[4].buffer = &id.v8;
tags[4].length = &tags[4].buffer_length;
tags[4].is_null = NULL;
tags[5].buffer_type = TSDB_DATA_TYPE_FLOAT;
tags[5].buffer_length = sizeof(id.f4);
tags[5].buffer = &id.f4;
tags[5].length = &tags[5].buffer_length;
tags[5].is_null = NULL;
tags[6].buffer_type = TSDB_DATA_TYPE_DOUBLE;
tags[6].buffer_length = sizeof(id.f8);
tags[6].buffer = &id.f8;
tags[6].length = &tags[6].buffer_length;
tags[6].is_null = NULL;
tags[7].buffer_type = TSDB_DATA_TYPE_BINARY;
tags[7].buffer_length = sizeof(id.bin);
tags[7].buffer = &id.bin;
tags[7].length = &tags[7].buffer_length;
tags[7].is_null = NULL;
tags[8].buffer_type = TSDB_DATA_TYPE_NCHAR;
tags[8].buffer_length = strlen(id.blob);
tags[8].buffer = &id.blob;
tags[8].length = &tags[8].buffer_length;
tags[8].is_null = NULL;
tags[9].buffer_type = TSDB_DATA_TYPE_UTINYINT;
tags[9].buffer_length = sizeof(id.u1);
tags[9].buffer = &id.u1;
tags[9].length = &tags[9].buffer_length;
tags[9].is_null = NULL;
tags[10].buffer_type = TSDB_DATA_TYPE_USMALLINT;
tags[10].buffer_length = sizeof(id.u2);
tags[10].buffer = &id.u2;
tags[10].length = &tags[10].buffer_length;
tags[10].is_null = NULL;
tags[11].buffer_type = TSDB_DATA_TYPE_UINT;
tags[11].buffer_length = sizeof(id.u4);
tags[11].buffer = &id.u4;
tags[11].length = &tags[11].buffer_length;
tags[11].is_null = NULL;
tags[12].buffer_type = TSDB_DATA_TYPE_UBIGINT;
tags[12].buffer_length = sizeof(id.u8);
tags[12].buffer = &id.u8;
tags[12].length = &tags[12].buffer_length;
tags[12].is_null = NULL;
// insert 10 records
struct {
int64_t ts[10];
int8_t b[10];
int8_t v1[10];
int16_t v2[10];
int32_t v4[10];
int64_t v8[10];
float f4[10];
double f8[10];
char bin[10][40];
char blob[10][80];
uint8_t u1[10];
uint16_t u2[10];
uint32_t u4[10];
uint64_t u8[10];
} v;
int32_t* t8_len = malloc(sizeof(int32_t) * 10);
int32_t* t16_len = malloc(sizeof(int32_t) * 10);
int32_t* t32_len = malloc(sizeof(int32_t) * 10);
int32_t* t64_len = malloc(sizeof(int32_t) * 10);
int32_t* float_len = malloc(sizeof(int32_t) * 10);
int32_t* double_len = malloc(sizeof(int32_t) * 10);
int32_t* bin_len = malloc(sizeof(int32_t) * 10);
int32_t* blob_len = malloc(sizeof(int32_t) * 10);
int32_t* u8_len = malloc(sizeof(int32_t) * 10);
int32_t* u16_len = malloc(sizeof(int32_t) * 10);
int32_t* u32_len = malloc(sizeof(int32_t) * 10);
int32_t* u64_len = malloc(sizeof(int32_t) * 10);
TAOS_MULTI_BIND params[14];
char is_null[10] = {0};
params[0].buffer_type = TSDB_DATA_TYPE_TIMESTAMP;
params[0].buffer_length = sizeof(v.ts[0]);
params[0].buffer = v.ts;
params[0].length = t64_len;
params[0].is_null = is_null;
params[0].num = 10;
params[1].buffer_type = TSDB_DATA_TYPE_BOOL;
params[1].buffer_length = sizeof(v.b[0]);
params[1].buffer = v.b;
params[1].length = t8_len;
params[1].is_null = is_null;
params[1].num = 10;
params[2].buffer_type = TSDB_DATA_TYPE_TINYINT;
params[2].buffer_length = sizeof(v.v1[0]);
params[2].buffer = v.v1;
params[2].length = t8_len;
params[2].is_null = is_null;
params[2].num = 10;
params[3].buffer_type = TSDB_DATA_TYPE_SMALLINT;
params[3].buffer_length = sizeof(v.v2[0]);
params[3].buffer = v.v2;
params[3].length = t16_len;
params[3].is_null = is_null;
params[3].num = 10;
params[4].buffer_type = TSDB_DATA_TYPE_INT;
params[4].buffer_length = sizeof(v.v4[0]);
params[4].buffer = v.v4;
params[4].length = t32_len;
params[4].is_null = is_null;
params[4].num = 10;
params[5].buffer_type = TSDB_DATA_TYPE_BIGINT;
params[5].buffer_length = sizeof(v.v8[0]);
params[5].buffer = v.v8;
params[5].length = t64_len;
params[5].is_null = is_null;
params[5].num = 10;
params[6].buffer_type = TSDB_DATA_TYPE_FLOAT;
params[6].buffer_length = sizeof(v.f4[0]);
params[6].buffer = v.f4;
params[6].length = float_len;
params[6].is_null = is_null;
params[6].num = 10;
params[7].buffer_type = TSDB_DATA_TYPE_DOUBLE;
params[7].buffer_length = sizeof(v.f8[0]);
params[7].buffer = v.f8;
params[7].length = double_len;
params[7].is_null = is_null;
params[7].num = 10;
params[8].buffer_type = TSDB_DATA_TYPE_BINARY;
params[8].buffer_length = sizeof(v.bin[0]);
params[8].buffer = v.bin;
params[8].length = bin_len;
params[8].is_null = is_null;
params[8].num = 10;
params[9].buffer_type = TSDB_DATA_TYPE_NCHAR;
params[9].buffer_length = sizeof(v.blob[0]);
params[9].buffer = v.blob;
params[9].length = blob_len;
params[9].is_null = is_null;
params[9].num = 10;
params[10].buffer_type = TSDB_DATA_TYPE_UTINYINT;
params[10].buffer_length = sizeof(v.u1[0]);
params[10].buffer = v.u1;
params[10].length = u8_len;
params[10].is_null = is_null;
params[10].num = 10;
params[11].buffer_type = TSDB_DATA_TYPE_USMALLINT;
params[11].buffer_length = sizeof(v.u2[0]);
params[11].buffer = v.u2;
params[11].length = u16_len;
params[11].is_null = is_null;
params[11].num = 10;
params[12].buffer_type = TSDB_DATA_TYPE_UINT;
params[12].buffer_length = sizeof(v.u4[0]);
params[12].buffer = v.u4;
params[12].length = u32_len;
params[12].is_null = is_null;
params[12].num = 10;
params[13].buffer_type = TSDB_DATA_TYPE_UBIGINT;
params[13].buffer_length = sizeof(v.u8[0]);
params[13].buffer = v.u8;
params[13].length = u64_len;
params[13].is_null = is_null;
params[13].num = 10;
// verify table names for upper/lower case
#define VERIFY_CNT 5
typedef struct {
char setTbName[20];
char showName[20];
char describeName[20];
char queryName[20];
char dropName[20];
} STbNames;
/**
* @brief
* 0 - success expected
* NonZero - fail expected
*/
typedef struct {
int32_t setTbName;
int32_t showName;
int32_t describeName;
int32_t queryName;
int32_t dropName;
} STbNamesResult;
STbNames tbName[VERIFY_CNT] = {0};
STbNamesResult tbNameResult[VERIFY_CNT] = {0};
STbNames* pTbName = NULL;
STbNamesResult* pTbNameResult = NULL;
pTbName = &tbName[0];
pTbNameResult = &tbNameResult[0];
strcpy(pTbName->setTbName, "Mn1");
strcpy(pTbName->showName, "mn1");
strcpy(pTbName->describeName, "mn1");
strcpy(pTbName->queryName, "mn1");
strcpy(pTbName->dropName, "mn1");
pTbName = &tbName[1];
pTbNameResult = &tbNameResult[1];
strcpy(pTbName->setTbName, "'Mn1'");
strcpy(pTbName->showName, "'mn1'");
strcpy(pTbName->describeName, "'mn1'");
strcpy(pTbName->queryName, "'mn1'");
strcpy(pTbName->dropName, "'mn1'");
pTbName = &tbName[2];
pTbNameResult = &tbNameResult[2];
strcpy(pTbName->setTbName, "\"Mn1\"");
strcpy(pTbName->showName, "\"mn1\"");
strcpy(pTbName->describeName, "\"mn1\"");
strcpy(pTbName->queryName, "\"mn1\"");
strcpy(pTbName->dropName, "\"mn1\"");
pTbName = &tbName[3];
pTbNameResult = &tbNameResult[3];
strcpy(pTbName->setTbName, "\"Mn1\"");
strcpy(pTbName->showName, "'mn1'");
strcpy(pTbName->describeName, "'mn1'");
strcpy(pTbName->queryName, "mn1");
strcpy(pTbName->dropName, "\"mn1\"");
pTbName = &tbName[4];
pTbNameResult = &tbNameResult[4];
strcpy(pTbName->setTbName, "`Mn1`");
strcpy(pTbName->showName, "Mn1"); // TODO support uniform of ``
strcpy(pTbName->describeName, "`Mn1`");
strcpy(pTbName->queryName, "`Mn1`");
strcpy(pTbName->dropName, "`Mn1`");
TAOS_STMT* stmt = NULL;
for (int n = 0; n < VERIFY_CNT; ++n) {
printf("\033[31m[%d] ===================================\033[0m\n", n);
pTbName = &tbName[n];
pTbNameResult = &tbNameResult[n];
char tmpStr[256] = {0};
// set table name
stmt = taos_stmt_init(taos);
if (!stmt) {
printf("\033[31m[%d] failed to execute taos_stmt_init. error:%s\033[0m\n", n);
exit(EXIT_FAILURE);
}
sql = "insert into ? using st1 tags(?,?,?,?,?,?,?,?,?,?,?,?,?) values(?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
code = taos_stmt_prepare(stmt, sql, 0);
if (code != 0) {
printf("\033[31mfailed to execute taos_stmt_prepare. error:%s\033[0m\n", taos_stmt_errstr(stmt));
taos_stmt_close(stmt);
exit(EXIT_FAILURE);
}
printf("[%d] taos_stmt_set_tbname_tags, tbname=%s\n", n, pTbName->setTbName);
code = taos_stmt_set_tbname_tags(stmt, pTbName->setTbName, tags);
if ((!pTbNameResult->setTbName && (0 != code)) || (pTbNameResult->setTbName && (0 == code))) {
printf("\033[31m[%d] failed to execute taos_stmt_set_tbname_tags. error:%s\033[0m\n", n, taos_stmt_errstr(stmt));
taos_stmt_close(stmt);
exit(EXIT_FAILURE);
}
if (code == 0) {
int64_t ts = 1591060628000 + 1000 * n;
for (int i = 0; i < 10; ++i) {
v.ts[i] = ts++;
is_null[i] = 0;
v.b[i] = (int8_t)i % 2;
v.v1[i] = (int8_t)i;
v.v2[i] = (int16_t)(i * 2);
v.v4[i] = (int32_t)(i * 4);
v.v8[i] = (int64_t)(i * 8);
v.f4[i] = (float)(i * 40);
v.f8[i] = (double)(i * 80);
for (int j = 0; j < sizeof(v.bin[0]); ++j) {
v.bin[i][j] = (char)(i + '0');
}
strcpy(v.blob[i], "一二三四五六七八九十");
v.u1[i] = (uint8_t)i;
v.u2[i] = (uint16_t)(i * 2);
v.u4[i] = (uint32_t)(i * 4);
v.u8[i] = (uint64_t)(i * 8);
t8_len[i] = sizeof(int8_t);
t16_len[i] = sizeof(int16_t);
t32_len[i] = sizeof(int32_t);
t64_len[i] = sizeof(int64_t);
float_len[i] = sizeof(float);
double_len[i] = sizeof(double);
bin_len[i] = sizeof(v.bin[0]);
blob_len[i] = (int32_t)strlen(v.blob[i]);
u8_len[i] = sizeof(uint8_t);
u16_len[i] = sizeof(uint16_t);
u32_len[i] = sizeof(uint32_t);
u64_len[i] = sizeof(uint64_t);
}
taos_stmt_bind_param_batch(stmt, params);
taos_stmt_add_batch(stmt);
if (taos_stmt_execute(stmt) != 0) {
printf("\033[31m[%d] failed to execute insert statement.error:%s\033[0m\n", n, taos_stmt_errstr(stmt));
taos_stmt_close(stmt);
exit(EXIT_FAILURE);
}
}
taos_stmt_close(stmt);
// show the table
printf("[%d] show tables, tbName = %s\n", n, pTbName->showName);
stmt = taos_stmt_init(taos);
sprintf(tmpStr, "show tables like %s", pTbName->showName);
taos_stmt_prepare(stmt, tmpStr, 0);
code = taos_stmt_execute(stmt);
if ((!pTbNameResult->showName && (0 != code)) || (pTbNameResult->showName && (0 == code))) {
printf("\033[31m[%d] failed to execute show tables like. error:%s\033[0m\n", n, taos_stmt_errstr(stmt));
taos_stmt_close(stmt);
exit(EXIT_FAILURE);
}
taos_stmt_close(stmt);
// describe the table
printf("[%d] describe tables, tbName = %s\n", n, pTbName->describeName);
stmt = taos_stmt_init(taos);
sprintf(tmpStr, "describe %s", pTbName->describeName);
taos_stmt_prepare(stmt, tmpStr, 0);
code = taos_stmt_execute(stmt);
if ((!pTbNameResult->describeName && (0 != code)) || (pTbNameResult->describeName && (0 == code))) {
printf("\033[31m[%d] failed to execute describe tables. error:%s\033[0m\n", n, taos_stmt_errstr(stmt));
taos_stmt_close(stmt);
exit(EXIT_FAILURE);
}
taos_stmt_close(stmt);
// query the records
printf("[%d] select statement, tbName = %s\n", n, pTbName->queryName);
stmt = taos_stmt_init(taos);
sprintf(tmpStr, "SELECT * FROM %s", pTbName->queryName);
taos_stmt_prepare(stmt, tmpStr, 0);
TAOS_BIND qparams[2];
int8_t v1 = 5;
int16_t v2 = 15;
qparams[0].buffer_type = TSDB_DATA_TYPE_TINYINT;
qparams[0].buffer_length = sizeof(v1);
qparams[0].buffer = &v1;
qparams[0].length = &qparams[0].buffer_length;
qparams[0].is_null = NULL;
qparams[1].buffer_type = TSDB_DATA_TYPE_SMALLINT;
qparams[1].buffer_length = sizeof(v2);
qparams[1].buffer = &v2;
qparams[1].length = &qparams[1].buffer_length;
qparams[1].is_null = NULL;
taos_stmt_bind_param(stmt, qparams);
code = taos_stmt_execute(stmt);
if ((!pTbNameResult->queryName && (0 != code)) || (pTbNameResult->queryName && (0 == code))) {
printf("\033[31m[%d] failed to execute select statement.error:%s\033[0m\n", n, taos_stmt_errstr(stmt));
taos_stmt_close(stmt);
exit(EXIT_FAILURE);
}
result = taos_stmt_use_result(stmt);
TAOS_ROW row;
int rows = 0;
int num_fields = taos_num_fields(result);
TAOS_FIELD* fields = taos_fetch_fields(result);
// fetch the records row by row
while ((row = taos_fetch_row(result))) {
char temp[256] = {0};
rows++;
taos_print_row(temp, row, fields, num_fields);
printf("[%d] row = %s\n", n, temp);
}
taos_free_result(result);
taos_stmt_close(stmt);
// drop table
printf("[%d] drop table, tbName = %s\n", n, pTbName->dropName);
stmt = taos_stmt_init(taos);
sprintf(tmpStr, "drop table %s", pTbName->dropName);
taos_stmt_prepare(stmt, tmpStr, 0);
code = taos_stmt_execute(stmt);
if ((!pTbNameResult->dropName && (0 != code)) || (pTbNameResult->dropName && (0 == code))) {
printf("\033[31m[%d] failed to drop table. error:%s\033[0m\n", n, taos_stmt_errstr(stmt));
taos_stmt_close(stmt);
exit(EXIT_FAILURE);
}
taos_stmt_close(stmt);
}
free(t8_len);
free(t16_len);
free(t32_len);
free(t64_len);
free(float_len);
free(double_len);
free(bin_len);
free(blob_len);
free(u8_len);
free(u16_len);
free(u32_len);
free(u64_len);
}
int main(int argc, char* argv[]) {
const char* host = "127.0.0.1";
const char* user = "root";
const char* passwd = "taosdata";
taos_options(TSDB_OPTION_TIMEZONE, "GMT-8");
TAOS* taos = taos_connect(host, user, passwd, "", 0);
if (taos == NULL) {
printf("\033[31mfailed to connect to db, reason:%s\033[0m\n", taos_errstr(taos));
exit(1);
}
char* info = taos_get_server_info(taos);
printf("server info: %s\n", info);
info = taos_get_client_info(taos);
printf("client info: %s\n", info);
printf("************ verify prepare *************\n");
verify_prepare(taos);
printf("************ verify prepare2 *************\n");
verify_prepare2(taos);
printf("************ verify prepare3 *************\n");
verify_prepare3(taos);
printf("************ verify prepare4 *************\n");
verify_prepare4(taos);
printf("************ verify end *************\n");
exit(EXIT_SUCCESS);
}
#include "os.h"
#include "taos.h"
#include "taoserror.h"
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
bool verbose = false;
void printThreadId(pthread_t id, char* buf)
{
size_t i;
for (i = sizeof(i); i; --i)
sprintf(buf + strlen(buf), "%02x", *(((unsigned char*) &id) + i - 1));
}
static int64_t getTimeInUs() {
struct timeval systemTime;
gettimeofday(&systemTime, NULL);
return (int64_t)systemTime.tv_sec * 1000000L + (int64_t)systemTime.tv_usec;
}
typedef struct {
char** lines;
int numLines;
} SThreadLinesBatch;
typedef struct {
TAOS* taos;
int protocol;
int numBatches;
SThreadLinesBatch *batches;
int64_t costTime;
} SThreadInsertArgs;
static void* insertLines(void* args) {
SThreadInsertArgs* insertArgs = (SThreadInsertArgs*) args;
char tidBuf[32] = {0};
printThreadId(pthread_self(), tidBuf);
for (int i = 0; i < insertArgs->numBatches; ++i) {
SThreadLinesBatch* batch = insertArgs->batches + i;
if (verbose) printf("%s, thread: 0x%s\n", "begin taos_insert_lines", tidBuf);
int64_t begin = getTimeInUs();
//int32_t code = taos_insert_lines(insertArgs->taos, batch->lines, batch->numLines);
TAOS_RES * res = taos_schemaless_insert(insertArgs->taos, batch->lines, batch->numLines, insertArgs->protocol, TSDB_SML_TIMESTAMP_MILLI_SECONDS);
int32_t code = taos_errno(res);
int64_t end = getTimeInUs();
insertArgs->costTime += end - begin;
if (verbose) printf("code: %d, %s. time used:%"PRId64", thread: 0x%s\n", code, tstrerror(code), end - begin, tidBuf);
}
return NULL;
}
int32_t getTelenetTemplate(char* lineTemplate, int templateLen) {
char* sample = "sta%d %lld 44.3 t0=False t1=127i8 t2=32 t3=%di32 t4=9223372036854775807i64 t5=11.12345f32 t6=22.123456789f64 t7=\"hpxzrdiw\" t8=\"ncharTagValue\" t9=127i8";
snprintf(lineTemplate, templateLen, "%s", sample);
return 0;
}
int32_t getLineTemplate(char* lineTemplate, int templateLen, int numFields) {
if (numFields <= 4) {
char* sample = "sta%d,t3=%di32 c3=2147483647i32,c4=9223372036854775807i64,c9=11.12345f32,c10=22.123456789f64 %lld";
snprintf(lineTemplate, templateLen, "%s", sample);
return 0;
}
if (numFields <= 13) {
char* sample = "sta%d,t0=true,t1=127i8,t2=32767i16,t3=%di32,t4=9223372036854775807i64,t9=11.12345f32,t10=22.123456789f64,t11=\"binaryTagValue\",t12=L\"ncharTagValue\" c0=true,c1=127i8,c2=32767i16,c3=2147483647i32,c4=9223372036854775807i64,c5=254u8,c6=32770u16,c7=2147483699u32,c8=9223372036854775899u64,c9=11.12345f32,c10=22.123456789f64,c11=\"binaryValue\",c12=L\"ncharValue\" %lld";
snprintf(lineTemplate, templateLen, "%s", sample);
return 0;
}
char* lineFormatTable = "sta%d,t0=true,t1=127i8,t2=32767i16,t3=%di32 ";
snprintf(lineTemplate+strlen(lineTemplate), templateLen-strlen(lineTemplate), "%s", lineFormatTable);
int offset[] = {numFields*2/5, numFields*4/5, numFields};
for (int i = 0; i < offset[0]; ++i) {
snprintf(lineTemplate+strlen(lineTemplate), templateLen-strlen(lineTemplate), "c%d=%di32,", i, i);
}
for (int i=offset[0]+1; i < offset[1]; ++i) {
snprintf(lineTemplate+strlen(lineTemplate), templateLen-strlen(lineTemplate), "c%d=%d.43f64,", i, i);
}
for (int i = offset[1]+1; i < offset[2]; ++i) {
snprintf(lineTemplate+strlen(lineTemplate), templateLen-strlen(lineTemplate), "c%d=\"%d\",", i, i);
}
char* lineFormatTs = " %lld";
snprintf(lineTemplate+strlen(lineTemplate)-1, templateLen-strlen(lineTemplate)+1, "%s", lineFormatTs);
return 0;
}
int32_t generateLine(char* line, int lineLen, char* lineTemplate, int protocol, int superTable, int childTable, int64_t ts) {
if (protocol == TSDB_SML_LINE_PROTOCOL) {
snprintf(line, lineLen, lineTemplate, superTable, childTable, ts);
} else if (protocol == TSDB_SML_TELNET_PROTOCOL) {
snprintf(line, lineLen, lineTemplate, superTable, ts, childTable);
}
return TSDB_CODE_SUCCESS;
}
int32_t setupSuperTables(TAOS* taos, char* lineTemplate, int protocol,
int numSuperTables, int numChildTables, int numRowsPerChildTable,
int maxBatchesPerThread, int64_t ts) {
printf("setup supertables...");
{
char** linesStb = calloc(numSuperTables, sizeof(char*));
for (int i = 0; i < numSuperTables; i++) {
char* lineStb = calloc(strlen(lineTemplate)+128, 1);
generateLine(lineStb, strlen(lineTemplate)+128, lineTemplate, protocol, i,
numSuperTables * numChildTables,
ts + numSuperTables * numChildTables * numRowsPerChildTable);
linesStb[i] = lineStb;
}
SThreadInsertArgs args = {0};
args.protocol = protocol;
args.batches = calloc(maxBatchesPerThread, sizeof(maxBatchesPerThread));
args.taos = taos;
args.batches[0].lines = linesStb;
args.batches[0].numLines = numSuperTables;
insertLines(&args);
free(args.batches);
for (int i = 0; i < numSuperTables; ++i) {
free(linesStb[i]);
}
free(linesStb);
}
return TSDB_CODE_SUCCESS;
}
int main(int argc, char* argv[]) {
int numThreads = 8;
int maxBatchesPerThread = 1024;
int numSuperTables = 1;
int numChildTables = 256;
int numRowsPerChildTable = 8192;
int numFields = 13;
int maxLinesPerBatch = 16384;
int protocol = TSDB_SML_TELNET_PROTOCOL;
int assembleSTables = 0;
int opt;
while ((opt = getopt(argc, argv, "s:c:r:f:t:b:p:w:hv")) != -1) {
switch (opt) {
case 's':
numSuperTables = atoi(optarg);
break;
case 'c':
numChildTables = atoi(optarg);
break;
case 'r':
numRowsPerChildTable = atoi(optarg);
break;
case 'f':
numFields = atoi(optarg);
break;
case 't':
numThreads = atoi(optarg);
break;
case 'b':
maxLinesPerBatch = atoi(optarg);
break;
case 'v':
verbose = true;
break;
case 'a':
assembleSTables = atoi(optarg);
break;
case 'p':
if (optarg[0] == 't') {
protocol = TSDB_SML_TELNET_PROTOCOL;
} else if (optarg[0] == 'l') {
protocol = TSDB_SML_LINE_PROTOCOL;
} else if (optarg[0] == 'j') {
protocol = TSDB_SML_JSON_PROTOCOL;
}
break;
case 'h':
fprintf(stderr, "Usage: %s -s supertable -c childtable -r rows -f fields -t threads -b maxlines_per_batch -p [t|l|j] -a assemble-stables -v\n",
argv[0]);
exit(0);
default: /* '?' */
fprintf(stderr, "Usage: %s -s supertable -c childtable -r rows -f fields -t threads -b maxlines_per_batch -p [t|l|j] -a assemble-stables -v\n",
argv[0]);
exit(-1);
}
}
TAOS_RES* result;
//const char* host = "127.0.0.1";
const char* host = NULL;
const char* user = "root";
const char* passwd = "taosdata";
taos_options(TSDB_OPTION_TIMEZONE, "GMT-8");
TAOS* taos = taos_connect(host, user, passwd, "", 0);
if (taos == NULL) {
printf("\033[31mfailed to connect to db, reason:%s\033[0m\n", taos_errstr(taos));
exit(1);
}
maxBatchesPerThread = (numSuperTables*numChildTables*numRowsPerChildTable)/(numThreads * maxLinesPerBatch) + 1;
char* info = taos_get_server_info(taos);
printf("server info: %s\n", info);
info = taos_get_client_info(taos);
printf("client info: %s\n", info);
result = taos_query(taos, "drop database if exists db;");
taos_free_result(result);
usleep(100000);
result = taos_query(taos, "create database db precision 'us';");
taos_free_result(result);
usleep(100000);
(void)taos_select_db(taos, "db");
time_t ct = time(0);
int64_t ts = ct * 1000 ;
char* lineTemplate = calloc(65536, sizeof(char));
if (protocol == TSDB_SML_LINE_PROTOCOL) {
getLineTemplate(lineTemplate, 65535, numFields);
} else if (protocol == TSDB_SML_TELNET_PROTOCOL ) {
getTelenetTemplate(lineTemplate, 65535);
}
if (assembleSTables) {
setupSuperTables(taos, lineTemplate, protocol,
numSuperTables, numChildTables, numRowsPerChildTable, maxBatchesPerThread, ts);
}
printf("generate lines...\n");
pthread_t* tids = calloc(numThreads, sizeof(pthread_t));
SThreadInsertArgs* argsThread = calloc(numThreads, sizeof(SThreadInsertArgs));
for (int i = 0; i < numThreads; ++i) {
argsThread[i].batches = calloc(maxBatchesPerThread, sizeof(SThreadLinesBatch));
argsThread[i].taos = taos;
argsThread[i].numBatches = 0;
argsThread[i].protocol = protocol;
}
int64_t totalLines = numSuperTables * numChildTables * numRowsPerChildTable;
int totalBatches = (int) ((totalLines) / maxLinesPerBatch);
if (totalLines % maxLinesPerBatch != 0) {
totalBatches += 1;
}
char*** allBatches = calloc(totalBatches, sizeof(char**));
for (int i = 0; i < totalBatches; ++i) {
allBatches[i] = calloc(maxLinesPerBatch, sizeof(char*));
int threadNo = i % numThreads;
int batchNo = i / numThreads;
argsThread[threadNo].batches[batchNo].lines = allBatches[i];
argsThread[threadNo].numBatches = batchNo + 1;
}
int l = 0;
for (int i = 0; i < numSuperTables; ++i) {
for (int j = 0; j < numChildTables; ++j) {
for (int k = 0; k < numRowsPerChildTable; ++k) {
int stIdx = i;
int ctIdx = numSuperTables*numChildTables + j;
char* line = calloc(strlen(lineTemplate)+128, 1);
generateLine(line, strlen(lineTemplate)+128, lineTemplate, protocol, stIdx, ctIdx, ts + l);
int batchNo = l / maxLinesPerBatch;
int lineNo = l % maxLinesPerBatch;
allBatches[batchNo][lineNo] = line;
argsThread[batchNo % numThreads].batches[batchNo/numThreads].numLines = lineNo + 1;
++l;
}
}
}
printf("begin multi-thread insertion...\n");
int64_t begin = taosGetTimestampUs();
for (int i=0; i < numThreads; ++i) {
pthread_create(tids+i, NULL, insertLines, argsThread+i);
}
for (int i = 0; i < numThreads; ++i) {
pthread_join(tids[i], NULL);
}
int64_t end = taosGetTimestampUs();
size_t linesNum = numSuperTables*numChildTables*numRowsPerChildTable;
printf("TOTAL LINES: %zu\n", linesNum);
printf("THREADS: %d\n", numThreads);
printf("TIME: %d(ms)\n", (int)(end-begin)/1000);
double throughput = (double)(totalLines)/(double)(end-begin) * 1000000;
printf("THROUGHPUT:%d/s\n", (int)throughput);
for (int i = 0; i < totalBatches; ++i) {
free(allBatches[i]);
}
free(allBatches);
for (int i = 0; i < numThreads; i++) {
free(argsThread[i].batches);
}
free(argsThread);
free(tids);
free(lineTemplate);
taos_close(taos);
return 0;
}
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "taos.h" // TAOS header file
#include "taoserror.h"
#include "os.h"
bool verbose = false;
bool describeTableFirst = false;
typedef struct{
TAOS* taos;
int numThreads;
int threadId;
int numSTables;
} SThreadArgs;
static int executeSql(TAOS *taos, char *command) {
if (verbose) {
printf("sql: %s\n", command);
}
TAOS_RES *pSql = NULL;
int32_t code = TSDB_CODE_SUCCESS;
pSql = taos_query(taos, command);
code = taos_errno(pSql);
if (code != 0) {
if (verbose) fprintf(stderr, "Failed to run %s, reason: %s\n", command, taos_errstr(pSql));
taos_free_result(pSql);
return code;
}
taos_free_result(pSql);
return 0;
}
void* threadFunc(void* args) {
char* sqlDescribeSTable = "describe st%d";
char* sqlCreateSTable = "create table st%d (ts timestamp, value double) "
"tags(t0 nchar(20), t1 nchar(20), t2 nchar(20), t3 nchar(20), t4 nchar(20), "
"t5 nchar(20), t6 nchar(20), t7 nchar(20), t8 nchar(20), t9 nchar(20))";
char* sqlInsertData = "insert into t%d using st%d tags('t%d', 't%d', 't%d', 't%d', 't%d', 't%d', 't%d', 't%d', 't%d', 't%d') values(%lld, %d.%d)";
SThreadArgs* param = args;
int interval = param->numSTables/param->numThreads;
if (param->numSTables % param->numThreads != 0) {
++interval;
}
int start = param->threadId*interval;
int end = (param->threadId+1)*interval > param->numSTables ? param->numSTables : (param->threadId+1)*interval;
int r = rand();
for (int i = start; i < end; ++i) {
int tableId = i;
char sql0[1024] = {0};
char sql1[1024] = {0};
char sql2[1024] = {0};
sprintf(sql0, sqlDescribeSTable, tableId);
sprintf(sql1, sqlCreateSTable, tableId);
time_t ct = time(0);
int64_t ts = ct * 1000;
sprintf(sql2, sqlInsertData, tableId, tableId, r, r, r, r, r, r, r, r, r, r, ts + tableId, r, r);
if (describeTableFirst) {
executeSql(param->taos, sql0);
}
executeSql(param->taos, sql1);
executeSql(param->taos, sql2);
}
return NULL;
}
int main(int argc, char *argv[]) {
int numSTables = 20000;
int numThreads = 32;
int opt;
while ((opt = getopt(argc, argv, "s:t:fvh")) != -1) {
switch (opt) {
case 's':
numSTables = atoi(optarg);
break;
case 't':
numThreads = atoi(optarg);
break;
case 'f':
describeTableFirst = true;
break;
case 'v':
verbose = true;
break;
case 'h':
fprintf(stderr, "Usage: %s -s supertable -t thread -FirstDescribeSTable -Verbose\n", argv[0]);
exit(0);
default:
fprintf(stderr, "Usage: %s -s supertable -t thread -FirstDescribeSTable -Verbose\n", argv[0]);
exit(-1);
}
}
// connect to server
TAOS *taos = taos_connect(NULL, "root", "taosdata", NULL, 0);
if (taos == NULL) {
printf("failed to connect to server, reason:%s\n", "null taos" /*taos_errstr(taos)*/);
exit(1);
}
executeSql(taos, "drop database if exists sqlsml");
executeSql(taos, "create database sqlsml");
executeSql(taos, "use sqlsml");
pthread_t* tids = calloc(numThreads, sizeof(pthread_t));
SThreadArgs* threadArgs = calloc(numThreads, sizeof(SThreadArgs));
for (int i = 0; i < numThreads; ++i) {
threadArgs[i].numSTables = numSTables;
threadArgs[i].numThreads = numThreads;
threadArgs[i].threadId = i;
threadArgs[i].taos = taos;
}
int64_t begin = taosGetTimestampUs();
for (int i = 0; i < numThreads; ++i) {
pthread_create(tids+i, NULL, threadFunc, threadArgs+i);
}
for (int i = 0; i < numThreads; ++i) {
pthread_join(tids[i], NULL);
}
int64_t end = taosGetTimestampUs();
printf("TIME: %d(ms)\n", (int)((end-begin)/1000));
printf("THROUGHPUT: %d\n", (int)((numSTables * 1e6) / (end-begin)));
free(threadArgs);
free(tids);
taos_close(taos);
taos_cleanup();
}
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <taos.h> // include TDengine header file
#include <unistd.h>
typedef struct {
char server_ip[64];
char db_name[64];
char tbl_name[64];
} param;
int g_thread_exit_flag = 0;
void *insert_rows(void *sarg);
void streamCallBack(void *param, TAOS_RES *res, TAOS_ROW row) {
// in this simple demo, it just print out the result
char temp[128];
TAOS_FIELD *fields = taos_fetch_fields(res);
int numFields = taos_num_fields(res);
taos_print_row(temp, row, fields, numFields);
printf("\n%s\n", temp);
}
int main(int argc, char *argv[]) {
TAOS *taos;
char db_name[64];
char tbl_name[64];
char sql[1024] = {0};
if (argc != 4) {
printf("usage: %s server-ip dbname tblname\n", argv[0]);
exit(0);
}
strcpy(db_name, argv[2]);
strcpy(tbl_name, argv[3]);
// create pthread to insert into row per second for stream calc
param *t_param = (param *)malloc(sizeof(param));
if (NULL == t_param) {
printf("failed to malloc\n");
exit(1);
}
memset(t_param, 0, sizeof(param));
strcpy(t_param->server_ip, argv[1]);
strcpy(t_param->db_name, db_name);
strcpy(t_param->tbl_name, tbl_name);
pthread_t pid;
pthread_create(&pid, NULL, (void *(*)(void *))insert_rows, t_param);
sleep(3); // waiting for database is created.
// open connection to database
taos = taos_connect(argv[1], "root", "taosdata", db_name, 0);
if (taos == NULL) {
printf("failed to connet to server:%s\n", argv[1]);
free(t_param);
exit(1);
}
// starting stream calc,
printf("please input stream SQL:[e.g., select count(*) from tblname interval(5s) sliding(2s);]\n");
fgets(sql, sizeof(sql), stdin);
if (sql[0] == 0) {
printf("input NULL stream SQL, so exit!\n");
free(t_param);
exit(1);
}
// param is set to NULL in this demo, it shall be set to the pointer to app context
TAOS_STREAM *pStream = taos_open_stream(taos, sql, streamCallBack, 0, NULL, NULL);
if (NULL == pStream) {
printf("failed to create stream\n");
free(t_param);
exit(1);
}
printf("press any key to exit\n");
getchar();
taos_close_stream(pStream);
g_thread_exit_flag = 1;
pthread_join(pid, NULL);
taos_close(taos);
free(t_param);
return 0;
}
void *insert_rows(void *sarg) {
TAOS * taos;
char command[1024] = {0};
param *winfo = (param *)sarg;
if (NULL == winfo) {
printf("para is null!\n");
exit(1);
}
taos = taos_connect(winfo->server_ip, "root", "taosdata", NULL, 0);
if (taos == NULL) {
printf("failed to connet to server:%s\n", winfo->server_ip);
exit(1);
}
// drop database
sprintf(command, "drop database %s;", winfo->db_name);
if (taos_query(taos, command) != 0) {
printf("failed to drop database, reason:%s\n", taos_errstr(taos));
exit(1);
}
// create database
sprintf(command, "create database %s;", winfo->db_name);
if (taos_query(taos, command) != 0) {
printf("failed to create database, reason:%s\n", taos_errstr(taos));
exit(1);
}
// use database
sprintf(command, "use %s;", winfo->db_name);
if (taos_query(taos, command) != 0) {
printf("failed to use database, reason:%s\n", taos_errstr(taos));
exit(1);
}
// create table
sprintf(command, "create table %s (ts timestamp, speed int);", winfo->tbl_name);
if (taos_query(taos, command) != 0) {
printf("failed to create table, reason:%s\n", taos_errstr(taos));
exit(1);
}
// insert data
int64_t begin = (int64_t)time(NULL);
int index = 0;
while (1) {
if (g_thread_exit_flag) break;
index++;
sprintf(command, "insert into %s values (%ld, %d)", winfo->tbl_name, (begin + index) * 1000, index);
if (taos_query(taos, command)) {
printf("failed to insert row [%s], reason:%s\n", command, taos_errstr(taos));
}
sleep(1);
}
taos_close(taos);
return 0;
}
// sample code for TDengine subscribe/consume API
// to compile: gcc -o subscribe subscribe.c -ltaos
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <taos.h> // include TDengine header file
#include <unistd.h>
int nTotalRows;
void print_result(TAOS_RES* res, int blockFetch) {
TAOS_ROW row = NULL;
int num_fields = taos_num_fields(res);
TAOS_FIELD* fields = taos_fetch_fields(res);
int nRows = 0;
if (blockFetch) {
nRows = taos_fetch_block(res, &row);
// for (int i = 0; i < nRows; i++) {
// taos_print_row(buf, row + i, fields, num_fields);
// puts(buf);
//}
} else {
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);
}
void subscribe_callback(TAOS_SUB* tsub, TAOS_RES* res, void* param, int code) { print_result(res, *(int*)param); }
void check_row_count(int line, TAOS_RES* res, int expected) {
int actual = 0;
TAOS_ROW row;
while ((row = taos_fetch_row(res))) {
actual++;
}
if (actual != expected) {
printf("line %d: row count mismatch, expected: %d, actual: %d\n", line, expected, actual);
} else {
printf("line %d: %d rows consumed as expected\n", line, actual);
}
}
void do_query(TAOS* taos, const char* sql) {
TAOS_RES* res = taos_query(taos, sql);
taos_free_result(res);
}
void run_test(TAOS* taos) {
do_query(taos, "drop database if exists test;");
usleep(100000);
do_query(taos, "create database test;");
usleep(100000);
do_query(taos, "use test;");
usleep(100000);
do_query(taos, "create table meters(ts timestamp, a int) tags(area int);");
do_query(taos, "create table t0 using meters tags(0);");
do_query(taos, "create table t1 using meters tags(1);");
do_query(taos, "create table t2 using meters tags(2);");
do_query(taos, "create table t3 using meters tags(3);");
do_query(taos, "create table t4 using meters tags(4);");
do_query(taos, "create table t5 using meters tags(5);");
do_query(taos, "create table t6 using meters tags(6);");
do_query(taos, "create table t7 using meters tags(7);");
do_query(taos, "create table t8 using meters tags(8);");
do_query(taos, "create table t9 using meters tags(9);");
do_query(taos, "insert into t0 values('2020-01-01 00:00:00.000', 0);");
do_query(taos, "insert into t0 values('2020-01-01 00:01:00.000', 0);");
do_query(taos, "insert into t0 values('2020-01-01 00:02:00.000', 0);");
do_query(taos, "insert into t1 values('2020-01-01 00:00:00.000', 0);");
do_query(taos, "insert into t1 values('2020-01-01 00:01:00.000', 0);");
do_query(taos, "insert into t1 values('2020-01-01 00:02:00.000', 0);");
do_query(taos, "insert into t1 values('2020-01-01 00:03:00.000', 0);");
do_query(taos, "insert into t2 values('2020-01-01 00:00:00.000', 0);");
do_query(taos, "insert into t2 values('2020-01-01 00:01:00.000', 0);");
do_query(taos, "insert into t2 values('2020-01-01 00:01:01.000', 0);");
do_query(taos, "insert into t2 values('2020-01-01 00:01:02.000', 0);");
do_query(taos, "insert into t3 values('2020-01-01 00:01:02.000', 0);");
do_query(taos, "insert into t4 values('2020-01-01 00:01:02.000', 0);");
do_query(taos, "insert into t5 values('2020-01-01 00:01:02.000', 0);");
do_query(taos, "insert into t6 values('2020-01-01 00:01:02.000', 0);");
do_query(taos, "insert into t7 values('2020-01-01 00:01:02.000', 0);");
do_query(taos, "insert into t8 values('2020-01-01 00:01:02.000', 0);");
do_query(taos, "insert into t9 values('2020-01-01 00:01:02.000', 0);");
// super tables subscription
usleep(1000000);
TAOS_SUB* tsub = taos_subscribe(taos, 0, "test", "select * from meters;", NULL, NULL, 0);
TAOS_RES* res = taos_consume(tsub);
check_row_count(__LINE__, res, 18);
res = taos_consume(tsub);
check_row_count(__LINE__, res, 0);
do_query(taos, "insert into t0 values('2020-01-01 00:02:00.001', 0);");
do_query(taos, "insert into t8 values('2020-01-01 00:01:03.000', 0);");
res = taos_consume(tsub);
check_row_count(__LINE__, res, 2);
do_query(taos, "insert into t2 values('2020-01-01 00:01:02.001', 0);");
do_query(taos, "insert into t1 values('2020-01-01 00:03:00.001', 0);");
res = taos_consume(tsub);
check_row_count(__LINE__, res, 2);
do_query(taos, "insert into t1 values('2020-01-01 00:03:00.002', 0);");
res = taos_consume(tsub);
check_row_count(__LINE__, res, 1);
// keep progress information and restart subscription
taos_unsubscribe(tsub, 1);
do_query(taos, "insert into t0 values('2020-01-01 00:04:00.000', 0);");
tsub = taos_subscribe(taos, 1, "test", "select * from meters;", NULL, NULL, 0);
res = taos_consume(tsub);
check_row_count(__LINE__, res, 24);
// keep progress information and continue previous subscription
taos_unsubscribe(tsub, 1);
tsub = taos_subscribe(taos, 0, "test", "select * from meters;", NULL, NULL, 0);
res = taos_consume(tsub);
check_row_count(__LINE__, res, 0);
// don't keep progress information and continue previous subscription
taos_unsubscribe(tsub, 0);
tsub = taos_subscribe(taos, 0, "test", "select * from meters;", NULL, NULL, 0);
res = taos_consume(tsub);
check_row_count(__LINE__, res, 24);
// single meter subscription
taos_unsubscribe(tsub, 0);
tsub = taos_subscribe(taos, 0, "test", "select * from t0;", NULL, NULL, 0);
res = taos_consume(tsub);
check_row_count(__LINE__, res, 5);
res = taos_consume(tsub);
check_row_count(__LINE__, res, 0);
do_query(taos, "insert into t0 values('2020-01-01 00:04:00.001', 0);");
res = taos_consume(tsub);
check_row_count(__LINE__, res, 1);
taos_unsubscribe(tsub, 0);
}
int main(int argc, char* argv[]) {
const char* host = "127.0.0.1";
const char* user = "root";
const char* passwd = "taosdata";
const char* sql = "select * from meters;";
const char* topic = "test-multiple";
int async = 1, restart = 0, keep = 1, test = 0, blockFetch = 0;
for (int i = 1; i < argc; i++) {
if (strncmp(argv[i], "-h=", 3) == 0) {
host = argv[i] + 3;
continue;
}
if (strncmp(argv[i], "-u=", 3) == 0) {
user = argv[i] + 3;
continue;
}
if (strncmp(argv[i], "-p=", 3) == 0) {
passwd = argv[i] + 3;
continue;
}
if (strcmp(argv[i], "-sync") == 0) {
async = 0;
continue;
}
if (strcmp(argv[i], "-restart") == 0) {
restart = 1;
continue;
}
if (strcmp(argv[i], "-single") == 0) {
sql = "select * from t0;";
topic = "test-single";
continue;
}
if (strcmp(argv[i], "-nokeep") == 0) {
keep = 0;
continue;
}
if (strncmp(argv[i], "-sql=", 5) == 0) {
sql = argv[i] + 5;
topic = "test-custom";
continue;
}
if (strcmp(argv[i], "-test") == 0) {
test = 1;
continue;
}
if (strcmp(argv[i], "-block-fetch") == 0) {
blockFetch = 1;
continue;
}
}
TAOS* taos = taos_connect(host, user, passwd, "", 0);
if (taos == NULL) {
printf("failed to connect to db, reason:%s\n", taos_errstr(taos));
exit(1);
}
if (test) {
run_test(taos);
taos_close(taos);
exit(0);
}
taos_select_db(taos, "test");
TAOS_SUB* tsub = NULL;
if (async) {
// create an asynchronized subscription, the callback function will be called every 1s
tsub = taos_subscribe(taos, restart, topic, sql, subscribe_callback, &blockFetch, 1000);
} else {
// create an synchronized subscription, need to call 'taos_consume' manually
tsub = taos_subscribe(taos, restart, topic, sql, NULL, NULL, 0);
}
if (tsub == NULL) {
printf("failed to create subscription.\n");
exit(0);
}
if (async) {
getchar();
} else
while (1) {
TAOS_RES* res = taos_consume(tsub);
if (res == NULL) {
printf("failed to consume data.");
break;
} else {
print_result(res, blockFetch);
getchar();
}
}
printf("total rows consumed: %d\n", nTotalRows);
taos_unsubscribe(tsub, keep);
taos_close(taos);
return 0;
}
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package main
import (
"database/sql"
"flag"
"fmt"
"log"
"math/rand"
"os"
"runtime"
"strconv"
"sync"
"time"
_ "github.com/taosdata/driver-go/taosSql"
)
const (
maxLocationSize = 32
//maxSqlBufSize = 65480
)
var locations = [maxLocationSize]string{
"Beijing", "Shanghai", "Guangzhou", "Shenzhen",
"HangZhou", "Tianjin", "Wuhan", "Changsha",
"Nanjing", "Xian"}
type config struct {
hostName string
serverPort int
user string
password string
dbName string
supTblName string
tablePrefix string
mode string
numOftables int
numOfRecordsPerTable int
numOfRecordsPerReq int
numOfThreads int
startTimestamp string
startTs int64
keep int
days int
}
var configPara config
var taosDriverName = "taosSql"
var url string
func init() {
flag.StringVar(&configPara.hostName, "h", "127.0.0.1", "The host to connect to TDengine server.")
flag.IntVar(&configPara.serverPort, "p", 6030, "The TCP/IP port number to use for the connection to TDengine server.")
flag.StringVar(&configPara.user, "u", "root", "The TDengine user name to use when connecting to the server.")
flag.StringVar(&configPara.password, "P", "taosdata", "The password to use when connecting to the server.")
flag.StringVar(&configPara.dbName, "d", "test", "Destination database.")
flag.StringVar(&configPara.tablePrefix, "m", "d", "Table prefix name.")
flag.StringVar(&configPara.mode, "M", "r", "mode,r:raw,s:stmt")
flag.IntVar(&configPara.numOftables, "t", 2, "The number of tables.")
flag.IntVar(&configPara.numOfRecordsPerTable, "n", 10, "The number of records per table.")
flag.IntVar(&configPara.numOfRecordsPerReq, "r", 3, "The number of records per request.")
flag.IntVar(&configPara.numOfThreads, "T", 1, "The number of threads.")
flag.StringVar(&configPara.startTimestamp, "s", "2020-10-01 08:00:00", "The start timestamp for one table.")
flag.Parse()
configPara.keep = 365 * 20
configPara.days = 30
configPara.supTblName = "meters"
startTs, err := time.ParseInLocation("2006-01-02 15:04:05", configPara.startTimestamp, time.Local)
if err == nil {
configPara.startTs = startTs.UnixNano() / 1e6
}
}
func printAllArgs() {
fmt.Printf("\n============= args parse result: =============\n")
fmt.Printf("hostName: %v\n", configPara.hostName)
fmt.Printf("serverPort: %v\n", configPara.serverPort)
fmt.Printf("usr: %v\n", configPara.user)
fmt.Printf("password: %v\n", configPara.password)
fmt.Printf("dbName: %v\n", configPara.dbName)
fmt.Printf("mode: %v\n", configPara.mode)
fmt.Printf("tablePrefix: %v\n", configPara.tablePrefix)
fmt.Printf("numOftables: %v\n", configPara.numOftables)
fmt.Printf("numOfRecordsPerTable: %v\n", configPara.numOfRecordsPerTable)
fmt.Printf("numOfRecordsPerReq: %v\n", configPara.numOfRecordsPerReq)
fmt.Printf("numOfThreads: %v\n", configPara.numOfThreads)
fmt.Printf("startTimestamp: %v[%v]\n", configPara.startTimestamp, configPara.startTs)
fmt.Printf("================================================\n")
}
func main() {
printAllArgs()
fmt.Printf("Please press enter key to continue....\n")
_, _ = fmt.Scanln()
url = "root:taosdata@/tcp(" + configPara.hostName + ":" + strconv.Itoa(configPara.serverPort) + ")/"
//url = fmt.Sprintf("%s:%s@/tcp(%s:%d)/%s?interpolateParams=true", configPara.user, configPara.password, configPara.hostName, configPara.serverPort, configPara.dbName)
// open connect to taos server
//db, err := sql.Open(taosDriverName, url)
//if err != nil {
// fmt.Println("Open database error: %s\n", err)
// os.Exit(1)
//}
//defer db.Close()
rand.Seed(time.Now().Unix())
if configPara.mode == "s" {
fmt.Printf("\n======== start stmt mode test ========\n")
db, err := sql.Open("taosSql", url)
if err != nil {
log.Fatalf("Open database error: %s\n", err)
}
defer db.Close()
demodbStmt := configPara.dbName
demotStmt := "demotStmt"
drop_database_stmt(db, demodbStmt)
create_database_stmt(db, demodbStmt)
use_database_stmt(db, demodbStmt)
create_table_stmt(db, demotStmt)
insert_data_stmt(db, demotStmt)
select_data_stmt(db, demotStmt)
return
}
createDatabase(configPara.dbName, configPara.supTblName)
fmt.Printf("======== create database success! ========\n\n")
//create_table(db, stblName)
multiThreadCreateTable(configPara.numOfThreads, configPara.numOftables, configPara.dbName, configPara.tablePrefix)
fmt.Printf("======== create super table and child tables success! ========\n\n")
//insert_data(db, demot)
multiThreadInsertData(configPara.numOfThreads, configPara.numOftables, configPara.dbName, configPara.tablePrefix)
fmt.Printf("======== insert data into child tables success! ========\n\n")
//select_data(db, demot)
selectTest(configPara.dbName, configPara.tablePrefix, configPara.supTblName)
fmt.Printf("======== select data success! ========\n\n")
fmt.Printf("======== end demo ========\n")
}
func createDatabase(dbName string, supTblName string) {
db, err := sql.Open(taosDriverName, url)
if err != nil {
fmt.Printf("Open database error: %s\n", err)
os.Exit(1)
}
defer db.Close()
// drop database if exists
sqlStr := "drop database if exists " + dbName
_, err = db.Exec(sqlStr)
checkErr(err, sqlStr)
time.Sleep(time.Second)
// create database
sqlStr = "create database " + dbName + " keep " + strconv.Itoa(configPara.keep) + " days " + strconv.Itoa(configPara.days)
_, err = db.Exec(sqlStr)
checkErr(err, sqlStr)
// use database
//sqlStr = "use " + dbName
//_, err = db.Exec(sqlStr)
//checkErr(err, sqlStr)
sqlStr = "create table if not exists " + dbName + "." + supTblName + " (ts timestamp, current float, voltage int, phase float) tags(location binary(64), groupId int);"
_, err = db.Exec(sqlStr)
checkErr(err, sqlStr)
}
func multiThreadCreateTable(threads int, nTables int, dbName string, tablePrefix string) {
st := time.Now().UnixNano()
if threads < 1 {
threads = 1
}
a := nTables / threads
if a < 1 {
threads = nTables
a = 1
}
b := nTables % threads
last := 0
endTblId := 0
wg := sync.WaitGroup{}
for i := 0; i < threads; i++ {
startTblId := last
if i < b {
endTblId = last + a
} else {
endTblId = last + a - 1
}
last = endTblId + 1
wg.Add(1)
go createTable(dbName, tablePrefix, startTblId, endTblId, &wg)
}
wg.Wait()
et := time.Now().UnixNano()
fmt.Printf("create tables spent duration: %6.6fs\n", (float32(et-st))/1e9)
}
func createTable(dbName string, childTblPrefix string, startTblId int, endTblId int, wg *sync.WaitGroup) {
//fmt.Printf("subThread[%d]: create table from %d to %d \n", unix.Gettid(), startTblId, endTblId)
// windows.GetCurrentThreadId()
db, err := sql.Open(taosDriverName, url)
if err != nil {
fmt.Printf("Open database error: %s\n", err)
os.Exit(1)
}
defer db.Close()
for i := startTblId; i <= endTblId; i++ {
sqlStr := "create table if not exists " + dbName + "." + childTblPrefix + strconv.Itoa(i) + " using " + dbName + ".meters tags('" + locations[i%maxLocationSize] + "', " + strconv.Itoa(i) + ");"
//fmt.Printf("sqlStr: %v\n", sqlStr)
_, err = db.Exec(sqlStr)
checkErr(err, sqlStr)
}
wg.Done()
runtime.Goexit()
}
func generateRowData(ts int64) string {
voltage := rand.Int() % 1000
current := 200 + rand.Float32()
phase := rand.Float32()
values := "( " + strconv.FormatInt(ts, 10) + ", " + strconv.FormatFloat(float64(current), 'f', 6, 64) + ", " + strconv.Itoa(voltage) + ", " + strconv.FormatFloat(float64(phase), 'f', 6, 64) + " ) "
return values
}
func insertData(dbName string, childTblPrefix string, startTblId int, endTblId int, wg *sync.WaitGroup) {
//fmt.Printf("subThread[%d]: insert data to table from %d to %d \n", unix.Gettid(), startTblId, endTblId)
// windows.GetCurrentThreadId()
db, err := sql.Open(taosDriverName, url)
if err != nil {
fmt.Printf("Open database error: %s\n", err)
os.Exit(1)
}
defer db.Close()
tmpTs := configPara.startTs
//rand.New(rand.NewSource(time.Now().UnixNano()))
for tID := startTblId; tID <= endTblId; tID++ {
totalNum := 0
for {
sqlStr := "insert into " + dbName + "." + childTblPrefix + strconv.Itoa(tID) + " values "
currRowNum := 0
for {
tmpTs += 1000
valuesOfRow := generateRowData(tmpTs)
currRowNum += 1
totalNum += 1
sqlStr = fmt.Sprintf("%s %s", sqlStr, valuesOfRow)
if currRowNum >= configPara.numOfRecordsPerReq || totalNum >= configPara.numOfRecordsPerTable {
break
}
}
res, err := db.Exec(sqlStr)
checkErr(err, sqlStr)
count, err := res.RowsAffected()
checkErr(err, "rows affected")
if count != int64(currRowNum) {
fmt.Printf("insert data, expect affected:%d, actual:%d\n", currRowNum, count)
os.Exit(1)
}
if totalNum >= configPara.numOfRecordsPerTable {
break
}
}
}
wg.Done()
runtime.Goexit()
}
func multiThreadInsertData(threads int, nTables int, dbName string, tablePrefix string) {
st := time.Now().UnixNano()
if threads < 1 {
threads = 1
}
a := nTables / threads
if a < 1 {
threads = nTables
a = 1
}
b := nTables % threads
last := 0
endTblId := 0
wg := sync.WaitGroup{}
for i := 0; i < threads; i++ {
startTblId := last
if i < b {
endTblId = last + a
} else {
endTblId = last + a - 1
}
last = endTblId + 1
wg.Add(1)
go insertData(dbName, tablePrefix, startTblId, endTblId, &wg)
}
wg.Wait()
et := time.Now().UnixNano()
fmt.Printf("insert data spent duration: %6.6fs\n", (float32(et-st))/1e9)
}
func selectTest(dbName string, tbPrefix string, supTblName string) {
db, err := sql.Open(taosDriverName, url)
if err != nil {
fmt.Printf("Open database error: %s\n", err)
os.Exit(1)
}
defer db.Close()
// select sql 1
limit := 3
offset := 0
sqlStr := "select * from " + dbName + "." + supTblName + " limit " + strconv.Itoa(limit) + " offset " + strconv.Itoa(offset)
rows, err := db.Query(sqlStr)
checkErr(err, sqlStr)
defer rows.Close()
fmt.Printf("query sql: %s\n", sqlStr)
for rows.Next() {
var (
ts string
current float32
voltage int
phase float32
location string
groupid int
)
err := rows.Scan(&ts, &current, &voltage, &phase, &location, &groupid)
if err != nil {
checkErr(err, "rows scan fail")
}
fmt.Printf("ts:%s\t current:%f\t voltage:%d\t phase:%f\t location:%s\t groupid:%d\n", ts, current, voltage, phase, location, groupid)
}
// check iteration error
if rows.Err() != nil {
checkErr(err, "rows next iteration error")
}
// select sql 2
sqlStr = "select avg(voltage), min(voltage), max(voltage) from " + dbName + "." + tbPrefix + strconv.Itoa(rand.Int()%configPara.numOftables)
rows, err = db.Query(sqlStr)
checkErr(err, sqlStr)
defer rows.Close()
fmt.Printf("\nquery sql: %s\n", sqlStr)
for rows.Next() {
var (
voltageAvg float32
voltageMin int
voltageMax int
)
err := rows.Scan(&voltageAvg, &voltageMin, &voltageMax)
if err != nil {
checkErr(err, "rows scan fail")
}
fmt.Printf("avg(voltage):%f\t min(voltage):%d\t max(voltage):%d\n", voltageAvg, voltageMin, voltageMax)
}
// check iteration error
if rows.Err() != nil {
checkErr(err, "rows next iteration error")
}
// select sql 3
sqlStr = "select last(*) from " + dbName + "." + supTblName
rows, err = db.Query(sqlStr)
checkErr(err, sqlStr)
defer rows.Close()
fmt.Printf("\nquery sql: %s\n", sqlStr)
for rows.Next() {
var (
lastTs string
lastCurrent float32
lastVoltage int
lastPhase float32
)
err := rows.Scan(&lastTs, &lastCurrent, &lastVoltage, &lastPhase)
if err != nil {
checkErr(err, "rows scan fail")
}
fmt.Printf("last(ts):%s\t last(current):%f\t last(voltage):%d\t last(phase):%f\n", lastTs, lastCurrent, lastVoltage, lastPhase)
}
// check iteration error
if rows.Err() != nil {
checkErr(err, "rows next iteration error")
}
}
func drop_database_stmt(db *sql.DB, demodb string) {
st := time.Now().Nanosecond()
// drop test db
res, err := db.Exec("drop database if exists " + demodb)
checkErr(err, "drop database "+demodb)
affectd, err := res.RowsAffected()
checkErr(err, "drop db, res.RowsAffected")
et := time.Now().Nanosecond()
fmt.Printf("drop database result:\n %d row(s) affectd (%6.6fs)\n\n", affectd, (float32(et-st))/1e9)
}
func create_database_stmt(db *sql.DB, demodb string) {
st := time.Now().Nanosecond()
// create database
//var stmt interface{}
stmt, err := db.Prepare("create database ?")
checkErr(err, "create db, db.Prepare")
//var res driver.Result
res, err := stmt.Exec(demodb)
checkErr(err, "create db, stmt.Exec")
//fmt.Printf("Query OK, %d row(s) affected()", res.RowsAffected())
affectd, err := res.RowsAffected()
checkErr(err, "create db, res.RowsAffected")
et := time.Now().Nanosecond()
fmt.Printf("create database result:\n %d row(s) affectd (%6.6fs)\n\n", affectd, (float32(et-st))/1e9)
}
func use_database_stmt(db *sql.DB, demodb string) {
st := time.Now().Nanosecond()
// create database
//var stmt interface{}
stmt, err := db.Prepare("use " + demodb)
checkErr(err, "use db, db.Prepare")
res, err := stmt.Exec()
checkErr(err, "use db, stmt.Exec")
affectd, err := res.RowsAffected()
checkErr(err, "use db, res.RowsAffected")
et := time.Now().Nanosecond()
fmt.Printf("use database result:\n %d row(s) affectd (%6.6fs)\n\n", affectd, (float32(et-st))/1e9)
}
func create_table_stmt(db *sql.DB, demot string) {
st := time.Now().Nanosecond()
// create table
// (ts timestamp, id int, name binary(8), len tinyint, flag bool, notes binary(8), fv float, dv double)
stmt, err := db.Prepare("create table ? (? timestamp, ? int, ? binary(10), ? tinyint, ? bool, ? binary(8), ? float, ? double)")
checkErr(err, "create table db.Prepare")
res, err := stmt.Exec(demot, "ts", "id", "name", "len", "flag", "notes", "fv", "dv")
checkErr(err, "create table stmt.Exec")
affectd, err := res.RowsAffected()
checkErr(err, "create table res.RowsAffected")
et := time.Now().Nanosecond()
fmt.Printf("create table result:\n %d row(s) affectd (%6.6fs)\n\n", affectd, (float32(et-st))/1e9)
}
func insert_data_stmt(db *sql.DB, demot string) {
st := time.Now().Nanosecond()
// insert data into table
stmt, err := db.Prepare("insert into ? values(?, ?, ?, ?, ?, ?, ?, ?) (?, ?, ?, ?, ?, ?, ?, ?) (?, ?, ?, ?, ?, ?, ?, ?)")
checkErr(err, "insert db.Prepare")
res, err := stmt.Exec(demot, "now", 1000, "'haidian'", 6, true, "'AI world'", 6987.654, 321.987,
"now+1s", 1001, "'changyang'", 7, false, "'DeepMode'", 12356.456, 128634.456,
"now+2s", 1002, "'chuangping'", 8, true, "'database'", 3879.456, 65433478.456)
checkErr(err, "insert data, stmt.Exec")
affectd, err := res.RowsAffected()
checkErr(err, "res.RowsAffected")
et := time.Now().Nanosecond()
fmt.Printf("insert data result:\n %d row(s) affectd (%6.6fs)\n\n", affectd, (float32(et-st))/1e9)
}
func select_data_stmt(db *sql.DB, demot string) {
st := time.Now().Nanosecond()
stmt, err := db.Prepare("select ?, ?, ?, ?, ?, ?, ?, ? from ?") // go binary mode
checkErr(err, "db.Prepare")
rows, err := stmt.Query("ts", "id", "name", "len", "flag", "notes", "fv", "dv", demot)
checkErr(err, "stmt.Query")
fmt.Printf("%10s%s%8s %5s %8s%s %s %10s%s %7s%s %8s%s %11s%s %14s%s\n", " ", "ts", " ", "id", " ", "name", " ", "len", " ", "flag", " ", "notes", " ", "fv", " ", " ", "dv")
var affectd int
for rows.Next() {
var ts string
var name string
var id int
var len int8
var flag bool
var notes string
var fv float32
var dv float64
err = rows.Scan(&ts, &id, &name, &len, &flag, &notes, &fv, &dv)
//fmt.Println("start scan fields from row.rs, &fv:", &fv)
//err = rows.Scan(&fv)
checkErr(err, "rows.Scan")
fmt.Printf("%s\t", ts)
fmt.Printf("%d\t", id)
fmt.Printf("%10s\t", name)
fmt.Printf("%d\t", len)
fmt.Printf("%t\t", flag)
fmt.Printf("%s\t", notes)
fmt.Printf("%06.3f\t", fv)
fmt.Printf("%09.6f\n", dv)
affectd++
}
et := time.Now().Nanosecond()
fmt.Printf("insert data result:\n %d row(s) affectd (%6.6fs)\n\n", affectd, (float32(et-st))/1e9)
}
func checkErr(err error, prompt string) {
if err != nil {
fmt.Printf("%s\n", prompt)
panic(err)
}
}
worker_processes 1;
user root;
error_log logs/error.log;
events {
worker_connections 1024;
}
http {
lua_package_path '$prefix/lua/?.lua;$prefix/rest/?.lua;$prefix/rest/?/init.lua;;';
lua_package_cpath "$prefix/so/?.so;;";
lua_code_cache on;
server {
listen 7000;
server_name restapi;
charset utf-8;
lua_need_request_body on;
location ~ ^/api/([-_a-zA-Z0-9/]+) {
content_by_lua_file rest/$1.lua;
}
}
}
# Ignore everything in this directory
*
# Except this file
!.gitignore
local config = {
host = "127.0.0.1",
port = 6030,
database = "",
user = "root",
password = "taosdata",
max_packet_size = 1024 * 1024 ,
connection_pool_size = 64
}
return config
local _M = {}
local driver = require "luaconnector51"
local water_mark = 0
local occupied = 0
local connection_pool = {}
function _M.new(o,config)
o = o or {}
o.connection_pool = connection_pool
o.water_mark = water_mark
o.occupied = occupied
if #connection_pool == 0 then
for i = 1, config.connection_pool_size do
local res = driver.connect(config)
if res.code ~= 0 then
ngx.log(ngx.ERR, "connect--- failed:"..res.error)
return nil
else
local object = {obj = res.conn, state = 0}
table.insert(o.connection_pool,i, object)
ngx.log(ngx.INFO, "add connection, now pool size:"..#(o.connection_pool))
end
end
end
return setmetatable(o, { __index = _M })
end
function _M:get_connection()
local connection_obj
for i = 1, #connection_pool do
connection_obj = connection_pool[i]
if connection_obj.state == 0 then
connection_obj.state = 1
occupied = occupied +1
if occupied > water_mark then
water_mark = occupied
end
return connection_obj["obj"]
end
end
ngx.log(ngx.ERR,"ALERT! NO FREE CONNECTION.")
return nil
end
function _M:get_water_mark()
return water_mark
end
function _M:release_connection(conn)
local connection_obj
for i = 1, #connection_pool do
connection_obj = connection_pool[i]
if connection_obj["obj"] == conn then
connection_obj["state"] = 0
occupied = occupied -1
return
end
end
end
return _M
local driver = require "luaconnector51"
local cjson = require "cjson"
local Pool = require "tdpool"
local config = require "config"
ngx.say("start time:"..os.time())
local pool = Pool.new(Pool,config)
local conn = pool:get_connection()
local res = driver.query(conn,"drop database if exists nginx")
if res.code ~=0 then
ngx.say("drop db--- failed: "..res.error)
else
ngx.say("drop db--- pass.")
end
res = driver.query(conn,"create database nginx")
if res.code ~=0 then
ngx.say("create db--- failed: "..res.error)
else
ngx.say("create db--- pass.")
end
res = driver.query(conn,"use nginx")
if res.code ~=0 then
ngx.say("select db--- failed: "..res.error)
else
ngx.say("select db--- pass.")
end
res = driver.query(conn,"create table m1 (ts timestamp, speed int, owner binary(20), mark nchar(30))")
if res.code ~=0 then
ngx.say("create table---failed: "..res.error)
else
ngx.say("create table--- pass.")
end
res = driver.query(conn,"insert into m1 values ('2019-09-01 00:00:00.001', 0, 'robotspace', '世界人民大团结万岁'), ('2019-09-01 00:00:00.002',1,'Hilink','⾾⾿⿀⿁⿂⿃⿄⿅⿆⿇⿈⿉⿊⿋⿌⿍⿎⿏⿐⿑⿒⿓⿔⿕'),('2019-09-01 00:00:00.003',2,'Harmony', '₠₡₢₣₤₥₦₧₨₩₪₫€₭₮₯₰₱₲₳₴₵')")
if res.code ~=0 then
ngx.say("insert records failed: "..res.error)
return
else
if(res.affected == 3) then
ngx.say("insert records--- pass")
else
ngx.say("insert records---failed: expect 3 affected records, actually affected "..res.affected)
end
end
res = driver.query(conn,"select * from m1")
if res.code ~=0 then
ngx.say("select failed: "..res.error)
return
else
ngx.say(cjson.encode(res))
if (#(res.item) == 3) then
ngx.say("select--- pass")
else
ngx.say("select--- failed: expect 3 affected records, actually received "..#(res.item))
end
end
--[[
local flag = false
function query_callback(res)
if res.code ~=0 then
ngx.say("async_query_callback--- failed:"..res.error)
else
if(res.affected == 3) then
ngx.say("async_query_callback, insert records--- pass")
else
ngx.say("async_query_callback, insert records---failed: expect 3 affected records, actually affected "..res.affected)
end
end
flag = true
end
driver.query_a(conn,"insert into m1 values ('2019-09-01 00:00:00.001', 3, 'robotspace'),('2019-09-01 00:00:00.006', 4, 'Hilink'),('2019-09-01 00:00:00.007', 6, 'Harmony')", query_callback)
while not flag do
ngx.say("i am here once...")
ngx.sleep(0.001) -- time unit is second
end
--]]
ngx.say("pool water_mark:"..pool:get_water_mark())
pool:release_connection(conn)
ngx.say("end time:"..os.time())
# TDengine driver connector for Lua
It's a Lua implementation for [TDengine](https://github.com/taosdata/TDengine), an open-sourced big data platform designed and optimized for the Internet of Things (IoT), Connected Cars, Industrial IoT, and IT Infrastructure and Application Monitoring. You may need to install Lua5.3 .
As TDengine is built with lua-enable, the built-in lua module conflicts with external lua. The following commands require TDengine built with lua-disable.
To disable built-in lua:
mkdir debug && cd debug
cmake .. -DBUILD_LUA=false && cmake --build .
## Lua Dependencies
- Lua:
```
https://www.lua.org/
```
## Run with Lua Sample
Build driver lib:
```
./build.sh
```
Run lua sample:
```
lua test.lua
```
## Run performance test:
```
time lua benchmark.lua
```
## OpenResty Dependencies
- OpenResty:
```
http://openresty.org
```
## Run with OpenResty Sample
**This section demonstrates how to get binary file for connector. To be convenient for trial, an connector has been put into OpenResty work directory.
Because of difference on C API between Lua5.3 and Lua5.1, the files needed by connector for OpenResty are stored in local source directory and configured in script build.sh.**
Build driver lib:
```
cd lua51
./build.sh
```
Run OpenResty sample:
```
cd ..
cd OpenResty
sudo openresty -p .
curl http://127.0.0.1:7000/api/test
```
local driver = require "luaconnector"
local config = {
password = "taosdata",
host = "127.0.0.1",
port = 6030,
database = "",
user = "root",
max_packet_size = 1024 * 1024
}
local conn
local res = driver.connect(config)
if res.code ~=0 then
print("connect--- failed: "..res.error)
return
else
conn = res.conn
print("connect--- pass.")
end
local res = driver.query(conn,"drop database if exists demo")
res = driver.query(conn,"create database demo")
if res.code ~=0 then
print("create db--- failed: "..res.error)
return
else
print("create db--- pass.")
end
res = driver.query(conn,"use demo")
if res.code ~=0 then
print("select db--- failed: "..res.error)
return
else
print("select db--- pass.")
end
res = driver.query(conn,"create table m1 (ts timestamp, speed int,owner binary(20))")
if res.code ~=0 then
print("create table---failed: "..res.error)
return
else
print("create table--- pass.")
end
local base = 1617330000000
local index =0
local count = 100000
local t
while( index < count )
do
t = base + index
local q=string.format([[insert into m1 values (%d,0,'robotspace')]],t)
res = driver.query(conn,q)
if res.code ~=0 then
print("insert records failed: "..res.error)
return
else
end
index = index+1
end
print(string.format([["Done. %d records has been stored."]],count))
driver.close(conn)
lua_header_installed=`apt-cache policy liblua5.3-dev|grep Installed|grep none > /dev/null; echo $?`
if [ "$lua_header_installed" = "0" ]; then
echo "If need, please input root password to install liblua5.3-dev for build the connector.."
sudo apt install -y liblua5.3-dev
fi
gcc -std=c99 lua_connector.c -fPIC -shared -o luaconnector.so -Wall -ltaos -I/usr/include/lua5.3
gcc -std=c99 lua_connector51.c -fPIC -shared -o luaconnector51.so -Wall -ltaos
/*
** $Id: lauxlib.h,v 1.88.1.1 2007/12/27 13:02:25 roberto Exp $
** Auxiliary functions for building Lua libraries
** See Copyright Notice in lua.h
*/
#ifndef lauxlib_h
#define lauxlib_h
#include <stddef.h>
#include <stdio.h>
#include "lua.h"
/* extra error code for `luaL_load' */
#define LUA_ERRFILE (LUA_ERRERR+1)
typedef struct luaL_Reg {
const char *name;
lua_CFunction func;
} luaL_Reg;
LUALIB_API void (luaL_openlib) (lua_State *L, const char *libname,
const luaL_Reg *l, int nup);
LUALIB_API void (luaL_register) (lua_State *L, const char *libname,
const luaL_Reg *l);
LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e);
LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e);
LUALIB_API int (luaL_typerror) (lua_State *L, int narg, const char *tname);
LUALIB_API int (luaL_argerror) (lua_State *L, int numarg, const char *extramsg);
LUALIB_API const char *(luaL_checklstring) (lua_State *L, int numArg,
size_t *l);
LUALIB_API const char *(luaL_optlstring) (lua_State *L, int numArg,
const char *def, size_t *l);
LUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int numArg);
LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int nArg, lua_Number def);
LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int numArg);
LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int nArg,
lua_Integer def);
LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg);
LUALIB_API void (luaL_checktype) (lua_State *L, int narg, int t);
LUALIB_API void (luaL_checkany) (lua_State *L, int narg);
LUALIB_API int (luaL_newmetatable) (lua_State *L, const char *tname);
LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname);
LUALIB_API void (luaL_where) (lua_State *L, int lvl);
LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...);
LUALIB_API int (luaL_checkoption) (lua_State *L, int narg, const char *def,
const char *const lst[]);
/* pre-defined references */
#define LUA_NOREF (-2)
#define LUA_REFNIL (-1)
LUALIB_API int (luaL_ref) (lua_State *L, int t);
LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref);
LUALIB_API int (luaL_loadfile) (lua_State *L, const char *filename);
LUALIB_API int (luaL_loadbuffer) (lua_State *L, const char *buff, size_t sz,
const char *name);
LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s);
LUALIB_API lua_State *(luaL_newstate) (void);
LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p,
const char *r);
LUALIB_API const char *(luaL_findtable) (lua_State *L, int idx,
const char *fname, int szhint);
/* From Lua 5.2. */
LUALIB_API int luaL_fileresult(lua_State *L, int stat, const char *fname);
LUALIB_API int luaL_execresult(lua_State *L, int stat);
LUALIB_API int (luaL_loadfilex) (lua_State *L, const char *filename,
const char *mode);
LUALIB_API int (luaL_loadbufferx) (lua_State *L, const char *buff, size_t sz,
const char *name, const char *mode);
LUALIB_API void luaL_traceback (lua_State *L, lua_State *L1, const char *msg,
int level);
LUALIB_API void (luaL_setfuncs) (lua_State *L, const luaL_Reg *l, int nup);
LUALIB_API void (luaL_pushmodule) (lua_State *L, const char *modname,
int sizehint);
LUALIB_API void *(luaL_testudata) (lua_State *L, int ud, const char *tname);
LUALIB_API void (luaL_setmetatable) (lua_State *L, const char *tname);
/*
** ===============================================================
** some useful macros
** ===============================================================
*/
#define luaL_argcheck(L, cond,numarg,extramsg) \
((void)((cond) || luaL_argerror(L, (numarg), (extramsg))))
#define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL))
#define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL))
#define luaL_checkint(L,n) ((int)luaL_checkinteger(L, (n)))
#define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d)))
#define luaL_checklong(L,n) ((long)luaL_checkinteger(L, (n)))
#define luaL_optlong(L,n,d) ((long)luaL_optinteger(L, (n), (d)))
#define luaL_typename(L,i) lua_typename(L, lua_type(L,(i)))
#define luaL_dofile(L, fn) \
(luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0))
#define luaL_dostring(L, s) \
(luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0))
#define luaL_getmetatable(L,n) (lua_getfield(L, LUA_REGISTRYINDEX, (n)))
#define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n)))
/* From Lua 5.2. */
#define luaL_newlibtable(L, l) \
lua_createtable(L, 0, sizeof(l)/sizeof((l)[0]) - 1)
#define luaL_newlib(L, l) (luaL_newlibtable(L, l), luaL_setfuncs(L, l, 0))
/*
** {======================================================
** Generic Buffer manipulation
** =======================================================
*/
typedef struct luaL_Buffer {
char *p; /* current position in buffer */
int lvl; /* number of strings in the stack (level) */
lua_State *L;
char buffer[LUAL_BUFFERSIZE];
} luaL_Buffer;
#define luaL_addchar(B,c) \
((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \
(*(B)->p++ = (char)(c)))
/* compatibility only */
#define luaL_putchar(B,c) luaL_addchar(B,c)
#define luaL_addsize(B,n) ((B)->p += (n))
LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B);
LUALIB_API char *(luaL_prepbuffer) (luaL_Buffer *B);
LUALIB_API void (luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l);
LUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s);
LUALIB_API void (luaL_addvalue) (luaL_Buffer *B);
LUALIB_API void (luaL_pushresult) (luaL_Buffer *B);
/* }====================================================== */
#endif
/*
** $Id: lua.h,v 1.218.1.5 2008/08/06 13:30:12 roberto Exp $
** Lua - An Extensible Extension Language
** Lua.org, PUC-Rio, Brazil (http://www.lua.org)
** See Copyright Notice at the end of this file
*/
#ifndef lua_h
#define lua_h
#include <stdarg.h>
#include <stddef.h>
#include "luaconf.h"
#define LUA_VERSION "Lua 5.1"
#define LUA_RELEASE "Lua 5.1.4"
#define LUA_VERSION_NUM 501
#define LUA_COPYRIGHT "Copyright (C) 1994-2008 Lua.org, PUC-Rio"
#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo & W. Celes"
/* mark for precompiled code (`<esc>Lua') */
#define LUA_SIGNATURE "\033Lua"
/* option for multiple returns in `lua_pcall' and `lua_call' */
#define LUA_MULTRET (-1)
/*
** pseudo-indices
*/
#define LUA_REGISTRYINDEX (-10000)
#define LUA_ENVIRONINDEX (-10001)
#define LUA_GLOBALSINDEX (-10002)
#define lua_upvalueindex(i) (LUA_GLOBALSINDEX-(i))
/* thread status */
#define LUA_OK 0
#define LUA_YIELD 1
#define LUA_ERRRUN 2
#define LUA_ERRSYNTAX 3
#define LUA_ERRMEM 4
#define LUA_ERRERR 5
typedef struct lua_State lua_State;
typedef int (*lua_CFunction) (lua_State *L);
/*
** functions that read/write blocks when loading/dumping Lua chunks
*/
typedef const char * (*lua_Reader) (lua_State *L, void *ud, size_t *sz);
typedef int (*lua_Writer) (lua_State *L, const void* p, size_t sz, void* ud);
/*
** prototype for memory-allocation functions
*/
typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize);
/*
** basic types
*/
#define LUA_TNONE (-1)
#define LUA_TNIL 0
#define LUA_TBOOLEAN 1
#define LUA_TLIGHTUSERDATA 2
#define LUA_TNUMBER 3
#define LUA_TSTRING 4
#define LUA_TTABLE 5
#define LUA_TFUNCTION 6
#define LUA_TUSERDATA 7
#define LUA_TTHREAD 8
/* minimum Lua stack available to a C function */
#define LUA_MINSTACK 20
/*
** generic extra include file
*/
#if defined(LUA_USER_H)
#include LUA_USER_H
#endif
/* type of numbers in Lua */
typedef LUA_NUMBER lua_Number;
/* type for integer functions */
typedef LUA_INTEGER lua_Integer;
/*
** state manipulation
*/
LUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud);
LUA_API void (lua_close) (lua_State *L);
LUA_API lua_State *(lua_newthread) (lua_State *L);
LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf);
/*
** basic stack manipulation
*/
LUA_API int (lua_gettop) (lua_State *L);
LUA_API void (lua_settop) (lua_State *L, int idx);
LUA_API void (lua_pushvalue) (lua_State *L, int idx);
LUA_API void (lua_remove) (lua_State *L, int idx);
LUA_API void (lua_insert) (lua_State *L, int idx);
LUA_API void (lua_replace) (lua_State *L, int idx);
LUA_API int (lua_checkstack) (lua_State *L, int sz);
LUA_API void (lua_xmove) (lua_State *from, lua_State *to, int n);
/*
** access functions (stack -> C)
*/
LUA_API int (lua_isnumber) (lua_State *L, int idx);
LUA_API int (lua_isstring) (lua_State *L, int idx);
LUA_API int (lua_iscfunction) (lua_State *L, int idx);
LUA_API int (lua_isuserdata) (lua_State *L, int idx);
LUA_API int (lua_type) (lua_State *L, int idx);
LUA_API const char *(lua_typename) (lua_State *L, int tp);
LUA_API int (lua_equal) (lua_State *L, int idx1, int idx2);
LUA_API int (lua_rawequal) (lua_State *L, int idx1, int idx2);
LUA_API int (lua_lessthan) (lua_State *L, int idx1, int idx2);
LUA_API lua_Number (lua_tonumber) (lua_State *L, int idx);
LUA_API lua_Integer (lua_tointeger) (lua_State *L, int idx);
LUA_API int (lua_toboolean) (lua_State *L, int idx);
LUA_API const char *(lua_tolstring) (lua_State *L, int idx, size_t *len);
LUA_API size_t (lua_objlen) (lua_State *L, int idx);
LUA_API lua_CFunction (lua_tocfunction) (lua_State *L, int idx);
LUA_API void *(lua_touserdata) (lua_State *L, int idx);
LUA_API lua_State *(lua_tothread) (lua_State *L, int idx);
LUA_API const void *(lua_topointer) (lua_State *L, int idx);
/*
** push functions (C -> stack)
*/
LUA_API void (lua_pushnil) (lua_State *L);
LUA_API void (lua_pushnumber) (lua_State *L, lua_Number n);
LUA_API void (lua_pushinteger) (lua_State *L, lua_Integer n);
LUA_API void (lua_pushlstring) (lua_State *L, const char *s, size_t l);
LUA_API void (lua_pushstring) (lua_State *L, const char *s);
LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt,
va_list argp);
LUA_API const char *(lua_pushfstring) (lua_State *L, const char *fmt, ...);
LUA_API void (lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n);
LUA_API void (lua_pushboolean) (lua_State *L, int b);
LUA_API void (lua_pushlightuserdata) (lua_State *L, void *p);
LUA_API int (lua_pushthread) (lua_State *L);
/*
** get functions (Lua -> stack)
*/
LUA_API void (lua_gettable) (lua_State *L, int idx);
LUA_API void (lua_getfield) (lua_State *L, int idx, const char *k);
LUA_API void (lua_rawget) (lua_State *L, int idx);
LUA_API void (lua_rawgeti) (lua_State *L, int idx, int n);
LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec);
LUA_API void *(lua_newuserdata) (lua_State *L, size_t sz);
LUA_API int (lua_getmetatable) (lua_State *L, int objindex);
LUA_API void (lua_getfenv) (lua_State *L, int idx);
/*
** set functions (stack -> Lua)
*/
LUA_API void (lua_settable) (lua_State *L, int idx);
LUA_API void (lua_setfield) (lua_State *L, int idx, const char *k);
LUA_API void (lua_rawset) (lua_State *L, int idx);
LUA_API void (lua_rawseti) (lua_State *L, int idx, int n);
LUA_API int (lua_setmetatable) (lua_State *L, int objindex);
LUA_API int (lua_setfenv) (lua_State *L, int idx);
/*
** `load' and `call' functions (load and run Lua code)
*/
LUA_API void (lua_call) (lua_State *L, int nargs, int nresults);
LUA_API int (lua_pcall) (lua_State *L, int nargs, int nresults, int errfunc);
LUA_API int (lua_cpcall) (lua_State *L, lua_CFunction func, void *ud);
LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt,
const char *chunkname);
LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data);
/*
** coroutine functions
*/
LUA_API int (lua_yield) (lua_State *L, int nresults);
LUA_API int (lua_resume) (lua_State *L, int narg);
LUA_API int (lua_status) (lua_State *L);
/*
** garbage-collection function and options
*/
#define LUA_GCSTOP 0
#define LUA_GCRESTART 1
#define LUA_GCCOLLECT 2
#define LUA_GCCOUNT 3
#define LUA_GCCOUNTB 4
#define LUA_GCSTEP 5
#define LUA_GCSETPAUSE 6
#define LUA_GCSETSTEPMUL 7
#define LUA_GCISRUNNING 9
LUA_API int (lua_gc) (lua_State *L, int what, int data);
/*
** miscellaneous functions
*/
LUA_API int (lua_error) (lua_State *L);
LUA_API int (lua_next) (lua_State *L, int idx);
LUA_API void (lua_concat) (lua_State *L, int n);
LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud);
LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud);
LUA_API void lua_setexdata(lua_State *L, void *exdata);
LUA_API void *lua_getexdata(lua_State *L);
/*
** ===============================================================
** some useful macros
** ===============================================================
*/
#define lua_pop(L,n) lua_settop(L, -(n)-1)
#define lua_newtable(L) lua_createtable(L, 0, 0)
#define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n)))
#define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0)
#define lua_strlen(L,i) lua_objlen(L, (i))
#define lua_isfunction(L,n) (lua_type(L, (n)) == LUA_TFUNCTION)
#define lua_istable(L,n) (lua_type(L, (n)) == LUA_TTABLE)
#define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA)
#define lua_isnil(L,n) (lua_type(L, (n)) == LUA_TNIL)
#define lua_isboolean(L,n) (lua_type(L, (n)) == LUA_TBOOLEAN)
#define lua_isthread(L,n) (lua_type(L, (n)) == LUA_TTHREAD)
#define lua_isnone(L,n) (lua_type(L, (n)) == LUA_TNONE)
#define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0)
#define lua_pushliteral(L, s) \
lua_pushlstring(L, "" s, (sizeof(s)/sizeof(char))-1)
#define lua_setglobal(L,s) lua_setfield(L, LUA_GLOBALSINDEX, (s))
#define lua_getglobal(L,s) lua_getfield(L, LUA_GLOBALSINDEX, (s))
#define lua_tostring(L,i) lua_tolstring(L, (i), NULL)
/*
** compatibility macros and functions
*/
#define lua_open() luaL_newstate()
#define lua_getregistry(L) lua_pushvalue(L, LUA_REGISTRYINDEX)
#define lua_getgccount(L) lua_gc(L, LUA_GCCOUNT, 0)
#define lua_Chunkreader lua_Reader
#define lua_Chunkwriter lua_Writer
/* hack */
LUA_API void lua_setlevel (lua_State *from, lua_State *to);
/*
** {======================================================================
** Debug API
** =======================================================================
*/
/*
** Event codes
*/
#define LUA_HOOKCALL 0
#define LUA_HOOKRET 1
#define LUA_HOOKLINE 2
#define LUA_HOOKCOUNT 3
#define LUA_HOOKTAILRET 4
/*
** Event masks
*/
#define LUA_MASKCALL (1 << LUA_HOOKCALL)
#define LUA_MASKRET (1 << LUA_HOOKRET)
#define LUA_MASKLINE (1 << LUA_HOOKLINE)
#define LUA_MASKCOUNT (1 << LUA_HOOKCOUNT)
typedef struct lua_Debug lua_Debug; /* activation record */
/* Functions to be called by the debuger in specific events */
typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar);
LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar);
LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar);
LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n);
LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n);
LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n);
LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n);
LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count);
LUA_API lua_Hook lua_gethook (lua_State *L);
LUA_API int lua_gethookmask (lua_State *L);
LUA_API int lua_gethookcount (lua_State *L);
/* From Lua 5.2. */
LUA_API void *lua_upvalueid (lua_State *L, int idx, int n);
LUA_API void lua_upvaluejoin (lua_State *L, int idx1, int n1, int idx2, int n2);
LUA_API int lua_loadx (lua_State *L, lua_Reader reader, void *dt,
const char *chunkname, const char *mode);
LUA_API const lua_Number *lua_version (lua_State *L);
LUA_API void lua_copy (lua_State *L, int fromidx, int toidx);
LUA_API lua_Number lua_tonumberx (lua_State *L, int idx, int *isnum);
LUA_API lua_Integer lua_tointegerx (lua_State *L, int idx, int *isnum);
/* From Lua 5.3. */
LUA_API int lua_isyieldable (lua_State *L);
struct lua_Debug {
int event;
const char *name; /* (n) */
const char *namewhat; /* (n) `global', `local', `field', `method' */
const char *what; /* (S) `Lua', `C', `main', `tail' */
const char *source; /* (S) */
int currentline; /* (l) */
int nups; /* (u) number of upvalues */
int linedefined; /* (S) */
int lastlinedefined; /* (S) */
char short_src[LUA_IDSIZE]; /* (S) */
/* private part */
int i_ci; /* active function */
};
/* }====================================================================== */
/******************************************************************************
* Copyright (C) 1994-2008 Lua.org, PUC-Rio. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
******************************************************************************/
#endif
#include <stdio.h>
#include <math.h>
#include <stdarg.h>
#include <stdlib.h>
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
#include <taos.h>
struct cb_param{
lua_State* state;
int callback;
void * stream;
};
struct async_query_callback_param{
lua_State* state;
int callback;
};
static int l_connect(lua_State *L){
TAOS * taos=NULL;
const char* host;
const char* database;
const char* user;
const char* password;
int port;
luaL_checktype(L, 1, LUA_TTABLE);
lua_getfield(L, 1,"host");
if (lua_isstring(L,-1)){
host = lua_tostring(L, -1);
// printf("host = %s\n", host);
}
lua_getfield(L, 1, "port");
if (lua_isnumber(L, -1)){
port = lua_tonumber(L, -1);
//printf("port = %d\n", port);
}
lua_getfield(L, 1, "database");
if (lua_isstring(L, -1)){
database = lua_tostring(L, -1);
//printf("database = %s\n", database);
}
lua_getfield(L, 1, "user");
if (lua_isstring(L, -1)){
user = lua_tostring(L, -1);
//printf("user = %s\n", user);
}
lua_getfield(L, 1, "password");
if (lua_isstring(L, -1)){
password = lua_tostring(L, -1);
//printf("password = %s\n", password);
}
lua_settop(L,0);
taos_init();
lua_newtable(L);
int table_index = lua_gettop(L);
taos = taos_connect(host, user,password,database, port);
if (taos == NULL) {
printf("failed to connect server, reason:%s\n", taos_errstr(taos));
lua_pushinteger(L, -1);
lua_setfield(L, table_index, "code");
lua_pushstring(L, taos_errstr(taos));
lua_setfield(L, table_index, "error");
lua_pushlightuserdata(L,NULL);
lua_setfield(L, table_index, "conn");
}else{
// printf("success to connect server\n");
lua_pushinteger(L, 0);
lua_setfield(L, table_index, "code");
lua_pushstring(L, taos_errstr(taos));
lua_setfield(L, table_index, "error");
lua_pushlightuserdata(L,taos);
lua_setfield(L, table_index, "conn");
}
return 1;
}
static int l_query(lua_State *L){
TAOS *taos= (TAOS*)lua_topointer(L,1);
const char* s = lua_tostring(L, 2);
TAOS_RES *result;
lua_newtable(L);
int table_index = lua_gettop(L);
// printf("receive command:%s\r\n",s);
result = taos_query(taos, s);
int32_t code = taos_errno(result);
if( code != 0){
printf("failed, reason:%s\n", taos_errstr(result));
lua_pushinteger(L, -1);
lua_setfield(L, table_index, "code");
lua_pushstring(L, taos_errstr(result));
lua_setfield(L, table_index, "error");
return 1;
}else{
//printf("success to query.\n");
TAOS_ROW row;
int rows = 0;
int num_fields = taos_field_count(result);
const TAOS_FIELD *fields = taos_fetch_fields(result);
const int affectRows = taos_affected_rows(result);
// printf(" affect rows:%d\r\n", affectRows);
lua_pushinteger(L, 0);
lua_setfield(L, table_index, "code");
lua_pushinteger(L, affectRows);
lua_setfield(L, table_index, "affected");
lua_newtable(L);
while ((row = taos_fetch_row(result))) {
//printf("row index:%d\n",rows);
rows++;
lua_pushnumber(L,rows);
lua_newtable(L);
for (int i = 0; i < num_fields; ++i) {
if (row[i] == NULL) {
continue;
}
lua_pushstring(L,fields[i].name);
int32_t* length = taos_fetch_lengths(result);
switch (fields[i].type) {
case TSDB_DATA_TYPE_UTINYINT:
case TSDB_DATA_TYPE_TINYINT:
lua_pushinteger(L,*((char *)row[i]));
break;
case TSDB_DATA_TYPE_USMALLINT:
case TSDB_DATA_TYPE_SMALLINT:
lua_pushinteger(L,*((short *)row[i]));
break;
case TSDB_DATA_TYPE_UINT:
case TSDB_DATA_TYPE_INT:
lua_pushinteger(L,*((int *)row[i]));
break;
case TSDB_DATA_TYPE_UBIGINT:
case TSDB_DATA_TYPE_BIGINT:
lua_pushinteger(L,*((int64_t *)row[i]));
break;
case TSDB_DATA_TYPE_FLOAT:
lua_pushnumber(L,*((float *)row[i]));
break;
case TSDB_DATA_TYPE_DOUBLE:
lua_pushnumber(L,*((double *)row[i]));
break;
case TSDB_DATA_TYPE_JSON:
case TSDB_DATA_TYPE_BINARY:
case TSDB_DATA_TYPE_NCHAR:
//printf("type:%d, max len:%d, current len:%d\n",fields[i].type, fields[i].bytes, length[i]);
lua_pushlstring(L,(char *)row[i], length[i]);
break;
case TSDB_DATA_TYPE_TIMESTAMP:
lua_pushinteger(L,*((int64_t *)row[i]));
break;
case TSDB_DATA_TYPE_BOOL:
lua_pushinteger(L,*((char *)row[i]));
break;
case TSDB_DATA_TYPE_NULL:
default:
lua_pushnil(L);
break;
}
lua_settable(L,-3);
}
lua_settable(L,-3);
}
taos_free_result(result);
}
lua_setfield(L, table_index, "item");
return 1;
}
void async_query_callback(void *param, TAOS_RES *result, int code){
struct async_query_callback_param* p = (struct async_query_callback_param*) param;
//printf("\nin c,numfields:%d\n", numFields);
//printf("\nin c, code:%d\n", code);
lua_State *L = p->state;
lua_rawgeti(L, LUA_REGISTRYINDEX, p->callback);
lua_newtable(L);
int table_index = lua_gettop(L);
if( code < 0){
printf("failed, reason:%s\n", taos_errstr(result));
lua_pushinteger(L, -1);
lua_setfield(L, table_index, "code");
lua_pushstring(L,"something is wrong");// taos_errstr(taos));
lua_setfield(L, table_index, "error");
}else{
//printf("success to async query.\n");
const int affectRows = taos_affected_rows(result);
//printf(" affect rows:%d\r\n", affectRows);
lua_pushinteger(L, 0);
lua_setfield(L, table_index, "code");
lua_pushinteger(L, affectRows);
lua_setfield(L, table_index, "affected");
}
lua_call(L, 1, 0);
}
static int l_async_query(lua_State *L){
int r = luaL_ref(L, LUA_REGISTRYINDEX);
TAOS * taos = (TAOS*)lua_topointer(L,1);
const char * sqlstr = lua_tostring(L,2);
// int stime = luaL_checknumber(L,3);
lua_newtable(L);
int table_index = lua_gettop(L);
struct async_query_callback_param *p = malloc(sizeof(struct async_query_callback_param));
p->state = L;
p->callback=r;
// printf("r:%d, L:%d\n",r,L);
taos_query_a(taos,sqlstr,async_query_callback,p);
lua_pushnumber(L, 0);
lua_setfield(L, table_index, "code");
lua_pushstring(L, "ok");
lua_setfield(L, table_index, "error");
return 1;
}
void stream_cb(void *param, TAOS_RES *result, TAOS_ROW row){
struct cb_param* p = (struct cb_param*) param;
TAOS_FIELD *fields = taos_fetch_fields(result);
int numFields = taos_num_fields(result);
// printf("\nnumfields:%d\n", numFields);
//printf("\n\r-----------------------------------------------------------------------------------\n");
lua_State *L = p->state;
lua_rawgeti(L, LUA_REGISTRYINDEX, p->callback);
lua_newtable(L);
for (int i = 0; i < numFields; ++i) {
if (row[i] == NULL) {
continue;
}
lua_pushstring(L,fields[i].name);
switch (fields[i].type) {
case TSDB_DATA_TYPE_TINYINT:
lua_pushinteger(L,*((char *)row[i]));
break;
case TSDB_DATA_TYPE_SMALLINT:
lua_pushinteger(L,*((short *)row[i]));
break;
case TSDB_DATA_TYPE_INT:
lua_pushinteger(L,*((int *)row[i]));
break;
case TSDB_DATA_TYPE_BIGINT:
lua_pushinteger(L,*((int64_t *)row[i]));
break;
case TSDB_DATA_TYPE_FLOAT:
lua_pushnumber(L,*((float *)row[i]));
break;
case TSDB_DATA_TYPE_DOUBLE:
lua_pushnumber(L,*((double *)row[i]));
break;
case TSDB_DATA_TYPE_BINARY:
case TSDB_DATA_TYPE_NCHAR:
lua_pushstring(L,(char *)row[i]);
break;
case TSDB_DATA_TYPE_TIMESTAMP:
lua_pushinteger(L,*((int64_t *)row[i]));
break;
case TSDB_DATA_TYPE_BOOL:
lua_pushinteger(L,*((char *)row[i]));
break;
default:
lua_pushnil(L);
break;
}
lua_settable(L, -3);
}
lua_call(L, 1, 0);
// printf("-----------------------------------------------------------------------------------\n\r");
}
static int l_open_stream(lua_State *L){
int r = luaL_ref(L, LUA_REGISTRYINDEX);
TAOS * taos = (TAOS*)lua_topointer(L,1);
const char * sqlstr = lua_tostring(L,2);
int stime = luaL_checknumber(L,3);
lua_newtable(L);
int table_index = lua_gettop(L);
struct cb_param *p = malloc(sizeof(struct cb_param));
p->state = L;
p->callback=r;
// printf("r:%d, L:%d\n",r,L);
void * s = taos_open_stream(taos,sqlstr,stream_cb,stime,p,NULL);
if (s == NULL) {
printf("failed to open stream, reason:%s\n", taos_errstr(taos));
free(p);
lua_pushnumber(L, -1);
lua_setfield(L, table_index, "code");
lua_pushstring(L, taos_errstr(taos));
lua_setfield(L, table_index, "error");
lua_pushlightuserdata(L,NULL);
lua_setfield(L, table_index, "stream");
}else{
// printf("success to open stream\n");
lua_pushnumber(L, 0);
lua_setfield(L, table_index, "code");
lua_pushstring(L, taos_errstr(taos));
lua_setfield(L, table_index, "error");
p->stream = s;
lua_pushlightuserdata(L,p);
lua_setfield(L, table_index, "stream");//stream has different content in lua and c.
}
return 1;
}
static int l_close_stream(lua_State *L){
//TODO:get stream and free cb_param
struct cb_param *p = lua_touserdata(L,1);
taos_close_stream(p->stream);
free(p);
return 0;
}
static int l_close(lua_State *L){
TAOS *taos= (TAOS*)lua_topointer(L,1);
lua_newtable(L);
int table_index = lua_gettop(L);
if(taos == NULL){
lua_pushnumber(L, -1);
lua_setfield(L, table_index, "code");
lua_pushstring(L, "null pointer.");
lua_setfield(L, table_index, "error");
}else{
taos_close(taos);
lua_pushnumber(L, 0);
lua_setfield(L, table_index, "code");
lua_pushstring(L, "done.");
lua_setfield(L, table_index, "error");
}
return 1;
}
static const struct luaL_Reg lib[] = {
{"connect", l_connect},
{"query", l_query},
{"query_a",l_async_query},
{"close", l_close},
{"open_stream", l_open_stream},
{"close_stream", l_close_stream},
{NULL, NULL}
};
extern int luaopen_luaconnector51(lua_State* L)
{
// luaL_register(L, "luaconnector51", lib);
lua_newtable (L);
luaL_setfuncs(L,lib,0);
return 1;
}
/*
** Configuration header.
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
*/
#ifndef luaconf_h
#define luaconf_h
#ifndef WINVER
#define WINVER 0x0501
#endif
#include <limits.h>
#include <stddef.h>
/* Default path for loading Lua and C modules with require(). */
#if defined(_WIN32)
/*
** In Windows, any exclamation mark ('!') in the path is replaced by the
** path of the directory of the executable file of the current process.
*/
#define LUA_LDIR "!\\lua\\"
#define LUA_CDIR "!\\"
#define LUA_PATH_DEFAULT \
".\\?.lua;" "!\\lualib\\?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;"
#define LUA_CPATH_DEFAULT \
".\\?.dll;" "!\\lualib\\?.so;" LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll"
#else
/*
** Note to distribution maintainers: do NOT patch the following lines!
** Please read ../doc/install.html#distro and pass PREFIX=/usr instead.
*/
#ifndef LUA_MULTILIB
#define LUA_MULTILIB "lib"
#endif
#ifndef LUA_LMULTILIB
#define LUA_LMULTILIB "lib"
#endif
#define LUA_LROOT "/usr/local"
#define LUA_LUADIR "/lua/5.1/"
#define LUA_LJDIR "/luajit-2.1.0-beta3/"
#ifdef LUA_ROOT
#define LUA_JROOT LUA_ROOT
#define LUA_RLDIR LUA_ROOT "/share" LUA_LUADIR
#define LUA_RCDIR LUA_ROOT "/" LUA_MULTILIB LUA_LUADIR
#define LUA_RLPATH ";" LUA_RLDIR "?.lua;" LUA_RLDIR "?/init.lua"
#define LUA_RCPATH ";" LUA_RCDIR "?.so"
#else
#define LUA_JROOT LUA_LROOT
#define LUA_RLPATH
#define LUA_RCPATH
#endif
#define LUA_JPATH ";" LUA_JROOT "/share" LUA_LJDIR "?.lua"
#define LUA_LLDIR LUA_LROOT "/share" LUA_LUADIR
#define LUA_LCDIR LUA_LROOT "/" LUA_LMULTILIB LUA_LUADIR
#define LUA_LLPATH ";" LUA_LLDIR "?.lua;" LUA_LLDIR "?/init.lua"
#define LUA_LCPATH1 ";" LUA_LCDIR "?.so"
#define LUA_LCPATH2 ";" LUA_LCDIR "loadall.so"
#define LUA_PATH_DEFAULT "./?.lua" LUA_JPATH LUA_LLPATH LUA_RLPATH
#define LUA_CPATH_DEFAULT "./?.so" LUA_LCPATH1 LUA_RCPATH LUA_LCPATH2
#endif
/* Environment variable names for path overrides and initialization code. */
#define LUA_PATH "LUA_PATH"
#define LUA_CPATH "LUA_CPATH"
#define LUA_INIT "LUA_INIT"
/* Special file system characters. */
#if defined(_WIN32)
#define LUA_DIRSEP "\\"
#else
#define LUA_DIRSEP "/"
#endif
#define LUA_PATHSEP ";"
#define LUA_PATH_MARK "?"
#define LUA_EXECDIR "!"
#define LUA_IGMARK "-"
#define LUA_PATH_CONFIG \
LUA_DIRSEP "\n" LUA_PATHSEP "\n" LUA_PATH_MARK "\n" \
LUA_EXECDIR "\n" LUA_IGMARK "\n"
/* Quoting in error messages. */
#define LUA_QL(x) "'" x "'"
#define LUA_QS LUA_QL("%s")
/* Various tunables. */
#define LUAI_MAXSTACK 65500 /* Max. # of stack slots for a thread (<64K). */
#define LUAI_MAXCSTACK 8000 /* Max. # of stack slots for a C func (<10K). */
#define LUAI_GCPAUSE 200 /* Pause GC until memory is at 200%. */
#define LUAI_GCMUL 200 /* Run GC at 200% of allocation speed. */
#define LUA_MAXCAPTURES 32 /* Max. pattern captures. */
/* Configuration for the frontend (the luajit executable). */
#if defined(luajit_c)
#define LUA_PROGNAME "luajit" /* Fallback frontend name. */
#define LUA_PROMPT "> " /* Interactive prompt. */
#define LUA_PROMPT2 ">> " /* Continuation prompt. */
#define LUA_MAXINPUT 512 /* Max. input line length. */
#endif
/* Note: changing the following defines breaks the Lua 5.1 ABI. */
#define LUA_INTEGER ptrdiff_t
#define LUA_IDSIZE 60 /* Size of lua_Debug.short_src. */
/*
** Size of lauxlib and io.* on-stack buffers. Weird workaround to avoid using
** unreasonable amounts of stack space, but still retain ABI compatibility.
** Blame Lua for depending on BUFSIZ in the ABI, blame **** for wrecking it.
*/
#define LUAL_BUFFERSIZE (BUFSIZ > 16384 ? 8192 : BUFSIZ)
/* The following defines are here only for compatibility with luaconf.h
** from the standard Lua distribution. They must not be changed for LuaJIT.
*/
#define LUA_NUMBER_DOUBLE
#define LUA_NUMBER double
#define LUAI_UACNUMBER double
#define LUA_NUMBER_SCAN "%lf"
#define LUA_NUMBER_FMT "%.14g"
#define lua_number2str(s, n) sprintf((s), LUA_NUMBER_FMT, (n))
#define LUAI_MAXNUMBER2STR 32
#define LUA_INTFRMLEN "l"
#define LUA_INTFRM_T long
/* Linkage of public API functions. */
#if defined(LUA_BUILD_AS_DLL)
#if defined(LUA_CORE) || defined(LUA_LIB)
#define LUA_API __declspec(dllexport)
#else
#define LUA_API __declspec(dllimport)
#endif
#else
#define LUA_API extern
#endif
#define LUALIB_API LUA_API
/* Support for internal assertions. */
#if defined(LUA_USE_ASSERT) || defined(LUA_USE_APICHECK)
#include <assert.h>
#endif
#ifdef LUA_USE_ASSERT
#define lua_assert(x) assert(x)
#endif
#ifdef LUA_USE_APICHECK
#define luai_apicheck(L, o) { (void)L; assert(o); }
#else
#define luai_apicheck(L, o) { (void)L; }
#endif
#endif
/*
** LuaJIT -- a Just-In-Time Compiler for Lua. http://luajit.org/
**
** Copyright (C) 2005-2017 Mike Pall. All rights reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
** [ MIT license: http://www.opensource.org/licenses/mit-license.php ]
*/
#ifndef _LUAJIT_H
#define _LUAJIT_H
#include "lua.h"
#define OPENRESTY_LUAJIT
#define LUAJIT_VERSION "LuaJIT 2.1.0-beta3"
#define LUAJIT_VERSION_NUM 20100 /* Version 2.1.0 = 02.01.00. */
#define LUAJIT_VERSION_SYM luaJIT_version_2_1_0_beta3
#define LUAJIT_COPYRIGHT "Copyright (C) 2005-2017 Mike Pall"
#define LUAJIT_URL "http://luajit.org/"
/* Modes for luaJIT_setmode. */
#define LUAJIT_MODE_MASK 0x00ff
enum {
LUAJIT_MODE_ENGINE, /* Set mode for whole JIT engine. */
LUAJIT_MODE_DEBUG, /* Set debug mode (idx = level). */
LUAJIT_MODE_FUNC, /* Change mode for a function. */
LUAJIT_MODE_ALLFUNC, /* Recurse into subroutine protos. */
LUAJIT_MODE_ALLSUBFUNC, /* Change only the subroutines. */
LUAJIT_MODE_TRACE, /* Flush a compiled trace. */
LUAJIT_MODE_WRAPCFUNC = 0x10, /* Set wrapper mode for C function calls. */
LUAJIT_MODE_MAX
};
/* Flags or'ed in to the mode. */
#define LUAJIT_MODE_OFF 0x0000 /* Turn feature off. */
#define LUAJIT_MODE_ON 0x0100 /* Turn feature on. */
#define LUAJIT_MODE_FLUSH 0x0200 /* Flush JIT-compiled code. */
/* LuaJIT public C API. */
/* Control the JIT engine. */
LUA_API int luaJIT_setmode(lua_State *L, int idx, int mode);
/* Low-overhead profiling API. */
typedef void (*luaJIT_profile_callback)(void *data, lua_State *L,
int samples, int vmstate);
LUA_API void luaJIT_profile_start(lua_State *L, const char *mode,
luaJIT_profile_callback cb, void *data);
LUA_API void luaJIT_profile_stop(lua_State *L);
LUA_API const char *luaJIT_profile_dumpstack(lua_State *L, const char *fmt,
int depth, size_t *len);
/* Enforce (dynamic) linker error for version mismatches. Call from main. */
LUA_API void LUAJIT_VERSION_SYM(void);
#endif
/*
** Standard library header.
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
*/
#ifndef _LUALIB_H
#define _LUALIB_H
#include "lua.h"
#define LUA_FILEHANDLE "FILE*"
#define LUA_COLIBNAME "coroutine"
#define LUA_MATHLIBNAME "math"
#define LUA_STRLIBNAME "string"
#define LUA_TABLIBNAME "table"
#define LUA_IOLIBNAME "io"
#define LUA_OSLIBNAME "os"
#define LUA_LOADLIBNAME "package"
#define LUA_DBLIBNAME "debug"
#define LUA_BITLIBNAME "bit"
#define LUA_JITLIBNAME "jit"
#define LUA_FFILIBNAME "ffi"
#define LUA_THRLIBNAME "thread"
LUALIB_API int luaopen_base(lua_State *L);
LUALIB_API int luaopen_math(lua_State *L);
LUALIB_API int luaopen_string(lua_State *L);
LUALIB_API int luaopen_table(lua_State *L);
LUALIB_API int luaopen_io(lua_State *L);
LUALIB_API int luaopen_os(lua_State *L);
LUALIB_API int luaopen_package(lua_State *L);
LUALIB_API int luaopen_debug(lua_State *L);
LUALIB_API int luaopen_bit(lua_State *L);
LUALIB_API int luaopen_jit(lua_State *L);
LUALIB_API int luaopen_ffi(lua_State *L);
LUALIB_API void luaL_openlibs(lua_State *L);
#ifndef lua_assert
#define lua_assert(x) ((void)0)
#endif
#endif
#include <stdio.h>
#include <math.h>
#include <stdarg.h>
#include <stdlib.h>
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
#include <taos.h>
struct cb_param{
lua_State* state;
int callback;
void * stream;
};
struct async_query_callback_param{
lua_State* state;
int callback;
};
static int l_connect(lua_State *L){
TAOS * taos=NULL;
const char* host;
const char* database;
const char* user;
const char* password;
int port;
luaL_checktype(L, 1, LUA_TTABLE);
lua_getfield(L, 1,"host");
if (lua_isstring(L,-1)){
host = lua_tostring(L, -1);
// printf("host = %s\n", host);
}
lua_getfield(L, 1, "port");
if (lua_isinteger(L, -1)){
port = lua_tointeger(L, -1);
//printf("port = %d\n", port);
}
lua_getfield(L, 1, "database");
if (lua_isstring(L, -1)){
database = lua_tostring(L, -1);
//printf("database = %s\n", database);
}
lua_getfield(L, 1, "user");
if (lua_isstring(L, -1)){
user = lua_tostring(L, -1);
//printf("user = %s\n", user);
}
lua_getfield(L, 1, "password");
if (lua_isstring(L, -1)){
password = lua_tostring(L, -1);
//printf("password = %s\n", password);
}
lua_settop(L,0);
taos_init();
lua_newtable(L);
int table_index = lua_gettop(L);
taos = taos_connect(host, user,password,database, port);
if (taos == NULL) {
printf("failed to connect server, reason:%s\n", taos_errstr(taos));
lua_pushinteger(L, -1);
lua_setfield(L, table_index, "code");
lua_pushstring(L, taos_errstr(taos));
lua_setfield(L, table_index, "error");
lua_pushlightuserdata(L,NULL);
lua_setfield(L, table_index, "conn");
}else{
// printf("success to connect server\n");
lua_pushinteger(L, 0);
lua_setfield(L, table_index, "code");
lua_pushstring(L, taos_errstr(taos));
lua_setfield(L, table_index, "error");
lua_pushlightuserdata(L,taos);
lua_setfield(L, table_index, "conn");
}
return 1;
}
static int l_query(lua_State *L){
TAOS *taos= (TAOS*)lua_topointer(L,1);
const char* s = lua_tostring(L, 2);
TAOS_RES *result;
lua_newtable(L);
int table_index = lua_gettop(L);
// printf("receive command:%s\r\n",s);
result = taos_query(taos, s);
int32_t code = taos_errno(result);
if( code != 0){
printf("failed, reason:%s\n", taos_errstr(result));
lua_pushinteger(L, -1);
lua_setfield(L, table_index, "code");
lua_pushstring(L, taos_errstr(result));
lua_setfield(L, table_index, "error");
return 1;
}else{
//printf("success to query.\n");
TAOS_ROW row;
int rows = 0;
int num_fields = taos_field_count(result);
const TAOS_FIELD *fields = taos_fetch_fields(result);
const int affectRows = taos_affected_rows(result);
// printf(" affect rows:%d\r\n", affectRows);
lua_pushinteger(L, 0);
lua_setfield(L, table_index, "code");
lua_pushinteger(L, affectRows);
lua_setfield(L, table_index, "affected");
lua_newtable(L);
while ((row = taos_fetch_row(result))) {
//printf("row index:%d\n",rows);
rows++;
lua_pushnumber(L,rows);
lua_newtable(L);
for (int i = 0; i < num_fields; ++i) {
if (row[i] == NULL) {
continue;
}
lua_pushstring(L,fields[i].name);
int32_t* length = taos_fetch_lengths(result);
switch (fields[i].type) {
case TSDB_DATA_TYPE_UTINYINT:
case TSDB_DATA_TYPE_TINYINT:
lua_pushinteger(L,*((char *)row[i]));
break;
case TSDB_DATA_TYPE_USMALLINT:
case TSDB_DATA_TYPE_SMALLINT:
lua_pushinteger(L,*((short *)row[i]));
break;
case TSDB_DATA_TYPE_UINT:
case TSDB_DATA_TYPE_INT:
lua_pushinteger(L,*((int *)row[i]));
break;
case TSDB_DATA_TYPE_UBIGINT:
case TSDB_DATA_TYPE_BIGINT:
lua_pushinteger(L,*((int64_t *)row[i]));
break;
case TSDB_DATA_TYPE_FLOAT:
lua_pushnumber(L,*((float *)row[i]));
break;
case TSDB_DATA_TYPE_DOUBLE:
lua_pushnumber(L,*((double *)row[i]));
break;
case TSDB_DATA_TYPE_JSON:
case TSDB_DATA_TYPE_BINARY:
case TSDB_DATA_TYPE_NCHAR:
//printf("type:%d, max len:%d, current len:%d\n",fields[i].type, fields[i].bytes, length[i]);
lua_pushlstring(L,(char *)row[i], length[i]);
break;
case TSDB_DATA_TYPE_TIMESTAMP:
lua_pushinteger(L,*((int64_t *)row[i]));
break;
case TSDB_DATA_TYPE_BOOL:
lua_pushinteger(L,*((char *)row[i]));
break;
case TSDB_DATA_TYPE_NULL:
default:
lua_pushnil(L);
break;
}
lua_settable(L,-3);
}
lua_settable(L,-3);
}
taos_free_result(result);
}
lua_setfield(L, table_index, "item");
return 1;
}
void async_query_callback(void *param, TAOS_RES *result, int code){
struct async_query_callback_param* p = (struct async_query_callback_param*) param;
//printf("\nin c,numfields:%d\n", numFields);
//printf("\nin c, code:%d\n", code);
lua_State *L = p->state;
lua_rawgeti(L, LUA_REGISTRYINDEX, p->callback);
lua_newtable(L);
int table_index = lua_gettop(L);
if( code < 0){
printf("failed, reason:%s\n", taos_errstr(result));
lua_pushinteger(L, -1);
lua_setfield(L, table_index, "code");
lua_pushstring(L,"something is wrong");// taos_errstr(taos));
lua_setfield(L, table_index, "error");
}else{
//printf("success to async query.\n");
const int affectRows = taos_affected_rows(result);
//printf(" affect rows:%d\r\n", affectRows);
lua_pushinteger(L, 0);
lua_setfield(L, table_index, "code");
lua_pushinteger(L, affectRows);
lua_setfield(L, table_index, "affected");
}
lua_call(L, 1, 0);
}
static int l_async_query(lua_State *L){
int r = luaL_ref(L, LUA_REGISTRYINDEX);
TAOS * taos = (TAOS*)lua_topointer(L,1);
const char * sqlstr = lua_tostring(L,2);
// int stime = luaL_checknumber(L,3);
lua_newtable(L);
int table_index = lua_gettop(L);
struct async_query_callback_param *p = malloc(sizeof(struct async_query_callback_param));
p->state = L;
p->callback=r;
// printf("r:%d, L:%d\n",r,L);
taos_query_a(taos,sqlstr,async_query_callback,p);
lua_pushnumber(L, 0);
lua_setfield(L, table_index, "code");
lua_pushstring(L, "ok");
lua_setfield(L, table_index, "error");
return 1;
}
void stream_cb(void *param, TAOS_RES *result, TAOS_ROW row){
struct cb_param* p = (struct cb_param*) param;
TAOS_FIELD *fields = taos_fetch_fields(result);
int numFields = taos_num_fields(result);
// printf("\nnumfields:%d\n", numFields);
//printf("\n\r-----------------------------------------------------------------------------------\n");
lua_State *L = p->state;
lua_rawgeti(L, LUA_REGISTRYINDEX, p->callback);
lua_newtable(L);
for (int i = 0; i < numFields; ++i) {
if (row[i] == NULL) {
continue;
}
lua_pushstring(L,fields[i].name);
switch (fields[i].type) {
case TSDB_DATA_TYPE_TINYINT:
lua_pushinteger(L,*((char *)row[i]));
break;
case TSDB_DATA_TYPE_SMALLINT:
lua_pushinteger(L,*((short *)row[i]));
break;
case TSDB_DATA_TYPE_INT:
lua_pushinteger(L,*((int *)row[i]));
break;
case TSDB_DATA_TYPE_BIGINT:
lua_pushinteger(L,*((int64_t *)row[i]));
break;
case TSDB_DATA_TYPE_FLOAT:
lua_pushnumber(L,*((float *)row[i]));
break;
case TSDB_DATA_TYPE_DOUBLE:
lua_pushnumber(L,*((double *)row[i]));
break;
case TSDB_DATA_TYPE_BINARY:
case TSDB_DATA_TYPE_NCHAR:
lua_pushstring(L,(char *)row[i]);
break;
case TSDB_DATA_TYPE_TIMESTAMP:
lua_pushinteger(L,*((int64_t *)row[i]));
break;
case TSDB_DATA_TYPE_BOOL:
lua_pushinteger(L,*((char *)row[i]));
break;
default:
lua_pushnil(L);
break;
}
lua_settable(L, -3);
}
lua_call(L, 1, 0);
// printf("-----------------------------------------------------------------------------------\n\r");
}
static int l_open_stream(lua_State *L){
int r = luaL_ref(L, LUA_REGISTRYINDEX);
TAOS * taos = (TAOS*)lua_topointer(L,1);
const char * sqlstr = lua_tostring(L,2);
int stime = luaL_checknumber(L,3);
lua_newtable(L);
int table_index = lua_gettop(L);
struct cb_param *p = malloc(sizeof(struct cb_param));
p->state = L;
p->callback=r;
// printf("r:%d, L:%d\n",r,L);
void * s = taos_open_stream(taos,sqlstr,stream_cb,stime,p,NULL);
if (s == NULL) {
printf("failed to open stream, reason:%s\n", taos_errstr(taos));
free(p);
lua_pushnumber(L, -1);
lua_setfield(L, table_index, "code");
lua_pushstring(L, taos_errstr(taos));
lua_setfield(L, table_index, "error");
lua_pushlightuserdata(L,NULL);
lua_setfield(L, table_index, "stream");
}else{
// printf("success to open stream\n");
lua_pushnumber(L, 0);
lua_setfield(L, table_index, "code");
lua_pushstring(L, taos_errstr(taos));
lua_setfield(L, table_index, "error");
p->stream = s;
lua_pushlightuserdata(L,p);
lua_setfield(L, table_index, "stream");//stream has different content in lua and c.
}
return 1;
}
static int l_close_stream(lua_State *L){
//TODO:get stream and free cb_param
struct cb_param *p = lua_touserdata(L,1);
taos_close_stream(p->stream);
free(p);
return 0;
}
static int l_close(lua_State *L){
TAOS *taos= (TAOS*)lua_topointer(L,1);
lua_newtable(L);
int table_index = lua_gettop(L);
if(taos == NULL){
lua_pushnumber(L, -1);
lua_setfield(L, table_index, "code");
lua_pushstring(L, "null pointer.");
lua_setfield(L, table_index, "error");
}else{
taos_close(taos);
lua_pushnumber(L, 0);
lua_setfield(L, table_index, "code");
lua_pushstring(L, "done.");
lua_setfield(L, table_index, "error");
}
return 1;
}
static const struct luaL_Reg lib[] = {
{"connect", l_connect},
{"query", l_query},
{"query_a",l_async_query},
{"close", l_close},
{"open_stream", l_open_stream},
{"close_stream", l_close_stream},
{NULL, NULL}
};
extern int luaopen_luaconnector(lua_State* L)
{
luaL_newlib(L, lib);
return 1;
}
local driver = require "luaconnector"
local config = {
host = "127.0.0.1",
port = 6030,
database = "",
user = "root",
password = "taosdata",
max_packet_size = 1024 * 1024
}
local conn
local res = driver.connect(config)
if res.code ~=0 then
print("connect--- failed: "..res.error)
return
else
conn = res.conn
print("connect--- pass.")
end
local res = driver.query(conn,"drop database if exists demo")
res = driver.query(conn,"create database demo")
if res.code ~=0 then
print("create db--- failed: "..res.error)
return
else
print("create db--- pass.")
end
res = driver.query(conn,"use demo")
if res.code ~=0 then
print("select db--- failed: "..res.error)
return
else
print("select db--- pass.")
end
res = driver.query(conn,"create table m1 (ts timestamp, speed int, owner binary(20), mark nchar(30))")
if res.code ~=0 then
print("create table---failed: "..res.error)
return
else
print("create table--- pass.")
end
res = driver.query(conn,"insert into m1 values ('2019-09-01 00:00:00.001', 0, 'robotspace', '世界人民大团结万岁'), ('2019-09-01 00:00:00.002', 1, 'Hilink', '⾾⾿⿀⿁⿂⿃⿄⿅⿆⿇⿈⿉⿊⿋⿌⿍⿎⿏⿐⿑⿒⿓⿔⿕'),('2019-09-01 00:00:00.003', 2, 'Harmony', '₠₡₢₣₤₥₦₧₨₩₪₫€₭₮₯₰₱₲₳₴₵')")
if res.code ~=0 then
print("insert records failed: "..res.error)
return
else
if(res.affected == 3) then
print("insert records--- pass")
else
print("insert records---failed: expect 3 affected records, actually affected "..res.affected)
end
end
res = driver.query(conn,"select * from m1")
if res.code ~=0 then
print("select failed: "..res.error)
return
else
if (#(res.item) == 3) then
print("select--- pass")
print(res.item[1].mark)
print(res.item[2].mark)
print(res.item[3].mark)
else
print("select--- failed: expect 3 affected records, actually received "..#(res.item))
end
end
res = driver.query(conn,"CREATE TABLE thermometer (ts timestamp, degree double) TAGS(location binary(20), type int)")
if res.code ~=0 then
print(res.error)
return
else
print("create super table--- pass")
end
res = driver.query(conn,"CREATE TABLE therm1 USING thermometer TAGS ('beijing', 1)")
if res.code ~=0 then
print(res.error)
return
else
print("create table--- pass")
end
res = driver.query(conn,"INSERT INTO therm1 VALUES ('2019-09-01 00:00:00.001', 20),('2019-09-01 00:00:00.002', 21)")
if res.code ~=0 then
print(res.error)
return
else
if(res.affected == 2) then
print("insert records--- pass")
else
print("insert records---failed: expect 2 affected records, actually affected "..res.affected)
end
end
res = driver.query(conn,"SELECT COUNT(*) count, AVG(degree) AS av, MAX(degree), MIN(degree) FROM thermometer WHERE location='beijing' or location='tianjin' GROUP BY location, type")
if res.code ~=0 then
print("select from super table--- failed:"..res.error)
return
else
print("select from super table--- pass")
for i = 1, #(res.item) do
print("res:"..res.item[i].count)
end
end
function async_query_callback(res)
if res.code ~=0 then
print("async_query_callback--- failed:"..res.error)
return
else
if(res.affected == 3) then
print("async_query_callback, insert records--- pass")
else
print("async_query_callback, insert records---failed: expect 3 affected records, actually affected "..res.affected)
end
end
end
driver.query_a(conn,"INSERT INTO therm1 VALUES ('2019-09-01 00:00:00.005', 100),('2019-09-01 00:00:00.006', 101),('2019-09-01 00:00:00.007', 102)", async_query_callback)
function stream_callback(t)
print("------------------------")
print("continuous query result:")
for key, value in pairs(t) do
print("key:"..key..", value:"..value)
end
end
local stream
res = driver.open_stream(conn,"SELECT COUNT(*) as count, AVG(degree) as avg, MAX(degree) as max, MIN(degree) as min FROM thermometer interval(2s) sliding(2s);)",0, stream_callback)
if res.code ~=0 then
print("open stream--- failed:"..res.error)
return
else
print("open stream--- pass")
stream = res.stream
end
print("From now on we start continous insert in an definite (infinite if you want) loop.")
local loop_index = 0
while loop_index < 30 do
local t = os.time()*1000
local v = loop_index
res = driver.query(conn,string.format("INSERT INTO therm1 VALUES (%d, %d)",t,v))
if res.code ~=0 then
print("continous insertion--- failed:" .. res.error)
return
else
--print("insert successfully, affected:"..res.affected)
end
os.execute("sleep " .. 1)
loop_index = loop_index + 1
end
driver.close_stream(stream)
driver.close(conn)
%% Connect to TDengine
clear;
fprintf("Connecting to TDengine...");
dbName = 'tsdb';
user = 'root';
password = 'taosdata';
jdbcDriverName = 'com.taosdata.jdbc.TSDBDriver';
jdbcUrl = 'jdbc:TSDB://192.168.1.113:0/';
conn = database(dbName, user, password, jdbcDriverName, jdbcUrl)
if isempty(conn.Message)
fprintf("Connection is successfully established!\n");
else
fprintf("Failed to connect to server: %s\n", conn.Message);
end
%% Query a table in TDengine, and store the results in a MATLAB table object 'tb1'
% Please note that the select() function retrieves all rows in a table/supertale into MATLAB
sql = "select ts, distance1 from device1 limit 5";
fprintf("Execute query: %s\n", sql);
tic
tb1 = select(conn, sql);
timeused = toc;
fprintf("\tQuery completed!\n\tNumber of rows retrieved: %d\n\tNumber of columns in each row: %d\n\tTime used: %g\n", height(tb1), width(tb1), timeused);
% To go a bit further, we can convert the MATLAB table object to a MATLAB matrix object
data = table2array(tb1)
%% Query table names in a TDengine supertable, and store the results in a MATLAB table object 'stbmeta'
sql = "select tbname from devices limit 10";
fprintf("Execute query: %s\n", sql);
tic;
stbmeta = select(conn, sql);
timeused = toc;
fprintf("\tTables in supertable 'devices': %t", stbmeta);
fprintf("\tQuery completed!\n\tNumber of rows retrieved: %d\n\tNumber of columns in each row: %d\n\tTime used: %g\n", height(stbmeta), width(stbmeta), timeused);
%% Query a TDengine supertable, and stores the results in a MATLAB table object 'stb'
sql = "select ts, distance1 from devices";
fprintf("Execute query: %s\n", sql);
tic;
stb = select(conn, sql);
timeused = toc;
fprintf("\tQuery completed!\n\tNumber of rows retrieved: %d\n\tNumber of columns in each row: %d\n\tTime used: %g\n", height(stb), width(stb), timeused);
%% Query TDengine using cursors and specify the number of rows to fetch
sql = 'select * from device1';
rowLimit = 5;
fprintf("Execute query: %s with row limit set to %d\n", sql, rowLimit);
tic;
% Get cursor
cur = exec(conn, sql);
% Fetch data
cur = fetch(cur, rowLimit);
data = cur.Data
timeused = toc;
fprintf("\tQuery completed!\n\tNumber of rows retrieved: %d\n\tNumber of columns in each row: %d\n\tTime used: %g\n", size(data, 1), size(data, 2), timeused);
%% Query specific columns in a TDenigine table 'device1', and stores the results directly in a MATLAB cell array 'data'
sql = 'SELECT * FROM device1 order by ts asc';
fprintf("Execute query: %s\n", sql);
tic;
data = fetch(conn, sql);
timeused = toc;
fprintf("\tQuery completed!\n\tNumber of rows retrieved: %d\n\tNumber of columns in each row: %d\n\tTime used: %g\n", size(data, 1), size(data, 2), timeused);
% Let's now convert the cell array 'data' into some matrices, and make a plot of column 'c1' again the timestamp 'ts'
ts = cell2mat(data(:,1));
c1 = cell2mat(data(:,2));
%% Query aggregation results from a table
% TDengine is so powerful at aggregated computations. Let's calculate the max, mean, standard deviation and min values for every 10 minutes in the
% tb1's timeline, and then plot them together with all the data points in tb1
sql = sprintf('SELECT max(measure1), avg(measure1), stddev(measure1), min(measure1) FROM device1 WHERE ts >= %d and ts <= %d interval(10m)', ts(1), ts(end));
fprintf("Execute query: %s\n", sql);
tic;
c1_stats = fetch(conn, sql);
timeused = toc;
fprintf("\tQuery completed!\n\tNumber of rows retrieved: %d\n\tNumber of columns in each row: %d\n\tTime used: %g\n", size(c1_stats, 1), size(c1_stats, 2), timeused);
% Prepare data for plotting.
tsAsDate = datestr(ts/86400000 + datenum(1970,1,1), 'mm-dd HH:MM');
c1_stats = cell2mat(c1_stats);
c1_stats_ts = c1_stats(:, 1);
c1_stats_max = c1_stats(:, 2);
c1_stats_mean = c1_stats(:, 3);
c1_stats_stddev = c1_stats(:, 4);
c1_stats_min = c1_stats(:, 5);
c1_stats_tsAsDate = datestr(c1_stats(:,1)/86400000 + datenum(1970,1,1), 'mm-dd HH:MM');
%% Now let's plot the data and associated statistical aggregation calculation in a figure.
fh = figure(1);
set(fh,'position',[50 50 1300 700]);
h1 = scatter(ts, c1, 5, 'c');
hold on;
h2 = plot(c1_stats_ts + 300000, c1_stats_max, '-or', 'linewidth', 1);
hold on;
h3 = plot(c1_stats_ts + 300000, c1_stats_mean, '-xg', 'linewidth', 1);
hold on;
h4 = plot(c1_stats_ts + 300000, c1_stats_stddev, '-*y', 'linewidth', 1);
hold on;
h5 = plot(c1_stats_ts + 300000, c1_stats_min, '-+k', 'linewidth', 1);
xlabel('time');
ylabel('measurement1');
set(gca, 'xtick',[ts(1),ts(end/4),ts(2*end/4),ts(3*end/4),ts(end)]);
set(gca, 'xticklabel',{tsAsDate(1,:), tsAsDate(end/4,:),tsAsDate(2*end/4,:),tsAsDate(3*end/4,:),tsAsDate(end,:)});
xlim([ts(1), ts(end)]);
legend([h1, h2, h3, h4, h5], 'data points', 'max per 10 mins', 'mean per 10 mins', 'stddev per 10 mins', 'min per 10 mins');
title('Device Measurement Monitoring Demo');
grid on;
%% Insert data into TDengine using exec()
sql = 'insert into device1 (ts, distance1) values (now, -1)';
fprintf("Execute query: %s\n", sql);
cur = exec(conn, sql)
sql = 'select * from device1 limit 1';
fprintf("Execute query: %s\n", sql);
data = select(conn, sql)
conn.close;
%% Insert data into TDengine using datainsert()
% this is currently not supported
% colnames = {'ts','c1','c2','c3'};
% dat = {'now' 99 99 99};
% tbname = 'plane1';
% datainsert(conn, tbname, colnames, dat);
% cur = exec(conn, 'select * from ' + tbname);
% cur = fetch(cur, 5);
% data = cur.Data
# 如何在windows上使用nodejs进行TDengine应用开发
## 环境准备
(1)安装nodejs-10.22.0
下载链接:https://nodejs.org/dist/v10.22.0/node-v10.22.0-win-x64.zip
解压安装,把node配置到环境变量里
cmd启动命令行,查看node的版本
```shell
> node.exe --version
v10.22.0
> npm --version
6.14.6
```
(2)安装python2.7
下载链接:https://www.python.org/ftp/python/2.7.18/python-2.7.18.amd64.msi
查看python版本
```shell
>python --version
Python 2.7.18
```
(3)安装TDengine-client
下载地址:https://www.taosdata.com/cn/all-downloads/,选择一个合适的windows-client下载(client应该尽量与server端的版本保持一致)
使用client的taos shell连接server
```shell
>taos -h node5
Welcome to the TDengine shell from Linux, Client Version:2.0.6.0
Copyright (c) 2017 by TAOS Data, Inc. All rights reserved.
taos> show dnodes;
id | end_point | vnodes | cores | status | role | create_time | offline reason |
============================================================================================================================================
1 | node5:6030 | 7 | 1 | ready | any | 2020-10-26 09:45:26.308 | |
Query OK, 1 row(s) in set (0.036000s)
```
注意:
* 检查能否在client的机器上ping通server的fqdn
* 如果你的dns server并没有提供到server的域名解析,可以将server的hostname配置到client的hosts文件中
## 应用开发
(1)建立nodejs项目
```
npm init
```
(2)安装windows-build-tools
```
npm install --global --production windows-build-tools
```
(3)安装td2.0-connector驱动
``` tdshell
npm install td2.0-connector
```
(4)nodejs访问tdengine的示例程序
```javascript
const taos = require('td2.0-connector');
var host = null;
var port = 6030;
for (var i = 2; i < global.process.argv.length; i++) {
var key = global.process.argv[i].split("=")[0];
var value = global.process.argv[i].split("=")[1];
if ("host" == key) {
host = value;
}
if ("port" == key) {
port = value;
}
}
if (host == null) {
console.log("Usage: node nodejsChecker.js host=<hostname> port=<port>");
process.exit(0);
}
// establish connection
var conn = taos.connect({host: host, user: "root", password: "taosdata", port: port});
var cursor = conn.cursor();
// create database
executeSql("create database if not exists testnodejs", 0);
// use db
executeSql("use testnodejs", 0);
// drop table
executeSql("drop table if exists testnodejs.weather", 0);
// create table
executeSql("create table if not exists testnodejs.weather(ts timestamp, temperature float, humidity int)", 0);
// insert
executeSql("insert into testnodejs.weather (ts, temperature, humidity) values(now, 20.5, 34)", 1);
// select
executeQuery("select * from testnodejs.weather");
// close connection
conn.close();
function executeQuery(sql) {
var start = new Date().getTime();
var promise = cursor.query(sql, true);
var end = new Date().getTime();
promise.then(function (result) {
printSql(sql, result != null, (end - start));
result.pretty();
});
}
function executeSql(sql, affectRows) {
var start = new Date().getTime();
var promise = cursor.execute(sql);
var end = new Date().getTime();
printSql(sql, promise == affectRows, (end - start));
}
function printSql(sql, succeed, cost) {
console.log("[ " + (succeed ? "OK" : "ERROR!") + " ] time cost: " + cost + " ms, execute statement ====> " + sql);
}
```
(5)测试nodejs程序
```shell
>node nodejsChecker.js
Usage: node nodejsChecker.js host=<hostname> port=<port>
# 提示指定host
>node nodejsChecker.js host=node5
Successfully connected to TDengine
Query OK, 0 row(s) affected (0.00997610s)
[ OK ] time cost: 14 ms, execute statement ====> create database if not exists testnodejs
Query OK, 0 row(s) affected (0.00235920s)
[ OK ] time cost: 4 ms, execute statement ====> use testnodejs
Query OK, 0 row(s) affected (0.06604280s)
[ OK ] time cost: 67 ms, execute statement ====> drop table if exists testnodejs.weather
Query OK, 0 row(s) affected (0.59403290s)
[ OK ] time cost: 595 ms, execute statement ====> create table if not exists testnodejs.weather(ts timestamp, temperature float, humidity int)
Query OK, 1 row(s) affected (0.01058950s)
[ OK ] time cost: 12 ms, execute statement ====> insert into testnodejs.weather (ts, temperature, humidity) values(now, 20.5, 34)
Query OK, 1 row(s) in set (0.00401490s)
[ OK ] time cost: 10 ms, execute statement ====> select * from testnodejs.weather
Connection is closed
ts | temperature | humidity |
=====================================================================
2020-10-27 18:49:15.547 | 20.5 | 34 |
```
## 指南
### 如何设置主机名和hosts
在server上查看hostname和fqdn
```shell
查看hostname
# hostname
taos-server
查看fqdn
# hostname -f
taos-server
```
windows下hosts文件位于:
C:\\Windows\System32\drivers\etc\hosts
修改hosts文件,添加server的ip和hostname
```
192.168.56.101 node5
```
> 什么是FQDN?
>
> FQDN(Full qualified domain name)全限定域名,fqdn由2部分组成:hostname+domainname。
>
> 例如,一个邮件服务器的fqdn可能是:mymail.somecollege.edu,其中mymail是hostname(主机名),somcollege.edu是domainname(域名)。本例中,.edu是顶级域名,.somecollege是二级域名。
>
> 当连接服务器时,必须指定fqdn,然后,dns服务器通过查看dns表,将hostname解析为相应的ip地址。如果只指定hostname(不指定domainname),应用程序可能服务解析主机名。因为如果你试图访问不在本地的远程服务器时,本地的dns服务器和可能没有远程服务器的hostname列表。
>
> 参考:https://kb.iu.edu/d/aiuv
/* This example is to show how to use the td-connector through the cursor only and is a bit more raw.
* No promises, object wrappers around data, functions that prettify the data, or anything.
* The cursor will generally use callback functions over promises, and return and store the raw data from the C Interface.
* It is advised to use the td-connector through the cursor and the TaosQuery class amongst other higher level APIs.
*/
// Get the td-connector package
const taos = require('td2.0-connector');
/* We will connect to TDengine by passing an object comprised of connection options to taos.connect and store the
* connection to the variable conn
*/
/*
* Connection Options
* host: the host to connect to
* user: the use to login as
* password: the password for the above user to login
* config: the location of the taos.cfg file, by default it is in /etc/taos
* port: the port we connect through
*/
var conn = taos.connect({host:"127.0.0.1", user:"root", password:"taosdata", config:"/etc/taos",port:0});
// Initialize our TDengineCursor, which we use to interact with TDengine
var c1 = conn.cursor();
//execute the sql
function execute(sql){
try {
c1.execute(sql);
}
catch(err) {
conn.close();
throw err;
}
}
// c1.execute(query) will execute the query
// Let's create a database named db
execute('create database if not exists db;')
// Now we will use database db
execute('use db;')
// Let's create a table called weather
// which stores some weather data like humidity, AQI (air quality index), temperature, and some notes as text
execute('create table if not exists weather (ts timestamp, humidity smallint, aqi int, temperature float, notes binary(30));');
// Let's get the description of the table weather
execute('describe db.weather');
// To get results, we run the function c1.fetchall()
// It only returns the query results as an array of result rows, but also stores the latest results in c1.data
try {
var tableDesc = c1.fetchall(); // The description variable here is equal to c1.data;
console.log(tableDesc);
}
catch (err) {
conn.close();
throw err;
}
// Let's try to insert some random generated data to test with
let stime = new Date();
let interval = 1000;
// Timestamps must be in the form of "YYYY-MM-DD HH:MM:SS.MMM" if they are in milliseconds
// "YYYY-MM-DD HH:MM:SS.MMMMMM" if they are in microseconds
// Thus, we create the following function to convert a javascript Date object to the correct formatting
function convertDateToTS(date) {
let tsArr = date.toISOString().split("T")
return "\"" + tsArr[0] + " " + tsArr[1].substring(0, tsArr[1].length-1) + "\"";
}
try {
for (let i = 0; i < 10000; i++) {
stime.setMilliseconds(stime.getMilliseconds() + interval);
let insertData = [convertDateToTS(stime),
parseInt(Math.random()*100),
parseInt(Math.random()*300),
parseFloat(Math.random()*10 + 30),
"\"random note!\""];
c1.execute('insert into db.weather values(' + insertData.join(',') + ' );');
}
}
catch (err) {
conn.close();
throw err;
}
// Now let's look at our newly inserted data
var retrievedData;
try {
c1.execute('select * from db.weather;')
retrievedData = c1.fetchall();
// c1.fields stores the names of each column retrieved
console.log(c1.fields);
console.log(retrievedData);
// timestamps retrieved are always JS Date Objects
// Numbers are numbers, big ints are big ints, and strings are strings
}
catch (err) {
conn.close();
throw err;
}
// Let's try running some basic functions
try {
c1.execute('select count(*), avg(temperature), max(temperature), min(temperature), stddev(temperature) from db.weather;')
c1.fetchall();
console.log(c1.fields);
console.log(c1.data);
}
catch(err) {
conn.close();
throw err;
}
conn.close();
// Feel free to fork this repository or copy this code and start developing your own apps and backends with NodeJS and TDengine!
/* This example is to show the preferred way to use the td-connector */
/* To run, enter node path/to/node-example.js */
// Get the td-connector package
const taos = require('td2.0-connector');
/* We will connect to TDengine by passing an object comprised of connection options to taos.connect and store the
* connection to the variable conn
*/
/*
* Connection Options
* host: the host to connect to
* user: the use to login as
* password: the password for the above user to login
* config: the location of the taos.cfg file, by default it is in /etc/taos
* port: the port we connect through
*/
var conn = taos.connect({host:"127.0.0.1", user:"root", password:"taosdata", config:"/etc/taos",port:0});
// Initialize our TDengineCursor, which we use to interact with TDengine
var c1 = conn.cursor();
// c1.query(query) will return a TaosQuery object, of which then we can execute. The execute function then returns a promise
// Let's create a database named db
try {
c1.execute('create database if not exists db;');
//var query = c1.query('create database if not exists db;');
//query.execute();
}
catch(err) {
conn.close();
throw err;
}
// Now we will use database db. As this query won't return any results,
// we can simplify the code and directly use the c1.execute() function. No need for a TaosQuery object to wrap around the query
try {
c1.execute('use db;');
}
catch (err) {
conn.close();
throw err;
}
// Let's create a table called weather
// which stores some weather data like humidity, AQI (air quality index), temperature, and some notes as text
// We can also immedietely execute a TaosQuery object by passing true as the secodn argument
// This will then return a promise that we can then attach a callback function to
try {
var promise = c1.query('create table if not exists weather (ts timestamp, humidity smallint, aqi int, temperature float, notes binary(30));', true);
promise.then(function(){
console.log("Table created!");
}).catch(function() {
console.log("Table couldn't be created.")
});
}
catch (err) {
conn.close();
throw err;
}
// Let's get the description of the table weather
// When using a TaosQuery object and then executing it, upon success it returns a TaosResult object, which is a wrapper around the
// retrieved data and allows us to easily access data and manipulate or display it.
try {
c1.query('describe db.weather;').execute().then(function(result){
// Result is an instance of TaosResult and has the function pretty() which instantly logs a prettified version to the console
result.pretty();
});
}
catch (err) {
conn.close();
throw err;
}
Date.prototype.Format = function(fmt){
var o = {
'M+': this.getMonth() + 1,
'd+': this.getDate(),
'H+': this.getHours(),
'm+': this.getMinutes(),
's+': this.getSeconds(),
'S+': this.getMilliseconds()
};
if (/(y+)/.test(fmt)) {
fmt = fmt.replace(RegExp.$1, (this.getFullYear() + '').substr(4 - RegExp.$1.length));
}
for (var k in o) {
if (new RegExp('(' + k + ')').test(fmt)) {
fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (('00' + o[k]).substr(String(o[k]).length)));
}
}
return fmt;
}
// Let's try to insert some random generated data to test with
// We will use the bind function of the TaosQuery object to easily bind values to question marks in the query
// For Timestamps, a normal Datetime object or TaosTimestamp or milliseconds can be passed in through the bind function
let stime = new Date();
let interval = 1000;
try {
for (let i = 0; i < 1000; i++) {
stime.setMilliseconds(stime.getMilliseconds() + interval);
//console.log(stime.Format('yyyy-MM-dd HH:mm:ss.SSS'));
let insertData = [stime,
parseInt(Math.random()*100),
parseInt(Math.random()*300),
parseFloat(Math.random()*10 + 30),
"Note"];
//c1.execute('insert into db.weather values(' + insertData.join(',') + ' );');
//var query = c1.query('insert into db.weather values(?, ?, ?, ?, ?);').bind(insertData);
//query.execute();
c1.execute('insert into db.weather values(\"'+stime.Format('yyyy-MM-dd HH:mm:ss.SSS')+'\",'+parseInt(Math.random() * 100)+','+parseInt(Math.random() * 300)+','+parseFloat(Math.random()*10 + 30)+',"Note");');
}
}catch (err) {
conn.close();
throw err;
}
// Now let's look at our newly inserted data
var retrievedData;
try {
c1.query('select * from db.weather limit 5 offset 100;', true).then(function(result){
//result.pretty();
console.log('=========>'+JSON.stringify(result));
// Neat!
});
}
catch (err) {
conn.close();
throw err;
}
// Let's try running some basic functions
try {
c1.query('select count(*), avg(temperature), max(temperature), min(temperature), stddev(temperature) from db.weather;', true)
.then(function(result) {
result.pretty();
})
}
catch(err) {
conn.close();
throw err;
}
conn.close();
// Feel free to fork this repository or copy this code and start developing your own apps and backends with NodeJS and TDengine!
//const taos = require('td2.0-connector');
const taos = require('../../../src/connector/nodejs/');
var host = null;
var port = 6030;
for(var i = 2; i < global.process.argv.length; i++){
var key = global.process.argv[i].split("=")[0];
var value = global.process.argv[i].split("=")[1];
if("host" == key){
host = value;
}
if("port" == key){
port = value;
}
}
if(host == null){
console.log("Usage: node nodejsChecker.js host=<hostname> port=<port>");
process.exit(0);
}
// establish connection
var conn = taos.connect({host:host, user:"root", password:"taosdata",port:port});
var cursor = conn.cursor();
// create database
executeSql("create database if not exists test", 0);
// use db
executeSql("use test", 0);
// drop table
executeSql("drop table if exists test.weather", 0);
// create table
executeSql("create table if not exists test.weather(ts timestamp, temperature float, humidity int)", 0);
// insert
executeSql("insert into test.weather (ts, temperature, humidity) values(now, 20.5, 34)", 1);
// select
executeQuery("select * from test.weather");
// close connection
conn.close();
function executeQuery(sql){
var start = new Date().getTime();
var promise = cursor.query(sql, true);
var end = new Date().getTime();
promise.then(function(result){
printSql(sql, result != null,(end - start));
result.pretty();
});
}
function executeSql(sql, affectRows){
var start = new Date().getTime();
var promise = cursor.execute(sql);
var end = new Date().getTime();
printSql(sql, promise == affectRows, (end - start));
}
function printSql(sql, succeed, cost){
console.log("[ "+(succeed ? "OK" : "ERROR!")+" ] time cost: " + cost + " ms, execute statement ====> " + sql);
}
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 c1 = conn.cursor(); // Initializing a new 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
const dbname = "nodejs_1970_db";
const tbname = "t1";
let dropDB = "drop database if exists " + dbname
console.log(dropDB);//asdasdasd
c1.execute(dropDB);///asdasd
let createDB = "create database " + dbname + " keep 36500"
console.log(createDB);
c1.execute(createDB);
let useTbl = "use " + dbname
console.log(useTbl)
c1.execute(useTbl);
let createTbl = "create table if not exists " + tbname + "(ts timestamp,id int)"
console.log(createTbl);
c1.execute(createTbl);
//1969-12-31 23:59:59.999
//1970-01-01 00:00:00.000
//1970-01-01 07:59:59.999
//1970-01-01 08:00:00.000a
//1628928479484 2021-08-14 08:07:59.484
let sql1 = "insert into " + dbname + "." + tbname + " values('1969-12-31 23:59:59.999',1)"
console.log(sql1);
c1.execute(sql1);
let sql2 = "insert into " + dbname + "." + tbname + " values('1970-01-01 00:00:00.000',2)"
console.log(sql2);
c1.execute(sql2);
let sql3 = "insert into " + dbname + "." + tbname + " values('1970-01-01 07:59:59.999',3)"
console.log(sql3);
c1.execute(sql3);
let sql4 = "insert into " + dbname + "." + tbname + " values('1970-01-01 08:00:00.000',4)"
console.log(sql4);
c1.execute(sql4);
let sql5 = "insert into " + dbname + "." + tbname + " values('2021-08-14 08:07:59.484',5)"
console.log(sql5);
c1.execute(sql5);
// Select
let query1 = "select * from " + dbname + "." + tbname
console.log(query1);
c1.execute(query1);
var d = c1.fetchall();
console.log(c1.fields);
for (let i = 0; i < d.length; i++)
console.log(d[i][0].valueOf());
//initialize
let initSql1 = "drop table if exists " + tbname
console.log(initSql1);
c1.execute(initSql1);
console.log(createTbl);
c1.execute(createTbl);
c1.execute(useTbl)
//-28800001 1969-12-31 23:59:59.999
//-28800000 1970-01-01 00:00:00.000
//-1 1970-01-01 07:59:59.999
//0 1970-01-01 08:00:00.00
//1628928479484 2021-08-14 08:07:59.484
let sql11 = "insert into " + dbname + "." + tbname + " values(-28800001,11)";
console.log(sql11);
c1.execute(sql11);
let sql12 = "insert into " + dbname + "." + tbname + " values(-28800000,12)"
console.log(sql12);
c1.execute(sql12);
let sql13 = "insert into " + dbname + "." + tbname + " values(-1,13)"
console.log(sql13);
c1.execute(sql13);
let sql14 = "insert into " + dbname + "." + tbname + " values(0,14)"
console.log(sql14);
c1.execute(sql14);
let sql15 = "insert into " + dbname + "." + tbname + " values(1628928479484,15)"
console.log(sql15);
c1.execute(sql15);
// Select
console.log(query1);
c1.execute(query1);
var d = c1.fetchall();
console.log(c1.fields);
for (let i = 0; i < d.length; i++)
console.log(d[i][0].valueOf());
setTimeout(function () {
conn.close();
}, 2000);
import taos
import time
import sys
import getopt
class ConnectorChecker:
def init(self):
self.host = "127.0.0.1"
self.dbName = "test"
self.tbName = "weather"
self.user = "root"
self.password = "taosdata"
def sethdt(self,FQDN,dbname,tbname):
if(FQDN):
self.host=FQDN
if(dbname):
self.dbname=dbname
if(tbname):
self.tbName
def printSql(self,sql,elapsed):
print("[ "+"OK"+" ]"+" time cost: %s ms, execute statement ====> %s"
%(elapsed,sql))
def executeQuery(self,sql):
try:
start=time.time()
execute = self.cl.execute(sql)
elapsed = (time.time()-start)*1000
self.printSql(sql,elapsed)
data = self.cl.fetchall()
numOfRows = self.cl.rowcount
numOfCols = len(self.cl.description)
for irow in range(numOfRows):
print("Row%d: ts=%s, temperature=%d, humidity=%f" %(irow, data[irow][0], data[irow][1],data[irow][2]))
except Exception as e:
print("Failure sql: %s,exception: %s" %sql,str(e))
def execute(self,sql):
try:
start=time.time()
execute = self.cl.execute(sql)
elapsed = (time.time()-start)*1000
self.printSql(sql,elapsed)
except Exception as e:
print("Failure sql: %s,exception: %s" %
sql,str(e))
def close(self):
print("connetion closed.")
self.cl.close()
self.conn.close()
def createDatabase(self):
sql="create database if not exists %s" % self.dbName
self.execute(sql)
def useDatabase(self):
sql="use %s" % self.dbName
self.execute(sql)
def createTable(self):
sql="create table if not exists %s.%s (ts timestamp, temperature float, humidity int)"%(self.dbName,self.tbName)
self.execute(sql)
def checkDropTable(self):
sql="drop table if exists " + self.dbName + "." + self.tbName + ""
self.execute(sql)
def checkInsert(self):
sql="insert into test.weather (ts, temperature, humidity) values(now, 20.5, 34)"
self.execute(sql)
def checkSelect(self):
sql = "select * from test.weather"
self.executeQuery(sql)
def srun(self):
try:
self.conn = taos.connect(host=self.host,user=self.user,password=self.password)
#self.conn = taos.connect(self.host,self.user,self.password)
except Exception as e:
print("connection failed: %s"%self.host)
exit(1)
print("[ OK ] Connection established.")
self.cl = self.conn.cursor()
def main(argv):
FQDN=''
dbname=''
tbname=''
try:
opts, args = getopt.getopt(argv,"h:d:t:",["FQDN=","ifile=","ofile="])
except getopt.GetoptError:
print ('PYTHONConnectorChecker.py -h <FQDN>')
sys.exit(2)
for opt, arg in opts:
if opt in ("-h", "--FQDN"):
FQDN=arg
elif opt in ("-d", "--dbname"):
dbname = arg
elif opt in ("-t", "--tbname"):
tbname = arg
checker = ConnectorChecker()
checker.init()
checker.sethdt(FQDN,dbname,tbname)
checker.srun()
checker.createDatabase()
checker.useDatabase()
checker.checkDropTable()
checker.createTable()
checker.checkInsert()
checker.checkSelect()
checker.checkDropTable()
checker.close()
if __name__ == "__main__":
main(sys.argv[1:])
"""
This is the sample code for TDengine python2 client.
"""
import taos
import sys
import datetime
import random
def exitProgram(conn):
conn.close()
sys.exit()
if __name__ == '__main__':
start_time = datetime.datetime(2019, 7, 1)
time_interval = datetime.timedelta(seconds=60)
# Connect to TDengine server.
#
# parameters:
# @host : TDengine server IP address
# @user : Username used to connect to TDengine server
# @password : Password
# @database : Database to use when connecting to TDengine server
# @config : Configuration directory
if len(sys.argv)>1:
hostname=sys.argv[1]
conn = taos.connect(host=hostname, user="root", password="taosdata", config="/etc/taos")
else:
conn = taos.connect(host="127.0.0.1", user="root", password="taosdata", config="/etc/taos")
# Generate a cursor object to run SQL commands
c1 = conn.cursor()
# Create a database named db
try:
c1.execute('create database if not exists db ')
except Exception as err:
conn.close()
raise(err)
# use database
try:
c1.execute('use db')
except Exception as err:
conn.close()
raise(err)
# create table
try:
c1.execute('create table if not exists t (ts timestamp, a int, b float, c binary(20))')
except Exception as err:
conn.close()
raise(err)
# insert data
for i in range(10):
try:
value = c1.execute("insert into t values ('%s', %d, %f, '%s')" % (start_time, random.randint(1,10), random.randint(1,10)/10.0, 'hello'))
#if insert, value is the affected rows
print(value)
except Exception as err:
conn.close()
raise(err)
start_time += time_interval
# query data and return data in the form of list
try:
c1.execute('select * from db.t')
except Exception as err:
conn.close()
raise(err)
# Column names are in c1.description list
cols = c1.description
# Use fetchall to fetch data in a list
data = c1.fetchall()
for col in data:
print(col)
print('Another query method ')
try:
c1.execute('select * from db.t')
except Exception as err:
conn.close()
raise(err)
# Use iterator to go through the retreived data
for col in c1:
print(col)
conn.close()
install build environment
===
/usr/bin/python3 -m pip install -r requirements.txt
run python version taosdemo
===
Usage: ./taosdemo.py [OPTION...]
Author: Shuduo Sang <sangshuduo@gmail.com>
-H, --help Show usage.
-N, --native flag, Use native interface if set. Default is using RESTful interface.
-h, --host <hostname> host, The host to connect to TDengine. Default is localhost.
-p, --port <port> port, The TCP/IP port number to use for the connection. Default is 0.
-u, --user <username> user, The user name to use when connecting to the server. Default is 'root'.
-P, --password <password> password, The password to use when connecting to the server. Default is 'taosdata'.
-l, --colsPerRec <number> num_of_columns_per_record, The number of columns per record. Default is 3.
-d, --dbname <dbname> database, Destination database. Default is 'test'.
-a, --replica <replications> replica, Set the replica parameters of the database, Default 1, min: 1, max: 5.
-m, --tbname <table prefix> table_prefix, Table prefix name. Default is 't'.
-M, --stable flag, Use super table. Default is no
-s, --stbname <stable prefix> stable_prefix, STable prefix name. Default is 'st'
-Q, --query <DEFAULT | NO | command> query, Execute query command. set 'DEFAULT' means select * from each table
-T, --threads <number> num_of_threads, The number of threads. Default is 1.
-C, --processes <number> num_of_processes, The number of threads. Default is 1.
-r, --batch <number> num_of_records_per_req, The number of records per request. Default is 1000.
-t, --numOfTb <number> num_of_tables, The number of tables. Default is 1.
-n, --numOfRec <number> num_of_records_per_table, The number of records per table. Default is 1.
-c, --config <path> config_directory, Configuration directory. Default is '/etc/taos/'.
-x, --inserOnly flag, Insert only flag.
-O, --outOfOrder out of order data insert, 0: In order, 1: Out of order. Default is in order.
-R, --rateOOOO <number> rate, Out of order data's rate--if order=1 Default 10, min: 0, max: 50.
-D, --deleteMethod <number> Delete data methods 0: don't delete, 1: delete by table, 2: delete by stable, 3: delete by database.
-v, --verbose Print verbose output
-g, --debug Print debug output
-y, --skipPrompt Skip read key for continous test, default is not skip
##
######## example-requirements.txt #######
##
####### Requirements without Version Specifiers ######
requests
multipledispatch
#beautifulsoup4
##
####### Requirements with Version Specifiers ######
## See https://www.python.org/dev/peps/pep-0440/#version-specifiers
#docopt == 0.6.1 # Version Matching. Must be version 0.6.1
#keyring >= 4.1.1 # Minimum version 4.1.1
#coverage != 3.5 # Version Exclusion. Anything except version 3.5
#Mopidy-Dirble ~= 1.1 # Compatible release. Same as >= 1.1, == 1.*
##
####### Refer to other requirements files ######
#-r other-requirements.txt
##
##
####### A particular file ######
#./downloads/numpy-1.9.2-cp34-none-win32.whl
#http://wxpython.org/Phoenix/snapshot-builds/wxPython_Phoenix-3.0.3.dev1820+49a8884-cp34-none-win_amd64.whl
##
####### Additional Requirements without Version Specifiers ######
## Same as 1st section, just here to show that you can put things in any order.
#rejected
#green
##
#!/usr/bin/python3
# * Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
# *
# * This program is free software: you can use, redistribute, and/or modify
# * it under the terms of the GNU Affero General Public License, version 3
# * or later ("AGPL"), as published by the Free Software Foundation.
# *
# * This program is distributed in the hope that it will be useful, but WITHOUT
# * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# * FITNESS FOR A PARTICULAR PURPOSE.
# *
# * You should have received a copy of the GNU Affero General Public License
# * along with this program. If not, see <http://www.gnu.org/licenses/>.
# -*- coding: utf-8 -*-
import sys
import getopt
import requests
import json
import random
import time
import datetime
import multiprocessing
from multiprocessing import Manager, Pool, Lock
from multipledispatch import dispatch
from concurrent.futures import ThreadPoolExecutor, wait, ALL_COMPLETED
@dispatch(str, str)
def v_print(msg, arg):
# type: (str, str) -> None
if verbose:
print(msg % arg)
@dispatch(str, str, str)
def v_print(msg, arg1, arg2):
# type: (str, str, str) -> None
if verbose:
print(msg % (arg1, arg2))
@dispatch(str, str, str, str)
def v_print(msg, arg1, arg2, arg3):
# type: (str, str, str, str) -> None
if verbose:
print(msg % (arg1, arg2, arg3))
@dispatch(str, str, str, str, str)
def v_print(msg, arg1, arg2, arg3, arg4):
# type: (str, str, str, str, str) -> None
if verbose:
print(msg % (arg1, arg2, arg3, arg4))
@dispatch(str, int)
def v_print(msg, arg):
# type: (str, int) -> None
if verbose:
print(msg % int(arg))
@dispatch(str, int, str)
def v_print(msg, arg1, arg2):
# type: (str, int, str) -> None
if verbose:
print(msg % (int(arg1), str(arg2)))
@dispatch(str, str, int)
def v_print(msg, arg1, arg2):
# type: (str, str, int) -> None
if verbose:
print(msg % (arg1, int(arg2)))
@dispatch(str, int, int)
def v_print(msg, arg1, arg2):
# type: (str, int, int) -> None
if verbose:
print(msg % (int(arg1), int(arg2)))
@dispatch(str, int, int, str)
def v_print(msg, arg1, arg2, arg3):
# type: (str, int, int, str) -> None
if verbose:
print(msg % (int(arg1), int(arg2), str(arg3)))
@dispatch(str, int, int, int)
def v_print(msg, arg1, arg2, arg3):
# type: (str, int, int, int) -> None
if verbose:
print(msg % (int(arg1), int(arg2), int(arg3)))
@dispatch(str, int, int, int, int)
def v_print(msg, arg1, arg2, arg3, arg4):
# type: (str, int, int, int, int) -> None
if verbose:
print(msg % (int(arg1), int(arg2), int(arg3), int(arg4)))
def restful_execute(host, port, user, password, cmd):
# type: (str, int, str, str, str) -> None
url = "http://%s:%d/rest/sql" % (host, restPort)
v_print("restful_execute - cmd: %s", cmd)
resp = requests.post(url, cmd, auth=(user, password))
v_print("resp status: %d", resp.status_code)
if debug:
v_print(
"resp text: %s",
json.dumps(
resp.json(),
sort_keys=True,
indent=2))
else:
print("resp: %s" % json.dumps(resp.json()))
def query_func(process, thread, cmd):
# type: (int, int, str) -> None
v_print("%d process %d thread cmd: %s", process, thread, cmd)
if oneMoreHost != "NotSupported" and random.randint(
0, 1) == 1:
v_print("%s", "Send to second host")
if native:
cursor2.execute(cmd)
else:
restful_execute(
oneMoreHost, port, user, password, cmd)
else:
v_print("%s%s%s", "Send ", cmd, " to the host")
if native:
pass
# cursor.execute(cmd)
else:
restful_execute(
host, port, user, password, cmd)
def query_data_process(cmd):
# type: (str) -> None
# establish connection if native
if native:
v_print("host:%s, user:%s passwd:%s configDir:%s ", host, user, password, configDir)
try:
conn = taos.connect(
host=host,
user=user,
password=password,
config=configDir)
v_print("conn: %s", str(conn.__class__))
except Exception as e:
print("Error: %s" % e.args[0])
sys.exit(1)
try:
cursor = conn.cursor()
v_print("cursor:%d %s", id(cursor), str(cursor.__class__))
except Exception as e:
print("Error: %s" % e.args[0])
conn.close()
sys.exit(1)
if native:
try:
cursor.execute(cmd)
cols = cursor.description
data = cursor.fetchall()
for col in data:
print(col)
except Exception as e:
conn.close()
print("Error: %s" % e.args[0])
sys.exit(1)
else:
restful_execute(
host,
port,
user,
password,
cmd)
if native:
cursor.close()
conn.close()
def create_stb():
for i in range(0, numOfStb):
if native:
cursor.execute(
"CREATE TABLE IF NOT EXISTS %s%d (ts timestamp, value float) TAGS (uuid binary(50))" %
(stbName, i))
else:
restful_execute(
host,
port,
user,
password,
"CREATE TABLE IF NOT EXISTS %s%d (ts timestamp, value float) TAGS (uuid binary(50))" %
(stbName, i)
)
def use_database():
if native:
cursor.execute("USE %s" % current_db)
else:
restful_execute(host, port, user, password, "USE %s" % current_db)
def create_databases():
for i in range(0, numOfDb):
v_print("will create database db%d", int(i))
if native:
cursor.execute(
"CREATE DATABASE IF NOT EXISTS %s%d" % (dbName, i))
else:
restful_execute(
host,
port,
user,
password,
"CREATE DATABASE IF NOT EXISTS %s%d" % (dbName, i))
def drop_tables():
# TODO
v_print("TODO: drop tables total %d", numOfTb)
pass
def drop_stable():
# TODO
v_print("TODO: drop stables total %d", numOfStb)
pass
def drop_databases():
v_print("drop databases total %d", numOfDb)
# drop exist databases first
for i in range(0, numOfDb):
v_print("will drop database db%d", int(i))
if native:
cursor.execute(
"DROP DATABASE IF EXISTS %s%d" %
(dbName, i))
else:
restful_execute(
host,
port,
user,
password,
"DROP DATABASE IF EXISTS %s%d" %
(dbName, i))
def insert_func(process, thread):
# type: (int, int) -> None
v_print("%d process %d thread, insert_func ", process, thread)
# generate uuid
uuid_int = random.randint(0, numOfTb + 1)
uuid = "%s" % uuid_int
v_print("uuid is: %s", uuid)
# establish connection if native
if native:
v_print("host:%s, user:%s passwd:%s configDir:%s ", host, user, password, configDir)
try:
conn = taos.connect(
host=host,
user=user,
password=password,
config=configDir)
v_print("conn: %s", str(conn.__class__))
except Exception as e:
print("Error: %s" % e.args[0])
sys.exit(1)
try:
cursor = conn.cursor()
v_print("cursor:%d %s", id(cursor), str(cursor.__class__))
except Exception as e:
print("Error: %s" % e.args[0])
conn.close()
sys.exit(1)
v_print("numOfRec %d:", numOfRec)
row = 0
while row < numOfRec:
v_print("row: %d", row)
sqlCmd = ['INSERT INTO ']
try:
sqlCmd.append(
"%s.%s%d " % (current_db, tbName, thread))
if (numOfStb > 0 and autosubtable):
sqlCmd.append("USING %s.%s%d TAGS('%s') " %
(current_db, stbName, numOfStb - 1, uuid))
start_time = datetime.datetime(
2021, 1, 25) + datetime.timedelta(seconds=row)
sqlCmd.append("VALUES ")
for batchIter in range(0, batch):
sqlCmd.append("('%s', %f) " %
(
start_time +
datetime.timedelta(
milliseconds=batchIter),
random.random()))
row = row + 1
if row >= numOfRec:
v_print("BREAK, row: %d numOfRec:%d", row, numOfRec)
break
except Exception as e:
print("Error: %s" % e.args[0])
cmd = ' '.join(sqlCmd)
if measure:
exec_start_time = datetime.datetime.now()
if native:
affectedRows = cursor.execute(cmd)
else:
restful_execute(
host, port, user, password, cmd)
if measure:
exec_end_time = datetime.datetime.now()
exec_delta = exec_end_time - exec_start_time
v_print(
"consume %d microseconds",
exec_delta.microseconds)
v_print("cmd: %s, length:%d", cmd, len(cmd))
if native:
cursor.close()
conn.close()
def create_tb_using_stb():
# TODO:
pass
def create_tb():
v_print("create_tb() numOfTb: %d", numOfTb)
for i in range(0, numOfDb):
if native:
cursor.execute("USE %s%d" % (dbName, i))
else:
restful_execute(
host, port, user, password, "USE %s%d" %
(dbName, i))
for j in range(0, numOfTb):
if native:
cursor.execute(
"CREATE TABLE %s%d (ts timestamp, value float)" %
(tbName, j))
else:
restful_execute(
host,
port,
user,
password,
"CREATE TABLE %s%d (ts timestamp, value float)" %
(tbName, j))
def insert_data_process(lock, i, begin, end):
# type: (multiprocessing._LockType, int, int, int) -> None
lock.acquire()
tasks = end - begin
v_print("insert_data_process:%d table from %d to %d, tasks %d", i, begin, end, tasks)
if (threads < (end - begin)):
for j in range(begin, end, threads):
with ThreadPoolExecutor(max_workers=threads) as executor:
k = end if ((j + threads) > end) else (j + threads)
workers = [
executor.submit(
insert_func,
i,
n) for n in range(
j,
k)]
wait(workers, return_when=ALL_COMPLETED)
else:
with ThreadPoolExecutor(max_workers=threads) as executor:
workers = [
executor.submit(
insert_func,
i,
j) for j in range(
begin,
end)]
wait(workers, return_when=ALL_COMPLETED)
lock.release()
def query_db(i):
if native:
cursor.execute("USE %s%d" % (dbName, i))
else:
restful_execute(
host, port, user, password, "USE %s%d" %
(dbName, i))
for j in range(0, numOfTb):
if native:
cursor.execute(
"SELECT COUNT(*) FROM %s%d" % (tbName, j))
else:
restful_execute(
host, port, user, password, "SELECT COUNT(*) FROM %s%d" %
(tbName, j))
def printConfig():
print("###################################################################")
print("# Use native interface: %s" % native)
print("# Server IP: %s" % host)
if native:
print("# Server port: %s" % port)
else:
print("# Server port: %s" % restPort)
print("# Configuration Dir: %s" % configDir)
print("# User: %s" % user)
print("# Password: %s" % password)
print("# Number of Columns per record: %s" % colsPerRecord)
print("# Number of Threads: %s" % threads)
print("# Number of Processes: %s" % processes)
print("# Number of Tables: %s" % numOfTb)
print("# Number of records per Table: %s" % numOfRec)
print("# Records/Request: %s" % batch)
print("# Database name: %s" % dbName)
print("# Replica: %s" % replica)
print("# Use STable: %s" % useStable)
print("# Table prefix: %s" % tbName)
if useStable:
print("# STable prefix: %s" % stbName)
print("# Data order: %s" % outOfOrder)
print("# Data out of order rate: %s" % rateOOOO)
print("# Delete method: %s" % deleteMethod)
print("# Query command: %s" % queryCmd)
print("# Insert Only: %s" % insertOnly)
print("# Verbose output %s" % verbose)
print("# Test time: %s" %
datetime.datetime.now().strftime("%d/%m/%Y %H:%M:%S"))
print("###################################################################")
if __name__ == "__main__":
native = False
verbose = False
debug = False
measure = True
dropDbOnly = False
colsPerRecord = 3
numOfDb = 1
dbName = "test"
replica = 1
batch = 1
numOfTb = 1
tbName = "tb"
useStable = False
numOfStb = 0
stbName = "stb"
numOfRec = 10
ieration = 1
host = "127.0.0.1"
configDir = "/etc/taos"
oneMoreHost = "NotSupported"
port = 6030
restPort = 6041
user = "root"
defaultPass = "taosdata"
processes = 1
threads = 1
insertOnly = False
autosubtable = False
queryCmd = "NO"
outOfOrder = 0
rateOOOO = 0
deleteMethod = 0
skipPrompt = False
try:
opts, args = getopt.gnu_getopt(sys.argv[1:],
'Nh:p:u:P:d:a:m:Ms:Q:T:C:r:l:t:n:c:xOR:D:vgyH',
[
'native', 'host', 'port', 'user', 'password', 'dbname', 'replica', 'tbname',
'stable', 'stbname', 'query', 'threads', 'processes',
'recPerReq', 'colsPerRecord', 'numOfTb', 'numOfRec', 'config',
'insertOnly', 'outOfOrder', 'rateOOOO', 'deleteMethod',
'verbose', 'debug', 'skipPrompt', 'help'
])
except getopt.GetoptError as err:
print('ERROR:', err)
print('Try `taosdemo.py --help` for more options.')
sys.exit(1)
if bool(opts) is False:
print('Try `taosdemo.py --help` for more options.')
sys.exit(1)
for key, value in opts:
if key in ['-H', '--help']:
print('')
print(
'taosdemo.py for TDengine')
print('')
print('Author: Shuduo Sang <sangshuduo@gmail.com>')
print('')
print('\t-H, --help Show usage.')
print('')
print('\t-N, --native flag, Use native interface if set. Default is using RESTful interface.')
print('\t-h, --host <hostname> host, The host to connect to TDengine. Default is localhost.')
print('\t-p, --port <port> port, The TCP/IP port number to use for the connection. Default is 0.')
print('\t-u, --user <username> user, The user name to use when connecting to the server. Default is \'root\'.')
print('\t-P, --password <password> password, The password to use when connecting to the server. Default is \'taosdata\'.')
print('\t-l, --colsPerRec <number> num_of_columns_per_record, The number of columns per record. Default is 3.')
print(
'\t-d, --dbname <dbname> database, Destination database. Default is \'test\'.')
print('\t-a, --replica <replications> replica, Set the replica parameters of the database, Default 1, min: 1, max: 5.')
print(
'\t-m, --tbname <table prefix> table_prefix, Table prefix name. Default is \'t\'.')
print(
'\t-M, --stable flag, Use super table. Default is no')
print(
'\t-s, --stbname <stable prefix> stable_prefix, STable prefix name. Default is \'st\'')
print('\t-Q, --query [NO|EACHTB|command] query, Execute query command. set \'EACHTB\' means select * from each table')
print(
'\t-T, --threads <number> num_of_threads, The number of threads. Default is 1.')
print(
'\t-C, --processes <number> num_of_processes, The number of threads. Default is 1.')
print('\t-r, --batch <number> num_of_records_per_req, The number of records per request. Default is 1000.')
print(
'\t-t, --numOfTb <number> num_of_tables, The number of tables. Default is 1.')
print('\t-n, --numOfRec <number> num_of_records_per_table, The number of records per table. Default is 1.')
print('\t-c, --config <path> config_directory, Configuration directory. Default is \'/etc/taos/\'.')
print('\t-x, --inserOnly flag, Insert only flag.')
print('\t-O, --outOfOrder out of order data insert, 0: In order, 1: Out of order. Default is in order.')
print('\t-R, --rateOOOO <number> rate, Out of order data\'s rate--if order=1 Default 10, min: 0, max: 50.')
print('\t-D, --deleteMethod <number> Delete data methods 0: don\'t delete, 1: delete by table, 2: delete by stable, 3: delete by database.')
print('\t-v, --verbose Print verbose output')
print('\t-g, --debug Print debug output')
print(
'\t-y, --skipPrompt Skip read key for continous test, default is not skip')
print('')
sys.exit(0)
if key in ['-N', '--native']:
try:
import taos
except Exception as e:
print("Error: %s" % e.args[0])
sys.exit(1)
native = True
if key in ['-h', '--host']:
host = value
if key in ['-p', '--port']:
port = int(value)
if key in ['-u', '--user']:
user = value
if key in ['-P', '--password']:
password = value
else:
password = defaultPass
if key in ['-d', '--dbname']:
dbName = value
if key in ['-a', '--replica']:
replica = int(value)
if replica < 1:
print("FATAL: number of replica need > 0")
sys.exit(1)
if key in ['-m', '--tbname']:
tbName = value
if key in ['-M', '--stable']:
useStable = True
numOfStb = 1
if key in ['-s', '--stbname']:
stbName = value
if key in ['-Q', '--query']:
queryCmd = str(value)
if key in ['-T', '--threads']:
threads = int(value)
if threads < 1:
print("FATAL: number of threads must be larger than 0")
sys.exit(1)
if key in ['-C', '--processes']:
processes = int(value)
if processes < 1:
print("FATAL: number of processes must be larger than 0")
sys.exit(1)
if key in ['-r', '--batch']:
batch = int(value)
if key in ['-l', '--colsPerRec']:
colsPerRec = int(value)
if key in ['-t', '--numOfTb']:
numOfTb = int(value)
v_print("numOfTb is %d", numOfTb)
if key in ['-n', '--numOfRec']:
numOfRec = int(value)
v_print("numOfRec is %d", numOfRec)
if numOfRec < 1:
print("FATAL: number of records must be larger than 0")
sys.exit(1)
if key in ['-c', '--config']:
configDir = value
v_print("config dir: %s", configDir)
if key in ['-x', '--insertOnly']:
insertOnly = True
v_print("insert only: %d", insertOnly)
if key in ['-O', '--outOfOrder']:
outOfOrder = int(value)
v_print("out of order is %d", outOfOrder)
if key in ['-R', '--rateOOOO']:
rateOOOO = int(value)
v_print("the rate of out of order is %d", rateOOOO)
if key in ['-D', '--deleteMethod']:
deleteMethod = int(value)
if (deleteMethod < 0) or (deleteMethod > 3):
print(
"inputed delete method is %d, valid value is 0~3, set to default 0" %
deleteMethod)
deleteMethod = 0
v_print("the delete method is %d", deleteMethod)
if key in ['-v', '--verbose']:
verbose = True
if key in ['-g', '--debug']:
debug = True
if key in ['-y', '--skipPrompt']:
skipPrompt = True
if verbose:
printConfig()
if not skipPrompt:
try:
input("Press any key to continue..")
except SyntaxError:
pass
# establish connection first if native
if native:
v_print("host:%s, user:%s passwd:%s configDir:%s ", host, user, password, configDir)
try:
conn = taos.connect(
host=host,
user=user,
password=password,
config=configDir)
v_print("conn: %s", str(conn.__class__))
except Exception as e:
print("Error: %s" % e.args[0])
sys.exit(1)
try:
cursor = conn.cursor()
v_print("cursor:%d %s", id(cursor), str(cursor.__class__))
except Exception as e:
print("Error: %s" % e.args[0])
conn.close()
sys.exit(1)
# drop data only if delete method be set
if deleteMethod > 0:
if deleteMethod == 1:
drop_tables()
print("Drop tables done.")
elif deleteMethod == 2:
drop_stables()
print("Drop super tables done.")
elif deleteMethod == 3:
drop_databases()
print("Drop Database done.")
sys.exit(0)
# create databases
drop_databases()
create_databases()
# use last database
current_db = "%s%d" % (dbName, (numOfDb - 1))
use_database()
if measure:
start_time_begin = time.time()
if numOfStb > 0:
create_stb()
if (autosubtable == False):
create_tb_using_stb()
else:
create_tb()
if measure:
end_time = time.time()
print(
"Total time consumed {} seconds for create table.".format(
(end_time - start_time_begin)))
if native:
cursor.close()
conn.close()
# start insert data
if measure:
start_time = time.time()
manager = Manager()
lock = manager.Lock()
pool = Pool(processes)
begin = 0
end = 0
quotient = numOfTb // processes
if quotient < 1:
processes = numOfTb
quotient = 1
remainder = numOfTb % processes
v_print(
"num of tables: %d, quotient: %d, remainder: %d",
numOfTb,
quotient,
remainder)
for i in range(processes):
begin = end
if i < remainder:
end = begin + quotient + 1
else:
end = begin + quotient
pool.apply_async(insert_data_process, args=(lock, i, begin, end,))
pool.close()
pool.join()
time.sleep(1)
if measure:
end_time = time.time()
print(
"Total time consumed {} seconds for insert data.".format(
(end_time - start_time)))
# query data
if queryCmd != "NO":
print("queryCmd: %s" % queryCmd)
query_data_process(queryCmd)
if measure:
end_time = time.time()
print(
"Total time consumed {} seconds.".format(
(end_time - start_time_begin)))
print("done")
......@@ -69,7 +69,7 @@ cp ${compile_dir}/build/lib/${libfile} ${pkg_dir}${install_home_pat
cp ${compile_dir}/../src/inc/taos.h ${pkg_dir}${install_home_path}/include
cp ${compile_dir}/../src/inc/taosdef.h ${pkg_dir}${install_home_path}/include
cp ${compile_dir}/../src/inc/taoserror.h ${pkg_dir}${install_home_path}/include
cp -r ${top_dir}/tests/examples/* ${pkg_dir}${install_home_path}/examples
cp -r ${top_dir}/examples/* ${pkg_dir}${install_home_path}/examples
#cp -r ${top_dir}/src/connector/python ${pkg_dir}${install_home_path}/connector
#cp -r ${top_dir}/src/connector/go ${pkg_dir}${install_home_path}/connector
#cp -r ${top_dir}/src/connector/nodejs ${pkg_dir}${install_home_path}/connector
......
......@@ -79,7 +79,7 @@ cp %{_compiledir}/../src/inc/taoserror.h %{buildroot}%{homepath}/incl
#cp -r %{_compiledir}/../src/connector/go %{buildroot}%{homepath}/connector
#cp -r %{_compiledir}/../src/connector/nodejs %{buildroot}%{homepath}/connector
#cp %{_compiledir}/build/lib/taos-jdbcdriver*.* %{buildroot}%{homepath}/connector ||:
cp -r %{_compiledir}/../tests/examples/* %{buildroot}%{homepath}/examples
cp -r %{_compiledir}/../examples/* %{buildroot}%{homepath}/examples
if [ -f %{_compiledir}/build/bin/jemalloc-config ]; then
mkdir -p %{buildroot}%{userlocalpath}/bin
......
......@@ -438,9 +438,9 @@ function install_connector() {
function install_examples() {
if [ "$osType" != "Darwin" ]; then
${csudo}cp -rf ${source_dir}/tests/examples/* ${install_main_dir}/examples
${csudo}cp -rf ${source_dir}/examples/* ${install_main_dir}/examples
else
${csudo}cp -rf ${source_dir}/tests/examples/* ${install_main_dir}/examples || ${csudo}cp -rf ${source_dir}/tests/examples/* ${install_main_2_dir}/examples
${csudo}cp -rf ${source_dir}/examples/* ${install_main_dir}/examples || ${csudo}cp -rf ${source_dir}/examples/* ${install_main_2_dir}/examples
fi
}
......
......@@ -134,7 +134,7 @@ chmod a+x ${install_dir}/install_client.sh
# Copy example code
mkdir -p ${install_dir}/examples
examples_dir="${top_dir}/tests/examples"
examples_dir="${top_dir}/examples"
cp -r ${examples_dir}/c ${install_dir}/examples
if [[ "$pagMode" != "lite" ]] && [[ "$cpuType" != "aarch32" ]]; then
cp -r ${examples_dir}/JDBC ${install_dir}/examples
......
......@@ -221,7 +221,7 @@ chmod a+x ${install_dir}/install.sh
# Copy example code
mkdir -p ${install_dir}/examples
examples_dir="${top_dir}/tests/examples"
examples_dir="${top_dir}/examples"
cp -r ${examples_dir}/c ${install_dir}/examples
if [[ "$pagMode" != "lite" ]] && [[ "$cpuType" != "aarch32" ]]; then
if [ -d ${examples_dir}/JDBC/connectionPools/target ]; then
......
Subproject commit a59aa3507ca2fe152f72ce25e696ee5f37c185b9
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册