Merge remote-tracking branch 'origin/docs/wade-3.0' into docs/wade-3.0-pym

This commit is contained in:
Yaming Pei 2024-08-02 10:00:16 +08:00
commit a96d47cb7b
37 changed files with 3858 additions and 1459 deletions

View File

@ -20,13 +20,13 @@ public static void main(String[] args) throws SQLException {
connProps.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8");
try (Connection conn = DriverManager.getConnection(jdbcUrl, connProps)) {
System.out.println("Connected");
System.out.println("Connected to " + jdbcUrl + " successfully.");
// you can use the connection for execute SQL here
} catch (SQLException ex) {
// handle any errors
System.out.println("SQLException: " + ex.getMessage());
// handle any errors, please refer to the JDBC specifications for detailed exceptions info
System.out.println("Failed to connect to " + jdbcUrl + "; ErrCode:" + ex.getErrorCode() + "; ErrMessage: " + ex.getMessage());
}
}
// ANCHOR_END: main

View File

@ -9,13 +9,13 @@ public class RESTConnectExample {
public static void main(String[] args) throws SQLException {
String jdbcUrl = "jdbc:TAOS-RS://localhost:6041?user=root&password=taosdata";
try (Connection conn = DriverManager.getConnection(jdbcUrl)){
System.out.println("Connected");
System.out.println("Connected to " + jdbcUrl + " successfully.");
// you can use the connection for execute SQL here
} catch (SQLException ex) {
// handle any errors
System.out.println("SQLException: " + ex.getMessage());
// handle any errors, please refer to the JDBC specifications for detailed exceptions info
System.out.println("Failed to connect to " + jdbcUrl + "; ErrCode:" + ex.getErrorCode() + "; ErrMessage: " + ex.getMessage());
}
}
// ANCHOR_END: main

View File

@ -16,14 +16,18 @@ public static void main(String[] args) throws SQLException {
String jdbcUrl = "jdbc:TAOS-RS://localhost:6041?user=root&password=taosdata";
Properties connProps = new Properties();
connProps.setProperty(TSDBDriver.PROPERTY_KEY_BATCH_LOAD, "true");
connProps.setProperty(TSDBDriver.PROPERTY_KEY_ENABLE_AUTO_RECONNECT, "true");
connProps.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
connProps.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8");
try (Connection conn = DriverManager.getConnection(jdbcUrl, connProps)){
System.out.println("Connected");
System.out.println("Connected to " + jdbcUrl + " successfully.");
// you can use the connection for execute SQL here
} catch (SQLException ex) {
// handle any errors
System.out.println("SQLException: " + ex.getMessage());
// handle any errors, please refer to the JDBC specifications for detailed exceptions info
System.out.println("Failed to connect to " + jdbcUrl + "; ErrCode:" + ex.getErrorCode() + "; ErrMessage: " + ex.getMessage());
}
}
// ANCHOR_END: main

View File

@ -1,6 +1,6 @@
// ANCHOR: createConnect
const taos = require("@tdengine/websocket");
// ANCHOR: createConnect
async function createConnect() {
let dsn = 'ws://localhost:6041';
let conf = new taos.WSConfig(dsn);

View File

@ -1,19 +1,21 @@
import taos
def test_connection():
def create_connection():
# all parameters are optional.
# if database is specified,
# then it must exist.
conn = taos.connect(host="localhost",
port=6030,
user="root",
password="taosdata",
database="log")
print('client info:', conn.client_info)
print('server info:', conn.server_info)
conn.close()
conn = None
try:
conn = taosws.connect(
user="root",
password="taosdata",
host="192.168.1.98",
port=6041,
)
except Exception as err:
print(f'Exception {err}')
finally:
if conn:
conn.close()
if __name__ == "__main__":
test_connection()
create_connection()

View File

@ -1,26 +1,53 @@
# ANCHOR: connect
import taosws
conn = taosws.connect("taosws://root:taosdata@localhost:6041")
def create_connection():
conn = None
# ANCHOR: connect
try:
conn = taosws.connect(
user="root",
password="taosdata",
host="localhost",
port=6041,
)
except Exception as err:
print(f'Exception {err}')
# ANCHOR_END: connect
return conn
# ANCHOR: basic
conn.execute("drop database if exists connwspy")
conn.execute("create database if not exists connwspy wal_retention_period 3600 keep 36500 ")
conn.execute("use connwspy")
conn.execute("create table if not exists stb (ts timestamp, c1 int) tags (t1 int)")
conn.execute("create table if not exists tb1 using stb tags (1)")
conn.execute("insert into tb1 values (now, 1)")
conn.execute("insert into tb1 values (now+1s, 2)")
conn.execute("insert into tb1 values (now+2s, 3)")
def create_db_table(conn):
# ANCHOR: create_db
try:
conn.execute("CREATE DATABASE IF NOT EXISTS power")
conn.execute("USE power")
conn.execute("CREATE STABLE IF NOT EXISTS meters (ts TIMESTAMP, current FLOAT, voltage INT, phase FLOAT) TAGS (groupId INT, location BINARY(24))")
conn.execute("CREATE TABLE `d0` USING `meters` TAGS(0, 'Los Angles')")
except Exception as err:
print(f'Exception {err}')
# ANCHOR_END: create_db
r = conn.execute("select * from stb")
result = conn.query("select * from stb")
num_of_fields = result.field_count
print(num_of_fields)
def insert(conn):
sql = """
INSERT INTO
power.d1001 USING power.meters TAGS('California.SanFrancisco', 2)
VALUES (NOW + 1a, 10.30000, 219, 0.31000)
(NOW + 2a, 12.60000, 218, 0.33000) (NOW + 3a, 12.30000, 221, 0.31000)
power.d1002 USING power.meters TAGS('California.SanFrancisco', 3)
VALUES (NOW + 1a, 10.30000, 218, 0.25000)
"""
try:
inserted = conn.execute(sql)
assert inserted == 8
except Exception as err:
print(f'Exception {err}')
for row in result:
print(row)
def query(conn):
result = conn.query("select * from stb")
num_of_fields = result.field_count
print(num_of_fields)
for row in result:
print(row)
# output:
# 3

View File

@ -1,14 +1,3 @@
```text
[+<protocol>]://[[<username>:<password>@]<host>:<port>][/<database>][?<p1>=<v1>[&<p2>=<v2>]]
|------------|---|-----------|-----------|------|------|------------|-----------------------|
| protocol | | username | password | host | port | database | params |
- **protocol**: Display using websocket protocol to establish connection.
- **username/password**: Database's username and password.
- **host/port**: Declare host and port. eg. `localhost:6041`
- **database**: Optional, use to specify database name.
- **params**: Other parameters. Like cloud Token.
```
```python
{{#include docs/examples/python/connect_websocket_examples.py:connect}}
{{#include docs/examples/python/connect_example.py}}
```

View File

@ -97,18 +97,63 @@ TDengine 提供了丰富的应用程序开发接口,为了便于用户快速
</TabItem>
<TabItem label="Python" value="python">
使用 `pip` 从 PyPI 安装:
- **安装前准备**
- 安装 Python。新近版本 taospy 包要求 Python 3.6.2+。早期版本 taospy 包要求 Python 3.7+。taos-ws-py 包要求 Python 3.7+。如果系统上还没有 Python 可参考 [Python BeginnersGuide](https://wiki.python.org/moin/BeginnersGuide/Download) 安装。
- 安装 [pip](https://pypi.org/project/pip/)。大部分情况下 Python 的安装包都自带了 pip 工具, 如果没有请参考 [pip documentation](https://pip.pypa.io/en/stable/installation/) 安装。
- 如果使用原生连接,还需[安装客户端驱动](../#安装客户端驱动)。客户端软件包含了 TDengine 客户端动态链接库(libtaos.so 或 taos.dll) 和 TDengine CLI。
```
pip install taospy
```
从 Git URL 安装:
```
pip install git+https://github.com/taosdata/taos-connector-python.git
```
- **使用 pip 安装**
- 卸载旧版本
如果以前安装过旧版本的 Python 连接器, 请提前卸载。
```
pip3 uninstall taos taospy
pip3 uninstall taos taos-ws-py
```
- 安装 `taospy`
- 最新版本
```
pip3 install taospy
```
- 指定某个特定版本安装
```
pip3 install taospy==2.3.0
```
- 从 GitHub 安装
```
pip3 install git+https://github.com/taosdata/taos-connector-python.git
```
:::note 此安装包为原生连接器
- 安装 `taos-ws-py`
```bash
pip3 install taos-ws-py
```
:::note 此安装包为 Websocket 连接器
- 同时安装 `taospy``taos-ws-py`
```bash
pip3 install taospy[ws]
```
- **安装验证**
<Tabs defaultValue="rest">
<TabItem value="native" label="原生连接">
对于原生连接,需要验证客户端驱动和 Python 连接器本身是否都正确安装。如果能成功导入 `taos` 模块,则说明已经正确安装了客户端驱动和 Python 连接器。可在 Python 交互式 Shell 中输入:
```python
import taos
```
</TabItem>
<TabItem value="rest" label="REST 连接">
对于 REST 连接,只需验证是否能成功导入 `taosrest` 模块。可在 Python 交互式 Shell 中输入:
```python
import taosrest
```
</TabItem>
<TabItem value="ws" label="WebSocket 连接">
对于 WebSocket 连接,只需验证是否能成功导入 `taosws` 模块。可在 Python 交互式 Shell 中输入:
```python
import taosws
```
</TabItem>
</Tabs>
</TabItem>
<TabItem label="Go" value="go">
@ -149,23 +194,26 @@ taos = { version = "*", default-features = false, features = ["ws"] }
</TabItem>
<TabItem label="Node.js" value="node">
Node.js 连接器通过不同的包提供不同的连接方式。
- **安装前准备**
- 安装 Node.js 开发环境, 使用14以上版本。下载链接 https://nodejs.org/en/download/
1. 安装 Node.js 原生连接器
- **安装**
- 使用 npm 安装 Node.js 连接器
```
npm install @tdengine/websocket
```
:::note Node.js 目前只支持 Websocket 连接
- **安装验证**
- 新建安装验证目录,例如:`~/tdengine-test`,下载 GitHub 上 [nodejsChecker.js 源代码](https://github.com/taosdata/TDengine/tree/main/docs/examples/node/websocketexample/nodejsChecker.js)到本地。
- 在命令行中执行以下命令。
```bash
npm init -y
npm install @tdengine/websocket
node nodejsChecker.js
```
- 执行以上步骤后,在命令行会输出 nodeChecker.js 连接 TDengine 实例,并执行简单插入和查询的结果。
```
npm install @tdengine/client
```
:::note
推荐 Node 版本大于等于 `node-v12.8.0` 小于 `node-v13.0.0`
:::
2. 安装 Node.js REST 连接器
```
npm install @tdengine/rest
```
</TabItem>
<TabItem label="C#" value="csharp">
@ -264,66 +312,16 @@ phpize && ./configure --enable-swoole && make -j && make install
在执行这一步之前,请确保有一个正在运行的,且可以访问到的 TDengine而且服务端的 FQDN 配置正确。以下示例代码,都假设 TDengine 安装在本机,且 FQDN默认 localhost 和 serverPort默认 6030 都使用默认配置。
### 连接参数
连接的配置项较多,因此在建立连接之前,我们能先介绍一下各语言连接器建立连接使用的参数。
<Tabs defaultValue="java" groupId="lang">
<TabItem label="Java" value="java">
Java 连接器建立连接的参数有 URL 和 properties下面分别详细介绍
Java 连接器建立连接的参数有 URL 和 Properties
TDengine 的 JDBC URL 规范格式为:
`jdbc:[TAOS|TAOS-RS]://[host_name]:[port]/[database_name]?[user={user}|&password={password}|&charset={charset}|&cfgdir={config_dir}|&locale={locale}|&timezone={timezone}]`
对于建立连接,原生连接与 REST 连接有细微不同。
**注**REST 连接中增加 `batchfetch` 参数并设置为 true将开启 WebSocket 连接。
**注意**:使用 JDBC 原生连接taos-jdbcdriver 需要依赖客户端驱动Linux 下是 libtaos.soWindows 下是 taos.dllmacOS 下是 libtaos.dylib
url 中的配置参数如下:
- user登录 TDengine 用户名,默认值 'root'。
- password用户登录密码默认值 'taosdata'。
- batchfetch: true在执行查询时批量拉取结果集false逐行拉取结果集。默认值为false。逐行拉取结果集使用 HTTP 方式进行数据传输。JDBC REST 连接支持批量拉取数据功能。taos-jdbcdriver 与 TDengine 之间通过 WebSocket 连接进行数据传输。相较于 HTTPWebSocket 可以使 JDBC REST 连接支持大数据量查询,并提升查询性能。
- charset: 当开启批量拉取数据时,指定解析字符串数据的字符集。
- batchErrorIgnoretrue在执行 Statement 的 executeBatch 时,如果中间有一条 SQL 执行失败,继续执行下面的 SQL 了。false不再执行失败 SQL 后的任何语句。默认值为false。
- httpConnectTimeout: 连接超时时间,单位 ms 默认值为 60000。
- httpSocketTimeout: socket 超时时间,单位 ms默认值为 60000。仅在 batchfetch 设置为 false 时生效。
- messageWaitTimeout: 消息超时时间, 单位 ms 默认值为 60000。 仅在 batchfetch 设置为 true 时生效。
- useSSL: 连接中是否使用 SSL。
- httpPoolSize: REST 并发请求大小,默认 20。
**注意**部分配置项比如locale、timezone在 REST 连接中不生效。
除了通过指定的 URL 获取连接,还可以使用 Properties 指定建立连接时的参数。
properties 中的配置参数如下:
- TSDBDriver.PROPERTY_KEY_USER登录 TDengine 用户名,默认值 'root'。
- TSDBDriver.PROPERTY_KEY_PASSWORD用户登录密码默认值 'taosdata'。
- TSDBDriver.PROPERTY_KEY_BATCH_LOAD: true在执行查询时批量拉取结果集false逐行拉取结果集。默认值为false。
- TSDBDriver.PROPERTY_KEY_BATCH_ERROR_IGNOREtrue在执行 Statement 的 executeBatch 时,如果中间有一条 SQL 执行失败,继续执行下面的 sq 了。false不再执行失败 SQL 后的任何语句。默认值为false。
- TSDBDriver.PROPERTY_KEY_CONFIG_DIR仅在使用 JDBC 原生连接时生效。客户端配置文件目录路径Linux OS 上默认值 `/etc/taos`Windows OS 上默认值 `C:/TDengine/cfg`
- TSDBDriver.PROPERTY_KEY_CHARSET客户端使用的字符集默认值为系统字符集。
- TSDBDriver.PROPERTY_KEY_LOCALE仅在使用 JDBC 原生连接时生效。 客户端语言环境,默认值系统当前 locale。
- TSDBDriver.PROPERTY_KEY_TIME_ZONE仅在使用 JDBC 原生连接时生效。 客户端使用的时区默认值为系统当前时区。因为历史的原因我们只支持POSIX标准的部分规范如UTC-8(代表中国上上海), GMT-8Asia/Shanghai 这几种形式。
- TSDBDriver.HTTP_CONNECT_TIMEOUT: 连接超时时间,单位 ms 默认值为 60000。仅在 REST 连接时生效。
- TSDBDriver.HTTP_SOCKET_TIMEOUT: socket 超时时间,单位 ms默认值为 60000。仅在 REST 连接且 batchfetch 设置为 false 时生效。
- TSDBDriver.PROPERTY_KEY_MESSAGE_WAIT_TIMEOUT: 消息超时时间, 单位 ms 默认值为 60000。 仅在 REST 连接且 batchfetch 设置为 true 时生效。
- TSDBDriver.PROPERTY_KEY_USE_SSL: 连接中是否使用 SSL。仅在 REST 连接时生效。
- TSDBDriver.HTTP_POOL_SIZE: REST 并发请求大小,默认 20。
- TSDBDriver.PROPERTY_KEY_ENABLE_COMPRESSION: 传输过程是否启用压缩。仅在使用 REST/Websocket 连接时生效。true: 启用false: 不启用。默认为 false。
- TSDBDriver.PROPERTY_KEY_ENABLE_AUTO_RECONNECT: 是否启用自动重连。仅在使用 Websocket 连接时生效。true: 启用false: 不启用。默认为 false。
> **注意**:启用自动重连仅对简单执行 SQL 语句以及 无模式写入、数据订阅有效。对于参数绑定无效。自动重连仅对连接建立时通过参数指定数据库有效,对后面的 `use db` 语句切换数据库无效。
- TSDBDriver.PROPERTY_KEY_RECONNECT_INTERVAL_MS: 自动重连重试间隔,单位毫秒,默认值 2000。仅在 PROPERTY_KEY_ENABLE_AUTO_RECONNECT 为 true 时生效。
- TSDBDriver.PROPERTY_KEY_RECONNECT_RETRY_COUNT: 自动重连重试次数,默认值 3仅在 PROPERTY_KEY_ENABLE_AUTO_RECONNECT 为 true 时生效。
- TSDBDriver.PROPERTY_KEY_DISABLE_SSL_CERT_VALIDATION: 关闭 SSL 证书验证 。仅在使用 Websocket 连接时生效。true: 启用false: 不启用。默认为 false。
**配置参数的优先级:**
通过前面三种方式获取连接,如果配置参数在 url、Properties、客户端配置文件中有重复则参数的`优先级由高到低`分别如下:
1. JDBC URL 参数,如上所述,可以在 JDBC URL 的参数中指定。
2. Properties connProps
3. 使用原生连接时TDengine 客户端驱动的配置文件 taos.cfg
例如:在 url 中指定了 password 为 taosdata在 Properties 中指定了 password 为 taosdemo那么JDBC 会使用 url 中的 password 建立连接。
URL 和 Properties 的详细参数说明和如何使用详见 [API 说明](../../reference/connector/java/#url-规范)
</TabItem>
<TabItem label="Python" value="python">
@ -372,6 +370,7 @@ properties 中的配置参数如下:
</Tabs>
### Websocket 连接
下面是各语言连接器建立 Websocket 连接代码样例。演示了如何使用 Websocket 连接方式连接到 TDengine 数据库,并对连接设定一些参数。整个过程主要涉及到数据库连接的建立和异常处理。
<Tabs defaultValue="java" groupId="lang">
<TabItem label="Java" value="java">
@ -380,10 +379,9 @@ properties 中的配置参数如下:
```
</TabItem>
<TabItem label="Python" value="python">
```python
{{#include docs/examples/python/connect_websocket_examples.py:connect}}
```
```python
{{#include docs/examples/python/connect_websocket_examples.py:connect}}
```
</TabItem>
<TabItem label="Go" value="go">
<ConnGo />
@ -392,9 +390,9 @@ properties 中的配置参数如下:
<ConnRust />
</TabItem>
<TabItem label="Node.js" value="node">
```js
{{#include docs/examples/node/websocketexample/sql_example.js:createConnect}}
```
```js
{{#include docs/examples/node/websocketexample/sql_example.js:createConnect}}
```
</TabItem>
<TabItem label="C#" value="csharp">
<ConnCSNative />
@ -411,6 +409,8 @@ properties 中的配置参数如下:
</Tabs>
### 原生连接
下面是各语言连接器建立原生连接代码样例。演示了如何使用原生连接方式连接到 TDengine 数据库,并对连接设定一些参数。整个过程主要涉及到数据库连接的建立和异常处理。
<Tabs defaultValue="java" groupId="lang">
<TabItem label="Java" value="java">
```java
@ -442,6 +442,8 @@ properties 中的配置参数如下:
</Tabs>
### REST 连接
下面是各语言连接器建立 RESt 连接代码样例。演示了如何使用 REST 连接方式连接到 TDengine 数据库。整个过程主要涉及到数据库连接的建立和异常处理。
<Tabs defaultValue="java" groupId="lang">
<TabItem label="Java" value="java">
```java
@ -449,7 +451,9 @@ properties 中的配置参数如下:
```
</TabItem>
<TabItem label="Python" value="python">
<ConnPythonNative />
```python
{{#include docs/examples/python/connect_rest_examples.py:connect}}
```
</TabItem>
<TabItem label="Go" value="go">
<ConnGo />

View File

@ -11,9 +11,9 @@ TDengine 对 SQL 语言提供了全面的支持,允许用户以熟悉的 SQL
下面介绍使用各语言连接器通过执行 SQL 完成建库、建表、写入数据和查询数据。
## 建库和表
以智能电表为例,展示如何使用连接器执行 SQL 来创建数据库和表。
下面以智能电表为例,展示使用各语言连接器如何执行 SQL 命令创建一个名为 `power` 的数据库,然后使用 `power` 数据库为默认数据库。
接着创建一个名为 `meters` 的超级表STABLE其表结构包含时间戳、电流、电压、相位等列以及分组 ID 和位置作为标签。
<Tabs defaultValue="java" groupId="lang">
<TabItem value="java" label="Java">
@ -25,6 +25,8 @@ TDengine 对 SQL 语言提供了全面的支持,允许用户以熟悉的 SQL
</TabItem>
<TabItem label="Python" value="python">
- Websocket 连接
</TabItem>
<TabItem label="Go" value="go">
</TabItem>
@ -45,7 +47,7 @@ TDengine 对 SQL 语言提供了全面的支持,允许用户以熟悉的 SQL
</Tabs>
## 插入数据
以智能电表为例,展示如何使用连接器执行 SQL 来插入数据。
下面以智能电表为例,展示如何使用连接器执行 SQL 来插入数据`power` 数据库的 `meters` 超级表样例使用 TDengine 自动建表 SQL 语法,写入 d1001 子表中 3 条数据,写入 d1002 子表中 1 条数据,然后打印出实际插入数据条数。
<Tabs defaultValue="java" groupId="lang">
<TabItem value="java" label="Java">
@ -80,9 +82,8 @@ NOW 为系统内部函数,默认为客户端所在计算机当前时间。 NOW
</TabItem>
</Tabs>
## 查询数据
以智能电表为例,展示如何使用各语言连接器执行 SQL 来查询数据,并将获取到的结果打印出来。
下面以智能电表为例,展示如何使用各语言连接器执行 SQL 来查询数据,`power` 数据库 `meters` 超级表中查询最多 100 行数据,并将获取到的结果按行打印出来。
<Tabs defaultValue="java" groupId="lang">
<TabItem label="Java" value="java">
@ -113,7 +114,6 @@ NOW 为系统内部函数,默认为客户端所在计算机当前时间。 NOW
</TabItem>
</Tabs>
## 执行带有 reqId 的 SQL
reqId 可用于请求链路追踪reqId 就像分布式系统中的 traceId 作用一样。一个请求可能需要经过多个服务或者模块才能完成。reqId 用于标识和关联这个请求的所有相关操作,以便于我们可以追踪和分析请求的完整路径。

View File

@ -153,12 +153,17 @@ st,t1=3,t2=4,t3=t3 c1=3i64,c6="passit" 1626006833640000000
## 无模式写入示例
下面以智能电表为例,介绍各语言连接器使用无模式写入接口写入数据的代码样例,包含了三种协议: InfluxDB 的行协议、OpenTSDB 的 TELNET 行协议和 OpenTSDB 的 JSON 格式协议。
:::note
- 因为无模式写入自动建表规则与之前执行 SQL 样例中不同,因此运行代码样例前请确保 `meters`、`metric_telnet` 和 `metric_json` 表不存在。
- OpenTSDB 的 TELNET 行协议和 OpenTSDB 的 JSON 格式协议只支持一个数据列,因此我们采用了其他示例。
:::
### Websocket 连接
<Tabs defaultValue="java" groupId="schemaless">
<TabItem value="java" label="Java">
```java
{{#include examples/JDBC/JDBCDemo/src/main/java/com/taosdata/example/SchemalessWsTest.java:schemaless}}
```
@ -190,9 +195,9 @@ writer.write(lineDemo, SchemalessProtocolType.LINE, SchemalessTimestampType.NANO
### 原生连接
<Tabs defaultValue="java" groupId="lang">
<TabItem label="Java" value="java">
```java
{{#include examples/JDBC/JDBCDemo/src/main/java/com/taosdata/example/SchemalessJniTest.java:schemaless}}
```
```java
{{#include examples/JDBC/JDBCDemo/src/main/java/com/taosdata/example/SchemalessJniTest.java:schemaless}}
```
执行带有 reqId 的无模式写入,此 reqId 可用于请求链路追踪。
@ -219,6 +224,29 @@ writer.write(lineDemo, SchemalessProtocolType.LINE, SchemalessTimestampType.NANO
</Tabs>
### REST 连接
<Tabs defaultValue="java" groupId="lang">
<TabItem label="Java" value="java">
不支持
</TabItem>
<TabItem label="Python" value="python">
</TabItem>
<TabItem label="Go" value="go">
</TabItem>
<TabItem label="Rust" value="rust">
</TabItem>
<TabItem label="C#" value="csharp">
</TabItem>
<TabItem label="R" value="r">
</TabItem>
<TabItem label="C" value="c">
</TabItem>
<TabItem label="PHP" value="php">
</TabItem>
</Tabs>
## 查询写入的数据
运行上节的样例代码,会在 power 数据库中自动建表,我们可以通过 taos shell 或者应用程序来查询数据。下面给出用 taos shell 查询超级表和 meters 表数据的样例。

View File

@ -13,7 +13,14 @@ import TabItem from "@theme/TabItem";
- 预编译当使用参数绑定时SQL 语句可以被预编译并缓存,后续使用不同的参数值执行时,可以直接使用预编译的版本,提高执行效率。
- 减少网络开销:参数绑定还可以减少发送到数据库的数据量,因为只需要发送参数值而不是完整的 SQL 语句,特别是在执行大量相似的插入或更新操作时,这种差异尤为明显。
下面我们继续以智能电表为例,展示各语言连接器使用参数绑定高效写入的功能。
下面我们继续以智能电表为例,展示各语言连接器使用参数绑定高效写入的功能:
1. 准备一个参数化的 SQL 插入语句,用于向超级表 `meters` 中插入数据。这个语句允许动态地指定子表名、标签和列值。
2. 循环生成多个子表及其对应的数据行。对于每个子表:
- 设置子表的名称和标签值(分组 ID 和位置)。
- 生成多行数据,每行包括一个时间戳、随机生成的电流、电压和相位值。
- 执行批量插入操作,将这些数据行插入到对应的子表中。
3. 最后打印实际插入表中的行数。
## Websocket 连接
<Tabs defaultValue="java" groupId="lang">
<TabItem value="java" label="Java">

View File

@ -7,7 +7,7 @@ toc_max_heading_level: 4
import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";
TDengine 提供了类似于消息队列产品的数据订阅和消费接口。在许多场景中采用TDengine 的时序大数据平台无须再集成消息队列产品从而简化应用程序设计并降低运维成本。本章介绍各语言连接器数据订阅的相关API以及使用方法。 数据订阅的基础知识请参考 [数据订阅](../../advanced/subscription/)
TDengine 提供了类似于消息队列产品的数据订阅和消费接口。在许多场景中,采用 TDengine 的时序大数据平台,无须再集成消息队列产品,从而简化应用程序设计并降低运维成本。本章介绍各语言连接器数据订阅的相关 API 以及使用方法。 数据订阅的基础知识请参考 [数据订阅](../../advanced/subscription/)
## 创建主题
请用 taos shell 或者 参考 [执行 SQL](../sql/) 章节用程序执行创建主题的 SQL`CREATE TOPIC IF NOT EXISTS topic_meters AS SELECT ts, current, voltage, phase, groupid, location FROM meters`
@ -16,7 +16,7 @@ TDengine 提供了类似于消息队列产品的数据订阅和消费接口。
**注意**
在 TDengine 连接器实现中,对于订阅查询,有以下限制。
- 查询语句限制:订阅查询只能使用 select 语句不支持其他类型的SQL如 insert、update或delete等。
- 查询语句限制:订阅查询只能使用 select 语句不支持其他类型的SQL如 insert、update delete 等。
- 原始始数据查询:订阅查询只能查询原始数据,而不能查询聚合或计算结果。
- 时间顺序限制:订阅查询只能按照时间正序查询数据。
@ -26,30 +26,29 @@ TDengine 消费者的概念跟 Kafka 类似,消费者通过订阅主题来接
### 创建参数
创建消费者的参数较多,非常灵活的支持了各种连接类型、 Offset 提交方式、压缩、重连、反序列化等特性。各语言连接器都适用的通用基础配置项如下表所示:
| 参数名称 | 类型 | 参数说明 | 备注 |
| :-----------------------: | :-----: | ----------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `td.connect.ip` | string | 服务端的 IP 地址 | |
| `td.connect.user` | string | 用户名 | |
| `td.connect.pass` | string | 密码 | |
| `td.connect.port` | integer | 服务端的端口号 | |
| `group.id` | string | 消费组 ID同一消费组共享消费进度 | <br />**必填项**。最大长度192。<br />每个topic最多可建立100个 consumer group |
| `client.id` | string | 客户端 ID | 最大长度192。 |
| `auto.offset.reset` | enum | 消费组订阅的初始位置 | <br />`earliest`: default(version < 3.2.0.0);从头开始订阅; <br/>`latest`: default(version >= 3.2.0.0);仅从最新数据开始订阅; <br/>`none`: 没有提交的 offset 无法订阅 |
| `enable.auto.commit` | boolean | 是否启用消费位点自动提交true: 自动提交客户端应用无需commitfalse客户端应用需要自行commit | 默认值为 true |
| `auto.commit.interval.ms` | integer | 消费记录自动提交消费位点时间间隔,单位为毫秒 | 默认值为 5000 |
| `msg.with.table.name` | boolean | 是否允许从消息中解析表名, 不适用于列订阅(列订阅时可将 tbname 作为列写入 subquery 语句从3.2.0.0版本该参数废弃恒为true | 默认关闭 |
| `enable.replay` | boolean | 是否开启数据回放功能 | 默认关闭 |
下面是各语言连接器创建参数:
<Tabs defaultValue="java" groupId="lang">
<TabItem value="java" label="Java">
Java 连接器创建消费者的参数为 Properties 可以设置如下参数:
Java 连接器创建消费者的参数为 Properties 可以设置的参数列表请参考 [API 说明](../../reference/connector/java/#消费者)
其他参数请参考上文通用基础配置项。
- td.connect.type: 连接方式。jni表示使用动态库连接的方式ws/WebSocket表示使用 WebSocket 进行数据通信。默认为 jni 方式。
- bootstrap.servers: TDengine 服务端所在的`ip:port`,如果使用 WebSocket 连接,则为 taosAdapter 所在的`ip:port`。
- enable.auto.commit: 是否允许自动提交。
- group.id: consumer: 所在的 group。
- value.deserializer: 结果集反序列化方法,可以继承 `com.taosdata.jdbc.tmq.ReferenceDeserializer`,并指定结果集 bean实现反序列化。也可以继承 `com.taosdata.jdbc.tmq.Deserializer`,根据 SQL 的 resultSet 自定义反序列化方式。
- httpConnectTimeout: 创建连接超时参数,单位 ms默认为 5000 ms。仅在 WebSocket 连接下有效。
- messageWaitTimeout: 数据传输超时参数,单位 ms默认为 10000 ms。仅在 WebSocket 连接下有效。
- httpPoolSize: 同一个连接下最大并行请求数。仅在 WebSocket 连接下有效。
- TSDBDriver.PROPERTY_KEY_ENABLE_COMPRESSION: 传输过程是否启用压缩。仅在使用 Websocket 连接时生效。true: 启用false: 不启用。默认为 false。
- TSDBDriver.PROPERTY_KEY_ENABLE_AUTO_RECONNECT: 是否启用自动重连。仅在使用 Websocket 连接时生效。true: 启用false: 不启用。默认为 false。
- TSDBDriver.PROPERTY_KEY_RECONNECT_INTERVAL_MS: 自动重连重试间隔,单位毫秒,默认值 2000。仅在 PROPERTY_KEY_ENABLE_AUTO_RECONNECT 为 true 时生效。
- TSDBDriver.PROPERTY_KEY_RECONNECT_RETRY_COUNT: 自动重连重试次数,默认值 3仅在 PROPERTY_KEY_ENABLE_AUTO_RECONNECT 为 true 时生效。
其他参数请参考:[Consumer 参数列表](../../develop/tmq/#数据订阅相关参数) 注意TDengine服务端自 3.2.0.0 版本开始消息订阅中的 auto.offset.reset 默认值发生变化。
:::note
- Java 连接器数据订阅 WebSocket 连接方式跟 原生连接方式,除了在创建消费者时参数不同之外,其他接口并无区别。因此我们以 Websocket 连接方式为例介绍数据订阅的其他功能。
:::
</TabItem>
<TabItem label="Python" value="python">
@ -79,12 +78,14 @@ Java 连接器创建消费者的参数为 Properties 可以设置如下参数
</Tabs>
### Websocket 连接
介绍各语言连接器使用 Websocket 连接方式创建消费者。指定连接的服务器地址,设置自动提交,从最新消息开始消费,指定 `group.id``client.id` 等信息。有的语言的连接器还支持反序列化参数。
<Tabs defaultValue="java" groupId="lang">
<TabItem value="java" label="Java">
```java
{{#include examples/JDBC/JDBCDemo/src/main/java/com/taosdata/example/AbsWsConsumerLoop.java:create_consumer}}
{{#include examples/JDBC/JDBCDemo/src/main/java/com/taosdata/example/WsConsumerLoopFull.java:create_consumer}}
```
</TabItem>
@ -126,12 +127,15 @@ Java 连接器创建消费者的参数为 Properties 可以设置如下参数
### 原生连接
介绍各语言连接器使用原生连接方式创建消费者。指定连接的服务器地址,设置自动提交,从最新消息开始消费,指定 `group.id``client.id` 等信息。有的语言的连接器还支持反序列化参数。
<Tabs groupId="lang">
<TabItem value="java" label="Java">
```java
{{#include examples/JDBC/JDBCDemo/src/main/java/com/taosdata/example/AbsConsumerLoop.java:create_consumer}}
{{#include examples/JDBC/JDBCDemo/src/main/java/com/taosdata/example/ConsumerLoopFull.java:create_consumer}}
```
@ -176,7 +180,7 @@ Java 连接器创建消费者的参数为 Properties 可以设置如下参数
<TabItem value="java" label="Java">
```java
{{#include examples/JDBC/JDBCDemo/src/main/java/com/taosdata/example/AbsConsumerLoop.java:poll_data_code_piece}}
{{#include examples/JDBC/JDBCDemo/src/main/java/com/taosdata/example/WsConsumerLoopFull.java:poll_data_code_piece}}
```
- `subscribe` 方法的参数含义为:订阅的主题列表(即名称),支持同时订阅多个主题。
@ -269,26 +273,7 @@ Java 连接器创建消费者的参数为 Properties 可以设置如下参数
<TabItem value="java" label="Java">
```java
// 获取订阅的 topicPartition
Set<TopicPartition assignment() throws SQLException;
// 获取 offset
long position(TopicPartition partition) throws SQLException;
Map<TopicPartition, Long position(String topic) throws SQLException;
Map<TopicPartition, Long beginningOffsets(String topic) throws SQLException;
Map<TopicPartition, Long endOffsets(String topic) throws SQLException;
Map<TopicPartition, OffsetAndMetadata committed(Set<TopicPartition partitions) throws SQLException;
// 指定下一次 poll 中使用的 offset
void seek(TopicPartition partition, long offset) throws SQLException;
void seekToBeginning(Collection<TopicPartition partitions) throws SQLException;
void seekToEnd(Collection<TopicPartition partitions) throws SQLException;
```
示例代码:
```java
{{#include examples/JDBC/JDBCDemo/src/main/java/com/taosdata/example/ConsumerOffsetSeek.java:consumer_seek}}
{{#include examples/JDBC/JDBCDemo/src/main/java/com/taosdata/example/WsConsumerLoopFull.java:consumer_seek}}
```
</TabItem>
@ -333,7 +318,6 @@ void seekToEnd(Collection<TopicPartition partitions) throws SQLException;
<Tabs groupId="lang">
<TabItem value="java" label="Java">
同 Websocket 代码样例。
</TabItem>
@ -378,17 +362,9 @@ void seekToEnd(Collection<TopicPartition partitions) throws SQLException;
<Tabs defaultValue="java" groupId="lang">
<TabItem value="java" label="Java">
```java
void commitSync() throws SQLException;
void commitSync(Map<TopicPartition, OffsetAndMetadata offsets) throws SQLException;
// 异步提交仅在 native 连接下有效
void commitAsync(OffsetCommitCallback<V callback) throws SQLException;
void commitAsync(Map<TopicPartition, OffsetAndMetadata offsets, OffsetCommitCallback<V callback) throws SQLException;
```
```java
{{#include examples/JDBC/JDBCDemo/src/main/java/com/taosdata/example/AbsConsumerLoop.java:commit_code_piece}}
{{#include examples/JDBC/JDBCDemo/src/main/java/com/taosdata/example/WsConsumerLoopFull.java:commit_code_piece}}
```
</TabItem>
@ -485,7 +461,7 @@ void commitAsync(Map<TopicPartition, OffsetAndMetadata offsets, OffsetCommitCall
<TabItem value="java" label="Java">
```java
{{#include examples/JDBC/JDBCDemo/src/main/java/com/taosdata/example/AbsConsumerLoop.java:unsubscribe_data_code_piece}}
{{#include examples/JDBC/JDBCDemo/src/main/java/com/taosdata/example/WsConsumerLoopFull.java:unsubscribe_data_code_piece}}
```
</TabItem>
@ -577,11 +553,14 @@ void commitAsync(Map<TopicPartition, OffsetAndMetadata offsets, OffsetCommitCall
### Websocket 连接
<Tabs defaultValue="java" groupId="lang">
<TabItem value="java" label="Java">
<details>
<summary>完整 Websocket 连接代码示例</summary>
```java
{{#include examples/JDBC/JDBCDemo/src/main/java/com/taosdata/example/AbsWsConsumerLoop.java:consumer_demo}}
{{#include examples/JDBC/JDBCDemo/src/main/java/com/taosdata/example/WsConsumerLoopFull.java:consumer_demo}}
```
**注意**:这里的 value.deserializer 配置参数值应该根据测试环境的包路径做相应的调整。
</details>
</TabItem>
<TabItem label="Python" value="python">
@ -624,10 +603,17 @@ void commitAsync(Map<TopicPartition, OffsetAndMetadata offsets, OffsetCommitCall
### 原生连接
<Tabs groupId="lang">
<TabItem value="java" label="Java">
<details>
<summary>完整原生连接代码示例</summary>
```java
{{#include examples/JDBC/JDBCDemo/src/main/java/com/taosdata/example/AbsConsumerLoopFull.java:consumer_demo}}
{{#include examples/JDBC/JDBCDemo/src/main/java/com/taosdata/example/ConsumerLoopFull.java:consumer_demo}}
```
**注意**:这里的 value.deserializer 配置参数值应该根据测试环境的包路径做相应的调整。
</details>
</TabItem>
<TabItem label="Python" value="python">

View File

@ -15,7 +15,7 @@ description: 让开发者能够快速上手的指南
7. 在很多场景下(如车辆管理),应用需要获取每个数据采集点的最新状态,那么建议你采用 TDengine 的 Cache 功能,而不用单独部署 Redis 等缓存软件。
8. 如果你发现 TDengine 的函数无法满足你的要求那么你可以使用用户自定义函数UDF来解决问题。
本部分内容就是按照上述顺序组织的。为便于理解TDengine 为每个功能和每个支持的编程语言都提供了示例代码。如果你希望深入了解 SQL 的使用,需要查看[SQL 手册](../taos-sql/)。如果想更深入地了解各连接器的使用,请阅读[连接器参考指南](../connector/)。如果还希望想将 TDengine 与第三方系统集成起来,比如 Grafana, 请参考[第三方工具](../third-party/)。
本部分内容就是按照上述顺序组织的。为便于理解TDengine 为每个功能和每个支持的编程语言都提供了示例代码。如果你希望深入了解 SQL 的使用,需要查看[SQL 手册](../taos-sql/)。如果想更深入地了解各连接器的使用,请阅读[连接器参考指南](../reference/connector/)。如果还希望想将 TDengine 与第三方系统集成起来,比如 Grafana, 请参考[第三方工具](../third-party/)。
如果在开发过程中遇到任何问题,请点击每个页面下方的["反馈问题"](https://github.com/taosdata/TDengine/issues/new/choose), 在 GitHub 上直接递交 Issue。

View File

@ -205,14 +205,13 @@ TDengine 的 JDBC URL 规范格式为:
**注**REST 连接中增加 `batchfetch` 参数并设置为 true将开启 WebSocket 连接。
##### 原生连接
**原生连接**
`jdbc:TAOS://taosdemo.com:6030/power?user=root&password=taosdata`,使用了 JDBC 原生连接的 TSDBDriver建立了到 hostname 为 taosdemo.com端口为 6030TDengine 的默认端口),数据库名为 power 的连接。这个 URL
中指定用户名user为 root密码password为 taosdata。
**注意**:使用 JDBC 原生连接taos-jdbcdriver 需要依赖客户端驱动Linux 下是 libtaos.soWindows 下是 taos.dllmacOS 下是 libtaos.dylib
对于原生连接 url 中支持的配置参数如下:
- user登录 TDengine 用户名,默认值 'root'。
- password用户登录密码默认值 'taosdata'。
- cfgdir客户端配置文件目录路径Linux OS 上默认值 `/etc/taos`Windows OS 上默认值 `C:/TDengine/cfg`。
@ -234,7 +233,7 @@ TDengine 中,只要保证 firstEp 和 secondEp 中一个节点有效,就可
> **注意**:这里的配置文件指的是调用 JDBC Connector 的应用程序所在机器上的配置文件Linux OS 上默认值 /etc/taos/taos.cfg Windows OS 上默认值 C://TDengine/cfg/taos.cfg。
##### Websocket 和 REST 连接
**Websocket 和 REST 连接**
使用 JDBC Websocket 或 REST 连接,不需要依赖客户端驱动。与 JDBC 原生连接相比,仅需要:
1. driverClass 指定为“com.taosdata.jdbc.rs.RestfulDriver”
@ -242,7 +241,6 @@ TDengine 中,只要保证 firstEp 和 secondEp 中一个节点有效,就可
3. 使用 6041 作为连接端口。
对于 Websocket 和 REST 连接url 中的配置参数如下:
- user登录 TDengine 用户名,默认值 'root'。
- password用户登录密码默认值 'taosdata'。
- batchfetch: true在执行查询时批量拉取结果集false逐行拉取结果集。默认值为false。逐行拉取结果集使用 HTTP 方式进行数据传输。JDBC REST 连接支持批量拉取数据功能。taos-jdbcdriver 与 TDengine 之间通过 WebSocket 连接进行数据传输。相较于 HTTPWebSocket 可以使 JDBC REST 连接支持大数据量查询,并提升查询性能。
@ -270,7 +268,6 @@ TDengine 中,只要保证 firstEp 和 secondEp 中一个节点有效,就可
> **注意**:应用中设置的 client parameter 为进程级别的,即如果要更新 client 的参数,需要重启应用。这是因为 client parameter 是全局参数,仅在应用程序的第一次设置生效。
properties 中的配置参数如下:
- TSDBDriver.PROPERTY_KEY_USER登录 TDengine 用户名,默认值 'root'。
- TSDBDriver.PROPERTY_KEY_PASSWORD用户登录密码默认值 'taosdata'。
- TSDBDriver.PROPERTY_KEY_BATCH_LOAD: true在执行查询时批量拉取结果集false逐行拉取结果集。默认值为false。
@ -292,10 +289,9 @@ properties 中的配置参数如下:
- TSDBDriver.PROPERTY_KEY_RECONNECT_RETRY_COUNT: 自动重连重试次数,默认值 3仅在 PROPERTY_KEY_ENABLE_AUTO_RECONNECT 为 true 时生效。
- TSDBDriver.PROPERTY_KEY_DISABLE_SSL_CERT_VALIDATION: 关闭 SSL 证书验证 。仅在使用 Websocket 连接时生效。true: 启用false: 不启用。默认为 false。
此外对 JDBC 原生连接,通过指定 URL 和 Properties 还可以指定其他参数比如日志级别、SQL 长度等。更多详细配置请参考[客户端配置](../../reference/config/)。
##### 配置参数的优先级
**配置参数的优先级**
通过前面三种方式获取连接,如果配置参数在 url、Properties、客户端配置文件中有重复则参数的`优先级由高到低`分别如下:
@ -308,142 +304,142 @@ properties 中的配置参数如下:
#### 接口说明
- `Connection connect(String url, java.util.Properties info) throws SQLException`
- **接口说明**:连接 TDengine 数据库
- **接口说明**:连接 TDengine 数据库
- **参数说明**
- `url`:连接地址 url详见上文 URL 规范
- `info`:连接属性,详见上文 Properties 章节
- **返回值**:连接对象
- **异常**:连接失败抛出 `SQLException` 异常
- `url`:连接地址 url详见上文 URL 规范
- `info`:连接属性,详见上文 Properties 章节
- **返回值**:连接对象
- **异常**:连接失败抛出 `SQLException` 异常
- `boolean acceptsURL(String url) throws SQLException`
- **接口说明**:判断驱动是否支持 url
- **接口说明**:判断驱动是否支持 url
- **参数说明**
- `url`:连接地址 url
- **返回值**`true`:支持,`false`:不支持
- **异常**url 非法抛出 `SQLException` 异常
- `url`:连接地址 url
- **返回值**`true`:支持,`false`:不支持
- **异常**url 非法抛出 `SQLException` 异常
- `DriverPropertyInfo[] getPropertyInfo(String url, java.util.Properties info) throws SQLException`
- **接口说明**:获取尝试连接数据库时可能需要的所有属性的详细信息。这些属性信息被封装在 DriverPropertyInfo 对象数组中返回。每个 DriverPropertyInfo 对象包含了一个数据库连接属性的详细信息,比如属性名、属性值、描述等
- **接口说明**:获取尝试连接数据库时可能需要的所有属性的详细信息。这些属性信息被封装在 DriverPropertyInfo 对象数组中返回。每个 DriverPropertyInfo 对象包含了一个数据库连接属性的详细信息,比如属性名、属性值、描述等
- **参数说明**
- `url`:一个 String 类型的参数,表示数据库的 URL
- `info`:一个 java.util.Properties 类型的参数,包含了尝试连接时用户可能提供的属性列表
- **返回值**:返回值类型为 `DriverPropertyInfo[]`,即 `DriverPropertyInfo` 对象的数组。每个 `DriverPropertyInfo` 对象包含了一个特定的数据库连接属性的详细信息
- **异常**:如果在获取属性信息的过程中发生数据库访问错误或其他错误,将抛出 `SQLException` 异常
- `url`:一个 String 类型的参数,表示数据库的 URL
- `info`:一个 java.util.Properties 类型的参数,包含了尝试连接时用户可能提供的属性列表
- **返回值**:返回值类型为 `DriverPropertyInfo[]`,即 `DriverPropertyInfo` 对象的数组。每个 `DriverPropertyInfo` 对象包含了一个特定的数据库连接属性的详细信息
- **异常**:如果在获取属性信息的过程中发生数据库访问错误或其他错误,将抛出 `SQLException` 异常
- `int getMajorVersion()`
- **接口说明**:获取 JDBC 驱动程序的主版本号
- **接口说明**:获取 JDBC 驱动程序的主版本号
- `int getMinorVersion()`
- **接口说明**:获取 JDBC 驱动程序的次版本号
- **接口说明**:获取 JDBC 驱动程序的次版本号
### 数据库元数据
`DatabaseMetaData` 是 JDBC API 的一部分,它提供了关于数据库的元数据的详细信息,元数据意味着关于数据库数据的数据。通过 `DatabaseMetaData` 接口,可以查询数据库服务器的详细信息,比如数据库产品名称、版本、已安装的功能、表、视图、存储过程的列表等。这对于了解和适应不同数据库的特性非常有用。
- `String getURL() throws SQLException`
- **接口说明**:获取用于连接数据库的 URL
- **返回值**:连接数据库的 URL
- **异常**:获取失败将抛出 `SQLException` 异常
- **接口说明**:获取用于连接数据库的 URL
- **返回值**:连接数据库的 URL
- **异常**:获取失败将抛出 `SQLException` 异常
- `String getUserName() throws SQLException`
- **接口说明**:获取用于连接获取数据库的用户名
- **返回值**:连接数据库的用户名
- **异常**:获取失败将抛出 `SQLException` 异常
- **接口说明**:获取用于连接获取数据库的用户名
- **返回值**:连接数据库的用户名
- **异常**:获取失败将抛出 `SQLException` 异常
- `String getDriverName() throws SQLException`
- **接口说明**:获取 JDBC 驱动程序的名称
- **返回值**:驱动名称字符串
- **异常**:获取失败将抛出 `SQLException` 异常
- **接口说明**:获取 JDBC 驱动程序的名称
- **返回值**:驱动名称字符串
- **异常**:获取失败将抛出 `SQLException` 异常
- `String getDriverVersion() throws SQLException`
- **接口说明**:获取 JDBC 驱动版本
- **返回值**:驱动版本字符串
- **异常**:获取失败将抛出 `SQLException` 异常
- **接口说明**:获取 JDBC 驱动版本
- **返回值**:驱动版本字符串
- **异常**:获取失败将抛出 `SQLException` 异常
- `int getDriverMajorVersion()`
- **接口说明**:获取 JDBC 驱动主版本号
- **接口说明**:获取 JDBC 驱动主版本号
- `int getDriverMinorVersion()`
- **接口说明**:获取 JDBC 驱动次版本号
- **接口说明**:获取 JDBC 驱动次版本号
- `String getDatabaseProductName() throws SQLException`
- **接口说明**:获取数据库产品的名称
- **接口说明**:获取数据库产品的名称
- `String getDatabaseProductVersion() throws SQLException`
- **接口说明**:获取数据库产品的版本号
- **接口说明**:获取数据库产品的版本号
- `String getIdentifierQuoteString() throws SQLException`
- **接口说明**:获取用于引用 SQL 标识符的字符串
- **接口说明**:获取用于引用 SQL 标识符的字符串
- `String getSQLKeywords() throws SQLException`
- **接口说明**:获取数据库特有的 SQL 关键字列表
- **接口说明**:获取数据库特有的 SQL 关键字列表
- `String getNumericFunctions() throws SQLException`
- **接口说明**:获取数据库支持的数值函数名称列表
- **接口说明**:获取数据库支持的数值函数名称列表
- `String getStringFunctions() throws SQLException`
- **接口说明**:获取数据库支持的字符串函数名称列表
- **接口说明**:获取数据库支持的字符串函数名称列表
- `String getSystemFunctions() throws SQLException`
- **接口说明**:获取数据库支持的系统函数名称列表
- **接口说明**:获取数据库支持的系统函数名称列表
- `String getTimeDateFunctions() throws SQLException`
- **接口说明**:获取数据库支持的时间日期函数名称列表
- **接口说明**:获取数据库支持的时间日期函数名称列表
- `String getCatalogTerm() throws SQLException`
- **接口说明**:获取数据库中目录的术语
- **接口说明**:获取数据库中目录的术语
- `String getCatalogSeparator() throws SQLException`
- **接口说明**:获取用于分隔目录和表名的分隔符
- **接口说明**:获取用于分隔目录和表名的分隔符
- `int getDefaultTransactionIsolation() throws SQLException`
- **接口说明**:获取数据库的默认事务隔离级别
- **接口说明**:获取数据库的默认事务隔离级别
- `boolean supportsTransactionIsolationLevel(int level) throws SQLException`
- **接口说明**:判断数据库是否支持给定的事务隔离级别
- **接口说明**:判断数据库是否支持给定的事务隔离级别
- **参数说明**
- `level`:事务隔离级别
- **返回值**`true`:支持,`false`:不支持
- **异常**:操作失败抛出 `SQLException` 异常
- `level`:事务隔离级别
- **返回值**`true`:支持,`false`:不支持
- **异常**:操作失败抛出 `SQLException` 异常
- `ResultSet getTables(String catalog, String schemaPattern, String tableNamePattern, String[] types) throws SQLException`
- **接口说明**:获取数据库中匹配指定模式的表信息
- **接口说明**:获取数据库中匹配指定模式的表信息
- **参数说明**
- `catalog`:目录名称;`null` 表示不指定目录
- `schemaPattern`模式名称的模式null 表示不指定模式
- `tableNamePattern`:表名称的模式
- `types`:表类型列表,返回指定类型的表
- **返回值**:包含表信息的 `ResultSet`
- **异常**:操作失败抛出 `SQLException` 异常
- `catalog`:目录名称;`null` 表示不指定目录
- `schemaPattern`模式名称的模式null 表示不指定模式
- `tableNamePattern`:表名称的模式
- `types`:表类型列表,返回指定类型的表
- **返回值**:包含表信息的 `ResultSet`
- **异常**:操作失败抛出 `SQLException` 异常
- `ResultSet getCatalogs() throws SQLException`
- **接口说明**:获取数据库中所有目录的信息
- **返回值**:包含目录信息的 `ResultSet`
- **异常**:操作失败抛出 `SQLException` 异常
- **接口说明**:获取数据库中所有目录的信息
- **返回值**:包含目录信息的 `ResultSet`
- **异常**:操作失败抛出 `SQLException` 异常
- `ResultSet getTableTypes() throws SQLException`
- **接口说明**:获取数据库支持的表类型
- **返回值**:包含表类型的 `ResultSet`
- **异常**:操作失败抛出 `SQLException` 异常
- **接口说明**:获取数据库支持的表类型
- **返回值**:包含表类型的 `ResultSet`
- **异常**:操作失败抛出 `SQLException` 异常
- `ResultSet getColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) throws SQLException`
- **接口说明**:获取指定表中匹配指定模式的列信息
- **接口说明**:获取指定表中匹配指定模式的列信息
- **参数说明**
- `catalog`:目录名称;`null` 表示不指定目录
- `schemaPattern`:模式名称的模式;`null` 表示不指定模式
- `tableNamePattern`:表名称的模式
- `columnNamePattern`:列名称的模式
- **返回值**:包含列信息的 `ResultSet`
- **异常**:操作失败抛出 `SQLException` 异常
- `catalog`:目录名称;`null` 表示不指定目录
- `schemaPattern`:模式名称的模式;`null` 表示不指定模式
- `tableNamePattern`:表名称的模式
- `columnNamePattern`:列名称的模式
- **返回值**:包含列信息的 `ResultSet`
- **异常**:操作失败抛出 `SQLException` 异常
- `ResultSet getPrimaryKeys(String catalog, String schema, String table) throws SQLException`
- **接口说明**:获取指定表的主键信息
- **接口说明**:获取指定表的主键信息
- **参数说明**
- `catalog`:目录名称;`null` 表示不指定目录
- `schema`:模式名称;`null` 表示不指定模式
- `table`:表名称
- **返回值**:包含主键信息的 `ResultSet`
- **异常**:操作失败抛出 `SQLException` 异常
- `catalog`:目录名称;`null` 表示不指定目录
- `schema`:模式名称;`null` 表示不指定模式
- `table`:表名称
- **返回值**:包含主键信息的 `ResultSet`
- **异常**:操作失败抛出 `SQLException` 异常
- `Connection getConnection() throws SQLException`
- **接口说明**:获取数据库连接。
@ -608,7 +604,7 @@ JDBC 驱动支持创建连接,返回支持 JDBC 标准的 `Connection` 接口
注:下面 abstract 类型接口会被具体实现类实现,因此建立连接后得到连接对象可以直接调用。
- `public abstract void write(String[] lines, SchemalessProtocolType protocolType, SchemalessTimestampType timestampType, Integer ttl, Long reqId) throws SQLException`
- `abstract void write(String[] lines, SchemalessProtocolType protocolType, SchemalessTimestampType timestampType, Integer ttl, Long reqId) throws SQLException`
- **接口说明**以指定的协议类型、时间戳类型、TTL生存时间和请求 ID 写入多行数据。
- **参数说明**
- `lines`:待写入的数据行数组。
@ -617,28 +613,28 @@ JDBC 驱动支持创建连接,返回支持 JDBC 标准的 `Connection` 接口
- `ttl`:数据的生存时间,单位天。
- `reqId`:请求 ID。
- **异常**:操作失败抛出 SQLException 异常。
- `public void write(String[] lines, SchemalessProtocolType protocolType, SchemalessTimestampType timestampType) throws SQLException`
- `void write(String[] lines, SchemalessProtocolType protocolType, SchemalessTimestampType timestampType) throws SQLException`
- **接口说明**:以指定的协议类型和时间戳类型写入多行数据。
- **参数说明**
- `lines`:待写入的数据行数组。
- `protocolType`:协议类型:支持 LINE TELNET JSON 三种。
- `timestampType`:时间戳类型,支持 HOURSMINUTESSECONDSMILLI_SECONDSMICRO_SECONDS 和 NANO_SECONDS。
- **异常**:操作失败抛出 SQLException 异常。
- `public void write(String line, SchemalessProtocolType protocolType, SchemalessTimestampType timestampType) throws SQLException`
- `void write(String line, SchemalessProtocolType protocolType, SchemalessTimestampType timestampType) throws SQLException`
- **接口说明**:以指定的协议类型和时间戳类型写入单行数据。
- **参数说明**
- `line`:待写入的数据行。
- `protocolType`:协议类型:支持 LINE TELNET JSON 三种。
- `timestampType`:时间戳类型,支持 HOURSMINUTESSECONDSMILLI_SECONDSMICRO_SECONDS 和 NANO_SECONDS。
- **异常**:操作失败抛出 SQLException 异常。
- `public void write(List<String> lines, SchemalessProtocolType protocolType, SchemalessTimestampType timestampType) throws SQLException`
- `void write(List<String> lines, SchemalessProtocolType protocolType, SchemalessTimestampType timestampType) throws SQLException`
- **接口说明**:以指定的协议类型和时间戳类型写入多行数据(使用列表)。
- **参数说明**
- `lines`:待写入的数据行列表。
- `protocolType`:协议类型:支持 LINE TELNET JSON 三种。
- `timestampType`:时间戳类型,支持 HOURSMINUTESSECONDSMILLI_SECONDSMICRO_SECONDS 和 NANO_SECONDS。
- **异常**:操作失败抛出 SQLException 异常。
- `public int writeRaw(String line, SchemalessProtocolType protocolType, SchemalessTimestampType timestampType) throws SQLException`
- `int writeRaw(String line, SchemalessProtocolType protocolType, SchemalessTimestampType timestampType) throws SQLException`
- **接口说明**:以指定的协议类型和时间戳类型写入多行回车符分割的原始数据,回车符分割,并返回操作结果。
- **参数说明**
- `line`:待写入的原始数据。
@ -646,7 +642,7 @@ JDBC 驱动支持创建连接,返回支持 JDBC 标准的 `Connection` 接口
- `timestampType`:时间戳类型,支持 HOURSMINUTESSECONDSMILLI_SECONDSMICRO_SECONDS 和 NANO_SECONDS。
- **返回值**:操作结果。
- **异常**:操作失败抛出 SQLException 异常。
- `public abstract int writeRaw(String line, SchemalessProtocolType protocolType, SchemalessTimestampType timestampType, Integer ttl, Long reqId) throws SQLException`
- `abstract int writeRaw(String line, SchemalessProtocolType protocolType, SchemalessTimestampType timestampType, Integer ttl, Long reqId) throws SQLException`
- **接口说明**以指定的协议类型、时间戳类型、TTL生存时间和请求 ID 写入多行回车符分割的原始数据,并返回操作结果。
- **参数说明**
- `line`:待写入的原始数据。
@ -1263,35 +1259,35 @@ ParameterMetaData 提供了参数元数据接口:
#### 扩展接口
- `public void setTableName(String name) throws SQLException`
- `void setTableName(String name) throws SQLException`
- **接口说明**:设置当前操作的表名。
- **参数说明**
- `name`:一个 String 类型的参数,表示要绑定的表名。
- `public void setTagNull(int index, int type)`
- `void setTagNull(int index, int type)`
- **接口说明**:为指定索引的标签设置 null 值。
- **参数说明**
- `index`:标签的索引位置。
- `type`:标签的数据类型。
- `public void setTagBoolean(int index, boolean value)`
- `void setTagBoolean(int index, boolean value)`
- **接口说明**:为指定索引的标签设置布尔值。
- **参数说明**
- `index`:标签的索引位置。
- `value`:要设置的布尔值。
- 下面接口除了要设置的值类型不同外,其余同 setTagBoolean不再赘述
- `public void setTagInt(int index, int value)`
- `public void setTagByte(int index, byte value)`
- `public void setTagShort(int index, short value)`
- `public void setTagLong(int index, long value)`
- `public void setTagTimestamp(int index, long value)`
- `public void setTagFloat(int index, float value)`
- `public void setTagDouble(int index, double value)`
- `public void setTagString(int index, String value)`
- `public void setTagNString(int index, String value)`
- `public void setTagJson(int index, String value)`
- `public void setTagVarbinary(int index, byte[] value)`
- `public void setTagGeometry(int index, byte[] value)`
- `void setTagInt(int index, int value)`
- `void setTagByte(int index, byte value)`
- `void setTagShort(int index, short value)`
- `void setTagLong(int index, long value)`
- `void setTagTimestamp(int index, long value)`
- `void setTagFloat(int index, float value)`
- `void setTagDouble(int index, double value)`
- `void setTagString(int index, String value)`
- `void setTagNString(int index, String value)`
- `void setTagJson(int index, String value)`
- `void setTagVarbinary(int index, byte[] value)`
- `void setTagGeometry(int index, byte[] value)`
- `public void setInt(int columnIndex, ArrayList<Integer> list) throws SQLException`
- `void setInt(int columnIndex, ArrayList<Integer> list) throws SQLException`
- **接口说明**:为指定列索引设置批量整型值。
- **参数说明**
- `columnIndex`:列的索引位置。
@ -1299,14 +1295,14 @@ ParameterMetaData 提供了参数元数据接口:
- **异常**
- 如果操作过程中发生错误,将抛出 SQLException 异常。
- 下面接口除了要设置的值类型不同外,其余同 setInt
- `public void setFloat(int columnIndex, ArrayList<Float> list) throws SQLException`
- `public void setTimestamp(int columnIndex, ArrayList<Long> list) throws SQLException`
- `public void setLong(int columnIndex, ArrayList<Long> list) throws SQLException`
- `public void setDouble(int columnIndex, ArrayList<Double> list) throws SQLException`
- `public void setBoolean(int columnIndex, ArrayList<Boolean> list) throws SQLException`
- `public void setByte(int columnIndex, ArrayList<Byte> list) throws SQLException`
- `public void setShort(int columnIndex, ArrayList<Short> list) throws SQLException`
- `public void setString(int columnIndex, ArrayList<String> list, int size) throws SQLException`
- `void setFloat(int columnIndex, ArrayList<Float> list) throws SQLException`
- `void setTimestamp(int columnIndex, ArrayList<Long> list) throws SQLException`
- `void setLong(int columnIndex, ArrayList<Long> list) throws SQLException`
- `void setDouble(int columnIndex, ArrayList<Double> list) throws SQLException`
- `void setBoolean(int columnIndex, ArrayList<Boolean> list) throws SQLException`
- `void setByte(int columnIndex, ArrayList<Byte> list) throws SQLException`
- `void setShort(int columnIndex, ArrayList<Short> list) throws SQLException`
- `void setString(int columnIndex, ArrayList<String> list, int size) throws SQLException`
- **接口说明**:为指定列索引设置字符串值列表。
- **参数说明**
- `columnIndex`:列的索引位置。
@ -1315,9 +1311,9 @@ ParameterMetaData 提供了参数元数据接口:
- **异常**
- 如果操作过程中发生错误,将抛出 SQLException 异常。
- 下面接口除了要设置的值类型不同外,其余同 setString
- `public void setVarbinary(int columnIndex, ArrayList<byte[]> list, int size) throws SQLException`
- `public void setGeometry(int columnIndex, ArrayList<byte[]> list, int size) throws SQLException`
- `public void setNString(int columnIndex, ArrayList<String> list, int size) throws SQLException`
- `void setVarbinary(int columnIndex, ArrayList<byte[]> list, int size) throws SQLException`
- `void setGeometry(int columnIndex, ArrayList<byte[]> list, int size) throws SQLException`
- `void setNString(int columnIndex, ArrayList<String> list, int size) throws SQLException`
- `void columnDataAddBatch() throws SQLException`
- **接口说明**:将 `setIntint columnIndex ArrayList<Integer> list` 等数组形式接口设置的数据添加到当前 PrepareStatement 对象的批处理中。
- **异常**
@ -1353,80 +1349,81 @@ JDBC 标准不支持数据订阅,因此本章所有接口都是扩展接口。
- TSDBDriver.PROPERTY_KEY_ENABLE_AUTO_RECONNECT: 是否启用自动重连。仅在使用 Websocket 连接时生效。true: 启用false: 不启用。默认为 false。
- TSDBDriver.PROPERTY_KEY_RECONNECT_INTERVAL_MS: 自动重连重试间隔,单位毫秒,默认值 2000。仅在 PROPERTY_KEY_ENABLE_AUTO_RECONNECT 为 true 时生效。
- TSDBDriver.PROPERTY_KEY_RECONNECT_RETRY_COUNT: 自动重连重试次数,默认值 3仅在 PROPERTY_KEY_ENABLE_AUTO_RECONNECT 为 true 时生效。
其他参数请参考:[Consumer 参数列表](../../develop/tmq/#数据订阅相关参数) 注意TDengine服务端自 3.2.0.0 版本开始消息订阅中的 auto.offset.reset 默认值发生变化。
- `public void subscribe(Collection<String> topics) throws SQLException`
其他参数请参考:[Consumer 参数列表](../../../develop/tmq/#创建参数) 注意TDengine服务端自 3.2.0.0 版本开始消息订阅中的 auto.offset.reset 默认值发生变化。
- `void subscribe(Collection<String> topics) throws SQLException`
- **接口说明**:订阅一组主题。
- **参数说明**
- `topics`:一个 `Collection<String>` 类型的参数,表示要订阅的主题列表。
- **异常**:如果在订阅过程中发生错误,将抛出 SQLException 异常。
- `public void unsubscribe() throws SQLException`
- `void unsubscribe() throws SQLException`
- **接口说明**:取消订阅所有主题。
- **异常**:如果在取消订阅过程中发生错误,将抛出 SQLException 异常。
- `public Set<String> subscription() throws SQLException`
- `Set<String> subscription() throws SQLException`
- **接口说明**:获取当前订阅的所有主题。
- **返回值**:返回值类型为 `Set<String>`,即当前订阅的所有主题集合。
- **异常**:如果在获取订阅信息过程中发生错误,将抛出 SQLException 异常。
- `public ConsumerRecords<V> poll(Duration timeout) throws SQLException`
- `ConsumerRecords<V> poll(Duration timeout) throws SQLException`
- **接口说明**:轮询消息。
- **参数说明**
- `timeout`:一个 `Duration` 类型的参数,表示轮询的超时时间。
- **返回值**:返回值类型为 `ConsumerRecords<V>`,即轮询到的消息记录。
- **异常**:如果在轮询过程中发生错误,将抛出 SQLException 异常。
- `public void commitAsync() throws SQLException`
- `void commitAsync() throws SQLException`
- **接口说明**:异步提交当前处理的消息的偏移量。
- **异常**:如果在提交过程中发生错误,将抛出 SQLException 异常。
- `public void commitSync() throws SQLException`
- `void commitSync() throws SQLException`
- **接口说明**:同步提交当前处理的消息的偏移量。
- **异常**:如果在提交过程中发生错误,将抛出 SQLException 异常。
- `public void close() throws SQLException`
- `void close() throws SQLException`
- **接口说明**:关闭消费者,释放资源。
- **异常**:如果在关闭过程中发生错误,将抛出 SQLException 异常。
- `public void seek(TopicPartition partition, long offset) throws SQLException`
- `void seek(TopicPartition partition, long offset) throws SQLException`
- **接口说明**:将给定分区的偏移量设置到指定的位置。
- **参数说明**
- `partition`:一个 `TopicPartition` 类型的参数,表示要操作的分区。
- `offset`:一个 `long` 类型的参数,表示要设置的偏移量。
- **异常**:如果在设置偏移量过程中发生错误,将抛出 SQLException 异常。
- `public long position(TopicPartition tp) throws SQLException`
- `long position(TopicPartition tp) throws SQLException`
- **接口说明**:获取给定分区当前的偏移量。
- **参数说明**
- `tp`:一个 `TopicPartition` 类型的参数,表示要查询的分区。
- **返回值**:返回值类型为 `long`,即给定分区当前的偏移量。
- **异常**:如果在获取偏移量过程中发生错误,将抛出 SQLException 异常。
- `public Map<TopicPartition, Long> beginningOffsets(String topic) throws SQLException`
- `Map<TopicPartition, Long> beginningOffsets(String topic) throws SQLException`
- **接口说明**:获取指定主题的每个分区的最早偏移量。
- **参数说明**
- `topic`:一个 `String` 类型的参数,表示要查询的主题。
- **返回值**:返回值类型为 `Map<TopicPartition, Long>`,即指定主题的每个分区的最早偏移量。
- **异常**:如果在获取最早偏移量过程中发生错误,将抛出 SQLException 异常。
- `public Map<TopicPartition, Long> endOffsets(String topic) throws SQLException`
- `Map<TopicPartition, Long> endOffsets(String topic) throws SQLException`
- **接口说明**:获取指定主题的每个分区的最新偏移量。
- **参数说明**
- `topic`:一个 `String` 类型的参数,表示要查询的主题。
- **返回值**:返回值类型为 `Map<TopicPartition, Long>`,即指定主题的每个分区的最新偏移量。
- **异常**:如果在获取最新偏移量过程中发生错误,将抛出 SQLException 异常。
- `public void seekToBeginning(Collection<TopicPartition> partitions) throws SQLException`
- `void seekToBeginning(Collection<TopicPartition> partitions) throws SQLException`
- **接口说明**:将一组分区的偏移量设置到最早的偏移量。
- **参数说明**
- `partitions`:一个 `Collection<TopicPartition>` 类型的参数,表示要操作的分区集合。
- **异常**:如果在设置偏移量过程中发生错误,将抛出 SQLException 异常。
- `public void seekToEnd(Collection<TopicPartition> partitions) throws SQLException`
- `void seekToEnd(Collection<TopicPartition> partitions) throws SQLException`
- **接口说明**:将一组分区的偏移量设置到最新的偏移量。
- **参数说明**
- `partitions`:一个 `Collection<TopicPartition>` 类型的参数,表示要操作的分区集合。
- **异常**:如果在设置偏移量过程中发生错误,将抛出 SQLException 异常。
- `public Set<TopicPartition> assignment() throws SQLException`
- `Set<TopicPartition> assignment() throws SQLException`
- **接口说明**:获取消费者当前分配的所有分区。
- **返回值**:返回值类型为 `Set<TopicPartition>`,即消费者当前分配的所有分区。
- **异常**:如果在获取分配的分区过程中发生错误,将抛出 SQLException 异常。
- `public OffsetAndMetadata committed(TopicPartition partition) throws SQLException`
- `OffsetAndMetadata committed(TopicPartition partition) throws SQLException`
- **接口说明**:获取指定分区最后提交的偏移量。
- **参数说明**
- `partition`:一个 `TopicPartition` 类型的参数,表示要查询的分区。
- **返回值**:返回值类型为 `OffsetAndMetadata`,即指定分区最后提交的偏移量。
- **异常**:如果在获取提交的偏移量过程中发生错误,将抛出 SQLException 异常。
- `public Map<TopicPartition, OffsetAndMetadata> committed(Set<TopicPartition> partitions) throws SQLException`
- `Map<TopicPartition, OffsetAndMetadata> committed(Set<TopicPartition> partitions) throws SQLException`
- **接口说明**:获取一组分区最后提交的偏移量。
- **参数说明**
- `partitions`:一个 `Set<TopicPartition>` 类型的参数,表示要查询的分区集合。
@ -1439,19 +1436,19 @@ ConsumerRecords 类提供了消费记录信息,可以迭代 ConsumerRecord 对
ConsumerRecord 提供的接口:
- `public String getTopic()`
- `String getTopic()`
- **接口说明**:获取消息的主题。
- **返回值**:返回值类型为 `String`,即消息的主题。
- `public String getDbName()`
- `String getDbName()`
- **接口说明**:获取数据库名称。
- **返回值**:返回值类型为 `String`,即数据库名称。
- `public int getVGroupId()`
- `int getVGroupId()`
- **接口说明**:获取虚拟组 ID。
- **返回值**:返回值类型为 `int`,即虚拟组 ID。
- `public V value()`
- `V value()`
- **接口说明**:获取消息的值。
- **返回值**:返回值类型为 `V`,即消息的值。
- `public long getOffset()`
- `long getOffset()`
- **接口说明**:获取消息的偏移量。
- **返回值**:返回值类型为 `long`,即消息的偏移量。
@ -1459,15 +1456,15 @@ ConsumerRecord 提供的接口:
TopicPartition 类提供了分区信息,包含消息主题和虚拟组 ID。
- `public TopicPartition(String topic, int vGroupId)`
- `TopicPartition(String topic, int vGroupId)`
- **接口说明**:构造一个新的 TopicPartition 实例,用于表示一个特定的主题和虚拟组 ID。
- **参数说明**
- `topic`:一个 `String` 类型的参数,表示消息的主题。
- `vGroupId`:一个 `int` 类型的参数,表示虚拟组 ID。
- `public String getTopic()`
- `String getTopic()`
- **接口说明**:获取此 TopicPartition 实例的主题。
- **返回值**:返回值类型为 `String`,即此 TopicPartition 实例的主题。
- `public int getVGroupId()`
- `int getVGroupId()`
- **接口说明**:获取此 TopicPartition 实例的虚拟组 ID。
- **返回值**:返回值类型为 `int`,即此 TopicPartition 实例的虚拟组 ID。
@ -1475,10 +1472,10 @@ TopicPartition 类提供了分区信息,包含消息主题和虚拟组 ID。
OffsetAndMetadata 类提供了偏移量元数据信息。
- `public long offset()`
- `long offset()`
- **接口说明**:获取此 OffsetAndMetadata 实例中的偏移量。
- **返回值**:返回值类型为 `long`,即此 OffsetAndMetadata 实例中的偏移量。
- `public String metadata()`
- `String metadata()`
- **接口说明**:获取此 OffsetAndMetadata 实例中的元数据。
- **返回值**:返回值类型为 `String`,即此 OffsetAndMetadata 实例中的元数据。

View File

@ -396,4 +396,803 @@ TDengine Go 连接器支持订阅功能,应用 API 如下:
## API 参考
全部 API 见 [driver-go 文档](https://pkg.go.dev/github.com/taosdata/driver-go/v3)
### database/sql 驱动
`driver-go` 实现了 Go 的 `database/sql/driver` 接口,可以直接使用 Go 的 `database/sql` 包。提供了三个驱动:`github.com/taosdata/driver-go/v3/taosSql` 、`github.com/taosdata/driver-go/v3/taosRestful` 和 `github.com/taosdata/driver-go/v3/taosWS` 分别对应 `原生连接`、`REST 连接` 和 `WebSocket 连接`。
#### DSN 规范
数据源名称具有通用格式,例如 [PEAR DB](http://pear.php.net/manual/en/package.database.db.intro-dsn.php),但没有类型前缀(方括号表示可选):
``` text
[username[:password]@][protocol[(address)]]/[dbname][?param1=value1&...&paramN=valueN]
```
完整形式的 DSN
```text
username:password@protocol(address)/dbname?param=value
```
##### 原生连接
导入驱动:
```go
import (
"database/sql"
_ "github.com/taosdata/driver-go/v3/taosSql"
)
```
使用 `taosSql` 作为 `driverName` 并且使用一个正确的 DSN 作为 `dataSourceName` 如下:
```go
var taosUri = "root:taosdata@tcp(localhost:6030)/"
taos, err := sql.Open("taosSql", taosUri)
```
支持的 DSN 参数:
* `cfg` 指定 taos.cfg 目录
* `cgoThread` 指定 cgo 同时执行的数量,默认为系统核数
* `cgoAsyncHandlerPoolSize` 指定异步函数的 handle 大小,默认为 10000
##### Rest 连接
导入驱动:
```go
import (
"database/sql"
_ "github.com/taosdata/driver-go/v3/taosRestful"
)
```
使用 `taosRestful` 作为 `driverName` 并且使用一个正确的 DSN 作为 `dataSourceName` 如下:
```go
var taosUri = "root:taosdata@http(localhost:6041)/"
taos, err := sql.Open("taosRestful", taosUri)
```
支持的 DSN 参数:
* `disableCompression` 是否接受压缩数据,默认为 true 不接受压缩数据,如果传输数据使用 gzip 压缩设置为 false。
* `readBufferSize` 读取数据的缓存区大小默认为 4K4096当查询结果数据量多时可以适当调大该值。
* `token` 连接云服务时使用的 token。
* `skipVerify` 是否跳过证书验证,默认为 false 不跳过证书验证,如果连接的是不安全的服务设置为 true。
##### WebSocket 连接
导入驱动:
```go
import (
"database/sql"
_ "github.com/taosdata/driver-go/v3/taosWS"
)
```
使用 `taosWS` 作为 `driverName` 并且使用一个正确的 DSN 作为 `dataSourceName` 如下:
```go
var taosUri = "root:taosdata@ws(localhost:6041)/"
taos, err := sql.Open("taosWS", taosUri)
```
支持的 DSN 参数:
* `enableCompression` 是否发送压缩数据,默认为 false 不发送压缩数据,如果传输数据使用压缩设置为 true。
* `readTimeout` 读取数据的超时时间,默认为 5m。
* `writeTimeout` 写入数据的超时时间,默认为 10s。
:::note
- 与原生连接方式不同REST 接口是无状态的。在使用 REST 连接时,需要在 SQL 中指定表、超级表的数据库名称。
- 如果在 DSN 中指定了 dbname那么REST 连接会默认使用/rest/sql/dbname 作为 restful 请求的 url在 SQL 中不需要指定 dbname。
:::
### 连接功能
Go 驱动支持创建连接,返回支持 `sql/driver` 标准的 `Connector` 接口的对象,还提供了 `af` 包,扩充了一些无模式写入接口。
#### 标准接口
`database/sql` 包中创建连接的接口
- `func Open(driverName, dataSourceName string) (*DB, error)`
- **接口说明**(`database/sql`)连接数据库
- **参数说明**
- `driverName`:驱动名称。
- `dataSourceName`:连接参数 DSN。
- **返回值**:连接对象,错误信息。
#### 扩展接口
`af` 包中创建连接的接口
- `func Open(host, user, pass, db string, port int) (*Connector, error)`
- **接口说明**:连接数据库。
- **参数说明**
- `host`:主机地址。
- `user`:用户名。
- `pass`:密码。
- `db`:数据库名称。
- `port`:端口号。
- **返回值**:连接对象,错误信息。
#### 无模式写入
`af` 包中使用原生连接进行无模式写入的接口。
- `func (conn *Connector) InfluxDBInsertLines(lines []string, precision string) error`
- **接口说明**:无模式写入 influxDB 格式数据。
- **参数说明**
- `lines`:写入的数据。
- `precision`:时间精度。
- **返回值**:错误信息。
- `func (conn *Connector) OpenTSDBInsertJsonPayload(payload string) error`
- **接口说明**:无模式写入 OpenTSDB JSON 格式数据。
- **参数说明**
- `payload`:写入的数据。
- **返回值**:错误信息。
- `func (conn *Connector) OpenTSDBInsertTelnetLines(lines []string) error`
- **接口说明**:无模式写入 OpenTSDB Telnet 格式数据。
- **参数说明**
- `lines`:写入的数据。
- **返回值**:错误信息。
`ws/schemaless` 包中使用 WebSocket 无模式写入的接口
- `func (s *Schemaless) Insert(lines string, protocol int, precision string, ttl int, reqID int64) error`
- **接口说明**:无模式写入数据。
- **参数说明**
- `lines`:写入的数据。
- `protocol`:写入的数据协议支持的协议 `InfluxDBLineProtocol = 1` `OpenTSDBTelnetLineProtocol = 2` `OpenTSDBJsonFormatProtocol = 3`。
- `precision`:时间精度。
- `ttl`数据过期时间0 表示不过期。
- `reqID`:请求 ID。
- **返回值**:错误信息。
### 执行 SQL
Go 驱动提供了符合 `database/sql` 标准的接口,支持以下功能:
1. **执行 SQL 语句**:执行静态 SQL 语句,并返回其生成的结果对象。
2. **查询执行**:可以执行返回数据集的查询(`SELECT` 语句)。
3. **更新执行**:可以执行影响行数的 SQL 语句,如 `INSERT`、`UPDATE`、`DELETE` 等。
4. **获取结果**:可以获取查询执行后返回的结果集,并遍历查询返回的数据。
5. **获取更新计数**:对于非查询 SQL 语句,可以获取执行后影响的行数。
6. **关闭资源**:释放数据库资源。
#### 标准接口
- `func (db *DB) Close() error`
- **接口说明**:关闭连接。
- **返回值**:错误信息。
- `func (db *DB) Exec(query string, args ...any) (Result, error)`
- **接口说明**:执行查询但不返回任何行。
- **参数说明**
- `query`:要执行的命令。
- `args`:命令参数。
- **返回值**Result 对象(只有影响行数),错误信息。
- `func (db *DB) Query(query string, args ...any) (*Rows, error)`
- **接口说明**:执行查询并返回行的结果。
- **参数说明**
- `query`:要执行的命令。
- `args`:命令参数。
- **返回值**Rows 对象,错误信息。
- `func (db *DB) QueryRow(query string, args ...any) *Row`
- **接口说明**:执行查询并返回一行结果。
- **参数说明**
- `query`:要执行的命令。
- `args`:命令参数。
- **返回值**Row 对象。
#### 扩展接口
- `func (db *DB) ExecContext(ctx context.Context, query string, args ...any) (Result, error)`
- **接口说明**:执行查询但不返回任何行。
- **参数说明**
- `ctx`:上下文,使用 Value 传递请求 id 进行链路追踪key 为 `taos_req_id` value 为 int64 类型值。
- `query`:要执行的命令。
- `args`:命令参数。
- **返回值**:结果 Result 对象(只有影响行数),错误信息。
- `func (db *DB) QueryContext(ctx context.Context, query string, args ...any) (*Rows, error)`
- **接口说明**:执行查询并返回行结果。
- **参数说明**
- `ctx`:上下文,使用 Value 传递请求 id 进行链路追踪key 为 `taos_req_id` value 为 int64 类型值。
- `query`:要执行的命令。
- `args`:命令参数。
- **返回值**:结果集 Rows 对象,错误信息。
- `func (db *DB) QueryRowContext(ctx context.Context, query string, args ...any) *Row`
- **接口说明**:执行查询并返回一行结果,错误信息会在扫描 Row 时延迟返回。
- **参数说明**
- `ctx`:上下文,使用 Value 传递请求 id 进行链路追踪key 为 `taos_req_id` value 为 int64 类型值。
- `query`:要执行的命令。
- `args`:命令参数。
- **返回值**:单行结果 Row 对象。
### 结果获取
Go 驱动支持获取查询结果集,以及对应的结果集元数据,提供了用于读取结果集中元数据和数据的方法。
#### 结果集
通过 `Rows` 对象获取查询结果集,提供了以下方法:
- `func (rs *Rows) Next() bool`
- **接口说明**:准备下一行数据。
- **返回值**:是否有下一行数据。
- `func (rs *Rows) Columns() ([]string, error)`
- **接口说明**:返回列名。
- **返回值**:列名,错误信息。
- `func (rs *Rows) Scan(dest ...any) error`
- **接口说明**:将当前行的列值复制到 dest 指向的值中。
- **参数说明**
- `dest`:目标值。
- **返回值**:错误信息。
- `func (rs *Rows) Close() error`
- **接口说明**:关闭行。
- **返回值**:错误信息。
- `func (r *Row) Scan(dest ...any) error`
- **接口说明**:将当前行的列值复制到 dest 指向的值中。
- **参数说明**
- `dest`:目标值。
- **返回值**:错误信息。
通过 `Result` 对象获取更新结果集,提供了以下方法:
- `func (dr driverResult) RowsAffected() (int64, error)`
- **接口说明**:返回受影响的行数。
- **返回值**:受影响的行数,错误信息。
#### 结果集元数据
通过 `Rows` 对象获取查询结果集元数据,提供了以下方法:
- `func (rs *Rows) ColumnTypes() ([]*ColumnType, error)`
- **接口说明**:返回列类型。
- **返回值**:列类型,错误信息。
- `func (ci *ColumnType) Name() string`
- **接口说明**:返回列名。
- **返回值**:列名。
- `func (ci *ColumnType) Length() (length int64, ok bool)`
- **接口说明**:返回列长度。
- **返回值**:列长度,是否有长度。
- `func (ci *ColumnType) ScanType() reflect.Type`
- **接口说明**:返回列类型对应的 Go 类型。
- **返回值**:列类型。
- `func (ci *ColumnType) DatabaseTypeName() string`
- **接口说明**:返回列类型数据库名称。
- **返回值**:列类型名称。
### 参数绑定
Prepare 允许使用预编译的 SQL 语句,可以提高性能并提供参数化查询的能力,从而增加安全性。
#### 标准接口
使用 `sql/driver` 的 `Conn` 接口中的 `Prepare` 方法准备一个与此连接绑定的准备好的语句,返回 `Stmt` 对象,使用。
- `Prepare(query string) (Stmt, error)`
- **接口说明**:准备返回一个与此连接绑定的准备好的语句(statement)。
- **参数说明**
- `query`:要进行参数绑定的语句。
- **返回值**Stmt 对象,错误信息。
- `func (s *Stmt) Exec(args ...any) (Result, error)`
- **接口说明**:使用给定的参数执行准备好的语句并返回总结该语句效果的结果(只可以绑定列值,不支持绑定表名和 tag
- **参数说明**
- `args`命令参数Go 原始类型会自动转换数据库类型,类型不匹配可能会丢精度,建议使用与数据库相同的类型,时间类型使用 int64 或 `RFC3339Nano` 格式化后的字符串。
- **返回值**:结果 Result 对象(只有影响行数),错误信息。
- `func (s *Stmt) Query(args ...any) (*Rows, error)`
- **接口说明**:使用给定的参数执行准备好的语句并返回行的结果。
- **参数说明**
- `args`命令参数Go 原始类型会自动转换数据库类型,类型不匹配可能会丢精度,建议使用与数据库相同的类型,时间类型使用 int64 或 `RFC3339Nano` 格式化后的字符串。
- **返回值**:结果集 Rows 对象,错误信息。
- `func (s *Stmt) Close() error`
- **接口说明**:关闭语句。
- **返回值**:错误信息。
#### 扩展接口
`af` 包中提供了使用原生连接进行参数绑定的更多接口
- `func (conn *Connector) Stmt() *Stmt`
- **接口说明**:返回一个与此连接绑定的 Stmt 对象。
- **返回值**Stmt 对象。
- `func (s *Stmt) Prepare(sql string) error`
- **接口说明**:准备一个 sql 。
- **参数说明**
- `sql`:要进行参数绑定的语句。
- **返回值**:错误信息。
- `func (s *Stmt) NumParams() (int, error)`
- **接口说明**:返回参数数量。
- **返回值**:参数数量,错误信息。
- `func (s *Stmt) SetTableNameWithTags(tableName string, tags *param.Param)`
- **接口说明**:设置表名和 tag。
- **参数说明**
- `tableName`:表名。
- `tags`tag。
- **返回值**:错误信息。
- `func (s *Stmt) SetTableName(tableName string) error`
- **接口说明**:设置表名。
- **参数说明**
- `tableName`:表名。
- **返回值**:错误信息。
- `func (s *Stmt) BindRow(row *param.Param) error`
- **接口说明**:绑定行。
- **参数说明**
- `row`:行数据。
- **返回值**:错误信息。
- `func (s *Stmt) GetAffectedRows() int`
- **接口说明**:获取受影响的行数。
- **返回值**:受影响的行数。
- `func (s *Stmt) AddBatch() error`
- **接口说明**:添加批处理。
- **返回值**:错误信息。
- `func (s *Stmt) Execute() error`
- **接口说明**:执行批处理。
- **返回值**:错误信息。
- `func (s *Stmt) UseResult() (driver.Rows, error)`
- **接口说明**:使用结果。
- **返回值**:结果集 Rows 对象,错误信息。
- `func (s *Stmt) Close() error`
- **接口说明**:关闭语句。
- **返回值**:错误信息。
`ws/stmt` 包提供了通过 WebSocket 进行参数绑定的接口
- `func (c *Connector) Init() (*Stmt, error)`
- **接口说明**:初始化。
- **返回值**Stmt 对象,错误信息。
- `func (s *Stmt) Prepare(sql string) error`
- **接口说明**:准备一个 sql 。
- **参数说明**
- `sql`:要进行参数绑定的语句。
- **返回值**:错误信息。
- `func (s *Stmt) SetTableName(name string) error`
- **接口说明**:设置表名。
- **参数说明**
- `name`:表名。
- **返回值**:错误信息。
- `func (s *Stmt) SetTags(tags *param.Param, bindType *param.ColumnType)`
- **接口说明**:设置 tag。
- **参数说明**
- `tags`tag。
- `bindType`:类型信息。
- **返回值**:错误信息。
- `func (s *Stmt) BindParam(params []*param.Param, bindType *param.ColumnType) error`
- **接口说明**:绑定参数。
- **参数说明**
- `params`:参数。
- `bindType`:类型信息。
- **返回值**:错误信息。
- `func (s *Stmt) AddBatch() error`
- **接口说明**:添加批处理。
- **返回值**:错误信息。
- `func (s *Stmt) Exec() error`
- **接口说明**:执行批处理。
- **返回值**:错误信息。
- `func (s *Stmt) GetAffectedRows() int`
- **接口说明**:获取受影响的行数。
- **返回值**:受影响的行数。
- `func (s *Stmt) UseResult() (*Rows, error)`
- **接口说明**:使用结果。
- **返回值**Rows 对象,错误信息。
- `func (s *Stmt) Close() error`
- **接口说明**:关闭语句。
- **返回值**:错误信息。
Rows 行结果参考 `sql/driver` 包中的 `Rows` 接口,提供以下接口
- `func (rs *Rows) Columns() []string`
- **接口说明**:返回列名。
- **返回值**:列名。
- `func (rs *Rows) ColumnTypeDatabaseTypeName(i int) string`
- **接口说明**:返回列类型数据库名称。
- **参数说明**
- `i`:列索引。
- **返回值**:列类型名称。
- `func (rs *Rows) ColumnTypeLength(i int) (length int64, ok bool)`
- **接口说明**:返回列长度。
- **参数说明**
- `i`:列索引。
- **返回值**:列长度,是否有长度。
- `func (rs *Rows) ColumnTypeScanType(i int) reflect.Type`
- **接口说明**:返回列类型对应的 Go 类型。
- **参数说明**
- `i`:列索引。
- **返回值**:列类型。
- `func (rs *Rows) Next(dest []driver.Value) error`
- **接口说明**:准备下一行数据,并赋值给目标。
- **参数说明**
- `dest`:目标值。
- **返回值**:错误信息。
- `func (rs *Rows) Close() error`
- **接口说明**:关闭行。
- **返回值**:错误信息。
`common/param` 包中提供了参数绑定数据结构
以下是按照偏移设置参数的接口:
- `func NewParam(size int) *Param`
- **接口说明**:创建一个参数绑定数据结构。
- **参数说明**
- `size`:参数数量。
- **返回值**Param 对象。
- `func (p *Param) SetBool(offset int, value bool)`
- **接口说明**:设置布尔值。
- **参数说明**
- `offset`:偏移量(列或标签)。
- `value`:布尔值。
- `func (p *Param) SetNull(offset int)`
- **接口说明**:设置空值。
- **参数说明**
- `offset`:偏移量(列或标签)。
- `func (p *Param) SetTinyint(offset int, value int)`
- **接口说明**:设置 Tinyint 值。
- **参数说明**
- `offset`:偏移量(列或标签)。
- `value`Tinyint 值。
- `func (p *Param) SetSmallint(offset int, value int)`
- **接口说明**:设置 Smallint 值。
- **参数说明**
- `offset`:偏移量(列或标签)。
- `value`Smallint 值。
- `func (p *Param) SetInt(offset int, value int)`
- **接口说明**:设置 Int 值。
- **参数说明**
- `offset`:偏移量(列或标签)。
- `value`Int 值。
- `func (p *Param) SetBigint(offset int, value int)`
- **接口说明**:设置 Bigint 值。
- **参数说明**
- `offset`:偏移量(列或标签)。
- `value`Bigint 值。
- `func (p *Param) SetUTinyint(offset int, value uint)`
- **接口说明**:设置 UTinyint 值。
- **参数说明**
- `offset`:偏移量(列或标签)。
- `value`UTinyint 值。
- `func (p *Param) SetUSmallint(offset int, value uint)`
- **接口说明**:设置 USmallint 值。
- **参数说明**
- `offset`:偏移量(列或标签)。
- `value`USmallint 值。
- `func (p *Param) SetUInt(offset int, value uint)`
- **接口说明**:设置 UInt 值。
- **参数说明**
- `offset`:偏移量(列或标签)。
- `value`UInt 值。
- `func (p *Param) SetUBigint(offset int, value uint)`
- **接口说明**:设置 UBigint 值。
- **参数说明**
- `offset`:偏移量(列或标签)。
- `value`UBigint 值。
- `func (p *Param) SetFloat(offset int, value float32)`
- **接口说明**:设置 Float 值。
- **参数说明**
- `offset`:偏移量(列或标签)。
- `value`Float 值。
- `func (p *Param) SetDouble(offset int, value float64)`
- **接口说明**:设置 Double 值。
- **参数说明**
- `offset`:偏移量(列或标签)。
- `value`Double 值。
- `func (p *Param) SetBinary(offset int, value []byte)`
- **接口说明**:设置 Binary 值。
- **参数说明**
- `offset`:偏移量(列或标签)。
- `value`Binary 值。
- `func (p *Param) SetVarBinary(offset int, value []byte)`
- **接口说明**:设置 VarBinary 值。
- **参数说明**
- `offset`:偏移量(列或标签)。
- `value`VarBinary 值。
- `func (p *Param) SetNchar(offset int, value string)`
- **接口说明**:设置 Nchar 值。
- **参数说明**
- `offset`:偏移量(列或标签)。
- `value`Nchar 值。
- `func (p *Param) SetTimestamp(offset int, value time.Time, precision int)`
- **接口说明**:设置 Timestamp 值。
- **参数说明**
- `offset`:偏移量(列或标签)。
- `value`Timestamp 值。
- `precision`:时间精度。
- `func (p *Param) SetJson(offset int, value []byte)`
- **接口说明**:设置 Json 值。
- **参数说明**
- `offset`:偏移量(列或标签)。
- `value`Json 值。
- `func (p *Param) SetGeometry(offset int, value []byte)`
- **接口说明**:设置 Geometry 值。
- **参数说明**
- `offset`:偏移量(列或标签)。
- `value`Geometry 值。
以下是链式调用设置参数的接口:
- `func (p *Param) AddBool(value bool) *Param`
- **接口说明**:添加布尔值。
- **参数说明**
- `value`:布尔值。
- **返回值**Param 对象。
其他类型与布尔值类似,具体接口如下:
- AddNull
- AddTinyint
- AddSmallint
- AddInt
- AddBigint
- AddUTinyint
- AddUSmallint
- AddUInt
- AddUBigint
- AddFloat
- AddDouble
- AddBinary
- AddVarBinary
- AddNchar
- AddTimestamp
- AddJson
- AddGeometry
以下是设置列类型信息的接口:
- `func NewColumnType(size int) *ColumnType`
- **接口说明**:创建一个列类型信息数据结构。
- **参数说明**
- `size`:列数量。
- **返回值**ColumnType 对象。
- `func (c *ColumnType) AddBool() *ColumnType`
- **接口说明**:添加布尔类型。
- **返回值**ColumnType 对象。
其他类型与布尔类型类似,具体接口如下:
- AddTinyint
- AddSmallint
- AddInt
- AddBigint
- AddUTinyint
- AddUSmallint
- AddUInt
- AddUBigint
- AddFloat
- AddDouble
- AddBinary
- AddVarBinary
- AddNchar
- AddTimestamp
- AddJson
- AddGeometry
### 数据订阅
Go 驱动支持数据订阅功能,提供了基于原生连接和 WebSocket 连接的数据订阅接口。原生实现在 `af/tmq` 包中WebSocket 实现在 `ws/tmq` 包中。
#### 消费者
- `func NewConsumer(conf *tmq.ConfigMap) (*Consumer, error)`
- **接口说明**:创建一个消费者。
- **参数说明**
- `conf`:配置信息。
- **返回值**Consumer 对象,错误信息。
配置信息定义为:
```go
type ConfigValue interface{}
type ConfigMap map[string]ConfigValue
```
创建消费者支持属性列表:
- `ws.url`WebSocket 连接地址。
- `ws.message.channelLen`WebSocket 消息通道缓存长度,默认 0。
- `ws.message.timeout`WebSocket 消息超时时间,默认 5m。
- `ws.message.writeWait`WebSocket 写入消息超时时间,默认 10s。
- `ws.message.enableCompression`WebSocket 是否启用压缩,默认 false。
- `ws.autoReconnect`WebSocket 是否自动重连,默认 false。
- `ws.reconnectIntervalMs`WebSocket 重连间隔时间毫秒,默认 2000。
- `ws.reconnectRetryCount`WebSocket 重连重试次数,默认 3。
其他参数请参考:[Consumer 参数列表](../../../develop/tmq/#数据订阅相关参数) 注意TDengine服务端自 3.2.0.0 版本开始消息订阅中的 auto.offset.reset 默认值发生变化。
- `func (c *Consumer) Subscribe(topic string, rebalanceCb RebalanceCb) error`
- **接口说明**:订阅主题。
- **参数说明**
- `topic`:主题。
- `rebalanceCb`:平衡回调(未使用)。
- **返回值**:错误信息。
- `func (c *Consumer) SubscribeTopics(topics []string, rebalanceCb RebalanceCb) error`
- **接口说明**:订阅主题列表。
- **参数说明**
- `topics`:主题列表。
- `rebalanceCb`:平衡回调(未使用)。
- **返回值**:错误信息。
- `func (c *Consumer) Unsubscribe() error`
- **接口说明**:取消订阅。
- **返回值**:错误信息。
- `func (c *Consumer) Poll(timeoutMs int) tmq.Event`
- **接口说明**:轮询事件。
- **参数说明**
- `timeoutMs`:超时时间。
- **返回值**:事件。
- `func (c *Consumer) Commit() ([]tmq.TopicPartition, error)`
- **接口说明**:提交偏移量。
- **返回值**TopicPartition 列表,错误信息。
- `func (c *Consumer) Assignment() (partitions []tmq.TopicPartition, err error)`
- **接口说明**:获取分配信息。
- **返回值**TopicPartition 列表,错误信息。
- `func (c *Consumer) Seek(partition tmq.TopicPartition, ignoredTimeoutMs int) error`
- **接口说明**:跳转到偏移量。
- **参数说明**
- `partition`:分区和偏移信息。
- `ignoredTimeoutMs`:超时时间(未使用)。
- **返回值**:错误信息。
- `func (c *Consumer) Committed(partitions []tmq.TopicPartition, timeoutMs int) (offsets []tmq.TopicPartition, err error)`
- **接口说明**:获取提交的偏移量。
- **参数说明**
- `partitions`:分区列表。
- `timeoutMs`:超时时间。
- **返回值**TopicPartition 列表,错误信息。
- `func (c *Consumer) CommitOffsets(offsets []tmq.TopicPartition) ([]tmq.TopicPartition, error) `
- **接口说明**:提交偏移量。
- **参数说明**
- `offsets`:偏移量列表。
- **返回值**TopicPartition 列表,错误信息。
- `func (c *Consumer) Position(partitions []tmq.TopicPartition) (offsets []tmq.TopicPartition, err error)`
- **接口说明**:获取当前偏移量。
- **参数说明**
- `partitions`:分区列表。
- **返回值**TopicPartition 列表,错误信息。
- `func (c *Consumer) Close() error`
- **接口说明**:关闭消费者。
- **返回值**:错误信息。
#### 消费记录
当 `Poll` 返回 `tmq.Event` 事件时,可以通过判断 `tmq.Event` 的类型获取消费记录或错误信息。当类型为 `*tmq.DataMessage` 时,可以获取消费记录。
- `func (m *DataMessage) Topic() string`
- **接口说明**:获取主题。
- **返回值**:主题。
- `func (m *DataMessage) DBName() string`
- **接口说明**:获取数据库名称。
- **返回值**:数据库名称。
- `func (m *DataMessage) Offset() Offset`
- **接口说明**:获取偏移量。
- **返回值**:偏移量。
- `func (m *DataMessage) Value() interface{}`
- **接口说明**:获取值,具体值为 `[]*tmq.data`。
- **返回值**:消费到的值。
tmq.data 结构如下:
```go
type Data struct {
TableName string
Data [][]driver.Value
}
```
- TableName 为表名
- Data 为数据,每个元素为一行数据,每行数据为一个数组,数组元素为列值。
当 Poll 返回类型为 `tmq.Error` 时,可以使用 `func (e Error) Error() string` 获取错误信息。
#### 分区信息
当消费到数据类型为 `*tmq.DataMessage` 时,可以从 `TopicPartition` 属性中获取分区信息。
```go
type TopicPartition struct {
Topic *string
Partition int32
Offset Offset
Metadata *string
Error error
}
```
- `Topic`:主题。
- `Partition`:分区。
- `Offset`:偏移量。
- `Metadata`:元数据(未使用)。
- `Error`:错误信息。
可以使用 `func (p TopicPartition) String() string` 获取分区信息。
#### 偏移量元数据
从 `TopicPartition` 中获取的偏移量信息,可以通过 `Offset` 属性获取偏移量元数据。当偏移量为 `-2147467247` 时表示未设置偏移量。
#### 反序列化
当消费到数据类型为 `*tmq.DataMessage` 时,可以使用 `func (m *DataMessage) Value() interface{}` 获取数据,数据类型为 `[]*tmq.data` 。
## 附录
[driver-go 文档](https://pkg.go.dev/github.com/taosdata/driver-go/v3)

View File

@ -607,7 +607,402 @@ stmt.execute()?;
一个可运行的示例请见 [GitHub 上的示例](https://github.com/taosdata/taos-connector-rust/blob/main/examples/bind.rs)。
其他相关结构体 API 使用说明请移步 Rust 文档托管网页:\<https://docs.rs/taos>。
## API 参考
Rust 连接器的接口分为同步接口和异步接口,一般同步接口是由异步接口实现,方法签名除 async 关键字外基本相同。对于同步接口和异步接口功能一样的接口,本文档只提供同步接口的说明。
对于 WebSocket 连接和原生连接两种方式,除了建立连接的 DSN 不同,其余接口调用没有区别。
### 连接功能
#### DSN
TaosBuilder 通过 DSN 连接描述字符串创建一个连接构造器。
DSN 描述字符串基本结构如下:
```text
<driver>[+<protocol>]://[[<username>:<password>@]<host>:<port>][/<database>][?<p1>=<v1>[&<p2>=<v2>]]
|------|------------|---|-----------|-----------|------|------|------------|-----------------------|
|driver| protocol | | username | password | host | port | database | params |
```
各部分意义见下表:
- **driver**: 必须指定驱动名以便连接器选择何种方式创建连接,支持如下驱动名:
- **taos**: 表名使用 TDengine 连接器驱动。
- **tmq**: 使用 TMQ 订阅数据。
- **http/ws**: 使用 Websocket 创建连接。
- **https/wss**: 在 Websocket 连接方式下显示启用 SSL/TLS 连接。
- **protocol**: 显示指定以何种方式建立连接,例如:`taos+ws://localhost:6041` 指定以 Websocket 方式建立连接。
- **username/password**: 用于创建连接的用户名及密码。
- **host/port**: 指定创建连接的服务器及端口,当不指定服务器地址及端口时(`taos://`),原生连接默认为 `localhost:6030`Websocket 连接默认为 `localhost:6041` 。
- **database**: 指定默认连接的数据库名,可选参数。
- **params**:其他可选参数。
一个完整的 DSN 描述字符串示例如下:`taos+ws://localhost:6041/test` 表示使用 Websocket`ws`)方式通过 `6041` 端口连接服务器 `localhost`,并指定默认数据库为 `test`。
#### TaosBuilder
TaosBuilder 结构体提供了建立连接,检查连接,以及获取服务端版本号等功能。
- `fn available_params() -> &'static [&'static str]`
- **接口说明**获取DSN中可用的参数列表。
- **返回值**:返回静态字符串切片的引用,包含可用的参数名称。
- `fn from_dsn<D: IntoDsn>(dsn: D) -> RawResult<Self>`
- **接口说明**使用DSN字符串创建连接不检查连接。
- **参数说明**
- `dsn`DSN字符串或可转换为DSN的类型。
- **返回值**:成功时返回自身类型的 `RawResult`,失败时返回错误。
- `fn client_version() -> &'static str`
- **接口说明**:获取客户端版本。
- **返回值**:返回客户端版本的静态字符串。
- `fn ping(&self, _: &mut Self::Target) -> RawResult<()>`
- **接口说明**:检查连接是否仍然存活。
- **参数说明**
- `_`:目标连接的可变引用。
- **返回值**:成功时返回空的 `RawResult`,失败时返回错误。
- `fn ready(&self) -> bool`
- **接口说明**:检查是否准备好连接。
- **返回值**大多数情况下返回true表示地址准备好连接。
- `fn build(&self) -> RawResult<Self::Target>`
- **接口说明**:从此结构创建新的连接。
- **返回值**:成功时返回目标连接类型的 `RawResult`,失败时返回错误。
### 执行 SQL
执行 SQL 主要涉及到 Taos 结构体,以及结果集 ResultSet 结构体,还有列信息 Field。
#### Taos
Taos 结构体提供了多个数据库操作的 API包括执行 SQL无模式写入以及一些常用数据库查询的封装如创建数据库获取
- `pub fn is_native(&self) -> bool`
- **接口说明**:判断连接是否使用本地协议。
- **返回值**:如果使用本地协议,则返回 `true`,否则返回 `false`。
- `pub fn is_ws(&self) -> bool`
- **接口说明**判断连接是否使用websocket协议。
- **返回值**如果使用websocket协议则返回 `true`,否则返回 `false`。
- `fn query<T: AsRef<str>>(&self, sql: T) -> RawResult<Self::ResultSet>`
- **接口说明**执行SQL查询。
- **参数说明**
- `sql`要执行的SQL语句。
- **返回值**:成功时返回结果集 `ResultSet` 的 `RawResult`,失败时返回错误。
- `fn query_with_req_id<T: AsRef<str>>(&self, sql: T, req_id: u64) -> RawResult<Self::ResultSet>`
- **接口说明**带请求ID执行SQL查询。
- **参数说明**
- `sql`要执行的SQL语句。
- `req_id`请求ID。
- **返回值**:成功时返回结果集 `ResultSet` 的 `RawResult`,失败时返回错误。
- `fn exec<T: AsRef<str>>(&self, sql: T) -> RawResult<usize>`
- **接口说明**执行SQL语句。
- **参数说明**
- `sql`要执行的SQL语句。
- **返回值**:成功时返回受影响的行数,失败时返回错误。
- `fn exec_many<T: AsRef<str>, I: IntoIterator<Item = T>>(&self, input: I) -> RawResult<usize>`
- **接口说明**批量执行SQL语句。
- **参数说明**
- `input`要执行的SQL语句集合。
- **返回值**:成功时返回总共受影响的行数,失败时返回错误。
- `fn query_one<T: AsRef<str>, O: DeserializeOwned>(&self, sql: T) -> RawResult<Option<O>>`
- **接口说明**执行SQL查询并返回单个结果。
- **参数说明**
- `sql`要执行的SQL语句。
- **返回值**:成功时返回可选的结果对象,失败时返回错误。
- `fn server_version(&self) -> RawResult<Cow<str>>`
- **接口说明**:获取服务器版本。
- **返回值**:成功时返回服务器版本字符串的 `RawResult`,失败时返回错误。
- `fn create_topic(&self, name: impl AsRef<str>, sql: impl AsRef<str>) -> RawResult<()>`
- **接口说明**:创建主题。
- **参数说明**
- `name`:主题名称。
- `sql`关联的SQL语句。
- **返回值**:成功时返回空的 `RawResult`,失败时返回错误。
- `fn databases(&self) -> RawResult<Vec<ShowDatabase>>`
- **接口说明**:获取数据库列表。
- **返回值**:成功时返回数据库列表的 `RawResult`,失败时返回错误。
- `fn topics(&self) -> RawResult<Vec<Topic>>`
- **接口说明**:获取主题信息。
- **返回值**:成功时返回主题列表的 `RawResult`,失败时返回错误。
- `fn describe(&self, table: &str) -> RawResult<Describe>`
- **接口说明**:描述表结构。
- **参数说明**
- `table`:表名称。
- **返回值**:成功时返回表描述的 `RawResult`,失败时返回错误。
- `fn database_exists(&self, name: &str) -> RawResult<bool>`
- **接口说明**:检查数据库是否存在。
- **参数说明**
- `name`:数据库名称。
- **返回值**:成功时返回布尔值的 `RawResult`,指示数据库是否存在,失败时返回错误。
- `fn put(&self, data: &SmlData) -> RawResult<()>`
- **接口说明**:写入无模式数据。
- **参数说明**
- `data`:无模式数据。
- **返回值**:成功时返回空的 `RawResult`,失败时返回错误。
#### ResultSet
ResultSet 结构体提供了结果集的一些方法,可以用来获取结果集的数据和元数据。
- `fn affected_rows(&self) -> i32`
- **接口说明**:获取受影响的行数。
- **返回值**:受影响的行数,类型为 `i32`。
- `fn precision(&self) -> Precision`
- **接口说明**:获取精度信息。
- **返回值**:精度信息,类型为 `Precision`。
- `fn fields(&self) -> &[Field]`
- **接口说明**:获取字段信息。见下文 Feild 结构体描述。
- **返回值**:字段信息数组的引用。
- `fn summary(&self) -> (usize, usize)`
- **接口说明**:获取摘要信息。
- **返回值**:包含两个 `usize` 类型的元组,分别表示某些统计信息。
- `fn num_of_fields(&self) -> usize`
- **接口说明**:获取字段数量。
- **返回值**:字段数量,类型为 `usize`。
- `fn blocks(&mut self) -> IBlockIter<'_, Self>`
- **接口说明**:获取原始数据块的迭代器。
- **返回值**:原始数据块的迭代器,类型为 `IBlockIter<'_, Self>`。
- `fn rows(&mut self) -> IRowsIter<'_, Self>`
- **接口说明**:获取按行查询的迭代器。
- **返回值**:按行查询的迭代器,类型为 `IRowsIter<'_, Self>`。
- `fn deserialize<T>(&mut self) -> Map<IRowsIter<'_, Self>, fn(_: Result<RowView<'_>, Error>) -> Result<T, Error>>`
- **接口说明**:反序列化行数据。
- **泛型参数**
- `T`:目标类型,需实现 `DeserializeOwned`。
- **返回值**:反序列化结果的映射,类型为 `Map<IRowsIter<'_, Self>, fn(_: Result<RowView<'_>, Error>) -> Result<T, Error>>`。
- `fn to_rows_vec(&mut self) -> Result<Vec<Vec<Value>>, Error>`
- **接口说明**:将结果集转换为值的二维向量。
- **返回值**:成功时返回值的二维向量,失败时返回错误,类型为 `Result<Vec<Vec<Value>>, Error>`。
#### Feild
Feild 结构体提供了字段信息的一些方法。
- `pub const fn empty() -> Field`
- **接口说明**:创建一个空的 `Field` 实例。
- **返回值**:返回一个空的 `Field` 实例。
- `pub fn new(name: impl Into<String>, ty: Ty, bytes: u32) -> Field`
- **接口说明**:创建一个新的 `Field` 实例。
- **参数说明**
- `name`:字段名称。
- `ty`:字段类型。
- `bytes`:字段数据长度。
- **返回值**:返回一个新的 `Field` 实例。
- `pub fn name(&self) -> &str`
- **接口说明**:获取字段名称。
- **返回值**:返回字段的名称。
- `pub fn escaped_name(&self) -> String`
- **接口说明**:获取转义后的字段名称。
- **返回值**:返回转义后的字段名称。
- `pub const fn ty(&self) -> Ty`
- **接口说明**:获取字段类型。
- **返回值**:返回字段的类型。
- `pub const fn bytes(&self) -> u32`
- **接口说明**:获取字段的预设长度。
- **返回值**:对于变长数据类型,返回其预设长度;对于其他类型,返回其字节宽度。
- `pub fn to_c_field(&self) -> c_field_t`
- **接口说明**:将 `Field` 实例转换为 C 语言结构体。
- **返回值**:返回 C 语言结构体表示的字段。
- `pub fn sql_repr(&self) -> String`
- **接口说明**:表示字段在 SQL 中的数据类型。
- **返回值**:例如:"INT", "VARCHAR(100)" 等 SQL 数据类型表示。
### 参数绑定
参数绑定功能主要由 Stmt 结构体支持。
#### Stmt
Stmt 结构体提供了参数绑定相关功能,用于实现高效写入。
- `fn init(taos: &Q) -> RawResult<Self>`
- **接口说明**:初始化参数绑定实例。
- **参数说明**
- `taos`:数据库连接实例。
- **返回值**:成功时返回初始化的实例,失败时返回错误。
- `fn init_with_req_id(taos: &Q, req_id: u64) -> RawResult<Self>`
- **接口说明**使用请求ID初始化参数绑定实例。
- **参数说明**
- `taos`:数据库连接实例。
- `req_id`请求ID。
- **返回值**:成功时返回初始化的实例,失败时返回错误。
- `fn prepare<S: AsRef<str>>(&mut self, sql: S) -> RawResult<&mut Self>`
- **接口说明**:准备要绑定的 SQL 语句。
- **参数说明**
- `sql`要准备的SQL语句。
- **返回值**:成功时返回自身的可变引用,失败时返回错误。
- `fn set_tbname<S: AsRef<str>>(&mut self, name: S) -> RawResult<&mut Self>`
- **接口说明**:设置表名称。
- **参数说明**
- `name`:表名称。
- **返回值**:成功时返回自身的可变引用,失败时返回错误。
- `fn set_tags(&mut self, tags: &[Value]) -> RawResult<&mut Self>`
- **接口说明**:设置标签。
- **参数说明**
- `tags`:标签数组。
- **返回值**:成功时返回自身的可变引用,失败时返回错误。
- `fn set_tbname_tags<S: AsRef<str>>(&mut self, name: S, tags: &[Value]) -> RawResult<&mut Self>`
- **接口说明**:设置表名称和标签。
- **参数说明**
- `name`:表名称。
- `tags`:标签数组。
- **返回值**:成功时返回自身的可变引用,失败时返回错误。
- `fn bind(&mut self, params: &[ColumnView]) -> RawResult<&mut Self>`
- **接口说明**:绑定参数。
- **参数说明**
- `params`:参数数组。
- **返回值**:成功时返回自身的可变引用,失败时返回错误。
- `fn add_batch(&mut self) -> RawResult<&mut Self>`
- **接口说明**:添加批处理。
- **返回值**:成功时返回自身的可变引用,失败时返回错误。
- `fn execute(&mut self) -> RawResult<usize>`
- **接口说明**:执行语句。
- **返回值**:成功时返回受影响的行数,失败时返回错误。
- `fn affected_rows(&self) -> usize`
- **接口说明**:获取受影响的行数。
- **返回值**:受影响的行数。
### 数据订阅
数据订阅主要涉及三个结构体,提供连接建立的 TmqBuilder 消费数据和提交偏移量的 Consumer以及偏移量 Offset。
#### TmqBuilder
同 TaosBuilder 类似TmqBuilder 提供了创建消费者对象的功能。
- `fn available_params() -> &'static [&'static str]`
- **接口说明**:获取 DSN 中可用的参数列表。
- **返回值**:返回静态字符串切片的引用,包含可用的参数名称。
- `fn from_dsn<D: IntoDsn>(dsn: D) -> RawResult<Self>`
- **接口说明**:使用 DSN 字符串创建连接,不检查连接。
- **参数说明**
- `dsn`DSN 字符串或可转换为DSN的类型。
- **返回值**:成功时返回自身类型的 `RawResult`,失败时返回错误。
- `fn client_version() -> &'static str`
- **接口说明**:获取客户端版本。
- **返回值**:返回客户端版本的静态字符串。
- `fn ping(&self, conn: &mut Self::Target) -> RawResult<()>`
- **接口说明**:检查连接是否仍然存活。
- **参数说明**
- `conn`:目标连接的可变引用。
- **返回值**:成功时返回空的 `RawResult`,失败时返回错误。
- `fn ready(&self) -> bool`
- **接口说明**:检查是否准备好连接。
- **返回值**大多数情况下返回true表示地址准备好连接。
- `fn build(&self) -> RawResult<Self::Target>`
- **接口说明**:从此结构创建新的连接。
- **返回值**:成功时返回目标连接类型的 `RawResult`,失败时返回错误。
#### Consumer
Consumer 结构体提供了订阅相关的功能,包括订阅,获取消息,提交偏移量,设置偏移量等。
- `fn subscribe<T: Into<String>, I: IntoIterator<Item = T> + Send>(&mut self, topics: I) -> RawResult<()>`
- **接口说明**:订阅一系列主题。
- **参数说明**
- `topics`:要订阅的主题列表。
- **返回值**:成功时返回空的 `RawResult`,失败时返回错误。
- `fn recv_timeout(&self, timeout: Timeout) -> RawResult<Option<(Self::Offset, MessageSet<Self::Meta, Self::Data>)>>`
- **接口说明**:在指定超时时间内接收消息。
- **参数说明**
- `timeout`:超时时间。
- **返回值**:成功时返回消息,失败时返回错误。
- `fn commit(&self, offset: Self::Offset) -> RawResult<()>`
- **接口说明**:提交给定的偏移量。
- **参数说明**
- `offset`:要提交的偏移量,见下文 Offset 结构体。
- **返回值**:成功时返回空的 `RawResult`,失败时返回错误。
- `fn commit_offset(&self, topic_name: &str, vgroup_id: VGroupId, offset: i64) -> RawResult<()>`
- **接口说明**:为特定主题和分区提交偏移量。
- **参数说明**
- `topic_name`:主题名称。
- `vgroup_id`:分区 ID。
- `offset`:要提交的偏移量。
- **返回值**:成功时返回空的 `RawResult`,失败时返回错误。
- `fn list_topics(&self) -> RawResult<Vec<String>>`
- **接口说明**:列出所有可用主题。
- **返回值**:成功时返回主题列表,失败时返回错误。
- `fn assignments(&self) -> Option<Vec<(String, Vec<Assignment>)>>`
- **接口说明**:获取当前分配的主题和分区。
- **返回值**:成功时返回分配信息,失败时返回 `None`。
- `fn offset_seek(&mut self, topic: &str, vg_id: VGroupId, offset: i64) -> RawResult<()>`
- **接口说明**:为特定主题和分区设置偏移量。
- **参数说明**
- `topic`:主题名称。
- `vg_id`:分区 ID。
- `offset`:要设置的偏移量。
- **返回值**:成功时返回空的 `RawResult`,失败时返回错误。
- `fn committed(&self, topic: &str, vgroup_id: VGroupId) -> RawResult<i64>`
- **接口说明**:获取特定主题和分区的已提交偏移量。
- **参数说明**
- `topic`:主题名称。
- `vgroup_id`:分区 ID。
- **返回值**:成功时返回偏移量,失败时返回错误。
- `fn position(&self, topic: &str, vgroup_id: VGroupId) -> RawResult<i64>`
- **接口说明**:获取特定主题和分区的当前位置。
- **参数说明**
- `topic`:主题名称。
- `vgroup_id`:分区 ID。
- **返回值**:成功时返回当前位置,失败时返回错误。
#### Offset
Offset 结构体提供了获取当前消息所属的数据库,主题和分区信息。
- `fn database(&self) -> &str`
- **接口说明**:获取当前消息的数据库名称。
- **返回值**:数据库名称的引用。
- `fn topic(&self) -> &str`
- **接口说明**:获取当前消息的主题名称。
- **返回值**:主题名称的引用。
- `fn vgroup_id(&self) -> VGroupId`
- **接口说明**:获取当前消息的分区 ID。
- **返回值**:分区 ID。
其他相关结构体 API 使用说明请移步 Rust 文档托管网页https://docs.rs/taos。
[taos]: https://github.com/taosdata/rust-connector-taos
[deadpool]: https://crates.io/crates/deadpool

View File

@ -99,507 +99,9 @@ TDengine 目前支持时间戳、数字、字符、布尔类型,与 Python 对
|NCHAR|str|
|JSON|str|
## 安装步骤
## 示例程序汇总
### 安装前准备
1. 安装 Python。新近版本 taospy 包要求 Python 3.6.2+。早期版本 taospy 包要求 Python 3.7+。taos-ws-py 包要求 Python 3.7+。如果系统上还没有 Python 可参考 [Python BeginnersGuide](https://wiki.python.org/moin/BeginnersGuide/Download) 安装。
2. 安装 [pip](https://pypi.org/project/pip/)。大部分情况下 Python 的安装包都自带了 pip 工具, 如果没有请参考 [pip documentation](https://pip.pypa.io/en/stable/installation/) 安装。
3. 如果使用原生连接,还需[安装客户端驱动](../#安装客户端驱动)。客户端软件包含了 TDengine 客户端动态链接库(libtaos.so 或 taos.dll) 和 TDengine CLI。
### 使用 pip 安装
#### 卸载旧版本
如果以前安装过旧版本的 Python 连接器, 请提前卸载。
```
pip3 uninstall taos taospy
```
:::note
较早的 TDengine 客户端软件包含了 Python 连接器。如果从客户端软件的安装目录安装了 Python 连接器,那么对应的 Python 包名是 `taos`。 所以上述卸载命令包含了 `taos` 不存在也没关系。
:::
#### 安装 `taospy`
<Tabs>
<TabItem label="从 PyPI 安装" value="pypi">
安装最新版本
```
pip3 install taospy
```
也可以指定某个特定版本安装。
```
pip3 install taospy==2.3.0
```
</TabItem>
<TabItem label="从 GitHub 安装" value="github">
```
pip3 install git+https://github.com/taosdata/taos-connector-python.git
```
</TabItem>
</Tabs>
#### 安装 `taos-ws-py`(可选)
taos-ws-py 包提供了通过 WebSocket 连接 TDengine 的能力,可选安装 taos-ws-py 以获得 WebSocket 连接 TDengine 的能力。
##### 和 taospy 同时安装
```bash
pip3 install taospy[ws]
```
##### 单独安装
```bash
pip3 install taos-ws-py
```
### 安装验证
<Tabs defaultValue="rest">
<TabItem value="native" label="原生连接">
对于原生连接,需要验证客户端驱动和 Python 连接器本身是否都正确安装。如果能成功导入 `taos` 模块,则说明已经正确安装了客户端驱动和 Python 连接器。可在 Python 交互式 Shell 中输入:
```python
import taos
```
</TabItem>
<TabItem value="rest" label="REST 连接">
对于 REST 连接,只需验证是否能成功导入 `taosrest` 模块。可在 Python 交互式 Shell 中输入:
```python
import taosrest
```
</TabItem>
<TabItem value="ws" label="WebSocket 连接">
对于 WebSocket 连接,只需验证是否能成功导入 `taosws` 模块。可在 Python 交互式 Shell 中输入:
```python
import taosws
```
</TabItem>
</Tabs>
:::tip
如果系统上有多个版本的 Python则可能有多个 `pip` 命令。要确保使用的 `pip` 命令路径是正确的。上面我们用 `pip3` 命令安装,排除了使用 Python 2.x 版本对应的 `pip` 的可能性。但是如果系统上有多个 Python 3.x 版本,仍需检查安装路径是否正确。最简单的验证方式是,在命令再次输入 `pip3 install taospy`, 就会打印出 `taospy` 的具体安装位置,比如在 Windows 上:
```
C:\> pip3 install taospy
Looking in indexes: https://pypi.tuna.tsinghua.edu.cn/simple
Requirement already satisfied: taospy in c:\users\username\appdata\local\programs\python\python310\lib\site-packages (2.3.0)
```
:::
## 建立连接
### 连通性测试
在用连接器建立连接之前,建议先测试本地 TDengine CLI 到 TDengine 集群的连通性。
<Tabs defaultValue="rest">
<TabItem value="native" label="原生连接">
请确保 TDengine 集群已经启动, 且集群中机器的 FQDN 如果启动的是单机版FQDN 默认为 hostname在本机能够解析, 可用 `ping` 命令进行测试:
```
ping <FQDN>
```
然后测试用 TDengine CLI 能否正常连接集群:
```
taos -h <FQDN> -p <PORT>
```
上面的 FQDN 可以为集群中任意一个 dnode 的 FQDN PORT 为这个 dnode 对应的 serverPort。
</TabItem>
<TabItem value="rest" label="REST 连接" groupId="connect">
对于 REST 连接, 除了确保集群已经启动,还要确保 taosAdapter 组件已经启动。可以使用如下 curl 命令测试:
```
curl -u root:taosdata http://<FQDN>:<PORT>/rest/sql -d "select server_version()"
```
上面的 FQDN 为运行 taosAdapter 的机器的 FQDN PORT 为 taosAdapter 配置的监听端口, 默认为 6041。
如果测试成功,会输出服务器版本信息,比如:
```json
{
"code": 0,
"column_meta": [
[
"server_version()",
"VARCHAR",
7
]
],
"data": [
[
"3.0.0.0"
]
],
"rows": 1
}
```
</TabItem>
<TabItem value="ws" label="WebSocket 连接" groupId="connect">
对于 WebSocket 连接, 除了确保集群已经启动,还要确保 taosAdapter 组件已经启动。可以使用如下 curl 命令测试:
```
curl -i -N -d "show databases" -H "Authorization: Basic cm9vdDp0YW9zZGF0YQ==" -H "Connection: Upgrade" -H "Upgrade: websocket" -H "Host: <FQDN>:<PORT>" -H "Origin: http://<FQDN>:<PORT>" http://<FQDN>:<PORT>/rest/sql
```
上面的 FQDN 为运行 taosAdapter 的机器的 FQDN PORT 为 taosAdapter 配置的监听端口, 默认为 6041。
如果测试成功,会输出服务器版本信息,比如:
```json
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Date: Tue, 21 Mar 2023 09:29:17 GMT
Transfer-Encoding: chunked
{"status":"succ","head":["server_version()"],"column_meta":[["server_version()",8,8]],"data":[["2.6.0.27"]],"rows":1}
```
</TabItem>
</Tabs>
### 指定 Host 和 Properties 获取连接
以下示例代码假设 TDengine 安装在本机, 且 FQDN 和 serverPort 都使用了默认配置。
<Tabs defaultValue="rest">
<TabItem value="native" label="原生连接" groupId="connect">
```python
{{#include docs/examples/python/connect_native_reference.py}}
```
`connect` 函数的所有参数都是可选的关键字参数。下面是连接参数的具体说明:
- `host` 要连接的节点的 FQDN。 没有默认值。如果不同提供此参数,则会连接客户端配置文件中的 firstEP。
- `user` TDengine 用户名。 默认值是 root。
- `password` TDengine 用户密码。 默认值是 taosdata。
- `port` 要连接的数据节点的起始端口,即 serverPort 配置。默认值是 6030。只有在提供了 host 参数的时候,这个参数才生效。
- `config` 客户端配置文件路径。 在 Windows 系统上默认是 `C:\TDengine\cfg`。 在 Linux/macOS 系统上默认是 `/etc/taos/`。
- `timezone` 查询结果中 TIMESTAMP 类型的数据,转换为 python 的 datetime 对象时使用的时区。默认为本地时区。
:::warning
`config` 和 `timezone` 都是进程级别的配置。建议一个进程建立的所有连接都使用相同的参数值。否则可能产生无法预知的错误。
:::
:::tip
`connect` 函数返回 `taos.TaosConnection` 实例。 在客户端多线程的场景下,推荐每个线程申请一个独立的连接实例,而不建议多线程共享一个连接。
:::
</TabItem>
<TabItem value="rest" label="REST 连接">
```python
{{#include docs/examples/python/connect_rest_examples.py:connect}}
```
`connect()` 函数的所有参数都是可选的关键字参数。下面是连接参数的具体说明:
- `url` taosAdapter REST 服务的 URL。默认是 \<http://localhost:6041>。
- `user` TDengine 用户名。默认是 root。
- `password` TDengine 用户密码。默认是 taosdata。
- `timeout`: HTTP 请求超时时间。单位为秒。默认为 `socket._GLOBAL_DEFAULT_TIMEOUT`。 一般无需配置。
</TabItem>
<TabItem value="websocket" label="WebSocket 连接">
```python
{{#include docs/examples/python/connect_websocket_examples.py:connect}}
```
`connect()` 函数参数为连接 url协议为 `taosws` 或 `ws`
</TabItem>
</Tabs>
### 配置参数的优先级
如果配置参数在参数和客户端配置文件中有重复,则参数的优先级由高到低分别如下:
1. 连接参数
2. 使用原生连接时TDengine 客户端驱动的配置文件 taos.cfg
## 使用示例
### 创建数据库和表
<Tabs defaultValue="rest">
<TabItem value="native" label="原生连接">
```python
{{#include docs/examples/python/create_db_native.py}}
```
</TabItem>
<TabItem value="rest" label="REST 连接">
```python
{{#include docs/examples/python/create_db_rest.py}}
```
</TabItem>
<TabItem value="websocket" label="WebSocket 连接">
```python
{{#include docs/examples/python/create_db_ws.py}}
```
</TabItem>
</Tabs>
### 插入数据
<Tabs defaultValue="rest">
<TabItem value="native" label="原生连接">
```python
{{#include docs/examples/python/insert_native.py:insert}}
```
</TabItem>
<TabItem value="rest" label="REST 连接">
```python
{{#include docs/examples/python/insert_rest.py:insert}}
```
</TabItem>
<TabItem value="websocket" label="WebSocket 连接">
```python
{{#include docs/examples/python/insert_ws.py:insert}}
```
</TabItem>
</Tabs>
> NOW 为系统内部函数,默认为客户端所在计算机当前时间。
> `NOW + 1s` 代表客户端当前时间往后加 1 秒数字后面代表时间单位a(毫秒)s(秒)m(分)h(小时)d(天)w(周)n(月)y(年)。
### 查询数据
<Tabs defaultValue="rest">
<TabItem value="native" label="原生连接">
`TaosConnection` 类的 `query` 方法可以用来查询数据,返回 `TaosResult` 类型的结果数据。
```python
{{#include docs/examples/python/insert_native.py:query}}
```
:::tip
查询结果只能获取一次。比如上面的示例中 `fetch_all()` 和 `fetch_all_into_dict()` 只能用一个。重复获取得到的结果为空列表。
:::
</TabItem>
<TabItem value="rest" label="REST 连接">
RestClient 类是对于 REST API 的直接封装。它只包含一个 sql() 方法用于执行任意 SQL 语句, 并返回执行结果。
```python
{{#include docs/examples/python/insert_rest.py:query}}
```
对于 `sql()` 方法更详细的介绍, 请参考 [RestClient](https://docs.taosdata.com/api/taospy/taosrest/restclient.html)。
</TabItem>
<TabItem value="websocket" label="WebSocket 连接">
`TaosConnection` 类的 `query` 方法可以用来查询数据,返回 `TaosResult` 类型的结果数据。
```python
{{#include docs/examples/python/insert_ws.py:query}}
```
</TabItem>
</Tabs>
### 执行带有 reqId 的 SQL
<RequestId />
<Tabs defaultValue="rest">
<TabItem value="native" label="原生连接">
类似上文介绍的使用方法,增加 `req_id` 参数。
```python
{{#include docs/examples/python/insert_native.py:req_id}}
```
</TabItem>
<TabItem value="rest" label="REST 连接">
类似上文介绍的使用方法,增加 `req_id` 参数。
```python
{{#include docs/examples/python/insert_rest.py:req_id}}
```
</TabItem>
<TabItem value="websocket" label="WebSocket 连接">
类似上文介绍的使用方法,增加 `req_id` 参数。
```python
{{#include docs/examples/python/insert_ws.py:req_id}}
```
</TabItem>
</Tabs>
### 通过参数绑定写入数据
TDengine 的 Python 连接器支持参数绑定风格的 Prepare API 方式写入数据,和大多数数据库类似,目前仅支持用 `?` 来代表待绑定的参数。
<Tabs>
<TabItem value="native" label="原生连接">
```python
{{#include docs/examples/python/stmt_native.py:stmt}}
```
</TabItem>
<TabItem value="websocket" label="WebSocket 连接">
```python
{{#include docs/examples/python/stmt_ws.py:stmt}}
```
</TabItem>
</Tabs>
### 无模式写入
连接器支持无模式写入功能。
<Tabs defaultValue="list">
<TabItem value="list" label="原生连接">
```python
{{#include docs/examples/python/schemaless_native.py}}
```
</TabItem>
<TabItem value="raw" label="WebSocket 连接">
```python
{{#include docs/examples/python/schemaless_ws.py}}
```
</TabItem>
</Tabs>
### 执行带有 reqId 的无模式写入
连接器的 `schemaless_insert` 和 `schemaless_insert_raw` 方法支持 `req_id` 可选参数,此 `req_id` 可用于请求链路追踪。
```python
conn.schemaless_insert(
lines=lineDemo,
protocol=taos.SmlProtocol.LINE_PROTOCOL,
precision=taos.SmlPrecision.NANO_SECONDS,
req_id=1,
)
```
### 数据订阅
连接器支持数据订阅功能,数据订阅功能请参考 [数据订阅文档](../../develop/tmq/)。
#### 创建 Topic
```python
{{#include docs/examples/python/tmq_native.py:create_topic}}
```
#### 创建 Consumer
```python
{{#include docs/examples/python/tmq_native.py:create_consumer}}
```
#### 订阅 topics
```python
{{#include docs/examples/python/tmq_native.py:subscribe}}
```
#### 消费数据
```python
{{#include docs/examples/python/tmq_native.py:consume}}
```
#### 获取消费进度
Consumer API 的 `assignment` 方法用于获取 Consumer 订阅的所有 topic 的消费进度,返回结果类型为 TopicPartition 列表。
```python
{{#include docs/examples/python/tmq_native.py:assignment}}
```
Consumer API 的 `seek` 方法用于重置 Consumer 的消费进度到指定位置,方法参数类型为 TopicPartition。
```python
{{#include docs/examples/python/tmq_native.py:consume}}
```
#### 关闭订阅
消费结束后,应当取消订阅,并关闭 Consumer。
```python
{{#include docs/examples/python/tmq_native.py:unsubscribe}}
```
#### 完整示例
```python
{{#include docs/examples/python/tmq_native.py}}
```
### 更多示例程序
| 示例程序链接 | 示例程序内容 |
| 示例程序链接 | 示例程序内容 |
| ------------------------------------------------------------------------------------------------------------- | ----------------------- |
| [bind_multi.py](https://github.com/taosdata/taos-connector-python/blob/main/examples/bind-multi.py) | 参数绑定, 一次绑定多行 |
| [bind_row.py](https://github.com/taosdata/taos-connector-python/blob/main/examples/bind-row.py) | 参数绑定,一次绑定一行 |
@ -607,24 +109,450 @@ Consumer API 的 `seek` 方法用于重置 Consumer 的消费进度到指定位
| [json_tag.py](https://github.com/taosdata/taos-connector-python/blob/main/examples/json-tag.py) | 使用 JSON 类型的标签 |
| [tmq_consumer.py](https://github.com/taosdata/taos-connector-python/blob/main/examples/tmq_consumer.py) | tmq 订阅 |
## 其它说明
### 关于纳秒 (nanosecond)
## 关于纳秒 (nanosecond)
由于目前 Python 对 nanosecond 支持的不完善(见下面的链接),目前的实现方式是在 nanosecond 精度时返回整数,而不是 ms 和 us 返回的 datetime 类型,应用开发者需要自行处理,建议使用 pandas 的 to_datetime()。未来如果 Python 正式完整支持了纳秒Python 连接器可能会修改相关接口。
1. https://stackoverflow.com/questions/10611328/parsing-datetime-strings-containing-nanoseconds
2. https://www.python.org/dev/peps/pep-0564/
## 重要更新
[**Release Notes**](https://github.com/taosdata/taos-connector-python/releases)
## API 参考
- [taos](https://docs.taosdata.com/api/taospy/taos/)
- [taosrest](https://docs.taosdata.com/api/taospy/taosrest)
## 常见问题
欢迎[提问或报告问题](https://github.com/taosdata/taos-connector-python/issues)。
## API 参考
### WebSocket 连接
#### URL 规范
```text
[+<protocol>]://[[<username>:<password>@]<host>:<port>][/<database>][?<p1>=<v1>[&<p2>=<v2>]]
|------------|---|-----------|-----------|------|------|------------|-----------------------|
| protocol | | username | password | host | port | database | params |
```
- **protocol**: 使用 websocket 协议建立连接。例如`ws://localhost:6041`
- **username/password**: 数据库的用户名和密码。
- **host/port**: 主机地址和端口号。例如`localhost:6041`
- **database**: 数据库名称。
- **params**: 其他参数。 例如token。
#### 建立连接
- `fn connect(dsn: Option<&str>, args: Option<&PyDict>) -> PyResult<Connection>`
- **接口说明**:建立 taosAdapter 连接。
- **参数说明**
- `dsn`: 类型 `Option<&str>` 可选数据源名称DSN用于指定要连接的数据库的位置和认证信息。
- `args`: 类型 `Option<&PyDict>` 可选,以 Python 字典的形式提供, 可用于设置
- `user`: 数据库的用户名
- `password`: 数据库的密码。
- `host`: 主机地址
- `port`: 端口号
- `database`: 数据库名称
- **返回值**:连接对象。
- **异常**:操作失败抛出 `ConnectionError` 异常。
- `fn cursor(&self) -> PyResult<Cursor>`
- **接口说明**创建一个新的数据库游标对象用于执行SQL命令和查询。
- **返回值**:数据库游标对象。
- **异常**:操作失败抛出 `ConnectionError` 异常。
#### 执行SQL
- `fn execute(&self, sql: &str) -> PyResult<i32>`
- **接口说明**:执行 sql 语句。
- **参数说明**
- `sql`:待执行的 sql 语句。
- **返回值**:影响的条数。
- **异常**:操作失败抛出 `QueryError` 异常。
- `fn execute_with_req_id(&self, sql: &str, req_id: u64) -> PyResult<i32>`
- **接口说明**:执行带有 req_id 的 sql 语句。
- **参数说明**
- `sql`:待执行的 sql 语句。
- `reqId`: 用于问题追踪。
- **返回值**:影响的条数。
- **异常**:操作失败抛出 `QueryError` 异常。
- `fn query(&self, sql: &str) -> PyResult<TaosResult>`
- **接口说明**:查询数据。
- **参数说明**
- `sql`:待执行的 sql 语句。
- **返回值**`TaosResult` 数据集对象。
- **异常**:操作失败抛出 `QueryError` 异常。
- `fn query_with_req_id(&self, sql: &str, req_id: u64) -> PyResult<TaosResult>`
- **接口说明**:查询带有 req_id 的 sql 语句。
- **参数说明**
- `sql`:待执行的 sql 语句。
- `reqId`: 用于问题追踪。
- **返回值**`TaosResult` 数据集对象。
- **异常**:操作失败抛出 `QueryError` 异常。
#### 数据集
TaosResult 对象可以通过循环遍历获取查询到的数据。
- `fn fields(&self) -> Vec<TaosField>`
- **接口说明**:获取查询数据的字段信息, 包括:名称,类型及字段长度。
- **返回值**`Vec<TaosField>` 字段信息数组。
- `fn field_count(&self) -> i32`
- **接口说明**:获取查询到的记录条数。
- **返回值**`i32` 查询到的记录条数。
#### 无模式写入
- `fn schemaless_insert(&self, lines: Vec<String>, protocol: PySchemalessProtocol, precision: PySchemalessPrecision, ttl: i32, req_id: u64) -> PyResult<()>`
- **接口说明**:无模式写入。
- **参数说明**
- `lines`:待写入的数据数组,无模式具体的数据格式可参考 `Schemaless 写入`。
- `protocol`: 协议类型
- `PySchemalessProtocol::Line` InfluxDB 行协议Line Protocol)。
- `PySchemalessProtocol::Telnet`OpenTSDB 文本行协议。
- `PySchemalessProtocol::Json` JSON 协议格式
- `precision`: 时间精度
- `PySchemalessPrecision::Hour` 小时
- `PySchemalessPrecision::Minute`:分钟
- `PySchemalessPrecision::Second` 秒
- `PySchemalessPrecision::Millisecond`:毫秒
- `PySchemalessPrecision::Microsecond`:微秒
- `PySchemalessPrecision::Nanosecond` 纳秒
- `ttl`:表过期时间,单位天。
- `reqId`: 用于问题追踪。
- **异常**:操作失败抛出 `DataError` 或 `OperationalError` 异常。
#### 参数绑定
- `fn statement(&self) -> PyResult<TaosStmt>`
- **接口说明**:使用 连接 对象创建 stmt 对象。
- **返回值**stmt 对象。
- **异常**:操作失败抛出 `ConnectionError` 异常。
- `fn prepare(&mut self, sql: &str) -> PyResult<()>`
- **接口说明**:绑定预编译 sql 语句。
- **参数说明**
- `sql`: 预编译的 SQL 语句。
- **异常**:操作失败抛出 `ProgrammingError` 异常。
- `fn set_tbname(&mut self, table_name: &str) -> PyResult<()>`
- **接口说明**:设置将要写入数据的表名。
- **参数说明**
- `tableName`: 表名,如果需要指定数据库, 例如: `db_name.table_name` 即可。
- **异常**:操作失败抛出 `ProgrammingError` 异常。
- `fn set_tags(&mut self, tags: Vec<PyTagView>) -> PyResult<()>`
- **接口说明**:设置表 Tags 数据, 用于自动建表。
- **参数说明**
- `paramsArray`: Tags 数据。
- **异常**:操作失败抛出 `ProgrammingError` 异常。
- `fn bind_param(&mut self, params: Vec<PyColumnView>) -> PyResult<()>`
- **接口说明**:绑定数据。
- **参数说明**
- `paramsArray`: 绑定数据。
- **异常**:操作失败抛出 `ProgrammingError` 异常。
- `fn add_batch(&mut self) -> PyResult<()>`
- **接口说明**:提交绑定数据。
- **异常**:操作失败抛出 `ProgrammingError` 异常。
- `fn execute(&mut self) -> PyResult<usize>`
- **接口说明**:执行将绑定的数据全部写入。
- **返回值**:写入条数。
- **异常**:操作失败抛出 `QueryError` 异常。
- `fn affect_rows(&mut self) -> PyResult<usize>`
- **接口说明** 获取写入条数。
- **返回值**:写入条数。
- `fn close(&self) -> PyResult<()>`
- **接口说明** 关闭 stmt 对象。
#### 数据订阅
- **创建消费者支持属性列表**
- host主机地址。
- port端口号。
- group.id所在的 group。
- client.id客户端id。
- td.connect.user: 数据库用户名。
- td.connect.pass: 数据库密码。
- td.connect.token数据库的连接token。
- auto.offset.reset来确定消费位置为最新数据latest还是包含旧数据earliest
- enable.auto.commit是否允许自动提交。
- auto.commit.interval.ms自动提交间隔
- `fn Consumer(conf: Option<&PyDict>, dsn: Option<&str>) -> PyResult<Self>`
- **接口说明** 消费者构造函数。
- `conf`: 类型 `Option<&PyDict>` 可选,以 Python 字典的形式提供, 具体配置参见属性列表。
- `dsn`: 类型 `Option<&str>` 可选数据源名称DSN用于指定要连接的数据库的位置和认证信息。
- **返回值**Consumer 消费者对象。
- **异常**:操作失败抛出 `ConsumerException` 异常。
- `fn subscribe(&mut self, topics: &PyList) -> PyResult<()>`
- **接口说明** 订阅一组主题。
- **参数说明**
- `topics`: 订阅的主题列表。
- **异常**:操作失败抛出 `ConsumerException` 异常。
- `fn unsubscribe(&mut self)`
- **接口说明** 取消订阅。
- **异常**:操作失败抛出 `ConsumerException` 异常。
- `fn poll(&mut self, timeout: Option<f64>) -> PyResult<Option<Message>>`
- **接口说明** 轮询消息。
- **参数说明**
- `timeoutMs`: 表示轮询的超时时间,单位毫秒。
- **返回值**`Message` 每个主题对应的数据。
- **异常**:操作失败抛出 `ConsumerException` 异常。
- `fn commit(&mut self, message: &mut Message) -> PyResult<()>`
- **接口说明** 提交当前处理的消息的偏移量。
- **参数说明**
- `message`: 类型 `Message`, 当前处理的消息的偏移量。
- **异常**:操作失败抛出 `ConsumerException` 异常。
- `fn assignment(&mut self) -> PyResult<Option<Vec<TopicAssignment>>>`
- **接口说明**:获取消费者当前分配的指定的分区或所有分区。
- **返回值**:返回值类型为 `Vec<TopicAssignment>`,即消费者当前分配的所有分区。
- **异常**:操作失败抛出 ConsumerException 异常。
- `fn seek(&mut self, topic: &str, vg_id: i32, offset: i64) -> PyResult<()>`
- **接口说明**:将给定分区的偏移量设置到指定的位置。
- **参数说明**
- `topic`: 订阅的主题。
- `vg_id`: vgroupid。
- `offset`:需要设置的的偏移量。
- **异常**:操作失败抛出 ConsumerException 异常。
- `fn committed(&mut self, topic: &str, vg_id: i32) -> PyResult<i64>`
- **接口说明**获取订阅主题的vgroupid分区最后提交的偏移量。
- **参数说明**
- `topic`: 订阅的主题。
- `vg_id`: vgroupid。
- **返回值**`i64`,分区最后提交的偏移量。
- **异常**:操作失败抛出 ConsumerException 异常。
- `fn position(&mut self, topic: &str, vg_id: i32) -> PyResult<i64>`
- **接口说明**:获取给定分区当前的偏移量。
- **参数说明**
- `topic`: 订阅的主题。
- `vg_id`: vgroupid。
- **返回值**`i64`,分区最后提交的偏移量。
- **异常**:操作失败抛出 ConsumerException 异常。
- `fn close(&mut self)`
- **接口说明**:关闭 tmq 连接。
- **异常**:操作失败抛出 ConsumerException 异常。
### Native 连接
#### 建立连接
- `def connect(*args, **kwargs):`
- **接口说明**:建立 taosAdapter 连接。
- **参数说明**
- `kwargs`: 以 Python 字典的形式提供, 可用于设置
- `user`: 数据库的用户名
- `password`: 数据库的密码。
- `host`: 主机地址
- `port`: 端口号
- `database`: 数据库名称
- `timezone`: 时区
- **返回值**`TaosConnection` 连接对象。
- **异常**:操作失败抛出 `AttributeError` 或 `ConnectionError` 异常。
- `def cursor(self)`
- **接口说明**创建一个新的数据库游标对象用于执行SQL命令和查询。
- **返回值**:数据库游标对象。
#### 执行SQL
- `def execute(self, operation, req_id: Optional[int] = None)`
- **接口说明**:执行 sql 语句。
- **参数说明**
- `operation`:待执行的 sql 语句。
- `reqId`: 用于问题追踪。
- **返回值**:影响的条数。
- **异常**:操作失败抛出 `ProgrammingError` 异常。
- `def query(self, sql: str, req_id: Optional[int] = None) -> TaosResult`
- **接口说明**:查询数据。
- **参数说明**
- `sql`:待执行的 sql 语句。
- `reqId`: 用于问题追踪。
- **返回值**`TaosResult` 数据集对象。
- **异常**:操作失败抛出 `ProgrammingError` 异常。
#### 数据集
TaosResult 对象可以通过循环遍历获取查询到的数据。
- `def fields(&self)`
- **接口说明**:获取查询数据的字段信息, 包括:名称,类型及字段长度。
- **返回值**`TaosFields` 字段信息 list。
- `def field_count(&self)`
- **接口说明**:获取查询到的记录条数。
- **返回值**:查询到的记录条数。
- `def fetch_all_into_dict(self)`
- **接口说明**:将所有的记录转换为字典。
- **返回值**:返回字典列表。
#### 无模式写入
- `def schemaless_insert(&self, lines: List[str], protocol: SmlProtocol, precision: SmlPrecision, req_id: Optional[int] = None, ttl: Optional[int] = None) -> int:`
- **接口说明**:无模式写入。
- **参数说明**
- `lines`:待写入的数据数组,无模式具体的数据格式可参考 `Schemaless 写入`。
- `protocol`: 协议类型
- `SmlProtocol.LINE_PROTOCOL` InfluxDB 行协议Line Protocol)。
- `SmlProtocol.TELNET_PROTOCOL`OpenTSDB 文本行协议。
- `SmlProtocol.JSON_PROTOCOL` JSON 协议格式
- `precision`: 时间精度
- `SmlPrecision.Hour` 小时
- `SmlPrecision.Minute`:分钟
- `SmlPrecision.Second` 秒
- `SmlPrecision.Millisecond`:毫秒
- `SmlPrecision.Microsecond`:微秒
- `SmlPrecision.Nanosecond` 纳秒
- `ttl`:表过期时间,单位天。
- `reqId`: 用于问题追踪。
- **返回值**:影响的条数。
- **异常**:操作失败抛出 `SchemalessError` 异常。
#### 参数绑定
- `def statement(self, sql=None)`
- **接口说明**:使用连接对象创建 stmt 对象, 如果 sql 不空会进行调用 prepare。
- `sql`: 预编译的 SQL 语句。
- **返回值**stmt 对象。
- **异常**:操作失败抛出 `StatementError` 异常。
- `def prepare(self, sql)`
- **接口说明**:绑定预编译 sql 语句。
- **参数说明**
- `sql`: 预编译的 SQL 语句。
- **异常**:操作失败抛出 `StatementError` 异常。
- `def set_tbname(self, name)`
- **接口说明**:设置将要写入数据的表名。
- **参数说明**
- `name`: 表名,如果需要指定数据库, 例如: `db_name.table_name` 即可。
- **异常**:操作失败抛出 `StatementError` 异常。
- `def set_tbname_tags(self, name, tags):`
- **接口说明**:设置表和 Tags 数据, 用于自动建表。
- **参数说明**
- `name`: 表名,如果需要指定数据库, 例如: `db_name.table_name` 即可。
- `tags`: Tags 数据。
- **异常**:操作失败抛出 `StatementError` 异常。
- `def bind_param(self, params, add_batch=True)`
- **接口说明**:绑定一组数据并提交。
- **参数说明**
- `params`: 绑定数据。
- `add_batch`: 是否提交绑定数据。
- **异常**:操作失败抛出 `StatementError` 异常。
- `def bind_param_batch(self, binds, add_batch=True)`
- **接口说明**:绑定多组数据并提交。
- **参数说明**
- `binds`: 绑定数据。
- `add_batch`: 是否提交绑定数据。
- **异常**:操作失败抛出 `StatementError` 异常。
- `def add_batch(self)`
- **接口说明**:提交绑定数据。
- **异常**:操作失败抛出 `StatementError` 异常。
- `def execute(self)`
- **接口说明**:执行将绑定的数据全部写入。
- **异常**:操作失败抛出 `StatementError` 异常。
- `def affected_rows(self)`
- **接口说明** 获取写入条数。
- **返回值**:写入条数。
- `def close(&self)`
- **接口说明** 关闭 stmt 对象。
#### 数据订阅
- **创建消费者支持属性列表**
- td.connect.ip主机地址。
- td.connect.port端口号。
- group.id所在的 group。
- client.id客户端id。
- td.connect.user: 数据库用户名。
- td.connect.pass: 数据库密码。
- td.connect.token数据库的连接token。
- auto.offset.reset来确定消费位置为最新数据latest还是包含旧数据earliest
- enable.auto.commit是否允许自动提交。
- auto.commit.interval.ms自动提交间隔
- `def Consumer(configs)`
- **接口说明** 消费者构造函数。
- `configs`: Python 字典的形式提供, 具体配置参见属性列表。
- **返回值**Consumer 消费者对象。
- **异常**:操作失败抛出 `TmqError` 异常。
- `def subscribe(self, topics)`
- **接口说明** 订阅一组主题。
- **参数说明**
- `topics`: 订阅的主题列表。
- **异常**:操作失败抛出 `TmqError` 异常。
- `def unsubscribe(self)`
- **接口说明** 取消订阅。
- **异常**:操作失败抛出 `TmqError` 异常。
- `def poll(self, timeout: float = 1.0)`
- **接口说明** 轮询消息。
- **参数说明**
- `timeout`: 表示轮询的超时时间,单位毫秒。
- **返回值**`Message` 每个主题对应的数据。
- **异常**:操作失败抛出 `TmqError` 异常。
- `def commit(self, message: Message = None, offsets: [TopicPartition] = None)`
- **接口说明** 提交当前处理的消息的偏移量。
- **参数说明**
- `message`: 类型 `Message`, 当前处理的消息的偏移量。
- `offsets`: 类型 `[TopicPartition]`, 提交一批消息的偏移量。
- **异常**:操作失败抛出 `TmqError` 异常。
- `def assignment(self)`
- **接口说明**:获取消费者当前分配的指定的分区或所有分区。
- **返回值**:返回值类型为 `[TopicPartition]`,即消费者当前分配的所有分区。
- **异常**:操作失败抛出 TmqError 异常。
- `def seek(self, partition)`
- **接口说明**:将给定分区的偏移量设置到指定的位置。
- **参数说明**
- `partition`: 需要设置的的偏移量。
- `topic`: 订阅的主题
- `partition`: 分区
- `offset`: 偏移量
- **异常**:操作失败抛出 `TmqError` 异常。
- `def committed(self, partitions)`
- **接口说明**:获取订阅主题的分区最后提交的偏移量。
- **参数说明**
- `partition`: 需要设置的的偏移量。
- `topic`: 订阅的主题
- `partition`: 分区
- **返回值**`partition`,分区最后提交的偏移量。
- **异常**:操作失败抛出 `TmqError` 异常。
- `def position(self, partitions)`
- **接口说明**:获取给定分区当前的偏移量。
- **参数说明**
- `partition`: 需要设置的的偏移量。
- `topic`: 订阅的主题
- `partition`: 分区
- **返回值**`partition`,分区最后提交的偏移量。
- **异常**:操作失败抛出 TmqError 异常。
- `def close(self)`
- **接口说明**:关闭 tmq 连接。
- **异常**:操作失败抛出 TmqError 异常。
### REST 连接
- `def connect(**kwargs) -> TaosRestConnection`
- **接口说明**:建立 taosAdapter 连接。
- **参数说明**
- `kwargs`: 以 Python 字典的形式提供, 可用于设置
- `user`: 数据库的用户名
- `password`: 数据库的密码。
- `host`: 主机地址
- `port`: 端口号
- `database`: 数据库名称
- **返回值**:连接对象。
- **异常**:操作失败抛出 `ConnectError` 异常。
- `def execute(self, sql: str, req_id: Optional[int] = None) -> Optional[int]`
- **接口说明**:执行 sql 语句。
- **参数说明**
- `sql`:待执行的 sql 语句。
- `reqId`: 用于问题追踪。
- **返回值**:影响的条数。
- **异常**:操作失败抛出 `ConnectError` 或 `HTTPError` 异常。
- `def query(self, sql: str, req_id: Optional[int] = None) -> Result`
- **接口说明**:查询数据。
- **参数说明**
- `sql`:待执行的 sql 语句。
- `reqId`: 用于问题追踪。
- **返回值**`Result` 数据集对象。
- **异常**:操作失败抛出 `ConnectError` 或 `HTTPError` 异常。
- `RestClient(self, url: str, token: str = None, database: str = None, user: str = "root", password: str = "taosdata", timeout: int = None, convert_timestamp: bool = True, timezone: Union[str, datetime.tzinfo] = None)`
- **接口说明**:建立 taosAdapter 连接 client。
- **参数说明**
- `url`: taosAdapter REST 服务的 URL。默认是 \<http://localhost:6041>。
- `user`: 数据库的用户名。
- `password`: 数据库的密码。
- `database`: 数据库名称。
- `timezone`: 时区。
- `timeout`: HTTP 请求超时时间。单位为秒。
- `convert_timestamp`: 是否将时间戳从STR类型转换为datetime类型。
- `timezone`: 时区.
- **返回值**:连接对象。
- **异常**:操作失败抛出 `ConnectError` 异常。
- `def sql(self, q: str, req_id: Optional[int] = None) -> dict`
- **接口说明**:执行 sql 语句。
- **参数说明**
- `sql`:待执行的 sql 语句。
- `reqId`: 用于问题追踪。
- **返回值**:返回字典列表。
- **异常**:操作失败抛出 `ConnectError` 或 `HTTPError` 异常。

View File

@ -28,15 +28,6 @@ Node.js 连接器目前仅支持 Websocket 连接器, 其通过 taosAdapter
| :------------------: | :----------------------: | :----------------: |
| 3.1.0 | 新版本发布,支持 WebSocket 连接 | 3.2.0.0 及更高版本 |
## 支持的功能特性
- 连接管理
- SQL写入
- SQL查询
- 参数绑定
- 数据订阅
- 无模式写入
## 处理异常
在调用连接器 api 报错后,通过 try catch 可以获取到错误的信息和错误码。
@ -85,227 +76,6 @@ Node.js 连接器目前仅支持 Websocket 连接器, 其通过 taosAdapter
**注意**JSON 类型仅在 tag 中支持。
## 安装步骤
### 安装前准备
- 安装 Node.js 开发环境, 使用14以上版本。下载链接 https://nodejs.org/en/download/
### 使用 npm 安装 Node.js 连接器
```bash
npm install @tdengine/websocket
```
### 安装验证
验证方法:
- 新建安装验证目录,例如:`~/tdengine-test`,下载 GitHub 上 [nodejsChecker.js 源代码](https://github.com/taosdata/TDengine/tree/main/docs/examples/node/websocketexample/nodejsChecker.js)到本地。
- 在命令行中执行以下命令。
```bash
npm init -y
npm install @tdengine/websocket
node nodejsChecker.js
```
- 执行以上步骤后,在命令行会输出 nodeChecker.js 连接 TDengine 实例,并执行简单插入和查询的结果。
## 建立连接
安装并引用 `@tdengine/websocket` 包。
**注意**
- 链接器使用结束后,需要调用 taos.destroy() 释放连接器资源
```javascript
const taos = require("@tdengine/websocket");
//数据库操作......
taos.destroy();
```
```javascript
WSConfig配置Websocket参数如下:
getToken(): string | undefined | null;
setToken(token: string): void;
getUser(): string | undefined | null;
setUser(user: string): void;
getPwd(): string | undefined | null;
setPwd(pws: string): void;
getDb(): string | undefined | null;
setDb(db: string): void;
getUrl(): string;
setUrl(url: string): void;
setTimeOut(ms: number): void;
getTimeOut(): number | undefined | null;
```
```javascript
{{#include docs/examples/node/websocketexample/sql_example.js:createConnect}}
```
## 使用示例
### 创建数据库和表
```javascript
{{#include docs/examples/node/websocketexample/sql_example.js:create_db_and_table}}
```
> **注意**:如果不使用 `USE power` 指定数据库,则后续对表的操作都需要增加数据库名称作为前缀,如 power.meters。
### 插入数据
```javascript
{{#include docs/examples/node/websocketexample/sql_example.js:insertData}}
```
> NOW 为系统内部函数,默认为客户端所在计算机当前时间。
> `NOW + 1s` 代表客户端当前时间往后加 1 秒数字后面代表时间单位a(毫秒)s(秒)m(分)h(小时)d(天)w(周)n(月)y(年)。
### 查询数据
```javascript
{{#include docs/examples/node/websocketexample/sql_example.js:queryData}}
```
> 查询到的数据
```javascript
wsRow:meta:=> [
{ name: 'ts', type: 'TIMESTAMP', length: 8 },
{ name: 'current', type: 'FLOAT', length: 4 },
{ name: 'voltage', type: 'INT', length: 4 },
{ name: 'phase', type: 'FLOAT', length: 4 },
{ name: 'location', type: 'VARCHAR', length: 64},
{ name: 'groupid', type: 'INT', length: 4 }
]
wsRow:data:=> [
[ 1714013737536n, 12.3, 221, 0.31, 'California.SanFrancisco', 3 ]
]
```
### 执行带有 reqId 的 SQL
<RequestId />
```javascript
{{#include docs/examples/node/websocketexample/sql_example.js:sqlWithReqid}}
```
### 通过参数绑定写入数据
TDengine 的 NodeJs 连接器支持参数绑定风格的 Prepare API 方式写入数据,和大多数数据库类似,目前仅支持用 ? 来代表待绑定的参数。采用这种方式写入数据时,能避免 SQL 语法解析的资源消耗,从而在很多情况下显著提升写入性能。
**注意**
- 预处理语句中指定数据库与子表名称不要使用 `db.?`,应直接使用 `?`,然后在 setTableName 中指定数据库,如:`stmt.setTableName("db.t1")`。
示例代码:
```javascript
{{#include docs/examples/node/websocketexample/stmt_example.js}}
```
用于设定 TAG/VALUES 数据列的取值的方法总共有:
```javascript
setBoolean(params: any[]): void;
setTinyInt(params: any[]): void;
setUTinyInt(params: any[]): void;
setSmallInt(params: any[]): void;
setUSmallInt(params: any[]): void;
setInt(params: any[]): void;
setUInt(params: any[]): void;
setBigint(params: any[]): void;
setUBigint(params: any[]): void;
setFloat(params: any[]): void;
setDouble(params: any[]): void;
setVarchar(params: any[]): void;
setBinary(params: any[]): void;
setNchar(params: any[]): void;
setJson(params: any[]): void;
setVarBinary(params: any[]): void;
setGeometry(params: any[]): void;
setTimestamp(params: any[]): void;
```
**注意**JSON 类型仅在 tag 中支持。
### 无模式写入
TDengine 支持无模式写入功能。无模式写入兼容 InfluxDB 的 行协议Line Protocol、OpenTSDB 的 telnet 行协议和 OpenTSDB 的 JSON 格式协议。详情请参见[无模式写入](../../reference/schemaless/)。
```javascript
{{#include docs/examples/node/websocketexample/line_example.js}}
```
### 执行带有 reqId 的无模式写入
此 reqId 可用于请求链路追踪。
```javascript
await wsSchemaless.schemalessInsert([influxdbData], SchemalessProto.InfluxDBLineProtocol, Precision.NANO_SECONDS, ttl, reqId);
await wsSchemaless.schemalessInsert([telnetData], SchemalessProto.OpenTSDBTelnetLineProtocol, Precision.NANO_SECONDS, ttl, reqId);
await wsSchemaless.schemalessInsert([jsonData], SchemalessProto.OpenTSDBJsonFormatProtocol, Precision.NANO_SECONDS, ttl, reqId);
```
### 数据订阅
TDengine NodeJs 连接器支持订阅功能,应用 API 如下:
#### 创建 Topic
```javascript
{{#include docs/examples/node/websocketexample/tmq_example.js:create_topic}}
```
#### 创建 Consumer
```javascript
{{#include docs/examples/node/websocketexample/tmq_example.js:create_consumer}}
```
> 参数说明
- taos.TMQConstants.CONNECT_USER: 用户名。
- taos.TMQConstants.CONNECT_PASS: 密码。
- taos.TMQConstants.GROUP_ID: 所在的 group。
- taos.TMQConstants.CLIENT_ID: client id。
- taos.TMQConstants.WS_URL: taosAdapter 的url地址。
- taos.TMQConstants.AUTO_OFFSET_RESET: 来确定消费位置为最新数据latest还是包含旧数据earliest
- taos.TMQConstants.ENABLE_AUTO_COMMIT: 是否允许自动提交。
- taos.TMQConstants.AUTO_COMMIT_INTERVAL_MS: 自动提交间隔。
- taos.TMQConstants.CONNECT_MESSAGE_TIMEOUT: 数据传输超时参数,单位 ms默认为 10000 ms。
其他参数请参考:[Consumer 参数列表](../../develop/tmq/#数据订阅相关参数) 注意 TDengine 服务端自3.2.0.0版本开始消息订阅中的 auto.offset.reset 默认值发生变化。
#### 订阅消费数据
```javascript
{{#include docs/examples/node/websocketexample/tmq_example.js:subscribe}}
```
#### 指定订阅 Offset
```javascript
{{#include docs/examples/node/websocketexample/tmq_example.js:assignment}}
```
#### 关闭订阅
```javascript
// 取消订阅
consumer.unsubscribe();
// 关闭消费
consumer.close()
// 释放连接器资源
taos.destroy();
```
详情请参考:[数据订阅](../../develop/tmq)
#### 完整示例
```javascript
{{#include docs/examples/node/websocketexample/tmq_example.js}}
```
## 更多示例程序
| 示例程序 | 示例程序描述 |
@ -330,4 +100,286 @@ taos.destroy();
**原因**:一般都是因为配置 FQDN 不正确。 可以参考[如何彻底搞懂 TDengine 的 FQDN](https://www.taosdata.com/blog/2021/07/29/2741.html) 。
## API 参考
Node.js 连接器(`@tdengine/websocket`, 其通过 taosAdapter 提供的 Websocket 接口连接 TDengine 实例。
### URL 规范
```text
[+<protocol>]://[[<username>:<password>@]<host>:<port>][/<database>][?<p1>=<v1>[&<p2>=<v2>]]
|------------|---|-----------|-----------|------|------|------------|-----------------------|
| protocol | | username | password | host | port | database | params |
```
- **protocol**: 使用 websocket 协议建立连接。例如`ws://localhost:6041`
- **username/password**: 数据库的用户名和密码。
- **host/port**: 主机地址和端口号。例如`localhost:6041`
- **database**: 数据库名称。
- **params**: 其他参数。 例如token。
- 完整 URL 示例:
```js
ws://root:taosdata@localhost:6041
```
### WSConfig
除了通过指定的 URL 获取连接,还可以使用 WSConfig 指定建立连接时的参数。
```js
try {
let url = 'ws://127.0.0.1:6041'
let conf = WsSql.NewConfig(url)
conf.setUser('root')
conf.setPwd('taosdata')
conf.setDb('db')
conf.setTimeOut(500)
let wsSql = await WsSql.open(conf);
} catch (e) {
console.error(e);
}
```
WSConfig 中的配置如下:
- setUrl(url string) 设置 taosAdapter 连接地址 url详见上文 URL 规范。
- setUser(user: string) 设置数据库用户名。
- setPwd(pws:string) 设置数据库密码。
- setDb(db: string) 设置数据库名称。
- setTimeOut(ms : number) 设置连接超时,单位毫秒。
- setToken(token: string) 设置 taosAdapter 认证token。
### 连接功能
- `static async open(wsConfig:WSConfig):Promise<WsSql>`
- **接口说明**:建立 taosAdapter 连接。
- **参数说明**
- `wsConfig`:连接配置,详见上文 WSConfig 章节。
- **返回值**:连接对象。
- **异常**:连接失败抛出 `TDWebSocketClientError` 异常。
- `destroyed()`
- **接口说明**:释放销毁资源。
- **异常**:连接失败抛出 `TDWebSocketClientError` 异常。
### 获取 taosc 版本号
- `async version(): Promise<string>`
- **接口说明**:获取 taosc 客户端版本。
- **返回值**taosc 客户端版本号。
- **异常**:连接失败抛出 `TDWebSocketClientError` 异常。
### 执行 SQL
- `async exec(sql: string, reqId?: number): Promise<TaosResult>`
- **接口说明**:执行 sql 语句。
- **参数说明**
- `sql`:待执行的 sql 语句。
- `reqId`: 请求 id 非必填,用于问题追踪。
- **返回值**:执行结果
```js
TaosResult {
affectRows: number, 影响的条数
timing: number, 执行时长
totalTime: number, 响应总时长
}
```
- **异常**:连接失败抛出 `TDWebSocketClientError` 异常。
- `async query(sql: string, reqId?:number): Promise<WSRows>`
- **接口说明**:查询数据。
- **参数说明**
- `sql`:待执行的查询 sql 语句。
- `reqId`: 请求 id 非必填,用于问题追踪。
- **返回值**WSRows 数据集对象。
- **异常**:连接失败抛出 `TDWebSocketClientError` 异常。
### 数据集
- `getMeta():Array<TDengineMeta> | null`
- **接口说明**:获取查询结果的的列的数量、类型和长度。
- **返回值**TDengineMeta 数据对象数组。
```js
export interface TDengineMeta {
name: string,
type: string,
length: number,
}
```
- `async next(): Promise<boolean>`
- **接口说明**:将游标从当前位置向后移动一行。用于遍历查询结果集。
- **返回值**:如果新的当前行有效,则返回 true如果结果集中没有更多行则返回 false。
- **异常**:连接失败抛出 `TDWebSocketClientError` 异常。
- `getData(): Array<any>`
- **接口说明**:返回查询的一行数据。
- **返回值**:返回查询的一行数据,此接口需要搭配 next 接口一起使用。
- `async close():Promise<void>`
- **接口说明**:数据读取完成后,释放结果集。
- **异常**:连接失败抛出 `TDWebSocketClientError` 异常。
### 无模式写入
- `async schemalessInsert(lines: Array<string>, protocol: SchemalessProto, precision: Precision, ttl: number, reqId?: number): Promise<void>`
- **接口说明**:无模式写入。
- **参数说明**
- `lines`:待写入的数据数组,无模式具体的数据格式可参考 `Schemaless 写入`。
- `protocol`: 协议类型
- `SchemalessProto.InfluxDBLineProtocol`InfluxDB 行协议Line Protocol)。
- `SchemalessProto.OpenTSDBTelnetLineProtocol`OpenTSDB 文本行协议。
- `SchemalessProto.OpenTSDBJsonFormatProtocol`JSON 协议格式。
- `precision`: 时间精度
- `Precision.HOURS` 小时
- `Precision.MINUTES`:分钟
- `Precision.SECONDS`:秒
- `Precision.MILLI_SECONDS`:毫秒
- `Precision.MICRO_SECONDS`:微秒
- `Precision.NANO_SECONDS` 纳秒
- `ttl`:表过期时间,单位天。
- `reqId`: 用于问题追踪,可选。
- **异常**:连接失败抛出 `TaosResultError` 异常。
### 参数绑定
- `async stmtInit(reqId?:number): Promise<WsStmt>`
- **接口说明** 使用 WsSql 对象创建 stmt 对象。
- **参数说明**
- `reqId`: 请求 id 非必填,用于问题追踪。
- **返回值**stmt 对象。
- **异常**:连接失败抛出 `TDWebSocketClientError` 异常。
- `async prepare(sql: string): Promise<void>`
- **接口说明** 绑定预编译 sql 语句。
- **参数说明**
- `sql`: 预编译的 SQL 语句。
- **异常**:连接失败抛出 `TDWebSocketClientError` 异常。
- `async setTableName(tableName: string): Promise<void>`
- **接口说明** 设置将要写入数据的表名。
- **参数说明**
- `tableName`: 表名,如果需要指定数据库, 例如: `db_name.table_name` 即可。
- **异常**:连接失败抛出 `TDWebSocketClientError` 异常。
通过 StmtBindParams 对象设置绑定数据。
- `setBoolean(params :any[])`
- **接口说明** 设置布尔值。
- **参数说明**
- `params`: 布尔类型列表。
- **异常**:连接失败抛出 `TDWebSocketClientError` 异常。
- 下面接口除了要设置的值类型不同外,其余同 setBoolean
- `setTinyInt(params :any[])`
- `setUTinyInt(params :any[])`
- `setSmallInt(params :any[])`
- `setUSmallInt(params :any[])`
- `setInt(params :any[])`
- `setUInt(params :any[])`
- `setBigint(params :any[])`
- `setUBigint(params :any[])`
- `setFloat(params :any[])`
- `setDouble(params :any[])`
- `setVarchar(params :any[])`
- `setBinary(params :any[])`
- `setNchar(params :any[])`
- `setJson(params :any[])`
- `setVarBinary(params :any[])`
- `setGeometry(params :any[])`
- `setTimestamp(params :any[])`
- `async setTags(paramsArray:StmtBindParams): Promise<void>`
- **接口说明** 设置表 Tags 数据,用于自动建表。
- **参数说明**
- `paramsArray`: Tags 数据。
- **异常**:连接失败抛出 `TDWebSocketClientError` 异常。
- `async bind(paramsArray:StmtBindParams): Promise<void>`
- **接口说明** 绑定数据。
- **参数说明**
- `paramsArray`: 绑定数据。
- **异常**:连接失败抛出 `TDWebSocketClientError` 异常。
- `async batch(): Promise<void>`
- **接口说明** 提交绑定数据。
- **异常**:连接失败抛出 `TDWebSocketClientError` 异常。
- `async exec(): Promise<void>`
- **接口说明** 执行将绑定的数据全部写入。
- **异常**:连接失败抛出 `TDWebSocketClientError` 异常。
- `getLastAffected()`
- **接口说明** 获取写入条数。
- **返回值**:写入条数。
- `async close(): Promise<void>`
- **接口说明** 关闭 stmt 对象。
- **异常**:连接失败抛出 `TDWebSocketClientError` 异常。
### 数据订阅
- **创建消费者支持属性列表**
- taos.TMQConstants.CONNECT_USER: 用户名。
- taos.TMQConstants.CONNECT_PASS: 密码。
- taos.TMQConstants.GROUP_ID: 所在的 group。
- taos.TMQConstants.CLIENT_ID: 客户端id。
- taos.TMQConstants.WS_URL: taosAdapter 的url地址。
- taos.TMQConstants.AUTO_OFFSET_RESET: 来确定消费位置为最新数据latest还是包含旧数据earliest
- taos.TMQConstants.ENABLE_AUTO_COMMIT: 是否允许自动提交。
- taos.TMQConstants.AUTO_COMMIT_INTERVAL_MS: 自动提交间隔。
- taos.TMQConstants.CONNECT_MESSAGE_TIMEOUT: 数据传输超时参数,单位 ms默认为 10000 ms。
- `static async newConsumer(wsConfig:Map<string, any>):Promise<WsConsumer>`
- **接口说明** 消费者构造函数。
- **参数说明**
- `wsConfig`: 创建消费者属性配置。
- **返回值**WsConsumer 消费者对象。
- **异常**:如果在执行过程中出现异常,抛出 `TDWebSocketClientError` 错误。
- `async subscribe(topics: Array<string>, reqId?:number): Promise<void>`
- **接口说明** 订阅一组主题。
- **参数说明**
- `topics`: 订阅的主题列表。
- `reqId`: 请求 id 非必填,用于问题追踪。
- **异常**:失败抛出 `TDWebSocketClientError` 异常。
- `async unsubscribe(reqId?:number): Promise<void>`
- **接口说明** 取消订阅。
- **参数说明**
- `reqId`: 请求 id 非必填,用于问题追踪。
- **异常**:失败抛出 `TDWebSocketClientError` 异常。
- `async poll(timeoutMs: number, reqId?:number):Promise<Map<string, TaosResult>>`
- **接口说明** 轮询消息。
- **参数说明**
- `timeoutMs`: 表示轮询的超时时间,单位毫秒。
- `reqId`: 请求 id 非必填,用于问题追踪。
- **返回值**`Map<string, TaosResult>` 每个主题对应的数据。
- **异常**:失败抛出 `TDWebSocketClientError` 异常。
- `async subscription(reqId?:number):Promise<Array<string>>`
- **接口说明** 获取当前订阅的所有主题。
- **参数说明**
- `reqId`: 请求 id 非必填,用于问题追踪。
- **返回值**`Array<string>` 主题列表。
- **异常**:失败抛出 `TDWebSocketClientError` 异常。
- `async commit(reqId?:number):Promise<Array<TopicPartition>>`
- **接口说明** 提交当前处理的消息的偏移量。
- **参数说明**
- `reqId`: 请求 id 非必填,用于问题追踪。
- **返回值**`Array<TopicPartition>` 每个主题的消费进度。
- **异常**:失败抛出 `TDWebSocketClientError` 异常。
- `async committed(partitions:Array<TopicPartition>, reqId?:number):Promise<Array<TopicPartition>>`
- **接口说明**:获取一组分区最后提交的偏移量。
- **参数说明**
- `partitions`:一个 `Array<TopicPartition>` 类型的参数,表示要查询的分区集合。
- `reqId`: 请求 id 非必填,用于问题追踪。
- **返回值**`Array<TopicPartition>`,即一组分区最后提交的偏移量。
- **异常**:如果在获取提交的偏移量过程中发生错误,将抛出 TDWebSocketClientError 异常。
- `async seek(partition:TopicPartition, reqId?:number):Promise<void>`
- **接口说明**:将给定分区的偏移量设置到指定的位置。
- **参数说明**
- `partition`:一个 `TopicPartition` 类型的参数,表示要操作的分区和要设置的偏移量。
- `reqId`: 请求 id 非必填,用于问题追踪。
- **异常**:如果在设置偏移量过程中发生错误,将抛出 TDWebSocketClientError 异常。
- `async positions(partitions:Array<TopicPartition>, reqId?:number):Promise<Array<TopicPartition>>`
- **接口说明**:获取给定分区当前的偏移量。
- **参数说明**
- `partitions`:一个 `TopicPartition` 类型的参数,表示要查询的分区。
- `reqId`: 请求 id 非必填,用于问题追踪。
- **返回值**`Array<TopicPartition>`,即一组分区最后提交的偏移量。
- **异常**:如果在获取偏移量过程中发生错误,将抛出 TDWebSocketClientError 异常。
- `async seekToBeginning(partitions:Array<TopicPartition>):Promise<void>`
- **接口说明**:将一组分区的偏移量设置到最早的偏移量。
- **参数说明**
- `partitions`:一个 `Array<TopicPartition>` 类型的参数,表示要操作的分区集合。
- **异常**:如果在设置偏移量过程中发生错误,将抛出 TDWebSocketClientError 异常。
- `async seekToEnd(partitions:Array<TopicPartition>):Promise<void>`
- **接口说明**:将一组分区的偏移量设置到最新的偏移量。
- **参数说明**
- `partitions`:一个 `Array<TopicPartition>` 类型的参数,表示要操作的分区集合。
- **异常**:如果在设置偏移量过程中发生错误,将抛出 TDWebSocketClientError 异常。
- `async assignment(topics?:string[]):Promise<Array<TopicPartition>>`
- **接口说明**:获取消费者当前分配的指定的分区或所有分区。
- **参数说明**
- `topics`:需要获取的分区(非必填),不填表示获取全部的分区
- **返回值**:返回值类型为 `Array<TopicPartition>`,即消费者当前分配的所有分区。
- **异常**:如果在获取分配的分区过程中发生错误,将抛出 TDWebSocketClientError 异常。
- `async close():Promise<void>`
- **接口说明**:关闭 tmq 连接。
- **异常**:操作失败抛出 `TDWebSocketClientError` 异常。

View File

@ -1207,3 +1207,741 @@ namespace WSADO
### 更多示例程序
[示例程序](https://github.com/taosdata/taos-connector-dotnet/tree/3.0/examples)
## API 参考
### ADO.NET 驱动
`TDengine.Data.Client` 接口实现了 ADO.NET 驱动,支持连接 TDengine 数据库,进行数据操作。
#### 参数规范
ConnectionStringBuilder 使用 key-value 对方式设置连接参数key 为参数名value 为参数值,不同参数之间使用分号 `;` 分割。
例如:
```csharp
"protocol=WebSocket;host=127.0.0.1;port=6041;useSSL=false"
```
##### 原生连接
例如:`"host=127.0.0.1;port=6030;username=root;password=taosdata;protocol=Native;db=test"`
支持的参数如下:
- `host`TDengine 运行实例的地址。
- `port`TDengine 运行实例的端口。
- `username`:连接的用户名。
- `password`:连接的密码。
- `protocol`:连接的协议,可选值为 Native 或 WebSocket默认为 Native。
- `db`:连接的数据库。
- `timezone`:时区,默认为本地时区。
##### WebSocket 连接
例如:`"protocol=WebSocket;host=127.0.0.1;port=6041;useSSL=false;enableCompression=true;autoReconnect=true;reconnectIntervalMs=10;reconnectRetryCount=5"`
支持的参数如下:
- `host`TDengine 运行实例的地址。
- `port`TDengine 运行实例的端口。
- `username`:连接的用户名。
- `password`:连接的密码。
- `protocol`:连接的协议,可选值为 Native 或 WebSocket默认为 Native。
- `db`:连接的数据库。
- `timezone`:时区,默认为本地时区。
- `connTimeout`:连接超时时间,默认为 1 分钟。
- `readTimeout`:读取超时时间,默认为 5 分钟。
- `writeTimeout`:发送超时时间,默认为 10 秒。
- `token`:连接 TDengine cloud 的 token。
- `useSSL`:是否使用 SSL 连接,默认为 false。
- `enableCompression`:是否启用 WebSocket 压缩,默认为 false。
- `autoReconnect`:是否自动重连,默认为 false。
- `reconnectRetryCount`:重连次数,默认为 3。
- `reconnectIntervalMs`:重连间隔毫秒时间,默认为 2000。
#### 接口说明
`ConnectionStringBuilder` 类提供了连接配置字符串的解析功能。
- `public ConnectionStringBuilder(string connectionString)`
- **接口说明**ConnectionStringBuilder 构造函数。
- **参数说明**
- `connectionString`:连接配置字符串。
### 连接功能
C# 驱动支持创建 ADO.NET 连接,返回支持 ADO.NET 标准的 `DbConnection` 接口的对象,还提供了 `ITDengineClient` 接口,扩充了一些无模式写入接口。
#### 标准接口
ADO.NET 连接支持的标准接口如下:
- `public TDengineConnection(string connectionString)`
- **接口说明**TDengineConnection 构造函数。
- **参数说明**
- `connectionString`:连接配置字符串。
- **异常**:格式错误抛出 `ArgumentException` 异常。
- `public void ChangeDatabase(string databaseName)`
- **接口说明**:切换数据库。
- **参数说明**
- `databaseName`:数据库名。
- **异常**:执行失败抛出 `TDengineError` 异常。
- `public void Close()`
- **接口说明**:关闭连接。
- `public void Open()`
- **接口说明**:打开连接。
- **异常**:打开失败抛出 `TDengineError` 异常WebSocket 连接可能存在网络异常须注意处理。
- `public string ServerVersion`
- **接口说明**:返回服务器版本。
- **返回值**:服务器版本字符串。
- **异常**:执行失败抛出 `TDengineError` 异常。
- `public string DataSource`
- **接口说明**:返回数据源。
- **返回值**:创建连接 host 配置。
- `public string Database`
- **接口说明**:返回连接数据库。
- **返回值**:创建连接 db 配置。
- `public TDengineCommand(TDengineConnection connection)`
- **接口说明**TDengineCommand 构造函数。
- **参数说明**
- `connection`TDengineConnection 对象。
- **异常**:执行失败抛出 `TDengineError` 异常。
- `public void Prepare()`
- **接口说明**:检查连接和命令文本,并准备命令执行。
- **异常**:未执行 open 或未设置 CommandText 抛出 `InvalidOperationException` 异常。
- `public string CommandText`
- **接口说明**:获取或设置命令文本。
- **返回值**:命令文本。
- `public new virtual TDengineParameterCollection Parameters`
- **接口说明**:获取参数集合。
- **返回值**TDengineParameterCollection 对象。
#### 无模式写入
- `public static ITDengineClient Open(ConnectionStringBuilder builder)`
- **接口说明**:打开连接。
- **参数说明**
- `builder`:连接配置。
- **返回值**ITDengineClient 接口。
- **异常**:打开失败抛出 `TDengineError` 异常WebSocket 连接可能存在网络异常须注意处理。
- `void SchemalessInsert(string[] lines, TDengineSchemalessProtocol protocol,TDengineSchemalessPrecision precision, int ttl, long reqId)`
- **接口说明**:无模式写入。
- **参数说明**
- `lines`:数据行数组。
- `protocol`:数据协议,支持协议:`TSDB_SML_LINE_PROTOCOL = 1` `TSDB_SML_TELNET_PROTOCOL = 2` `TSDB_SML_JSON_PROTOCOL = 3`。
- `precision`:时间精度,支持配置:`TSDB_SML_TIMESTAMP_NOT_CONFIGURED = 0` `TSDB_SML_TIMESTAMP_HOURS = 1` `TSDB_SML_TIMESTAMP_MINUTES = 2` `TSDB_SML_TIMESTAMP_SECONDS = 3` `TSDB_SML_TIMESTAMP_MILLI_SECONDS = 4` `TSDB_SML_TIMESTAMP_MICRO_SECONDS = 5` `TSDB_SML_TIMESTAMP_NANO_SECONDS = 6`。
- `ttl`数据过期时间0表示不配置。
- `reqId`:请求 ID。
- **异常**:执行失败抛出 `TDengineError` 异常。
### 执行 SQL
C# 驱动提供了符合 ADO.NET 标准的 `DbCommand` 接口,支持以下功能:
1. **执行 SQL 语句**:执行静态 SQL 语句,并返回其生成的结果对象。
2. **查询执行**:可以执行返回数据集的查询(`SELECT` 语句)。
3. **更新执行**:可以执行影响行数的 SQL 语句,如 `INSERT`、`UPDATE`、`DELETE` 等。
4. **获取结果**:可以获取查询执行后返回的结果集(`ResultSet` 对象),并遍历查询返回的数据。
5. **获取更新计数**:对于非查询 SQL 语句,可以获取执行后影响的行数。
6. **关闭资源**:提供了关闭的方法,以释放数据库资源。
另外 C# 驱动还提供了用于请求链路跟踪的扩展接口。
#### 标准接口
- `public int ExecuteNonQuery()`
- **接口说明**:执行 SQL 语句,返回受影响的行数。
- **返回值**:受影响的行数。
- **异常**:执行失败抛出 `TDengineError` 异常。
- `public object ExecuteScalar()`
- **接口说明**:执行查询,并返回查询结果的第一行第一列。
- **返回值**:查询结果的第一行第一列。
- **异常**:执行失败抛出 `TDengineError` 异常。
- `public DbDataReader ExecuteReader()`
- **接口说明**:执行查询,并返回查询结果的数据读取器。
- **返回值**:查询结果的数据读取器。
- **异常**:执行失败抛出 `TDengineError` 异常。
- `public void Dispose();`
- **接口说明**:释放资源。
#### 扩展接口
扩展接口主要用于请求链路跟踪。
- `IRows Query(string query, long reqId)`
- **接口说明**:执行查询,返回查询结果。
- **参数说明**
- `query`:查询语句。
- `reqId`:请求 ID。
- **返回值**:查询结果。
- **异常**:执行失败抛出 `TDengineError` 异常。
- `long Exec(string query, long reqId)`
- **接口说明**:执行 SQL 语句。
- **参数说明**
- `query`SQL 语句。
- `reqId`:请求 ID。
- **返回值**:受影响的行数。
- **异常**:执行失败抛出 `TDengineError` 异常。
### 结果获取
C# 驱动提供了符合 ADO.NET 标准的 `DbDataReader` 接口,提供了用于读取结果集中元数据和数据的方法。
#### 结果集
`DbDataReader` 接口提供了以下方法获取结果集:
- `public bool GetBoolean(int ordinal)`
- **接口说明**:获取指定列的布尔值。
- **参数说明**
- `ordinal`:列索引。
- **返回值**:布尔值。
- **异常**:类型不对应抛出 `InvalidCastException` 异常。
- `public byte GetByte(int ordinal)`
- **接口说明**:获取指定列的字节值。
- **参数说明**
- `ordinal`:列索引。
- **返回值**:字节值。
- **异常**:类型不对应抛出 `InvalidCastException` 异常。
- `public long GetBytes(int ordinal, long dataOffset, byte[] buffer, int bufferOffset, int length)`
- **接口说明**:获取指定列的字节值。
- **参数说明**
- `ordinal`:列索引。
- `dataOffset`:数据偏移量。
- `buffer`:缓冲区。
- `bufferOffset`:缓冲区偏移量。
- `length`:长度。
- **返回值**:字节值。
- **异常**:类型不对应抛出 `InvalidCastException` 异常。
- `public char GetChar(int ordinal)`
- **接口说明**:获取指定列的字符值。
- **参数说明**
- `ordinal`:列索引。
- **返回值**:字符值。
- **异常**:类型不对应抛出 `InvalidCastException` 异常。
- `public long GetChars(int ordinal, long dataOffset, char[] buffer, int bufferOffset, int length)`
- **接口说明**:获取指定列的字符值。
- **参数说明**
- `ordinal`:列索引。
- `dataOffset`:数据偏移量。
- `buffer`:缓冲区。
- `bufferOffset`:缓冲区偏移量。
- `length`:长度。
- **返回值**:字符值。
- **异常**:类型不对应抛出 `InvalidCastException` 异常。
- `public DateTime GetDateTime(int ordinal)`
- **接口说明**:获取指定列的日期时间值。
- **参数说明**
- `ordinal`:列索引。
- **返回值**:日期时间值。
- **异常**:类型不对应抛出 `InvalidCastException` 异常。
- `public double GetDouble(int ordinal)`
- **接口说明**:获取指定列的双精度浮点数值。
- **参数说明**
- `ordinal`:列索引。
- **返回值**:双精度浮点数值。
- **异常**:类型不对应抛出 `InvalidCastException` 异常。
- `public float GetFloat(int ordinal)`
- **接口说明**:获取指定列的单精度浮点数值。
- **参数说明**
- `ordinal`:列索引。
- **返回值**:单精度浮点数值。
- **异常**:类型不对应抛出 `InvalidCastException` 异常。
- `public short GetInt16(int ordinal)`
- **接口说明**:获取指定列的 16 位整数值。
- **参数说明**
- `ordinal`:列索引。
- **返回值**16 位整数值。
- **异常**:类型不对应抛出 `InvalidCastException` 异常。
- `public int GetInt32(int ordinal)`
- **接口说明**:获取指定列的 32 位整数值。
- **参数说明**
- `ordinal`:列索引。
- **返回值**32 位整数值。
- **异常**:类型不对应抛出 `InvalidCastException` 异常。
- `public long GetInt64(int ordinal)`
- **接口说明**:获取指定列的 64 位整数值。
- **参数说明**
- `ordinal`:列索引。
- **返回值**64 位整数值。
- **异常**:类型不对应抛出 `InvalidCastException` 异常。
- `public string GetString(int ordinal)`
- **接口说明**:获取指定列的字符串值。
- **参数说明**
- `ordinal`:列索引。
- **返回值**:字符串值。
- **异常**:类型不对应抛出 `InvalidCastException` 异常。
- `public object GetValue(int ordinal)`
- **接口说明**:获取指定列的值。
- **参数说明**
- `ordinal`:列索引。
- **返回值** 结果对象。
- `public int GetValues(object[] values)`
- **接口说明**:获取所有列的值。
- **参数说明**
- `values`:值数组。
- **返回值**:值数量。
- `public bool IsDBNull(int ordinal)`
- **接口说明**:判断指定列是否为 NULL。
- **参数说明**
- `ordinal`:列索引。
- **返回值**:是否为 NULL。
- `public int RecordsAffected`
- **接口说明**:获取受影响的行数。
- **返回值**:受影响的行数。
- `public bool HasRows`
- **接口说明**:结果是否有行数据。
- **返回值**:结果是否有行数据。
- `public bool Read()`
- **接口说明**:读取下一行。
- **返回值**:是否读取成功。
- `public IEnumerator GetEnumerator()`
- **接口说明**:获取枚举器。
- **返回值**:枚举器。
- `public void Close()`
- **接口说明**:关闭结果集。
#### 结果集元数据
`DbDataReader` 接口提供了以下方法获取结果集元数据:
- `public DataTable GetSchemaTable()`
- **接口说明**:获取结果集元数据。
- **返回值**:结果集元数据。
- `public string GetDataTypeName(int ordinal)`
- **接口说明**:获取指定列的数据类型名称。
- **参数说明**
- `ordinal`:列索引。
- **返回值**:数据类型名称。
- ` public Type GetFieldType(int ordinal)`
- **接口说明**:获取指定列的数据类型。
- **参数说明**
- `ordinal`:列索引。
- **返回值**:数据类型。
- `public string GetName(int ordinal)`
- **接口说明**:获取指定列的名称。
- **参数说明**
- `ordinal`:列索引。
- **返回值**:列名称。
- ` public int GetFieldSize(int ordinal)`
- **接口说明**:获取指定列的大小。
- **参数说明**
- `ordinal`:列索引。
- **返回值**:列大小。
- `public int GetOrdinal(string name)`
- **接口说明**:获取指定列的索引。
- **参数说明**
- `name`:列名称。
- **返回值**:列索引。
- `public int FieldCount`
- **接口说明**:获取列数。
- **返回值**:列数。
### 参数绑定
`TDengineCommand` 类支持参数绑定。
#### 标准接口
`TDengineCommand` 类继承了 `DbCommand` 接口,支持以下功能:
- `public string CommandText`
- **接口说明**:获取或设置命令文本,支持参数绑定。
- **返回值**:命令文本。
- `public new virtual TDengineParameterCollection Parameters`
- **接口说明**:获取参数集合。
- **返回值**`TDengineParameterCollection` 对象。
#### 参数元数据
`TDengineParameterCollection` 继承了 `DbParameterCollection` 接口,支持以下功能:
- `public int Add(object value)`
- **接口说明**:添加参数。
- **参数说明**
- `value`:参数值。
- **返回值**:参数索引。
- `public void Clear()`
- **接口说明**:清空参数。
- `public bool Contains(object value)`
- **接口说明**:是否包含参数。
- **参数说明**
- `value`:参数值。
- **返回值**:是否包含参数。
- `public int IndexOf(object value)`
- **接口说明**:获取参数索引。
- **参数说明**
- `value`:参数值。
- **返回值**:参数索引。
- `public void Insert(int index, object value)`
- **接口说明**:插入参数。
- **参数说明**
- `index`:索引。
- `value`:参数值。
- `public void Remove(object value)`
- **接口说明**:移除参数。
- **参数说明**
- `value`:参数值。
- `public void RemoveAt(int index)`
- **接口说明**:移除参数。
- **参数说明**
- `index`:索引。
- `public void RemoveAt(string parameterName)`
- **接口说明**:移除参数。
- **参数说明**
- `parameterName`:参数名。
- `public int Count`
- **接口说明**:获取参数数量。
- **返回值**:参数数量。
- `public int IndexOf(string parameterName)`
- **接口说明**:获取参数索引。
- **参数说明**
- `parameterName`:参数名。
- **返回值**:参数索引。
- `public bool Contains(string value)`
- **接口说明**:是否包含参数。
- **参数说明**
- `value`:参数名。
- **返回值**:是否包含参数。
- `public void CopyTo(Array array, int index)`
- **接口说明**:复制参数。
- **参数说明**
- `array`:目标数组。
- `index`:索引。
- `public IEnumerator GetEnumerator()`
- **接口说明**:获取枚举器。
- **返回值**:枚举器。
- `public void AddRange(Array values)`
- **接口说明**:添加参数。
- **参数说明**
- `values`:参数数组。
`TDengineParameter` 继承了 `DbParameter` 接口,支持以下功能:
- `public TDengineParameter(string name, object value)`
- **接口说明**TDengineParameter 构造函数。
- **参数说明**
- `name`:参数名,需要以 @ 开头,如 @0、@1、@2 等。
- `value`:参数值,需要 C# 列类型与 TDengine 列类型一一对应。
- `public string ParameterName`
- **接口说明**:获取或设置参数名。
- **返回值**:参数名。
- `public object Value`
- **接口说明**:获取或设置参数值。
- **返回值**:参数值。
#### 扩展接口
`ITDengineClient` 接口提供了扩展的参数绑定接口。
- `IStmt StmtInit(long reqId)`
- **接口说明**:初始化 statement 对象。
- **参数说明**
- `reqId`:请求 ID。
- **返回值**:实现 IStmt 接口的对象。
- **异常**:执行失败抛出 `TDengineError` 异常。
`IStmt` 接口提供了扩展的参数绑定接口。
- `void Prepare(string query)`
- **接口说明**:准备 statement。
- **参数说明**
- `query`:查询语句。
- **异常**:执行失败抛出 `TDengineError` 异常。
- `bool IsInsert()`
- **接口说明**:判断是否为插入语句。
- **返回值**:是否为插入语句。
- **异常**:执行失败抛出 `TDengineError` 异常。
- `void SetTableName(string tableName)`
- **接口说明**:设置表名。
- **参数说明**
- `tableName`:表名。
- **异常**:执行失败抛出 `TDengineError` 异常。
- `void SetTags(object[] tags)`
- **接口说明**:设置标签。
- **参数说明**
- `tags`:标签数组。
- **异常**:执行失败抛出 `TDengineError` 异常。
- `TaosFieldE[] GetTagFields()`
- **接口说明**:获取标签属性。
- **返回值**:标签属性数组。
- **异常**:执行失败抛出 `TDengineError` 异常。
- `TaosFieldE[] GetColFields()`
- **接口说明**:获取列属性。
- **返回值**:列属性数组。
- **异常**:执行失败抛出 `TDengineError` 异常。
- `void BindRow(object[] row)`
- **接口说明**:绑定行。
- **参数说明**
- `row`:行数据数组。
- **异常**:执行失败抛出 `TDengineError` 异常。
- `void BindColumn( TaosFieldE[] fields,params Array[] arrays)`
- **接口说明**:绑定全部列。
- **参数说明**
- `fields`:字段属性数组。
- `arrays`:多列数据数组。
- **异常**:执行失败抛出 `TDengineError` 异常。
- `void AddBatch()`
- **接口说明**:添加批处理。
- **异常**:执行失败抛出 `TDengineError` 异常。
- `void Exec()`
- **接口说明**:执行参数绑定。
- **异常**:执行失败抛出 `TDengineError` 异常。
- `long Affected()`
- **接口说明**:获取受影响的行数。
- **返回值**:受影响的行数。
- **异常**:执行失败抛出 `TDengineError` 异常。
- `IRows Result()`
- **接口说明**:获取结果。
- **返回值**:结果对象。
- **异常**:执行失败抛出 `TDengineError` 异常。
### 数据订阅
`ConsumerBuilder` 类提供了消费者构建相关接口,`ConsumeResult` 类提供了消费结果相关接口,`TopicPartitionOffset` 类提供了分区偏移量相关接口。`ReferenceDeserializer` 和 `DictionaryDeserializer` 提供了反序列化的支持。
#### 消费者
- `public ConsumerBuilder(IEnumerable<KeyValuePair<string, string>> config)`
- **接口说明**ConsumerBuilder 构造函数。
- **参数说明**
- `config`:消费配置。
创建消费者支持属性列表:
- `useSSL`:是否使用 SSL 连接,默认为 false
- `token`:连接 TDengine cloud 的 token
- `ws.message.enableCompression`:是否启用 WebSocket 压缩,默认为 false
- `ws.autoReconnect`:是否自动重连,默认为 false
- `ws.reconnect.retry.count`:重连次数,默认为 3
- `ws.reconnect.interval.ms`:重连间隔毫秒时间,默认为 2000
其他参数请参考:[Consumer 参数列表](../../develop/tmq/#数据订阅相关参数) 注意TDengine服务端自 3.2.0.0 版本开始消息订阅中的 auto.offset.reset 默认值发生变化。
- `public IConsumer<TValue> Build()`
- **接口说明**:构建消费者。
- **返回值**:消费者对象。
`IConsumer` 接口提供了消费者相关 API
- `ConsumeResult<TValue> Consume(int millisecondsTimeout)`
- **接口说明**:消费消息。
- **参数说明**
- `millisecondsTimeout`:毫秒超时时间。
- **返回值**:消费结果。
- **异常**:执行失败抛出 `TDengineError` 异常。
- `List<TopicPartition> Assignment { get; }`
- **接口说明**:获取分配信息。
- **返回值**:分配信息。
- **异常**:执行失败抛出 `TDengineError` 异常。
- `List<string> Subscription()`
- **接口说明**:获取订阅的主题。
- **返回值**:主题列表。
- **异常**:执行失败抛出 `TDengineError` 异常。
- `void Subscribe(IEnumerable<string> topic)`
- **接口说明**:订阅主题列表。
- **参数说明**
- `topic`:主题列表。
- **异常**:执行失败抛出 `TDengineError` 异常。
- `void Subscribe(string topic)`
- **接口说明**:订阅单个主题。
- **参数说明**
- `topic`:主题。
- **异常**:执行失败抛出 `TDengineError` 异常。
- `void Unsubscribe()`
- **接口说明**:取消订阅。
- **异常**:执行失败抛出 `TDengineError` 异常。
- `void Commit(ConsumeResult<TValue> consumerResult)`
- **接口说明**:提交消费结果。
- **参数说明**
- `consumerResult`:消费结果。
- **异常**:执行失败抛出 `TDengineError` 异常。
- `List<TopicPartitionOffset> Commit()`
- **接口说明**:提交全部消费结果。
- **返回值**:分区偏移量。
- **异常**:执行失败抛出 `TDengineError` 异常。
- `void Commit(IEnumerable<TopicPartitionOffset> offsets)`
- **接口说明**:提交消费结果。
- **参数说明**
- `offsets`:分区偏移量。
- **异常**:执行失败抛出 `TDengineError` 异常。
- `void Seek(TopicPartitionOffset tpo)`
- **接口说明**:跳转到分区偏移量。
- **参数说明**
- `tpo`:分区偏移量。
- **异常**:执行失败抛出 `TDengineError` 异常。
- `List<TopicPartitionOffset> Committed(TimeSpan timeout)`
- **接口说明**:获取分区偏移量。
- **参数说明**
- `timeout`:超时时间(未使用)。
- **返回值**:分区偏移量。
- **异常**:执行失败抛出 `TDengineError` 异常。
- `List<TopicPartitionOffset> Committed(IEnumerable<TopicPartition> partitions, TimeSpan timeout)`
- **接口说明**:获取指定分区偏移量。
- **参数说明**
- `partitions`:分区列表。
- `timeout`:超时时间(未使用)。
- **返回值**:分区偏移量。
- **异常**:执行失败抛出 `TDengineError` 异常。
- `Offset Position(TopicPartition partition)`
- **接口说明**:获取消费位置。
- **参数说明**
- `partition`:分区。
- **返回值**:偏移量。
- **异常**:执行失败抛出 `TDengineError` 异常。
- `void Close()`
- **接口说明**:关闭消费者。
#### 消费记录
`ConsumeResult` 类提供了消费结果相关接口:
- `public List<TmqMessage<TValue>> Message`
- **接口说明**:获取消息列表。
- **返回值**:消息列表。
`TmqMessage` 类提供了消息具体内容:
```csharp
public class TmqMessage<TValue>
{
public string TableName { get; set; }
public TValue Value { get; set; }
}
```
- `TableName`:表名
- `Value`:消息内容
#### 分区信息
从 `ConsumeResult` 获取 `TopicPartitionOffset`
```csharp
public TopicPartitionOffset TopicPartitionOffset
```
`TopicPartitionOffset` 类提供了获取分区信息的接口:
- `public string Topic { get; }`
- **接口说明**:获取主题。
- **返回值**:主题。
- `public Partition Partition { get; }`
- **接口说明**:获取分区。
- **返回值**:分区。
- `public Offset Offset { get; }`
- **接口说明**:获取偏移量。
- **返回值**:偏移量。
- `public TopicPartition TopicPartition`
- **接口说明**:获取主题分区。
- **返回值**:主题分区。
- `public string ToString()`
- **接口说明**:转换为字符串。
- **返回值**:字符串信息。
#### 偏移量元数据
`Offset` 类提供了偏移量相关接口:
- `public long Value`
- **接口说明**:获取偏移量值。
- **返回值**:偏移量值。
#### 反序列化
C# 驱动提供了两个反序列化类:`ReferenceDeserializer` 和 `DictionaryDeserializer`。它们都实现了 `IDeserializer` 接口。
ReferenceDeserializer 用来将消费到的一条记录反序列化为一个对象,需要保证对象类的属性名与消费到的数据的列名能够对应,且类型能够匹配。
DictionaryDeserializer 则会将消费到的一行数据反序列化为一个 `Dictionary<string, object>` 对象,其 key 为列名,值为对象。
ReferenceDeserializer 和 DictionaryDeserializer 的接口不会被用户直接调用,请参考使用样例。

View File

@ -12,13 +12,13 @@ TDengine 提供了丰富的应用程序开发接口,为了便于用户快速
目前 TDengine 的原生接口连接器可支持的平台包括X64/ARM64 等硬件平台,以及 Linux/Win64 等开发环境。对照矩阵如下:
| **CPU** | **OS** | **Java** | **Python** | **Go** | **Node.js** | **C#** | **Rust** | C/C++ |
| -------------- | --------- | -------- | ---------- | ------ | ----------- | ------ | -------- | ----- |
| **X86 64bit** | **Linux** | ● | ● | ● | ● | ● | ● | ● |
| **X86 64bit** | **Win64** | ● | ● | ● | ● | ● | ● | ● |
| **X86 64bit** | **macOS** | ● | ● | ● | ○ | ○ | ● | ● |
| **ARM64** | **Linux** | ● | ● | ● | ● | ○ | ○ | ● |
| **ARM64** | **macOS** | ● | ● | ● | ○ | ○ | ● | ● |
| **CPU** | **OS** | **Java** | **Python** | **Go** | **Node.js** | **C#** | **Rust** | C/C++ |
| ------------- | --------- | -------- | ---------- | ------ | ----------- | ------ | -------- | ----- |
| **X86 64bit** | **Linux** | ● | ● | ● | ● | ● | ● | ● |
| **X86 64bit** | **Win64** | ● | ● | ● | ● | ● | ● | ● |
| **X86 64bit** | **macOS** | ● | ● | ● | ○ | ○ | ● | ● |
| **ARM64** | **Linux** | ● | ● | ● | ● | ○ | ○ | ● |
| **ARM64** | **macOS** | ● | ● | ● | ○ | ○ | ● | ● |
其中 ● 表示官方测试验证通过,○ 表示非官方测试验证通过,-- 表示未经验证。
@ -30,7 +30,7 @@ TDengine 版本更新往往会增加新的功能特性,列表中的连接器
| **TDengine 版本** | **Java** | **Python** | **Go** | **C#** | **Node.js** | **Rust** |
| ---------------------- | --------- | ---------- | ------------ | ------------- | --------------- | -------- |
| **3.0.0.0 及以上** | 3.0.2以上 | 当前版本 | 3.0 分支 | 3.0.0 | 3.0.0 | 当前版本 |
| **3.0.0.0 及以上** | 3.0.2以上 | 当前版本 | 3.0 分支 | 3.0.0 | 3.1.0 | 当前版本 |
| **2.4.0.14 及以上** | 2.0.38 | 当前版本 | develop 分支 | 1.0.2 - 1.0.6 | 2.0.10 - 2.0.12 | 当前版本 |
| **2.4.0.4 - 2.4.0.13** | 2.0.37 | 当前版本 | develop 分支 | 1.0.2 - 1.0.6 | 2.0.10 - 2.0.12 | 当前版本 |
| **2.2.x.x ** | 2.0.36 | 当前版本 | master 分支 | n/a | 2.0.7 - 2.0.9 | 当前版本 |
@ -44,11 +44,11 @@ TDengine 版本更新往往会增加新的功能特性,列表中的连接器
| **功能特性** | **Java** | **Python** | **Go** | **C#** | **Node.js** | **Rust** |
| ------------------- | -------- | ---------- | ------ | ------ | ----------- | -------- |
| **连接管理** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 |
| **普通查询** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 |
| **参数绑定** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 |
| **数据订阅TMQ** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 |
| **Schemaless** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 |
| **连接管理** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 |
| **普通查询** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 |
| **参数绑定** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 |
| **数据订阅TMQ** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 |
| **Schemaless** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 |
:::info
由于不同编程语言数据库框架规范不同,并不意味着所有 C/C++ 接口都需要对应封装支持。
@ -56,14 +56,14 @@ TDengine 版本更新往往会增加新的功能特性,列表中的连接器
### 使用 http (REST 或 WebSocket) 接口
| **功能特性** | **Java** | **Python** | **Go** | **C# ** | **Node.js** | **Rust** |
| ------------------------------ | -------- | ---------- | -------- | ---- | ----------- | -------- |
| **连接管理** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 |
| **普通查询** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 |
| **参数绑定** | 支持 | 支持 | 支持 | 支持 | 暂不支持 | 支持 |
| **数据订阅TMQ** | 支持 | 支持 | 支持 | 支持 | 暂不支持 | 支持 |
| **Schemaless** | 支持 | 支持 | 支持 | 支持 | 暂不支持 | 支持 |
| **批量拉取(基于 WebSocket** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 |
| **功能特性** | **Java** | **Python** | **Go** | **C# ** | **Node.js** | **Rust** |
| ------------------------------ | -------- | ---------- | ------ | ------- | ----------- | -------- |
| **连接管理** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 |
| **普通查询** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 |
| **参数绑定** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 |
| **数据订阅TMQ** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 |
| **Schemaless** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 |
| **批量拉取(基于 WebSocket** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 |
:::warning

View File

@ -32,14 +32,14 @@ config.setProperty("msg.with.table.name", "true");
config.setProperty("enable.auto.commit", "true");
config.setProperty("auto.commit.interval.ms", "1000");
config.setProperty("group.id", "group1");
config.setProperty("client.id", "1");
config.setProperty("client.id", "client1");
config.setProperty("value.deserializer", "com.taosdata.example.AbsConsumerLoop$ResultDeserializer");
config.setProperty("value.deserializer.encoding", "UTF-8");
try {
this.consumer = new TaosConsumer<>(config);
} catch (SQLException ex) {
// handle exception
System.out.println("SQLException: " + ex.getMessage());
// handle any errors, please refer to the JDBC specifications for detailed exceptions info
System.out.println("Failed to create jni consumer with " + config.getProperty("bootstrap.servers") + " ErrCode:" + ex.getErrorCode() + "; ErrMessage: " + ex.getMessage());
throw new SQLException("Failed to create consumer", ex);
}
// ANCHOR_END: create_consumer
@ -63,10 +63,10 @@ try {
process(bean);
}
}
} catch (Exception ex){
// handle exception
System.out.println("SQLException: " + ex.getMessage());
} catch (SQLException ex){
// handle any errors, please refer to the JDBC specifications for detailed exceptions info
System.out.println("Failed to poll data; ErrCode:" + ex.getErrorCode() + "; ErrMessage: " + ex.getMessage());
throw new SQLException("Failed to poll data", ex);
} finally {
consumer.close();
shutdownLatch.countDown();
@ -90,10 +90,10 @@ try {
consumer.commitSync();
}
}
} catch (Exception ex){
// handle exception
System.out.println("SQLException: " + ex.getMessage());
} catch (SQLException ex){
// handle any errors, please refer to the JDBC specifications for detailed exceptions info
System.out.println("Failed to execute consumer functions. ErrCode:" + ex.getErrorCode() + "; ErrMessage: " + ex.getMessage());
throw new SQLException("Failed to execute consumer functions", ex);
} finally {
consumer.close();
shutdownLatch.countDown();
@ -105,9 +105,10 @@ try {
// ANCHOR: unsubscribe_data_code_piece
try {
consumer.unsubscribe();
} catch (Exception ex){
// handle exception
System.out.println("SQLException: " + ex.getMessage());
} catch (SQLException ex){
// handle any errors, please refer to the JDBC specifications for detailed exceptions info
System.out.println("Failed to unsubscribe consumer. ErrCode:" + ex.getErrorCode() + "; ErrMessage: " + ex.getMessage());
throw new SQLException("Failed to unsubscribe consumer", ex);
} finally {
consumer.close();
}

View File

@ -1,136 +0,0 @@
package com.taosdata.example;
import com.taosdata.jdbc.tmq.ConsumerRecord;
import com.taosdata.jdbc.tmq.ConsumerRecords;
import com.taosdata.jdbc.tmq.ReferenceDeserializer;
import com.taosdata.jdbc.tmq.TaosConsumer;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.time.Duration;
import java.util.Collections;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;
// ANCHOR: consumer_demo
public abstract class AbsConsumerLoopFull {
private final TaosConsumer<ResultBean> consumer;
private final List<String> topics;
private final AtomicBoolean shutdown;
private final CountDownLatch shutdownLatch;
public AbsConsumerLoopFull() throws SQLException {
Properties config = new Properties();
config.setProperty("td.connect.type", "jni");
config.setProperty("bootstrap.servers", "localhost:6030");
config.setProperty("auto.offset.reset", "latest");
config.setProperty("msg.with.table.name", "true");
config.setProperty("enable.auto.commit", "true");
config.setProperty("auto.commit.interval.ms", "1000");
config.setProperty("group.id", "group1");
config.setProperty("client.id", "1");
config.setProperty("value.deserializer", "com.taosdata.example.AbsConsumerLoop$ResultDeserializer");
config.setProperty("value.deserializer.encoding", "UTF-8");
try {
this.consumer = new TaosConsumer<>(config);
} catch (SQLException ex) {
// handle exception
System.out.println("SQLException: " + ex.getMessage());
throw new SQLException("Failed to create consumer", ex);
}
this.topics = Collections.singletonList("topic_meters");
this.shutdown = new AtomicBoolean(false);
this.shutdownLatch = new CountDownLatch(1);
}
public abstract void process(ResultBean result);
public void pollData() throws SQLException {
try {
consumer.subscribe(topics);
while (!shutdown.get()) {
ConsumerRecords<ResultBean> records = consumer.poll(Duration.ofMillis(100));
for (ConsumerRecord<ResultBean> record : records) {
ResultBean bean = record.value();
process(bean);
}
}
consumer.unsubscribe();
} finally {
consumer.close();
shutdownLatch.countDown();
}
}
public void shutdown() throws InterruptedException {
shutdown.set(true);
shutdownLatch.await();
}
public static class ResultDeserializer extends ReferenceDeserializer<ResultBean> {
}
public static class ResultBean {
private Timestamp ts;
private double current;
private int voltage;
private double phase;
private int groupid;
private String location;
public Timestamp getTs() {
return ts;
}
public void setTs(Timestamp ts) {
this.ts = ts;
}
public double getCurrent() {
return current;
}
public void setCurrent(double current) {
this.current = current;
}
public int getVoltage() {
return voltage;
}
public void setVoltage(int voltage) {
this.voltage = voltage;
}
public double getPhase() {
return phase;
}
public void setPhase(double phase) {
this.phase = phase;
}
public int getGroupid() {
return groupid;
}
public void setGroupid(int groupid) {
this.groupid = groupid;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
}
}
// ANCHOR_END: consumer_demo

View File

@ -1,138 +0,0 @@
package com.taosdata.example;
import com.taosdata.jdbc.tmq.ConsumerRecord;
import com.taosdata.jdbc.tmq.ConsumerRecords;
import com.taosdata.jdbc.tmq.ReferenceDeserializer;
import com.taosdata.jdbc.tmq.TaosConsumer;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.time.Duration;
import java.util.Collections;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;
// ANCHOR: consumer_demo
public abstract class AbsWsConsumerLoop {
private final TaosConsumer<ResultBean> consumer;
private final List<String> topics;
private final AtomicBoolean shutdown;
private final CountDownLatch shutdownLatch;
public AbsWsConsumerLoop() throws SQLException {
// ANCHOR: create_consumer
Properties config = new Properties();
config.setProperty("td.connect.type", "ws");
config.setProperty("bootstrap.servers", "localhost:6041");
config.setProperty("auto.offset.reset", "latest");
config.setProperty("msg.with.table.name", "true");
config.setProperty("enable.auto.commit", "true");
config.setProperty("auto.commit.interval.ms", "1000");
config.setProperty("group.id", "group2");
config.setProperty("client.id", "1");
config.setProperty("value.deserializer", "com.taosdata.example.AbsConsumerLoopWs$ResultDeserializer");
config.setProperty("value.deserializer.encoding", "UTF-8");
try {
this.consumer = new TaosConsumer<>(config);
} catch (SQLException ex) {
// handle exception
System.out.println("SQLException: " + ex.getMessage());
throw new SQLException("Failed to create consumer", ex);
}
// ANCHOR_END: create_consumer
this.topics = Collections.singletonList("topic_speed");
this.shutdown = new AtomicBoolean(false);
this.shutdownLatch = new CountDownLatch(1);
}
public abstract void process(ResultBean result);
public void pollData() throws SQLException {
try {
consumer.subscribe(topics);
while (!shutdown.get()) {
ConsumerRecords<ResultBean> records = consumer.poll(Duration.ofMillis(100));
for (ConsumerRecord<ResultBean> record : records) {
ResultBean bean = record.value();
process(bean);
}
}
consumer.unsubscribe();
} finally {
consumer.close();
shutdownLatch.countDown();
}
}
public void shutdown() throws InterruptedException {
shutdown.set(true);
shutdownLatch.await();
}
public static class ResultDeserializer extends ReferenceDeserializer<ResultBean> {
}
public static class ResultBean {
private Timestamp ts;
private double current;
private int voltage;
private double phase;
private int groupid;
private String location;
public Timestamp getTs() {
return ts;
}
public void setTs(Timestamp ts) {
this.ts = ts;
}
public double getCurrent() {
return current;
}
public void setCurrent(double current) {
this.current = current;
}
public int getVoltage() {
return voltage;
}
public void setVoltage(int voltage) {
this.voltage = voltage;
}
public double getPhase() {
return phase;
}
public void setPhase(double phase) {
this.phase = phase;
}
public int getGroupid() {
return groupid;
}
public void setGroupid(int groupid) {
this.groupid = groupid;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
}
}
// ANCHOR_END: consumer_demo

View File

@ -0,0 +1,357 @@
package com.taosdata.example;
import com.alibaba.fastjson.JSON;
import com.taosdata.jdbc.TSDBDriver;
import com.taosdata.jdbc.tmq.*;
import java.sql.*;
import java.time.Duration;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
// ANCHOR: consumer_demo
public class ConsumerLoopFull {
static private Connection connection;
static private Statement statement;
public static TaosConsumer<ResultBean> getConsumer() throws SQLException{
// ANCHOR: create_consumer
Properties config = new Properties();
config.setProperty("td.connect.type", "jni");
config.setProperty("bootstrap.servers", "localhost:6030");
config.setProperty("auto.offset.reset", "latest");
config.setProperty("msg.with.table.name", "true");
config.setProperty("enable.auto.commit", "true");
config.setProperty("auto.commit.interval.ms", "1000");
config.setProperty("group.id", "group1");
config.setProperty("client.id", "1");
config.setProperty("td.connect.user", "root");
config.setProperty("td.connect.pass", "taosdata");
config.setProperty("value.deserializer", "com.taosdata.example.ConsumerLoopFull$ResultDeserializer");
config.setProperty("value.deserializer.encoding", "UTF-8");
try {
return new TaosConsumer<>(config);
} catch (SQLException ex) {
// handle any errors, please refer to the JDBC specifications for detailed exceptions info
System.out.println("Failed to create jni consumer, host : " + config.getProperty("bootstrap.servers") + "; ErrCode:" + ex.getErrorCode() + "; ErrMessage: " + ex.getMessage());
throw new SQLException("Failed to create consumer", ex);
} catch (Exception e) {
e.printStackTrace();
throw new SQLException("Failed to create consumer", e);
}
// ANCHOR_END: create_consumer
}
public static void pollDataExample() throws SQLException {
try (TaosConsumer<ResultBean> consumer = getConsumer()){
// subscribe to the topics
List<String> topics = Collections.singletonList("topic_meters");
consumer.subscribe(topics);
System.out.println("subscribe topics successfully");
for (int i = 0; i < 50; i++) {
// poll data
ConsumerRecords<ResultBean> records = consumer.poll(Duration.ofMillis(100));
for (ConsumerRecord<ResultBean> record : records) {
ResultBean bean = record.value();
// process the data here
System.out.println("data: " + JSON.toJSONString(bean));
}
}
// unsubscribe the topics
consumer.unsubscribe();
System.out.println("unsubscribed topics successfully");
} catch (SQLException ex) {
// handle any errors, please refer to the JDBC specifications for detailed exceptions info
System.out.println("Failed to poll data from topic_meters, ErrCode:" + ex.getErrorCode() + "; ErrMessage: " + ex.getMessage());
throw new SQLException("Failed to poll data from topic_meters", ex);
}
}
public static void pollExample() throws SQLException {
// ANCHOR: poll_data_code_piece
try (TaosConsumer<ResultBean> consumer = getConsumer()){
List<String> topics = Collections.singletonList("topic_meters");
// subscribe to the topics
consumer.subscribe(topics);
System.out.println("subscribe topics successfully");
for (int i = 0; i < 50; i++) {
// poll data
ConsumerRecords<ResultBean> records = consumer.poll(Duration.ofMillis(100));
for (ConsumerRecord<ResultBean> record : records) {
ResultBean bean = record.value();
// process the data here
System.out.println("data: " + JSON.toJSONString(bean));
}
}
} catch (SQLException ex) {
// handle any errors, please refer to the JDBC specifications for detailed exceptions info
System.out.println("Failed to poll data; ErrCode:" + ex.getErrorCode() + "; ErrMessage: " + ex.getMessage());
throw new SQLException("Failed to poll data", ex);
}
// ANCHOR_END: poll_data_code_piece
}
public static void seekExample() throws SQLException {
// ANCHOR: consumer_seek
try (TaosConsumer<ResultBean> consumer = getConsumer()){
List<String> topics = Collections.singletonList("topic_meters");
// subscribe to the topics
consumer.subscribe(topics);
System.out.println("subscribe topics successfully");
ConsumerRecords<ResultBean> records = ConsumerRecords.emptyRecord();
// make sure we have got some data
while (records.isEmpty()){
records = consumer.poll(Duration.ofMillis(100));
}
for (ConsumerRecord<ResultBean> record : records) {
System.out.println("first data polled: " + JSON.toJSONString(record.value()));
Set<TopicPartition> assignment = consumer.assignment();
// seek to the beginning of the all partitions
consumer.seekToBeginning(assignment);
System.out.println("assignment seek to beginning successfully");
break;
}
// poll data agagin
records = consumer.poll(Duration.ofMillis(100));
for (ConsumerRecord<ResultBean> record : records) {
// process the data here
System.out.println("second data polled: " + JSON.toJSONString(record.value()));
break;
}
} catch (SQLException ex) {
// handle any errors, please refer to the JDBC specifications for detailed exceptions info
System.out.println("seek example failed; ErrCode:" + ex.getErrorCode() + "; ErrMessage: " + ex.getMessage());
throw new SQLException("seek example failed", ex);
}
// ANCHOR_END: consumer_seek
}
public static void commitExample() throws SQLException {
// ANCHOR: commit_code_piece
try (TaosConsumer<ResultBean> consumer = getConsumer()){
List<String> topics = Collections.singletonList("topic_meters");
consumer.subscribe(topics);
for (int i = 0; i < 50; i++) {
ConsumerRecords<ResultBean> records = consumer.poll(Duration.ofMillis(100));
for (ConsumerRecord<ResultBean> record : records) {
ResultBean bean = record.value();
// process your data here
System.out.println("data: " + JSON.toJSONString(bean));
}
if (!records.isEmpty()) {
// after processing the data, commit the offset manually
consumer.commitSync();
}
}
} catch (SQLException ex){
// handle any errors, please refer to the JDBC specifications for detailed exceptions info
System.out.println("Failed to execute consumer functions. ErrCode:" + ex.getErrorCode() + "; ErrMessage: " + ex.getMessage());
throw new SQLException("Failed to execute consumer functions", ex);
}
// ANCHOR_END: commit_code_piece
}
public static void unsubscribeExample() throws SQLException {
TaosConsumer<ResultBean> consumer = getConsumer();
List<String> topics = Collections.singletonList("topic_meters");
consumer.subscribe(topics);
// ANCHOR: unsubscribe_data_code_piece
try {
consumer.unsubscribe();
} catch (SQLException ex){
// handle any errors, please refer to the JDBC specifications for detailed exceptions info
System.out.println("Failed to unsubscribe consumer. ErrCode:" + ex.getErrorCode() + "; ErrMessage: " + ex.getMessage());
throw new SQLException("Failed to unsubscribe consumer", ex);
} finally {
consumer.close();
}
// ANCHOR_END: unsubscribe_data_code_piece
}
public static class ResultDeserializer extends ReferenceDeserializer<ResultBean> {
}
// use this class to define the data structure of the result record
public static class ResultBean {
private Timestamp ts;
private double current;
private int voltage;
private double phase;
private int groupid;
private String location;
public Timestamp getTs() {
return ts;
}
public void setTs(Timestamp ts) {
this.ts = ts;
}
public double getCurrent() {
return current;
}
public void setCurrent(double current) {
this.current = current;
}
public int getVoltage() {
return voltage;
}
public void setVoltage(int voltage) {
this.voltage = voltage;
}
public double getPhase() {
return phase;
}
public void setPhase(double phase) {
this.phase = phase;
}
public int getGroupid() {
return groupid;
}
public void setGroupid(int groupid) {
this.groupid = groupid;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
}
public static void prepareData() throws SQLException{
StringBuilder insertQuery = new StringBuilder();
insertQuery.append("INSERT INTO " +
"power.d1001 USING power.meters TAGS(2,'California.SanFrancisco') " +
"VALUES ");
for (int i = 0; i < 10000; i++){
insertQuery.append("(NOW + ").append(i).append("a, 10.30000, 219, 0.31000) ");
}
try {
int affectedRows = statement.executeUpdate(insertQuery.toString());
assert affectedRows == 10000;
} catch (SQLException ex) {
System.out.println("Failed to insert data to power.meters, ErrCode:" + ex.getErrorCode() + "; ErrMessage: " + ex.getMessage());
throw new SQLException("Failed to insert data to power.meters", ex);
}
}
public static void prepareMeta() throws SQLException{
try {
statement.executeUpdate("CREATE DATABASE IF NOT EXISTS power");
statement.executeUpdate("USE power");
statement.executeUpdate("CREATE STABLE IF NOT EXISTS meters (ts TIMESTAMP, current FLOAT, voltage INT, phase FLOAT) TAGS (groupId INT, location BINARY(24))");
statement.executeUpdate("CREATE TOPIC IF NOT EXISTS topic_meters AS SELECT ts, current, voltage, phase, groupid, location FROM meters");
} catch (SQLException ex) {
System.out.println("Failed to create db and table, ErrCode:" + ex.getErrorCode() + "; ErrMessage: " + ex.getMessage());
throw new SQLException("Failed to create db and table", ex);
}
}
public static void initConnection() throws SQLException {
String url = "jdbc:TAOS://localhost:6030?user=root&password=taosdata";
Properties properties = new Properties();
properties.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "C");
properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
try {
connection = DriverManager.getConnection(url, properties);
} catch (SQLException ex) {
System.out.println("Failed to create connection, url:" + url + "; ErrCode:" + ex.getErrorCode() + "; ErrMessage: " + ex.getMessage());
throw new SQLException("Failed to create connection", ex);
}
try {
statement = connection.createStatement();
} catch (SQLException ex) {
System.out.println("Failed to create statement, ErrCode:" + ex.getErrorCode() + "; ErrMessage: " + ex.getMessage());
throw new SQLException("Failed to create statement", ex);
}
System.out.println("Connection created successfully.");
}
public static void closeConnection() throws SQLException {
try {
if (statement != null) {
statement.close();
}
} catch (SQLException ex) {
System.out.println("Failed to close statement, ErrCode:" + ex.getErrorCode() + "; ErrMessage: " + ex.getMessage());
throw new SQLException("Failed to close statement", ex);
}
try {
if (connection != null) {
connection.close();
}
} catch (SQLException ex) {
System.out.println("Failed to close connection, ErrCode:" + ex.getErrorCode() + "; ErrMessage: " + ex.getMessage());
throw new SQLException("Failed to close connection", ex);
}
System.out.println("Connection closed Successfully.");
}
public static void main(String[] args) throws SQLException {
initConnection();
prepareMeta();
// create a single thread executor
ExecutorService executor = Executors.newSingleThreadExecutor();
// submit a task
executor.submit(() -> {
try {
// please use one example at a time
pollDataExample();
// seekExample();
// pollExample();
// commitExample();
unsubscribeExample();
} catch (SQLException ex) {
System.out.println("Failed to poll data from topic_meters, ErrCode:" + ex.getErrorCode() + "; ErrMessage: " + ex.getMessage());
}
System.out.println("pollDataExample executed successfully");
});
prepareData();
closeConnection();
System.out.println("Data prepared successfully");
// 关闭线程池不再接收新任务
executor.shutdown();
try {
// 等待直到所有任务完成
boolean result = executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
assert result;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} catch (Exception e){
e.printStackTrace();
System.out.println("Wait executor termination failed.");
}
System.out.println("program end.");
}
}
// ANCHOR_END: consumer_demo

View File

@ -54,9 +54,9 @@ try (TaosConsumer<AbsConsumerLoop.ResultBean> consumer = new TaosConsumer<>(conf
// you can handle data here
}
} catch (SQLException ex) {
// handle exception
System.out.println("SQLException: " + ex.getMessage());
throw new SQLException("Failed to create consumer", ex);
// handle any errors, please refer to the JDBC specifications for detailed exceptions info
System.out.println("Failed to execute consumer functions. server: " + config.getProperty("bootstrap.servers") + "; ErrCode:" + ex.getErrorCode() + "; ErrMessage: " + ex.getMessage());
throw new SQLException("Failed to execute consumer functions", ex);
}
// ANCHOR_END: consumer_seek
}

View File

@ -109,8 +109,9 @@ try (Statement statement = connection.createStatement();
}
// ANCHOR_END: jdbc_exception
} catch (SQLException ex) {
// handle any errors
System.out.println("SQLException: " + ex.getMessage());
// handle any errors, please refer to the JDBC specifications for detailed exceptions info
System.out.println("Error Code: " + ex.getErrorCode());
System.out.println("Message: " + ex.getMessage());
}
}

View File

@ -15,7 +15,7 @@ public class JdbcCreatDBDemo {
public static void main(String[] args) throws SQLException {
final String url = "jdbc:TAOS://" + host + ":6030/?user=" + user + "&password=" + password;
final String jdbcUrl = "jdbc:TAOS://" + host + ":6030/?user=" + user + "&password=" + password;
// get connection
Properties properties = new Properties();
@ -24,7 +24,7 @@ properties.setProperty("locale", "en_US.UTF-8");
properties.setProperty("timezone", "UTC-8");
System.out.println("get connection starting...");
// ANCHOR: create_db_and_table
try (Connection connection = DriverManager.getConnection(url, properties);
try (Connection connection = DriverManager.getConnection(jdbcUrl, properties);
Statement stmt = connection.createStatement()) {
// create database
@ -43,8 +43,8 @@ try (Connection connection = DriverManager.getConnection(url, properties);
assert rowsAffected == 0;
} catch (SQLException ex) {
// handle any errors
System.out.println("SQLException: " + ex.getMessage());
// handle any errors, please refer to the JDBC specifications for detailed exceptions info
System.out.println("Failed to create db and table, url:" + jdbcUrl + "; ErrCode:" + ex.getErrorCode() + "; ErrMessage: " + ex.getMessage());
}
// ANCHOR_END: create_db_and_table

View File

@ -15,7 +15,7 @@ public class JdbcInsertDataDemo {
public static void main(String[] args) throws SQLException {
final String url = "jdbc:TAOS://" + host + ":6030/?user=" + user + "&password=" + password;
final String jdbcUrl = "jdbc:TAOS://" + host + ":6030/?user=" + user + "&password=" + password;
// get connection
Properties properties = new Properties();
@ -24,7 +24,7 @@ properties.setProperty("locale", "en_US.UTF-8");
properties.setProperty("timezone", "UTC-8");
System.out.println("get connection starting...");
// ANCHOR: insert_data
try (Connection connection = DriverManager.getConnection(url, properties);
try (Connection connection = DriverManager.getConnection(jdbcUrl, properties);
Statement stmt = connection.createStatement()) {
// insert data, please make sure the database and table are created before
@ -39,10 +39,11 @@ try (Connection connection = DriverManager.getConnection(url, properties);
"(NOW + 1a, 10.30000, 218, 0.25000) ";
int affectedRows = stmt.executeUpdate(insertQuery);
// you can check affectedRows here
System.out.println("insert " + affectedRows + " rows.");
System.out.println("inserted into " + affectedRows + " rows to power.meters successfully.");
} catch (SQLException ex) {
// handle any errors
System.out.println("SQLException: " + ex.getMessage());
// handle any errors, please refer to the JDBC specifications for detailed exceptions info
System.out.println("Failed to insert data to power.meters, url:" + jdbcUrl + "; ErrCode:" + ex.getErrorCode() + "; ErrMessage: " + ex.getMessage());
}
// ANCHOR_END: insert_data
}

View File

@ -15,7 +15,7 @@ public class JdbcQueryDemo {
public static void main(String[] args) throws SQLException {
final String url = "jdbc:TAOS://" + host + ":6030/?user=" + user + "&password=" + password;
final String jdbcUrl = "jdbc:TAOS://" + host + ":6030/?user=" + user + "&password=" + password;
// get connection
Properties properties = new Properties();
@ -24,10 +24,10 @@ properties.setProperty("locale", "en_US.UTF-8");
properties.setProperty("timezone", "UTC-8");
System.out.println("get connection starting...");
// ANCHOR: query_data
try (Connection connection = DriverManager.getConnection(url, properties);
try (Connection connection = DriverManager.getConnection(jdbcUrl, properties);
Statement stmt = connection.createStatement();
// query data, make sure the database and table are created before
ResultSet resultSet = stmt.executeQuery("SELECT * FROM power.meters")) {
ResultSet resultSet = stmt.executeQuery("SELECT ts, current, location FROM power.meters limit 100")) {
Timestamp ts;
float current;
@ -39,11 +39,11 @@ try (Connection connection = DriverManager.getConnection(url, properties);
location = resultSet.getString("location");
// you can check data here
System.out.printf("%s, %f, %s\n", ts, current, location);
System.out.printf("ts: %s, current: %f, location: %s %n", ts, current, location);
}
} catch (SQLException ex) {
// handle any errors
System.out.println("SQLException: " + ex.getMessage());
// handle any errors, please refer to the JDBC specifications for detailed exceptions info
System.out.println("Failed to query data from power.meters, url:" + jdbcUrl + "; ErrCode:" + ex.getErrorCode() + "; ErrMessage: " + ex.getMessage());
}
// ANCHOR_END: query_data
}

View File

@ -15,7 +15,7 @@ public class JdbcReqIdDemo {
public static void main(String[] args) throws SQLException {
final String url = "jdbc:TAOS://" + host + ":6030/?user=" + user + "&password=" + password;
final String jdbcUrl = "jdbc:TAOS://" + host + ":6030/?user=" + user + "&password=" + password;
// get connection
Properties properties = new Properties();
@ -25,25 +25,20 @@ properties.setProperty("timezone", "UTC-8");
System.out.println("get connection starting...");
// ANCHOR: with_reqid
try (Connection connection = DriverManager.getConnection(url, properties);
try (Connection connection = DriverManager.getConnection(jdbcUrl, properties);
// Create a statement that allows specifying a request ID
AbstractStatement aStmt = (AbstractStatement) connection.createStatement()) {
boolean hasResultSet = aStmt.execute("CREATE DATABASE IF NOT EXISTS power", 1L);
assert !hasResultSet;
int rowsAffected = aStmt.executeUpdate("USE power", 2L);
assert rowsAffected == 0;
try (ResultSet rs = aStmt.executeQuery("SELECT * FROM meters limit 1", 3L)) {
try (ResultSet rs = aStmt.executeQuery("SELECT ts, current, location FROM power.meters limit 1", 3L)) {
while (rs.next()) {
Timestamp timestamp = rs.getTimestamp(1);
System.out.println("timestamp = " + timestamp);
}
}
} catch (SQLException ex) {
// handle any errors
System.out.println("SQLException: " + ex.getMessage());
// handle any errors, please refer to the JDBC specifications for detailed exceptions info
System.out.println("Failed to execute sql with reqId, url:" + jdbcUrl + "; ErrCode:" + ex.getErrorCode() + "; ErrMessage: " + ex.getMessage());
}
// ANCHOR_END: with_reqid
}

View File

@ -1,14 +1,12 @@
package com.taosdata.example;
import com.taosdata.jdbc.TSDBPreparedStatement;
import com.taosdata.jdbc.utils.StringUtils;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
// ANCHOR: para_bind
@ -46,22 +44,22 @@ public class ParameterBindingBasicDemo {
pstmt.setTimestamp(0, tsList);
// set column current
ArrayList<Float> f1List = new ArrayList<>();
ArrayList<Float> currentList = new ArrayList<>();
for (int j = 0; j < numOfRow; j++)
f1List.add(random.nextFloat() * 30);
pstmt.setFloat(1, f1List);
currentList.add(random.nextFloat() * 30);
pstmt.setFloat(1, currentList);
// set column voltage
ArrayList<Integer> f2List = new ArrayList<>();
ArrayList<Integer> voltageList = new ArrayList<>();
for (int j = 0; j < numOfRow; j++)
f2List.add(random.nextInt(300));
pstmt.setInt(2, f2List);
voltageList.add(random.nextInt(300));
pstmt.setInt(2, voltageList);
// set column phase
ArrayList<Float> f3List = new ArrayList<>();
ArrayList<Float> phaseList = new ArrayList<>();
for (int j = 0; j < numOfRow; j++)
f3List.add(random.nextFloat());
pstmt.setFloat(3, f3List);
phaseList.add(random.nextFloat());
pstmt.setFloat(3, phaseList);
// add column
pstmt.columnDataAddBatch();
}
@ -69,8 +67,8 @@ public class ParameterBindingBasicDemo {
pstmt.columnDataExecuteBatch();
}
} catch (SQLException ex) {
// handle any errors
System.out.println("SQLException: " + ex.getMessage());
// handle any errors, please refer to the JDBC specifications for detailed exceptions info
System.out.println("Failed to insert to table meters using stmt, url: " + jdbcUrl + "; ErrCode:" + ex.getErrorCode() + "; ErrMessage: " + ex.getMessage());
}
}

View File

@ -13,12 +13,12 @@ import java.sql.Statement;
public class SchemalessJniTest {
private static final String host = "127.0.0.1";
private static final String lineDemo = "meters,groupid=2,location=California.SanFrancisco current=10.3000002f64,voltage=219i32,phase=0.31f64 1626006833639";
private static final String telnetDemo = "stb0_0 1707095283260 4 host=host0 interface=eth0";
private static final String jsonDemo = "{\"metric\": \"meter_current\",\"timestamp\": 1626846400,\"value\": 10.3, \"tags\": {\"groupid\": 2, \"location\": \"California.SanFrancisco\", \"id\": \"d1001\"}}";
private static final String telnetDemo = "metric_telnet 1707095283260 4 host=host0 interface=eth0";
private static final String jsonDemo = "{\"metric\": \"metric_json\",\"timestamp\": 1626846400,\"value\": 10.3, \"tags\": {\"groupid\": 2, \"location\": \"California.SanFrancisco\", \"id\": \"d1001\"}}";
public static void main(String[] args) throws SQLException {
final String url = "jdbc:TAOS://" + host + ":6030/?user=root&password=taosdata";
try (Connection connection = DriverManager.getConnection(url)) {
final String jdbcUrl = "jdbc:TAOS://" + host + ":6030/?user=root&password=taosdata";
try (Connection connection = DriverManager.getConnection(jdbcUrl)) {
init(connection);
AbstractConnection conn = connection.unwrap(AbstractConnection.class);
@ -26,7 +26,8 @@ public class SchemalessJniTest {
conn.write(telnetDemo, SchemalessProtocolType.TELNET, SchemalessTimestampType.MILLI_SECONDS);
conn.write(jsonDemo, SchemalessProtocolType.JSON, SchemalessTimestampType.NOT_CONFIGURED);
} catch (SQLException ex) {
System.out.println("SQLException: " + ex.getMessage());
// handle any errors, please refer to the JDBC specifications for detailed exceptions info
System.out.println("Failed to insert data with schemaless, host:" + host + "; ErrCode:" + ex.getErrorCode() + "; ErrMessage: " + ex.getMessage());
}
}

View File

@ -13,8 +13,8 @@ import java.sql.Statement;
public class SchemalessWsTest {
private static final String host = "127.0.0.1";
private static final String lineDemo = "meters,groupid=2,location=California.SanFrancisco current=10.3000002f64,voltage=219i32,phase=0.31f64 1626006833639";
private static final String telnetDemo = "stb0_0 1707095283260 4 host=host0 interface=eth0";
private static final String jsonDemo = "{\"metric\": \"meter_current\",\"timestamp\": 1626846400,\"value\": 10.3, \"tags\": {\"groupid\": 2, \"location\": \"California.SanFrancisco\", \"id\": \"d1001\"}}";
private static final String telnetDemo = "metric_telnet 1707095283260 4 host=host0 interface=eth0";
private static final String jsonDemo = "{\"metric\": \"metric_json\",\"timestamp\": 1626846400,\"value\": 10.3, \"tags\": {\"groupid\": 2, \"location\": \"California.SanFrancisco\", \"id\": \"d1001\"}}";
public static void main(String[] args) throws SQLException {
final String url = "jdbc:TAOS-RS://" + host + ":6041?user=root&password=taosdata&batchfetch=true";
@ -26,7 +26,8 @@ public class SchemalessWsTest {
conn.write(telnetDemo, SchemalessProtocolType.TELNET, SchemalessTimestampType.MILLI_SECONDS);
conn.write(jsonDemo, SchemalessProtocolType.JSON, SchemalessTimestampType.SECONDS);
} catch (SQLException ex) {
System.out.println("SQLException: " + ex.getMessage());
// handle any errors, please refer to the JDBC specifications for detailed exceptions info
System.out.println("Failed to insert data with schemaless, host:" + host + "; ErrCode:" + ex.getErrorCode() + "; ErrMessage: " + ex.getMessage());
}
}

View File

@ -48,8 +48,8 @@ public class WSParameterBindingBasicDemo {
}
}
} catch (SQLException ex) {
// handle any errors
System.out.println("SQLException: " + ex.getMessage());
// handle any errors, please refer to the JDBC specifications for detailed exceptions info
System.out.println("Failed to insert to table meters using stmt, url: " + jdbcUrl + "; ErrCode:" + ex.getErrorCode() + "; ErrMessage: " + ex.getMessage());
}
}

View File

@ -36,7 +36,9 @@ public class WSParameterBindingDemo {
bindString(conn);
} catch (SQLException ex) {
System.out.println("SQLException: " + ex.getMessage());
// handle any errors, please refer to the JDBC specifications for detailed exceptions info
System.out.println("Error Code: " + ex.getErrorCode());
System.out.println("Message: " + ex.getMessage());
}
}

View File

@ -38,7 +38,9 @@ public class WSParameterBindingFullDemo {
bindString(conn);
} catch (SQLException ex) {
System.out.println("SQLException: " + ex.getMessage());
// handle any errors, please refer to the JDBC specifications for detailed exceptions info
System.out.println("Error Code: " + ex.getErrorCode());
System.out.println("Message: " + ex.getMessage());
}
}

View File

@ -0,0 +1,358 @@
package com.taosdata.example;
import com.alibaba.fastjson.JSON;
import com.taosdata.jdbc.TSDBDriver;
import com.taosdata.jdbc.tmq.*;
import java.sql.*;
import java.time.Duration;
import java.util.Collections;
import java.util.List;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
// ANCHOR: consumer_demo
public class WsConsumerLoopFull {
static private Connection connection;
static private Statement statement;
public static TaosConsumer<ResultBean> getConsumer() throws SQLException{
// ANCHOR: create_consumer
Properties config = new Properties();
config.setProperty("td.connect.type", "ws");
config.setProperty("bootstrap.servers", "localhost:6041");
config.setProperty("auto.offset.reset", "latest");
config.setProperty("msg.with.table.name", "true");
config.setProperty("enable.auto.commit", "true");
config.setProperty("auto.commit.interval.ms", "1000");
config.setProperty("group.id", "group1");
config.setProperty("client.id", "client1");
config.setProperty("td.connect.user", "root");
config.setProperty("td.connect.pass", "taosdata");
config.setProperty("value.deserializer", "com.taosdata.example.WsConsumerLoopFull$ResultDeserializer");
config.setProperty("value.deserializer.encoding", "UTF-8");
try {
return new TaosConsumer<>(config);
} catch (SQLException ex) {
// handle any errors, please refer to the JDBC specifications for detailed exceptions info
System.out.println("Failed to create websocket consumer, host : " + config.getProperty("bootstrap.servers") + "; ErrCode:" + ex.getErrorCode() + "; ErrMessage: " + ex.getMessage());
throw new SQLException("Failed to create consumer", ex);
} catch (Exception e) {
e.printStackTrace();
throw new SQLException("Failed to create consumer", e);
}
// ANCHOR_END: create_consumer
}
public static void pollDataExample() throws SQLException {
try (TaosConsumer<ResultBean> consumer = getConsumer()){
// subscribe to the topics
List<String> topics = Collections.singletonList("topic_meters");
consumer.subscribe(topics);
System.out.println("subscribe topics successfully");
for (int i = 0; i < 50; i++) {
// poll data
ConsumerRecords<ResultBean> records = consumer.poll(Duration.ofMillis(100));
for (ConsumerRecord<ResultBean> record : records) {
ResultBean bean = record.value();
// process the data here
System.out.println("data: " + JSON.toJSONString(bean));
}
}
// unsubscribe the topics
consumer.unsubscribe();
System.out.println("unsubscribed topics successfully");
} catch (SQLException ex) {
// handle any errors, please refer to the JDBC specifications for detailed exceptions info
System.out.println("Failed to poll data from topic_meters, ErrCode:" + ex.getErrorCode() + "; ErrMessage: " + ex.getMessage());
throw new SQLException("Failed to poll data from topic_meters", ex);
}
}
public static void pollExample() throws SQLException {
// ANCHOR: poll_data_code_piece
try (TaosConsumer<ResultBean> consumer = getConsumer()){
List<String> topics = Collections.singletonList("topic_meters");
// subscribe to the topics
consumer.subscribe(topics);
System.out.println("subscribe topics successfully");
for (int i = 0; i < 50; i++) {
// poll data
ConsumerRecords<ResultBean> records = consumer.poll(Duration.ofMillis(100));
for (ConsumerRecord<ResultBean> record : records) {
ResultBean bean = record.value();
// process the data here
System.out.println("data: " + JSON.toJSONString(bean));
}
}
} catch (SQLException ex) {
// handle any errors, please refer to the JDBC specifications for detailed exceptions info
System.out.println("Failed to poll data; ErrCode:" + ex.getErrorCode() + "; ErrMessage: " + ex.getMessage());
throw new SQLException("Failed to poll data", ex);
}
// ANCHOR_END: poll_data_code_piece
}
public static void seekExample() throws SQLException {
// ANCHOR: consumer_seek
try (TaosConsumer<ResultBean> consumer = getConsumer()){
List<String> topics = Collections.singletonList("topic_meters");
// subscribe to the topics
consumer.subscribe(topics);
System.out.println("subscribe topics successfully");
ConsumerRecords<ResultBean> records = ConsumerRecords.emptyRecord();
// make sure we have got some data
while (records.isEmpty()){
records = consumer.poll(Duration.ofMillis(100));
}
for (ConsumerRecord<ResultBean> record : records) {
System.out.println("first data polled: " + JSON.toJSONString(record.value()));
Set<TopicPartition> assignment = consumer.assignment();
// seek to the beginning of the all partitions
consumer.seekToBeginning(assignment);
System.out.println("assignment seek to beginning successfully");
break;
}
// poll data agagin
records = consumer.poll(Duration.ofMillis(100));
for (ConsumerRecord<ResultBean> record : records) {
// process the data here
System.out.println("second data polled: " + JSON.toJSONString(record.value()));
break;
}
} catch (SQLException ex) {
// handle any errors, please refer to the JDBC specifications for detailed exceptions info
System.out.println("seek example failed; ErrCode:" + ex.getErrorCode() + "; ErrMessage: " + ex.getMessage());
throw new SQLException("seek example failed", ex);
}
// ANCHOR_END: consumer_seek
}
public static void commitExample() throws SQLException {
// ANCHOR: commit_code_piece
try (TaosConsumer<ResultBean> consumer = getConsumer()){
List<String> topics = Collections.singletonList("topic_meters");
consumer.subscribe(topics);
for (int i = 0; i < 50; i++) {
ConsumerRecords<ResultBean> records = consumer.poll(Duration.ofMillis(100));
for (ConsumerRecord<ResultBean> record : records) {
ResultBean bean = record.value();
// process your data here
System.out.println("data: " + JSON.toJSONString(bean));
}
if (!records.isEmpty()) {
// after processing the data, commit the offset manually
consumer.commitSync();
}
}
} catch (SQLException ex){
// handle any errors, please refer to the JDBC specifications for detailed exceptions info
System.out.println("Failed to execute consumer functions. ErrCode:" + ex.getErrorCode() + "; ErrMessage: " + ex.getMessage());
throw new SQLException("Failed to execute consumer functions", ex);
}
// ANCHOR_END: commit_code_piece
}
public static void unsubscribeExample() throws SQLException {
TaosConsumer<ResultBean> consumer = getConsumer();
List<String> topics = Collections.singletonList("topic_meters");
consumer.subscribe(topics);
// ANCHOR: unsubscribe_data_code_piece
try {
consumer.unsubscribe();
} catch (SQLException ex){
// handle any errors, please refer to the JDBC specifications for detailed exceptions info
System.out.println("Failed to unsubscribe consumer. ErrCode:" + ex.getErrorCode() + "; ErrMessage: " + ex.getMessage());
throw new SQLException("Failed to unsubscribe consumer", ex);
} finally {
consumer.close();
}
// ANCHOR_END: unsubscribe_data_code_piece
}
public static class ResultDeserializer extends ReferenceDeserializer<ResultBean> {
}
// use this class to define the data structure of the result record
public static class ResultBean {
private Timestamp ts;
private double current;
private int voltage;
private double phase;
private int groupid;
private String location;
public Timestamp getTs() {
return ts;
}
public void setTs(Timestamp ts) {
this.ts = ts;
}
public double getCurrent() {
return current;
}
public void setCurrent(double current) {
this.current = current;
}
public int getVoltage() {
return voltage;
}
public void setVoltage(int voltage) {
this.voltage = voltage;
}
public double getPhase() {
return phase;
}
public void setPhase(double phase) {
this.phase = phase;
}
public int getGroupid() {
return groupid;
}
public void setGroupid(int groupid) {
this.groupid = groupid;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
}
public static void prepareData() throws SQLException{
StringBuilder insertQuery = new StringBuilder();
insertQuery.append("INSERT INTO " +
"power.d1001 USING power.meters TAGS(2,'California.SanFrancisco') " +
"VALUES ");
for (int i = 0; i < 10000; i++){
insertQuery.append("(NOW + ").append(i).append("a, 10.30000, 219, 0.31000) ");
}
try {
int affectedRows = statement.executeUpdate(insertQuery.toString());
assert affectedRows == 10000;
} catch (SQLException ex) {
System.out.println("Failed to insert data to power.meters, ErrCode:" + ex.getErrorCode() + "; ErrMessage: " + ex.getMessage());
throw new SQLException("Failed to insert data to power.meters", ex);
}
}
public static void prepareMeta() throws SQLException{
try {
statement.executeUpdate("CREATE DATABASE IF NOT EXISTS power");
statement.executeUpdate("USE power");
statement.executeUpdate("CREATE STABLE IF NOT EXISTS meters (ts TIMESTAMP, current FLOAT, voltage INT, phase FLOAT) TAGS (groupId INT, location BINARY(24))");
statement.executeUpdate("CREATE TOPIC IF NOT EXISTS topic_meters AS SELECT ts, current, voltage, phase, groupid, location FROM meters");
} catch (SQLException ex) {
System.out.println("Failed to create db and table, ErrCode:" + ex.getErrorCode() + "; ErrMessage: " + ex.getMessage());
throw new SQLException("Failed to create db and table", ex);
}
}
public static void initConnection() throws SQLException {
String url = "jdbc:TAOS://localhost:6030?user=root&password=taosdata";
Properties properties = new Properties();
properties.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "C");
properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
try {
connection = DriverManager.getConnection(url, properties);
} catch (SQLException ex) {
System.out.println("Failed to create connection, url:" + url + "; ErrCode:" + ex.getErrorCode() + "; ErrMessage: " + ex.getMessage());
throw new SQLException("Failed to create connection", ex);
}
try {
statement = connection.createStatement();
} catch (SQLException ex) {
System.out.println("Failed to create statement, ErrCode:" + ex.getErrorCode() + "; ErrMessage: " + ex.getMessage());
throw new SQLException("Failed to create statement", ex);
}
System.out.println("Connection created successfully.");
}
public static void closeConnection() throws SQLException {
try {
if (statement != null) {
statement.close();
}
} catch (SQLException ex) {
System.out.println("Failed to close statement, ErrCode:" + ex.getErrorCode() + "; ErrMessage: " + ex.getMessage());
throw new SQLException("Failed to close statement", ex);
}
try {
if (connection != null) {
connection.close();
}
} catch (SQLException ex) {
System.out.println("Failed to close connection, ErrCode:" + ex.getErrorCode() + "; ErrMessage: " + ex.getMessage());
throw new SQLException("Failed to close connection", ex);
}
System.out.println("Connection closed Successfully.");
}
public static void main(String[] args) throws SQLException {
initConnection();
prepareMeta();
// create a single thread executor
ExecutorService executor = Executors.newSingleThreadExecutor();
// submit a task
executor.submit(() -> {
try {
// please use one example at a time
pollDataExample();
// seekExample();
// pollExample();
// commitExample();
unsubscribeExample();
} catch (SQLException ex) {
System.out.println("Failed to poll data from topic_meters, ErrCode:" + ex.getErrorCode() + "; ErrMessage: " + ex.getMessage());
}
System.out.println("pollDataExample executed successfully");
});
prepareData();
closeConnection();
System.out.println("Data prepared successfully");
// 关闭线程池不再接收新任务
executor.shutdown();
try {
// 等待直到所有任务完成
boolean result = executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
assert result;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} catch (Exception e){
e.printStackTrace();
System.out.println("Wait executor termination failed.");
}
System.out.println("program end.");
}
}
// ANCHOR_END: consumer_demo