other:merge 3.0
This commit is contained in:
commit
4d8842c21f
|
@ -118,3 +118,4 @@ contrib/*
|
|||
!contrib/test
|
||||
sql
|
||||
debug*/
|
||||
.env
|
|
@ -10,7 +10,9 @@ ELSEIF (TD_WINDOWS)
|
|||
# INSTALL(DIRECTORY ${TD_SOURCE_DIR}/src/connector/python DESTINATION connector)
|
||||
# INSTALL(DIRECTORY ${TD_SOURCE_DIR}/src/connector/C\# DESTINATION connector)
|
||||
# INSTALL(DIRECTORY ${TD_SOURCE_DIR}/examples DESTINATION .)
|
||||
INSTALL(FILES ${TD_SOURCE_DIR}/packaging/cfg/taos.cfg DESTINATION cfg)
|
||||
INSTALL(CODE "IF (NOT EXISTS ${CMAKE_INSTALL_PREFIX}/cfg/taos.cfg)
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E copy ${TD_SOURCE_DIR}/packaging/cfg/taos.cfg ${CMAKE_INSTALL_PREFIX}/cfg/taos.cfg)
|
||||
ENDIF ()")
|
||||
INSTALL(FILES ${TD_SOURCE_DIR}/include/client/taos.h DESTINATION include)
|
||||
INSTALL(FILES ${TD_SOURCE_DIR}/include/util/taoserror.h DESTINATION include)
|
||||
INSTALL(FILES ${TD_SOURCE_DIR}/include/libs/function/taosudf.h DESTINATION include)
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
# taos-tools
|
||||
ExternalProject_Add(taos-tools
|
||||
GIT_REPOSITORY https://github.com/taosdata/taos-tools.git
|
||||
GIT_TAG c9cc20f
|
||||
GIT_TAG 3c7dafe
|
||||
SOURCE_DIR "${TD_SOURCE_DIR}/tools/taos-tools"
|
||||
BINARY_DIR ""
|
||||
#BUILD_IN_SOURCE TRUE
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
# taosws-rs
|
||||
ExternalProject_Add(taosws-rs
|
||||
GIT_REPOSITORY https://github.com/taosdata/taosws-rs.git
|
||||
GIT_TAG 9fa7e2f
|
||||
GIT_TAG 29424d5
|
||||
SOURCE_DIR "${TD_SOURCE_DIR}/tools/taosws-rs"
|
||||
BINARY_DIR ""
|
||||
#BUILD_IN_SOURCE TRUE
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
sidebar_label: Interval
|
||||
title: Aggregate by Time Window
|
||||
sidebar_label: Distinguished
|
||||
title: Distinguished Query for Time Series Database
|
||||
---
|
||||
|
||||
Aggregation by time window is supported in TDengine. For example, in the case where temperature sensors report the temperature every seconds, the average temperature for every 10 minutes can be retrieved by performing a query with a time window.
|
|
@ -0,0 +1,66 @@
|
|||
---
|
||||
sidebar_label: 消息队列
|
||||
title: 消息队列
|
||||
---
|
||||
|
||||
TDengine 3.0.0.0 开始对消息队列做了大幅的优化和增强以简化用户的解决方案。
|
||||
|
||||
## 创建订阅主题
|
||||
|
||||
```sql
|
||||
CREATE TOPIC [IF NOT EXISTS] topic_name AS {subquery | DATABASE db_name | STABLE stb_name };
|
||||
```
|
||||
|
||||
订阅主题包括三种:列订阅、超级表订阅和数据库订阅。
|
||||
|
||||
**列订阅是**用 subquery 描述,支持过滤和标量函数和 UDF 标量函数,不支持 JOIN、GROUP BY、窗口切分子句、聚合函数和 UDF 聚合函数。列订阅规则如下:
|
||||
|
||||
1. TOPIC 一旦创建则返回结果的字段确定
|
||||
2. 被订阅或用于计算的列不可被删除、修改
|
||||
3. 列可以新增,但新增的列不出现在订阅结果字段中
|
||||
4. 对于 select \*,则订阅展开为创建时所有的列(子表、普通表为数据列,超级表为数据列加标签列)
|
||||
|
||||
**超级表订阅和数据库订阅**规则如下:
|
||||
|
||||
1. 被订阅主体的 schema 变更不受限
|
||||
2. 返回消息中 schema 是块级别的,每块的 schema 可能不一样
|
||||
3. 列变更后写入的数据若未落盘,将以写入时的 schema 返回
|
||||
4. 列变更后写入的数据若未已落盘,将以落盘时的 schema 返回
|
||||
|
||||
## 删除订阅主题
|
||||
|
||||
```sql
|
||||
DROP TOPIC [IF EXISTS] topic_name;
|
||||
```
|
||||
|
||||
此时如果该订阅主题上存在 consumer,则此 consumer 会收到一个错误。
|
||||
|
||||
## 查看订阅主题
|
||||
|
||||
## SHOW TOPICS
|
||||
|
||||
```sql
|
||||
SHOW TOPICS;
|
||||
```
|
||||
|
||||
显示当前数据库下的所有主题的信息。
|
||||
|
||||
## 创建消费组
|
||||
|
||||
消费组的创建只能通过 TDengine 客户端驱动或者连接器所提供的 API 创建。
|
||||
|
||||
## 删除消费组
|
||||
|
||||
```sql
|
||||
DROP CONSUMER GROUP [IF EXISTS] cgroup_name ON topic_name;
|
||||
```
|
||||
|
||||
删除主题 topic_name 上的消费组 cgroup_name。
|
||||
|
||||
## 查看消费组
|
||||
|
||||
```sql
|
||||
SHOW CONSUMERS;
|
||||
```
|
||||
|
||||
显示当前数据库下所有活跃的消费者的信息。
|
|
@ -1,53 +0,0 @@
|
|||
---
|
||||
title: Naming & Restrictions
|
||||
---
|
||||
|
||||
## Naming Rules
|
||||
|
||||
1. Only characters from the English alphabet, digits and underscore are allowed
|
||||
2. Names cannot start with a digit
|
||||
3. Case insensitive without escape character "\`"
|
||||
4. Identifier with escape character "\`"
|
||||
To support more flexible table or column names, a new escape character "\`" is introduced. For more details please refer to [escape](/taos-sql/escape).
|
||||
|
||||
## Password Rule
|
||||
|
||||
The legal character set is `[a-zA-Z0-9!?$%^&*()_–+={[}]:;@~#|<,>.?/]`.
|
||||
|
||||
## General Limits
|
||||
|
||||
- Maximum length of database name is 32 bytes, and it can't include "." or special characters.
|
||||
- Maximum length of table name is 192 bytes, excluding the database name prefix and the separator.
|
||||
- Maximum length of each data row is 48K bytes. Please note that the upper limit includes the extra 2 bytes consumed by each column of BINARY/NCHAR type.
|
||||
- Maximum length of column name is 64.
|
||||
- Maximum number of columns is 4096. There must be at least 2 columns, and the first column must be timestamp.
|
||||
- Maximum length of tag name is 64.
|
||||
- Maximum number of tags is 128. There must be at least 1 tag. The total length of tag values should not exceed 16K bytes.
|
||||
- Maximum length of singe SQL statement is 1048576, i.e. 1 MB. It can be configured in the parameter `maxSQLLength` in the client side, the applicable range is [65480, 1048576].
|
||||
- At most 4096 columns can be returned by `SELECT`. Functions in the query statement constitute columns. An error is returned if the limit is exceeded.
|
||||
- Maximum numbers of databases, STables, tables are dependent only on the system resources.
|
||||
- Maximum number of replicas for a database is 3.
|
||||
- Maximum length of user name is 23 bytes.
|
||||
- Maximum length of password is 15 bytes.
|
||||
- Maximum number of rows depends only on the storage space.
|
||||
- Maximum number of vnodes for a single database is 1024.
|
||||
|
||||
## Restrictions of Table/Column Names
|
||||
|
||||
### Name Restrictions of Table/Column
|
||||
|
||||
The name of a table or column can only be composed of ASCII characters, digits and underscore and it cannot start with a digit. The maximum length is 192 bytes. Names are case insensitive. The name mentioned in this rule doesn't include the database name prefix and the separator.
|
||||
|
||||
### Name Restrictions After Escaping
|
||||
|
||||
To support more flexible table or column names, new escape character "\`" is introduced in TDengine to avoid the conflict between table name and keywords and break the above restrictions for table names. The escape character is not counted in the length of table name.
|
||||
|
||||
With escaping, the string inside escape characters are case sensitive, i.e. will not be converted to lower case internally.
|
||||
|
||||
For example:
|
||||
\`aBc\` and \`abc\` are different table or column names, but "abc" and "aBc" are same names because internally they are all "abc".
|
||||
|
||||
:::note
|
||||
The characters inside escape characters must be printable characters.
|
||||
|
||||
:::
|
|
@ -0,0 +1,122 @@
|
|||
---
|
||||
sidebar_label: 流式计算
|
||||
title: 流式计算
|
||||
---
|
||||
|
||||
在时序数据的处理中,经常要对原始数据进行清洗、预处理,再使用时序数据库进行长久的储存。用户通常需要在时序数据库之外再搭建 Kafka、Flink、Spark 等流计算处理引擎,增加了用户的开发成本和维护成本。
|
||||
|
||||
使用 TDengine 3.0 的流式计算引擎能够最大限度的减少对这些额外中间件的依赖,真正将数据的写入、预处理、长期存储、复杂分析、实时计算、实时报警触发等功能融为一体,并且,所有这些任务只需要使用 SQL 完成,极大降低了用户的学习成本、使用成本。
|
||||
|
||||
## 创建流式计算
|
||||
|
||||
```sql
|
||||
CREATE STREAM [IF NOT EXISTS] stream_name [stream_options] INTO stb_name AS subquery
|
||||
stream_options: {
|
||||
TRIGGER [AT_ONCE | WINDOW_CLOSE | MAX_DELAY time]
|
||||
WATERMARK time
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
其中 subquery 是 select 普通查询语法的子集:
|
||||
|
||||
```sql
|
||||
subquery: SELECT [DISTINCT] select_list
|
||||
from_clause
|
||||
[WHERE condition]
|
||||
[PARTITION BY tag_list]
|
||||
[window_clause]
|
||||
[group_by_clause]
|
||||
```
|
||||
|
||||
不支持 order_by,limit,slimit,fill 语句
|
||||
|
||||
例如,如下语句创建流式计算,同时自动创建名为 avg_vol 的超级表,此流计算以一分钟为时间窗口、30 秒为前向增量统计这些电表的平均电压,并将来自 meters 表的数据的计算结果写入 avg_vol 表,不同 partition 的数据会分别创建子表并写入不同子表。
|
||||
|
||||
```sql
|
||||
CREATE STREAM avg_vol_s INTO avg_vol AS
|
||||
SELECT _wstartts, count(*), avg(voltage) FROM meters PARTITION BY tbname INTERVAL(1m) SLIDING(30s);
|
||||
```
|
||||
|
||||
## 删除流式计算
|
||||
|
||||
```sql
|
||||
DROP STREAM [IF NOT EXISTS] stream_name
|
||||
```
|
||||
|
||||
仅删除流式计算任务,由流式计算写入的数据不会被删除。
|
||||
|
||||
## 展示流式计算
|
||||
|
||||
```sql
|
||||
SHOW STREAMS;
|
||||
```
|
||||
|
||||
## 流式计算的触发模式
|
||||
|
||||
在创建流时,可以通过 TRIGGER 指令指定流式计算的触发模式。
|
||||
|
||||
对于非窗口计算,流式计算的触发是实时的;对于窗口计算,目前提供 3 种触发模式:
|
||||
|
||||
1. AT_ONCE:写入立即触发
|
||||
|
||||
2. WINDOW_CLOSE:窗口关闭时触发(窗口关闭由事件时间决定,可配合 watermark 使用,详见《流式计算的乱序数据容忍策略》)
|
||||
|
||||
3. MAX_DELAY time:若窗口关闭,则触发计算。若窗口未关闭,且未关闭时长超过 max delay 指定的时间,则触发计算。
|
||||
|
||||
由于窗口关闭是由事件时间决定的,如事件流中断、或持续延迟,则事件时间无法更新,可能导致无法得到最新的计算结果。
|
||||
|
||||
因此,流式计算提供了以事件时间结合处理时间计算的 MAX_DELAY 触发模式。
|
||||
|
||||
MAX_DELAY 模式在窗口关闭时会立即触发计算。此外,当数据写入后,计算触发的时间超过 max delay 指定的时间,则立即触发计算
|
||||
|
||||
## 流式计算的乱序数据容忍策略
|
||||
|
||||
在创建流时,可以在 stream_option 中指定 watermark。
|
||||
|
||||
流式计算通过 watermark 来度量对乱序数据的容忍程度,watermark 默认为 0。
|
||||
|
||||
T = 最新事件时间 - watermark
|
||||
|
||||
每批到来的数据都会以上述公式更新窗口关闭时间,并将窗口结束时间 < T 的所有打开的窗口关闭,若触发模式为 WINDOW_CLOSE 或 MAX_DELAY,则推送窗口聚合结果。
|
||||
|
||||
流式计算的过期数据处理策略
|
||||
对于已关闭的窗口,再次落入该窗口中的数据被标记为过期数据,对于过期数据,流式计算提供两种处理方式:
|
||||
|
||||
1. 直接丢弃:这是常见流式计算引擎提供的默认(甚至是唯一)计算模式
|
||||
|
||||
2. 重新计算:从 TSDB 中重新查找对应窗口的所有数据并重新计算得到最新结果
|
||||
|
||||
无论在哪种模式下,watermark 都应该被妥善设置,来得到正确结果(直接丢弃模式)或避免频繁触发重算带来的性能开销(重新计算模式)。
|
||||
|
||||
## 流式计算的数据填充策略
|
||||
|
||||
TODO
|
||||
|
||||
## 流式计算与会话窗口(session window)
|
||||
|
||||
```sql
|
||||
window_clause: {
|
||||
SESSION(ts_col, tol_val)
|
||||
| STATE_WINDOW(col)
|
||||
| INTERVAL(interval_val [, interval_offset]) [SLIDING (sliding_val)] [FILL(fill_mod_and_val)]
|
||||
}
|
||||
```
|
||||
|
||||
其中,SESSION 是会话窗口,tol_val 是时间间隔的最大范围。在 tol_val 时间间隔范围内的数据都属于同一个窗口,如果连续的两条数据的时间超过 tol_val,则自动开启下一个窗口。
|
||||
|
||||
## 流式计算的监控与流任务分布查询
|
||||
|
||||
TODO
|
||||
|
||||
## 流式计算的内存控制与存算分离
|
||||
|
||||
TODO
|
||||
|
||||
## 流式计算的暂停与恢复
|
||||
|
||||
```sql
|
||||
STOP STREAM stream_name;
|
||||
|
||||
RESUME STREAM stream_name;
|
||||
```
|
|
@ -0,0 +1,59 @@
|
|||
---
|
||||
sidebar_label: 命名与边界限制
|
||||
title: 命名与边界限制
|
||||
---
|
||||
|
||||
## 名称命名规则
|
||||
|
||||
1. 合法字符:英文字符、数字和下划线
|
||||
2. 允许英文字符或下划线开头,不允许以数字开头
|
||||
3. 不区分大小写
|
||||
4. 转义后表(列)名规则:
|
||||
为了兼容支持更多形式的表(列)名,TDengine 引入新的转义符 "`"。可用让表名与关键词不冲突,同时不受限于上述表名称合法性约束检查
|
||||
转义后的表(列)名同样受到长度限制要求,且长度计算的时候不计算转义符。使用转义字符以后,不再对转义字符中的内容进行大小写统一
|
||||
|
||||
例如:\`aBc\` 和 \`abc\` 是不同的表(列)名,但是 abc 和 aBc 是相同的表(列)名。
|
||||
需要注意的是转义字符中的内容必须是可打印字符。
|
||||
|
||||
## 密码合法字符集
|
||||
|
||||
`[a-zA-Z0-9!?$%^&*()_–+={[}]:;@~#|<,>.?/]`
|
||||
|
||||
去掉了 `` ‘“`\ `` (单双引号、撇号、反斜杠、空格)
|
||||
|
||||
## 一般限制
|
||||
|
||||
- 数据库名最大长度为 32
|
||||
- 表名最大长度为 192,不包括数据库名前缀和分隔符
|
||||
- 每行数据最大长度 48KB (注意:数据行内每个 BINARY/NCHAR 类型的列还会额外占用 2 个字节的存储位置)
|
||||
- 列名最大长度为 64
|
||||
- 最多允许 4096 列,最少需要 2 列,第一列必须是时间戳。
|
||||
- 标签名最大长度为 64
|
||||
- 最多允许 128 个,至少要有 1 个标签,一个表中标签值的总长度不超过 16KB
|
||||
- SQL 语句最大长度 1048576 个字符,也可通过客户端配置参数 maxSQLLength 修改,取值范围 65480 ~ 1048576
|
||||
- SELECT 语句的查询结果,最多允许返回 4096 列(语句中的函数调用可能也会占用一些列空间),超限时需要显式指定较少的返回数据列,以避免语句执行报错
|
||||
- 库的数目,超级表的数目、表的数目,系统不做限制,仅受系统资源限制
|
||||
- 数据库的副本数只能设置为 1 或 3
|
||||
- 用户名的最大长度是 23 个字节
|
||||
- 用户密码的最大长度是 15 个字节
|
||||
- 总数据行数取决于可用资源
|
||||
- 单个数据库的虚拟结点数上限为 1024
|
||||
|
||||
## 表(列)名合法性说明
|
||||
|
||||
### TDengine 中的表(列)名命名规则如下:
|
||||
|
||||
只能由字母、数字、下划线构成,数字不能在首位,长度不能超过 192 字节,不区分大小写。这里表名称不包括数据库名的前缀和分隔符。
|
||||
|
||||
### 转义后表(列)名规则:
|
||||
|
||||
为了兼容支持更多形式的表(列)名,TDengine 引入新的转义符 "`",可以避免表名与关键词的冲突,同时不受限于上述表名合法性约束检查,转义符不计入表名的长度。
|
||||
转义后的表(列)名同样受到长度限制要求,且长度计算的时候不计算转义符。使用转义字符以后,不再对转义字符中的内容进行大小写统一。
|
||||
|
||||
例如:
|
||||
\`aBc\` 和 \`abc\` 是不同的表(列)名,但是 abc 和 aBc 是相同的表(列)名。
|
||||
|
||||
:::note
|
||||
转义字符中的内容必须是可打印字符。
|
||||
|
||||
:::
|
|
@ -0,0 +1,154 @@
|
|||
---
|
||||
sidebar_label: 集群管理
|
||||
title: 集群管理
|
||||
---
|
||||
|
||||
组成 TDengine 集群的物理实体是 dnode (data node 的缩写),它是一个运行在操作系统之上的进程。在 dnode 中可以建立负责时序数据存储的 vnode (virtual node),在多节点集群环境下当某个数据库的 replica 为 3 时,该数据库中的每个 vgroup 由 3 个 vnode 组成;当数据库的 replica 为 1 时,该数据库中的每个 vgroup 由 1 个 vnode 组成。如果要想配置某个数据库为多副本,则集群中的 dnode 数量至少为 3。在 dnode 还可以创建 mnode (management node),单个集群中最多可以创建三个 mnode。在 TDengine 3.0.0.0 中为了支持存算分离,引入了一种新的逻辑节点 qnode (query node),qnode 和 vnode 既可以共存在一个 dnode 中,也可以完全分离在不同的 dnode 上。
|
||||
|
||||
## 创建数据节点
|
||||
|
||||
```sql
|
||||
CREATE DNODE {dnode_endpoint | dnode_host_name PORT port_val}
|
||||
```
|
||||
|
||||
其中 `dnode_endpoint` 是形成 `hostname:port`的格式。也可以分开指定 hostname 和 port。
|
||||
|
||||
实际操作中推荐先创建 dnode,再启动相应的 dnode 进程,这样该 dnode 就可以立即根据其配置文件中的 firstEP 加入集群。每个 dnode 在加入成功后都会被分配一个 ID。
|
||||
|
||||
## 查看数据节点
|
||||
|
||||
```sql
|
||||
SHOW DNODES;
|
||||
```
|
||||
|
||||
可以列出集群中所有的数据节点,所列出的字段有 dnode 的 ID, endpoint, status。
|
||||
|
||||
## 删除数据节点
|
||||
|
||||
```sql
|
||||
DROP DNODE {dnode_id | dnode_endpoint}
|
||||
```
|
||||
|
||||
可以用 dnoe_id 或 endpoint 两种方式从集群中删除一个 dnode。注意删除 dnode 不等于停止相应的进程。实际中推荐先将一个 dnode 删除之后再停止其所对应的进程。
|
||||
|
||||
## 修改数据节点配置
|
||||
|
||||
```sql
|
||||
ALTER DNODE dnode_id dnode_option
|
||||
|
||||
ALTER ALL DNODES dnode_option
|
||||
|
||||
dnode_option: {
|
||||
'resetLog'
|
||||
| 'balance' value
|
||||
| 'monitor' value
|
||||
| 'debugFlag' value
|
||||
| 'monDebugFlag' value
|
||||
| 'vDebugFlag' value
|
||||
| 'mDebugFlag' value
|
||||
| 'cDebugFlag' value
|
||||
| 'httpDebugFlag' value
|
||||
| 'qDebugflag' value
|
||||
| 'sdbDebugFlag' value
|
||||
| 'uDebugFlag' value
|
||||
| 'tsdbDebugFlag' value
|
||||
| 'sDebugflag' value
|
||||
| 'rpcDebugFlag' value
|
||||
| 'dDebugFlag' value
|
||||
| 'mqttDebugFlag' value
|
||||
| 'wDebugFlag' value
|
||||
| 'tmrDebugFlag' value
|
||||
| 'cqDebugFlag' value
|
||||
}
|
||||
```
|
||||
|
||||
上面语法中的这些可修改配置项其配置方式与 dnode 配置文件中的配置方式相同,区别是修改是动态的立即生效,且不需要重启 dnode。
|
||||
|
||||
## 添加管理节点
|
||||
|
||||
```sql
|
||||
CREATE MNODE ON DNODE dnode_id
|
||||
```
|
||||
|
||||
系统启动默认在 firstEP 节点上创建一个 MNODE,用户可以使用此语句创建更多的 MNODE 来提高系统可用性。一个集群最多存在三个 MNODE,一个 DNODE 上只能创建一个 MNODE。
|
||||
|
||||
## 查看管理节点
|
||||
|
||||
```sql
|
||||
SHOW MNODES;
|
||||
```
|
||||
|
||||
列出集群中所有的管理节点,包括其 ID,所在 DNODE 以及状态。
|
||||
|
||||
## 删除管理节点
|
||||
|
||||
```sql
|
||||
DROP MNODE ON DNODE dnode_id;
|
||||
```
|
||||
|
||||
删除 dnode_id 所指定的 DNODE 上的 MNODE。
|
||||
|
||||
## 创建查询节点
|
||||
|
||||
```sql
|
||||
CREATE QNODE ON DNODE dnode_id;
|
||||
```
|
||||
|
||||
系统启动默认没有 QNODE,用户可以创建 QNODE 来实现计算和存储的分离。一个 DNODE 上只能创建一个 QNODE。一个 DNODE 的 `supportVnodes` 参数如果不为 0,同时又在其上创建上 QNODE,则在该 dnode 中既有负责存储管理的 vnode 又有负责查询计算的 qnode,如果还在该 dnode 上创建了 mnode,则一个 dnode 上最多三种逻辑节点都可以存在。但通过配置也可以使其彻底分离。将一个 dnode 的`supportVnodes`配置为 0,可以选择在其上创建 mnode 或者 qnode 中的一种,这样可以实现三种逻辑节点在物理上的彻底分离。
|
||||
|
||||
## 查看查询节点
|
||||
|
||||
```sql
|
||||
SHOW QNODES;
|
||||
```
|
||||
|
||||
列出集群中所有查询节点,包括 ID,及所在 DNODE。
|
||||
|
||||
## 删除查询节点
|
||||
|
||||
```sql
|
||||
DROP QNODE ON DNODE dnode_id;
|
||||
```
|
||||
|
||||
删除 ID 为 dnode_id 的 DNODE 上的 QNODE,但并不会影响该 dnode 的状态。
|
||||
|
||||
## 修改客户端配置
|
||||
|
||||
如果将客户端也看作广义的集群的一部分,可以通过如下命令动态修改客户端配置参数。
|
||||
|
||||
```sql
|
||||
ALTER LOCAL local_option
|
||||
|
||||
local_option: {
|
||||
'resetLog'
|
||||
| 'rpcDebugFlag' value
|
||||
| 'tmrDebugFlag' value
|
||||
| 'cDebugFlag' value
|
||||
| 'uDebugFlag' value
|
||||
| 'debugFlag' value
|
||||
}
|
||||
```
|
||||
|
||||
上面语法中的参数与在配置文件中配置客户端的用法相同,但不需要重启客户端,修改后立即生效。
|
||||
|
||||
## 查看客户端配置
|
||||
|
||||
```sql
|
||||
SHOW LOCAL VARIABLES;
|
||||
```
|
||||
|
||||
## 合并 vgroup
|
||||
|
||||
```sql
|
||||
MERGE VGROUP vgroup_no1 vgroup_no2;
|
||||
```
|
||||
|
||||
如果在系统实际运行一段时间后,因为不同时间线的数据特征不同导致在 vgroups 之间的数据和负载分布不均衡,可以通过合并或拆分 vgroups 的方式逐步实现负载均衡。
|
||||
|
||||
## 拆分 vgroup
|
||||
|
||||
```sql
|
||||
SPLIT VGROUP vgroup_no;
|
||||
```
|
||||
|
||||
会创建一个新的 vgroup,并将指定 vgroup 中的数据按照一致性 HASH 迁移一部分到新的 vgroup 中。此过程中,原 vgroup 可以正常提供读写服务。
|
|
@ -0,0 +1,247 @@
|
|||
---
|
||||
sidebar_label: 元数据库
|
||||
title: 元数据库
|
||||
---
|
||||
|
||||
TDengine 内置了一个名为 `INFORMATION_SCHEMA` 的数据库,提供对数据库元数据、数据库系统信息和状态的访问,例如数据库或表的名称,当前执行的 SQL 语句等。该数据库存储有关 TDengine 维护的所有其他数据库的信息。它包含多个只读表。实际上,这些表都是视图,而不是基表,因此没有与它们关联的文件。所以对这些表只能查询,不能进行 INSERT 等写入操作。`INFORMATION_SCHEMA` 数据库旨在以一种更一致的方式来提供对 TDengine 支持的各种 SHOW 语句(如 SHOW TABLES、SHOW DATABASES)所提供的信息的访问。与 SHOW 语句相比,使用 SELECT ... FROM INFORMATION_SCHEMA.tablename 具有以下优点:
|
||||
|
||||
1. 可以使用 USE 语句将 INFORMATION_SCHEMA 设为默认数据库
|
||||
2. 可以使用 SELECT 语句熟悉的语法,只需要学习一些表名和列名
|
||||
3. 可以对查询结果进行筛选、排序等操作。事实上,可以使用任意 TDengine 支持的 SELECT 语句对 INFORMATION_SCHEMA 中的表进行查询
|
||||
4. TDengine 在后续演进中可以灵活的添加已有 INFORMATION_SCHEMA 中表的列,而不用担心对既有业务系统造成影响
|
||||
5. 与其他数据库系统更具互操作性。例如,Oracle 数据库用户熟悉查询 Oracle 数据字典中的表
|
||||
|
||||
Note: 由于 SHOW 语句已经被开发者熟悉和广泛使用,所以它们仍然被保留。
|
||||
|
||||
本章将详细介绍 `INFORMATION_SCHEMA` 这个内置元数据库中的表和表结构。
|
||||
|
||||
## INS_DNODES
|
||||
|
||||
提供 dnode 的相关信息。也可以使用 SHOW DNODES 来查询这些信息。
|
||||
|
||||
| # | **列名** | **数据类型** | **说明** |
|
||||
| --- | :------------: | ------------ | ------------------------- |
|
||||
| 1 | vnodes | SMALLINT | dnode 中的实际 vnode 个数 |
|
||||
| 2 | support_vnodes | SMALLINT | 最多支持的 vnode 个数 |
|
||||
| 3 | status | BINARY(10) | 当前状态 |
|
||||
| 4 | note | BINARY(256) | 离线原因等信息 |
|
||||
| 5 | id | SMALLINT | dnode id |
|
||||
| 6 | endpoint | BINARY(134) | dnode 的地址 |
|
||||
| 7 | create | TIMESTAMP | 创建时间 |
|
||||
|
||||
## INS_MNODES
|
||||
|
||||
提供 mnode 的相关信息。也可以使用 SHOW MNODES 来查询这些信息。
|
||||
|
||||
| # | **列名** | **数据类型** | **说明** |
|
||||
| --- | :---------: | ------------ | ------------------ |
|
||||
| 1 | id | SMALLINT | mnode id |
|
||||
| 2 | endpoint | BINARY(134) | mnode 的地址 |
|
||||
| 3 | role | BINARY(10) | 当前角色 |
|
||||
| 4 | role_time | TIMESTAMP | 成为当前角色的时间 |
|
||||
| 5 | create_time | TIMESTAMP | 创建时间 |
|
||||
|
||||
## INS_MODULES
|
||||
|
||||
提供组件的相关信息。也可以使用 SHOW MODULES 来查询这些信息
|
||||
|
||||
| # | **列名** | **数据类型** | **说明** |
|
||||
| --- | :------: | ------------ | ---------- |
|
||||
| 1 | id | SMALLINT | module id |
|
||||
| 2 | endpoint | BINARY(134) | 组件的地址 |
|
||||
| 3 | module | BINARY(10) | 组件状态 |
|
||||
|
||||
## INS_QNODES
|
||||
|
||||
当前系统中 QNODE 的信息。也可以使用 SHOW QNODES 来查询这些信息。
|
||||
|
||||
| # | **列名** | **数据类型** | **说明** |
|
||||
| --- | :---------: | ------------ | ------------ |
|
||||
| 1 | id | SMALLINT | qnode id |
|
||||
| 2 | endpoint | BINARY(134) | qnode 的地址 |
|
||||
| 3 | create_time | TIMESTAMP | 创建时间 |
|
||||
|
||||
## INS_CLUSTER
|
||||
|
||||
存储集群相关信息。
|
||||
|
||||
| # | **列名** | **数据类型** | **说明** |
|
||||
| --- | :---------: | ------------ | ---------- |
|
||||
| 1 | id | BIGINT | cluster id |
|
||||
| 2 | name | BINARY(134) | 集群名称 |
|
||||
| 3 | create_time | TIMESTAMP | 创建时间 |
|
||||
|
||||
## INS_DATABASES
|
||||
|
||||
提供用户创建的数据库对象的相关信息。也可以使用 SHOW DATABASES 来查询这些信息。
|
||||
|
||||
| # | **列名** | **数据类型** | **说明** |
|
||||
| --- | :------------------: | ---------------- | ------------------------------------------------ |
|
||||
| 1 | name | BINARY(32) | 数据库名 |
|
||||
| 2 | create_time | TIMESTAMP | 创建时间 |
|
||||
| 3 | ntables | INT | 数据库中表的数量,包含子表和普通表但不包含超级表 |
|
||||
| 4 | vgroups | INT | 数据库中有多少个 vgroup |
|
||||
| 6 | replica | INT | 副本数 |
|
||||
| 7 | quorum | BINARY(3) | 强一致性 |
|
||||
| 8 | duration | INT | 单文件存储数据的时间跨度 |
|
||||
| 9 | keep | INT | 数据保留时长 |
|
||||
| 10 | buffer | INT | 每个 vnode 写缓存的内存块大小,单位 MB |
|
||||
| 11 | pagesize | INT | 每个 VNODE 中元数据存储引擎的页大小,单位为 KB |
|
||||
| 12 | pages | INT | 每个 vnode 元数据存储引擎的缓存页个数 |
|
||||
| 13 | minrows | INT | 文件块中记录的最大条数 |
|
||||
| 14 | maxrows | INT | 文件块中记录的最小条数 |
|
||||
| 15 | comp | INT | 数据压缩方式 |
|
||||
| 16 | precision | BINARY(2) | 时间分辨率 |
|
||||
| 17 | status | BINARY(10) | 数据库状态 |
|
||||
| 18 | retention | BINARY (60) | 数据的聚合周期和保存时长 |
|
||||
| 19 | single_stable | BOOL | 表示此数据库中是否只可以创建一个超级表 |
|
||||
| 20 | cachemodel | BINARY(60) | 表示是否在内存中缓存子表的最近数据 |
|
||||
| 21 | cachesize | INT | 表示每个 vnode 中用于缓存子表最近数据的内存大小 |
|
||||
| 22 | wal_level | INT | WAL 级别 |
|
||||
| 23 | wal_fsync_period | INT | 数据落盘周期 |
|
||||
| 24 | wal_retention_period | INT | WAL 的保存时长 |
|
||||
| 25 | wal_retention_size | INT | WAL 的保存上限 |
|
||||
| 26 | wal_roll_period | INT | wal 文件切换时长 |
|
||||
| 27 | wal_segment_size | wal 单个文件大小 |
|
||||
|
||||
## INS_FUNCTIONS
|
||||
|
||||
用户创建的自定义函数的信息。
|
||||
|
||||
| # | **列名** | **数据类型** | **说明** |
|
||||
| --- | :---------: | ------------ | -------------- |
|
||||
| 1 | name | BINARY(64) | 函数名 |
|
||||
| 2 | comment | BINARY(255) | 补充说明 |
|
||||
| 3 | aggregate | INT | 是否为聚合函数 |
|
||||
| 4 | output_type | BINARY(31) | 输出类型 |
|
||||
| 5 | create_time | TIMESTAMP | 创建时间 |
|
||||
| 6 | code_len | INT | 代码长度 |
|
||||
| 7 | bufsize | INT | buffer 大小 |
|
||||
|
||||
## INS_INDEXES
|
||||
|
||||
提供用户创建的索引的相关信息。也可以使用 SHOW INDEX 来查询这些信息。
|
||||
|
||||
| # | **列名** | **数据类型** | **说明** |
|
||||
| --- | :--------------: | ------------ | ---------------------------------------------------------------------------------- |
|
||||
| 1 | db_name | BINARY(32) | 包含此索引的表所在的数据库名 |
|
||||
| 2 | table_name | BINARY(192) | 包含此索引的表的名称 |
|
||||
| 3 | index_name | BINARY(192) | 索引名 |
|
||||
| 4 | column_name | BINARY(64) | 建索引的列的列名 |
|
||||
| 5 | index_type | BINARY(10) | 目前有 SMA 和 FULLTEXT |
|
||||
| 6 | index_extensions | BINARY(256) | 索引的额外信息。对 SMA 类型的索引,是函数名的列表。对 FULLTEXT 类型的索引为 NULL。 |
|
||||
|
||||
## INS_STABLES
|
||||
|
||||
提供用户创建的超级表的相关信息。
|
||||
|
||||
| # | **列名** | **数据类型** | **说明** |
|
||||
| --- | :-----------: | ------------ | ------------------------ |
|
||||
| 1 | stable_name | BINARY(192) | 超级表表名 |
|
||||
| 2 | db_name | BINARY(64) | 超级表所在的数据库的名称 |
|
||||
| 3 | create_time | TIMESTAMP | 创建时间 |
|
||||
| 4 | columns | INT | 列数目 |
|
||||
| 5 | tags | INT | 标签数目 |
|
||||
| 6 | last_update | TIMESTAMP | 最后更新时间 |
|
||||
| 7 | table_comment | BINARY(1024) | 表注释 |
|
||||
| 8 | watermark | BINARY(64) | 窗口的关闭时间 |
|
||||
| 9 | max_delay | BINARY(64) | 推送计算结果的最大延迟 |
|
||||
| 10 | rollup | BINARY(128) | rollup 聚合函数 |
|
||||
|
||||
## INS_TABLES
|
||||
|
||||
提供用户创建的普通表和子表的相关信息
|
||||
|
||||
| # | **列名** | **数据类型** | **说明** |
|
||||
| --- | :-----------: | ------------ | ---------------- |
|
||||
| 1 | table_name | BINARY(192) | 表名 |
|
||||
| 2 | db_name | BINARY(64) | 数据库名 |
|
||||
| 3 | create_time | TIMESTAMP | 创建时间 |
|
||||
| 4 | columns | INT | 列数目 |
|
||||
| 5 | stable_name | BINARY(192) | 所属的超级表表名 |
|
||||
| 6 | uid | BIGINT | 表 id |
|
||||
| 7 | vgroup_id | INT | vgroup id |
|
||||
| 8 | ttl | INT | 表的生命周期 |
|
||||
| 9 | table_comment | BINARY(1024) | 表注释 |
|
||||
| 10 | type | BINARY(20) | 表类型 |
|
||||
|
||||
## INS_TAGS
|
||||
|
||||
| # | **列名** | **数据类型** | **说明** |
|
||||
| --- | :---------: | ------------- | ---------------------- |
|
||||
| 1 | table_name | BINARY(192) | 表名 |
|
||||
| 2 | db_name | BINARY(64) | 该表所在的数据库的名称 |
|
||||
| 3 | stable_name | BINARY(192) | 所属的超级表表名 |
|
||||
| 4 | tag_name | BINARY(64) | tag 的名称 |
|
||||
| 5 | tag_type | BINARY(64) | tag 的类型 |
|
||||
| 6 | tag_value | BINARY(16384) | tag 的值 |
|
||||
|
||||
## INS_USERS
|
||||
|
||||
提供系统中创建的用户的相关信息。
|
||||
|
||||
| # | **列名** | **数据类型** | **说明** |
|
||||
| --- | :---------: | ------------ | -------- |
|
||||
| 1 | user_name | BINARY(23) | 用户名 |
|
||||
| 2 | privilege | BINARY(256) | 权限 |
|
||||
| 3 | create_time | TIMESTAMP | 创建时间 |
|
||||
|
||||
## INS_GRANTS
|
||||
|
||||
提供企业版授权的相关信息。
|
||||
|
||||
| # | **列名** | **数据类型** | **说明** |
|
||||
| --- | :---------: | ------------ | -------------------------------------------------- |
|
||||
| 1 | version | BINARY(9) | 企业版授权说明:official(官方授权的)/trial(试用的) |
|
||||
| 2 | cpu_cores | BINARY(9) | 授权使用的 CPU 核心数量 |
|
||||
| 3 | dnodes | BINARY(10) | 授权使用的 dnode 节点数量 |
|
||||
| 4 | streams | BINARY(10) | 授权创建的流数量 |
|
||||
| 5 | users | BINARY(10) | 授权创建的用户数量 |
|
||||
| 6 | accounts | BINARY(10) | 授权创建的帐户数量 |
|
||||
| 7 | storage | BINARY(21) | 授权使用的存储空间大小 |
|
||||
| 8 | connections | BINARY(21) | 授权使用的客户端连接数量 |
|
||||
| 9 | databases | BINARY(11) | 授权使用的数据库数量 |
|
||||
| 10 | speed | BINARY(9) | 授权使用的数据点每秒写入数量 |
|
||||
| 11 | querytime | BINARY(9) | 授权使用的查询总时长 |
|
||||
| 12 | timeseries | BINARY(21) | 授权使用的测点数量 |
|
||||
| 13 | expired | BINARY(5) | 是否到期,true:到期,false:未到期 |
|
||||
| 14 | expire_time | BINARY(19) | 试用期到期时间 |
|
||||
|
||||
## INS_VGROUPS
|
||||
|
||||
系统中所有 vgroups 的信息。
|
||||
|
||||
| # | **列名** | **数据类型** | **说明** |
|
||||
| --- | :-------: | ------------ | ------------------------------------------------------ |
|
||||
| 1 | vgroup_id | INT | vgroup id |
|
||||
| 2 | db_name | BINARY(32) | 数据库名 |
|
||||
| 3 | tables | INT | 此 vgroup 内有多少表 |
|
||||
| 4 | status | BINARY(10) | 此 vgroup 的状态 |
|
||||
| 5 | v1_dnode | INT | 第一个成员所在的 dnode 的 id |
|
||||
| 6 | v1_status | BINARY(10) | 第一个成员的状态 |
|
||||
| 7 | v2_dnode | INT | 第二个成员所在的 dnode 的 id |
|
||||
| 8 | v2_status | BINARY(10) | 第二个成员的状态 |
|
||||
| 9 | v3_dnode | INT | 第三个成员所在的 dnode 的 id |
|
||||
| 10 | v3_status | BINARY(10) | 第三个成员的状态 |
|
||||
| 11 | nfiles | INT | 此 vgroup 中数据/元数据文件的数量 |
|
||||
| 12 | file_size | INT | 此 vgroup 中数据/元数据文件的大小 |
|
||||
| 13 | tsma | TINYINT | 此 vgroup 是否专用于 Time-range-wise SMA,1: 是, 0: 否 |
|
||||
|
||||
## INS_CONFIGS
|
||||
|
||||
系统配置参数。
|
||||
|
||||
| # | **列名** | **数据类型** | **说明** |
|
||||
| --- | :------: | ------------ | ------------ |
|
||||
| 1 | name | BINARY(32) | 配置项名称 |
|
||||
| 2 | value | BINARY(64) | 该配置项的值 |
|
||||
|
||||
## INS_DNODE_VARIABLES
|
||||
|
||||
系统中每个 dnode 的配置参数。
|
||||
|
||||
| # | **列名** | **数据类型** | **说明** |
|
||||
| --- | :------: | ------------ | ------------ |
|
||||
| 1 | dnode_id | INT | dnode 的 ID |
|
||||
| 2 | name | BINARY(32) | 配置项名称 |
|
||||
| 3 | value | BINARY(64) | 该配置项的值 |
|
|
@ -0,0 +1,94 @@
|
|||
---
|
||||
sidebar_label: 权限管理
|
||||
title: 权限管理
|
||||
---
|
||||
|
||||
本节讲述如何在 TDengine 中进行权限管理的相关操作。
|
||||
|
||||
## 创建用户
|
||||
|
||||
```sql
|
||||
CREATE USER use_name PASS password;
|
||||
```
|
||||
|
||||
创建用户。
|
||||
|
||||
use_name最长为23字节。
|
||||
|
||||
password最长为128字节,合法字符包括"a-zA-Z0-9!?$%^&*()_–+={[}]:;@~#|<,>.?/",不可以出现单双引号、撇号、反斜杠和空格,且不可以为空。
|
||||
|
||||
## 删除用户
|
||||
|
||||
```sql
|
||||
DROP USER user_name;
|
||||
```
|
||||
|
||||
## 修改用户信息
|
||||
|
||||
```sql
|
||||
ALTER USER user_name alter_user_clause
|
||||
|
||||
alter_user_clause: {
|
||||
PASS 'literal'
|
||||
| ENABLE value
|
||||
| SYSINFO value
|
||||
}
|
||||
```
|
||||
|
||||
- PASS:修改用户密码。
|
||||
- ENABLE:修改用户是否启用。1表示启用此用户,0表示禁用此用户。
|
||||
- SYSINFO:修改用户是否可查看系统信息。1表示可以查看系统信息,0表示不可以查看系统信息。
|
||||
|
||||
|
||||
## 授权
|
||||
|
||||
```sql
|
||||
GRANT privileges ON priv_level TO user_name
|
||||
|
||||
privileges : {
|
||||
ALL
|
||||
| priv_type [, priv_type] ...
|
||||
}
|
||||
|
||||
priv_type : {
|
||||
READ
|
||||
| WRITE
|
||||
}
|
||||
|
||||
priv_level : {
|
||||
dbname.*
|
||||
| *.*
|
||||
}
|
||||
```
|
||||
|
||||
对用户授权。
|
||||
|
||||
授权级别支持到DATABASE,权限有READ和WRITE两种。
|
||||
|
||||
TDengine 有超级用户和普通用户两类用户。超级用户缺省创建为root,拥有所有权限。使用超级用户创建出来的用户为普通用户。在未授权的情况下,普通用户可以创建DATABASE,并拥有自己创建的DATABASE的所有权限,包括删除数据库、修改数据库、查询时序数据和写入时序数据。超级用户可以给普通用户授予其他DATABASE的读写权限,使其可以在此DATABASE上读写数据,但不能对其进行删除和修改数据库的操作。
|
||||
|
||||
对于非DATABASE的对象,如USER、DNODE、UDF、QNODE等,普通用户只有读权限(一般为SHOW命令),不能创建和修改。
|
||||
|
||||
## 撤销授权
|
||||
|
||||
```sql
|
||||
REVOKE privileges ON priv_level FROM user_name
|
||||
|
||||
privileges : {
|
||||
ALL
|
||||
| priv_type [, priv_type] ...
|
||||
}
|
||||
|
||||
priv_type : {
|
||||
READ
|
||||
| WRITE
|
||||
}
|
||||
|
||||
priv_level : {
|
||||
dbname.*
|
||||
| *.*
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
收回对用户的授权。
|
|
@ -0,0 +1,28 @@
|
|||
---
|
||||
sidebar_label: 自定义函数
|
||||
title: 用户自定义函数
|
||||
---
|
||||
|
||||
除了 TDengine 的内置函数以外,用户还可以编写自己的函数逻辑并加入TDengine系统中。
|
||||
|
||||
## 创建函数
|
||||
|
||||
```sql
|
||||
CREATE [AGGREGATE] FUNCTION func_name AS library_path OUTPUTTYPE type_name [BUFSIZE value]
|
||||
```
|
||||
|
||||
语法说明:
|
||||
|
||||
AGGREGATE:标识此函数是标量函数还是聚集函数。
|
||||
func_name:函数名,必须与函数实现中udfNormalFunc的实际名称一致。
|
||||
library_path:包含UDF函数实现的动态链接库的绝对路径,是在客户端侧主机上的绝对路径。
|
||||
OUTPUTTYPE:标识此函数的返回类型。
|
||||
BUFSIZE:中间结果的缓冲区大小,单位是字节。不设置则默认为0。最大不可超过512字节。
|
||||
|
||||
关于如何开发自定义函数,请参考 [UDF使用说明](../../develop/udf)。
|
||||
|
||||
## 删除自定义函数
|
||||
|
||||
```sql
|
||||
DROP FUNCTION func_name
|
||||
```
|
|
@ -0,0 +1,47 @@
|
|||
---
|
||||
sidebar_label: 索引
|
||||
title: 使用索引
|
||||
---
|
||||
|
||||
TDengine 从 3.0.0.0 版本开始引入了索引功能,支持 SMA 索引和 FULLTEXT 索引。
|
||||
|
||||
## 创建索引
|
||||
|
||||
```sql
|
||||
CREATE FULLTEXT INDEX index_name ON tb_name (col_name [, col_name] ...)
|
||||
|
||||
CREATE SMA INDEX index_name ON tb_name index_option
|
||||
|
||||
index_option:
|
||||
FUNCTION(functions) INTERVAL(interval_val [, interval_offset]) [SLIDING(sliding_val)] [WATERMARK(watermark_val)] [MAX_DELAY(max_delay_val)]
|
||||
|
||||
functions:
|
||||
function [, function] ...
|
||||
```
|
||||
|
||||
### SMA 索引
|
||||
|
||||
对指定列按 INTERVAL 子句定义的时间窗口创建进行预聚合计算,预聚合计算类型由 functions_string 指定。SMA 索引能提升指定时间段的聚合查询的性能。目前,限制一个超级表只能创建一个 SMA INDEX。
|
||||
|
||||
- 支持的函数包括 MAX、MIN 和 SUM。
|
||||
- WATERMARK: 最小单位毫秒,取值范围 [0ms, 900000ms],默认值为 5 秒,只可用于超级表。
|
||||
- MAX_DELAY: 最小单位毫秒,取值范围 [1ms, 900000ms],默认值为 interval 的值(但不能超过最大值),只可用于超级表。注:不建议 MAX_DELAY 设置太小,否则会过于频繁的推送结果,影响存储和查询性能,如无特殊需求,取默认值即可。
|
||||
|
||||
### FULLTEXT 索引
|
||||
|
||||
对指定列建立文本索引,可以提升含有文本过滤的查询的性能。FULLTEXT 索引不支持 index_option 语法。现阶段只支持对 JSON 类型的标签列创建 FULLTEXT 索引。不支持多列联合索引,但可以为每个列分布创建 FULLTEXT 索引。
|
||||
|
||||
## 删除索引
|
||||
|
||||
```sql
|
||||
DROP INDEX index_name;
|
||||
```
|
||||
|
||||
## 查看索引
|
||||
|
||||
````sql
|
||||
```sql
|
||||
SHOW INDEXES FROM tbl_name [FROM db_name];
|
||||
````
|
||||
|
||||
显示在所指定的数据库或表上已创建的索引。
|
|
@ -0,0 +1,38 @@
|
|||
---
|
||||
sidebar_label: 异常恢复
|
||||
title: 异常恢复
|
||||
---
|
||||
|
||||
在一个复杂的应用场景中,连接和查询任务等有可能进入一种错误状态或者耗时过长迟迟无法结束,此时需要有能够终止这些连接或任务的方法。
|
||||
|
||||
## 终止连接
|
||||
|
||||
```sql
|
||||
KILL CONNECTION conn_id;
|
||||
```
|
||||
|
||||
conn_id 可以通过 `SHOW CONNECTIONS` 获取。
|
||||
|
||||
## 终止查询
|
||||
|
||||
```sql
|
||||
SHOW QUERY query_id;
|
||||
```
|
||||
|
||||
query_id 可以通过 `SHOW QUERIES` 获取。
|
||||
|
||||
## 终止事务
|
||||
|
||||
```sql
|
||||
KILL TRANSACTION trans_id
|
||||
```
|
||||
|
||||
trans_id 可以通过 `SHOW TRANSACTIONS` 获取。
|
||||
|
||||
## 重置客户端缓存
|
||||
|
||||
```sql
|
||||
RESET QUERY CACHE;
|
||||
```
|
||||
|
||||
如果在多客户端情况下出现元数据不同步的情况,可以用这条命令强制清空客户端缓存,随后客户端会从服务端拉取最新的元数据。
|
|
@ -1,4 +1,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using TDengineDriver;
|
||||
using TDengineDriver.Impl;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace TDengineExample
|
||||
|
@ -19,8 +22,8 @@ namespace TDengineExample
|
|||
{
|
||||
if (code == 0 && taosRes != IntPtr.Zero)
|
||||
{
|
||||
FetchRowAsyncCallback fetchRowAsyncCallback = new FetchRowAsyncCallback(FetchRowCallback);
|
||||
TDengine.FetchRowAsync(taosRes, fetchRowAsyncCallback, param);
|
||||
FetchRawBlockAsyncCallback fetchRowAsyncCallback = new FetchRawBlockAsyncCallback(FetchRawBlockCallback);
|
||||
TDengine.FetchRawBlockAsync(taosRes, fetchRowAsyncCallback, param);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -28,179 +31,44 @@ namespace TDengineExample
|
|||
}
|
||||
}
|
||||
|
||||
static void FetchRowCallback(IntPtr param, IntPtr taosRes, int numOfRows)
|
||||
// Iteratively call this interface until "numOfRows" is no greater than 0.
|
||||
static void FetchRawBlockCallback(IntPtr param, IntPtr taosRes, int numOfRows)
|
||||
{
|
||||
if (numOfRows > 0)
|
||||
{
|
||||
Console.WriteLine($"{numOfRows} rows async retrieved");
|
||||
DisplayRes(taosRes);
|
||||
TDengine.FetchRowAsync(taosRes, FetchRowCallback, param);
|
||||
IntPtr pdata = TDengine.GetRawBlock(taosRes);
|
||||
List<TDengineMeta> metaList = TDengine.FetchFields(taosRes);
|
||||
List<object> dataList = LibTaos.ReadRawBlock(pdata, metaList, numOfRows);
|
||||
|
||||
for (int i = 0; i < dataList.Count; i++)
|
||||
{
|
||||
if (i != 0 && (i+1) % metaList.Count == 0)
|
||||
{
|
||||
Console.WriteLine("{0}\t|", dataList[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.Write("{0}\t|", dataList[i]);
|
||||
}
|
||||
}
|
||||
Console.WriteLine("");
|
||||
TDengine.FetchRawBlockAsync(taosRes, FetchRawBlockCallback, param);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (numOfRows == 0)
|
||||
{
|
||||
Console.WriteLine("async retrieve complete.");
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"FetchRowAsync callback error, error code {numOfRows}");
|
||||
Console.WriteLine($"FetchRawBlockCallback callback error, error code {numOfRows}");
|
||||
}
|
||||
TDengine.FreeResult(taosRes);
|
||||
}
|
||||
}
|
||||
|
||||
public static void DisplayRes(IntPtr res)
|
||||
{
|
||||
if (!IsValidResult(res))
|
||||
{
|
||||
TDengine.Cleanup();
|
||||
System.Environment.Exit(1);
|
||||
}
|
||||
|
||||
List<TDengineMeta> metaList = TDengine.FetchFields(res);
|
||||
int fieldCount = metaList.Count;
|
||||
// metaList.ForEach((item) => { Console.Write("{0} ({1}) \t|\t", item.name, item.size); });
|
||||
|
||||
List<object> dataList = QueryRes(res, metaList);
|
||||
for (int index = 0; index < dataList.Count; index++)
|
||||
{
|
||||
if (index % fieldCount == 0 && index != 0)
|
||||
{
|
||||
Console.WriteLine("");
|
||||
}
|
||||
Console.Write("{0} \t|\t", dataList[index].ToString());
|
||||
|
||||
}
|
||||
Console.WriteLine("");
|
||||
}
|
||||
|
||||
public static bool IsValidResult(IntPtr res)
|
||||
{
|
||||
if ((res == IntPtr.Zero) || (TDengine.ErrorNo(res) != 0))
|
||||
{
|
||||
if (res != IntPtr.Zero)
|
||||
{
|
||||
Console.Write("reason: " + TDengine.Error(res));
|
||||
return false;
|
||||
}
|
||||
Console.WriteLine("");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static List<object> QueryRes(IntPtr res, List<TDengineMeta> meta)
|
||||
{
|
||||
IntPtr taosRow;
|
||||
List<object> dataRaw = new();
|
||||
while ((taosRow = TDengine.FetchRows(res)) != IntPtr.Zero)
|
||||
{
|
||||
dataRaw.AddRange(FetchRow(taosRow, res));
|
||||
}
|
||||
if (TDengine.ErrorNo(res) != 0)
|
||||
{
|
||||
Console.Write("Query is not complete, Error {0} {1}", TDengine.ErrorNo(res), TDengine.Error(res));
|
||||
}
|
||||
TDengine.FreeResult(res);
|
||||
Console.WriteLine("");
|
||||
return dataRaw;
|
||||
}
|
||||
|
||||
public static List<object> FetchRow(IntPtr taosRow, IntPtr taosRes)//, List<TDengineMeta> metaList, int numOfFiled
|
||||
{
|
||||
List<TDengineMeta> metaList = TDengine.FetchFields(taosRes);
|
||||
int numOfFiled = TDengine.FieldCount(taosRes);
|
||||
|
||||
|
||||
List<object> dataRaw = new();
|
||||
|
||||
IntPtr colLengthPrt = TDengine.FetchLengths(taosRes);
|
||||
int[] colLengthArr = new int[numOfFiled];
|
||||
Marshal.Copy(colLengthPrt, colLengthArr, 0, numOfFiled);
|
||||
|
||||
for (int i = 0; i < numOfFiled; i++)
|
||||
{
|
||||
TDengineMeta meta = metaList[i];
|
||||
IntPtr data = Marshal.ReadIntPtr(taosRow, IntPtr.Size * i);
|
||||
|
||||
if (data == IntPtr.Zero)
|
||||
{
|
||||
dataRaw.Add("NULL");
|
||||
continue;
|
||||
}
|
||||
switch ((TDengineDataType)meta.type)
|
||||
{
|
||||
case TDengineDataType.TSDB_DATA_TYPE_BOOL:
|
||||
bool v1 = Marshal.ReadByte(data) != 0;
|
||||
dataRaw.Add(v1);
|
||||
break;
|
||||
case TDengineDataType.TSDB_DATA_TYPE_TINYINT:
|
||||
sbyte v2 = (sbyte)Marshal.ReadByte(data);
|
||||
dataRaw.Add(v2);
|
||||
break;
|
||||
case TDengineDataType.TSDB_DATA_TYPE_SMALLINT:
|
||||
short v3 = Marshal.ReadInt16(data);
|
||||
dataRaw.Add(v3);
|
||||
break;
|
||||
case TDengineDataType.TSDB_DATA_TYPE_INT:
|
||||
int v4 = Marshal.ReadInt32(data);
|
||||
dataRaw.Add(v4);
|
||||
break;
|
||||
case TDengineDataType.TSDB_DATA_TYPE_BIGINT:
|
||||
long v5 = Marshal.ReadInt64(data);
|
||||
dataRaw.Add(v5);
|
||||
break;
|
||||
case TDengineDataType.TSDB_DATA_TYPE_FLOAT:
|
||||
float v6 = (float)Marshal.PtrToStructure(data, typeof(float));
|
||||
dataRaw.Add(v6);
|
||||
break;
|
||||
case TDengineDataType.TSDB_DATA_TYPE_DOUBLE:
|
||||
double v7 = (double)Marshal.PtrToStructure(data, typeof(double));
|
||||
dataRaw.Add(v7);
|
||||
break;
|
||||
case TDengineDataType.TSDB_DATA_TYPE_BINARY:
|
||||
string v8 = Marshal.PtrToStringUTF8(data, colLengthArr[i]);
|
||||
dataRaw.Add(v8);
|
||||
break;
|
||||
case TDengineDataType.TSDB_DATA_TYPE_TIMESTAMP:
|
||||
long v9 = Marshal.ReadInt64(data);
|
||||
dataRaw.Add(v9);
|
||||
break;
|
||||
case TDengineDataType.TSDB_DATA_TYPE_NCHAR:
|
||||
string v10 = Marshal.PtrToStringUTF8(data, colLengthArr[i]);
|
||||
dataRaw.Add(v10);
|
||||
break;
|
||||
case TDengineDataType.TSDB_DATA_TYPE_UTINYINT:
|
||||
byte v12 = Marshal.ReadByte(data);
|
||||
dataRaw.Add(v12.ToString());
|
||||
break;
|
||||
case TDengineDataType.TSDB_DATA_TYPE_USMALLINT:
|
||||
ushort v13 = (ushort)Marshal.ReadInt16(data);
|
||||
dataRaw.Add(v13);
|
||||
break;
|
||||
case TDengineDataType.TSDB_DATA_TYPE_UINT:
|
||||
uint v14 = (uint)Marshal.ReadInt32(data);
|
||||
dataRaw.Add(v14);
|
||||
break;
|
||||
case TDengineDataType.TSDB_DATA_TYPE_UBIGINT:
|
||||
ulong v15 = (ulong)Marshal.ReadInt64(data);
|
||||
dataRaw.Add(v15);
|
||||
break;
|
||||
case TDengineDataType.TSDB_DATA_TYPE_JSONTAG:
|
||||
string v16 = Marshal.PtrToStringUTF8(data, colLengthArr[i]);
|
||||
dataRaw.Add(v16);
|
||||
break;
|
||||
default:
|
||||
dataRaw.Add("nonsupport data type");
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
return dataRaw;
|
||||
}
|
||||
|
||||
static IntPtr GetConnection()
|
||||
{
|
||||
string host = "localhost";
|
||||
|
@ -223,16 +91,16 @@ namespace TDengineExample
|
|||
}
|
||||
}
|
||||
|
||||
//output:
|
||||
// Connect to TDengine success
|
||||
// 8 rows async retrieved
|
||||
// //output:
|
||||
// // Connect to TDengine success
|
||||
// // 8 rows async retrieved
|
||||
|
||||
// 1538548685500 | 11.8 | 221 | 0.28 | california.losangeles | 2 |
|
||||
// 1538548696600 | 13.4 | 223 | 0.29 | california.losangeles | 2 |
|
||||
// 1538548685000 | 10.8 | 223 | 0.29 | california.losangeles | 3 |
|
||||
// 1538548686500 | 11.5 | 221 | 0.35 | california.losangeles | 3 |
|
||||
// 1538548685000 | 10.3 | 219 | 0.31 | california.sanfrancisco | 2 |
|
||||
// 1538548695000 | 12.6 | 218 | 0.33 | california.sanfrancisco | 2 |
|
||||
// 1538548696800 | 12.3 | 221 | 0.31 | california.sanfrancisco | 2 |
|
||||
// 1538548696650 | 10.3 | 218 | 0.25 | california.sanfrancisco | 3 |
|
||||
// async retrieve complete.
|
||||
// // 1538548685500 | 11.8 | 221 | 0.28 | california.losangeles | 2 |
|
||||
// // 1538548696600 | 13.4 | 223 | 0.29 | california.losangeles | 2 |
|
||||
// // 1538548685000 | 10.8 | 223 | 0.29 | california.losangeles | 3 |
|
||||
// // 1538548686500 | 11.5 | 221 | 0.35 | california.losangeles | 3 |
|
||||
// // 1538548685000 | 10.3 | 219 | 0.31 | california.sanfrancisco | 2 |
|
||||
// // 1538548695000 | 12.6 | 218 | 0.33 | california.sanfrancisco | 2 |
|
||||
// // 1538548696800 | 12.3 | 221 | 0.31 | california.sanfrancisco | 2 |
|
||||
// // 1538548696650 | 10.3 | 218 | 0.25 | california.sanfrancisco | 3 |
|
||||
// // async retrieve complete.
|
|
@ -1,4 +1,5 @@
|
|||
using TDengineDriver;
|
||||
using TDengineDriver.Impl;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace TDengineExample
|
||||
|
@ -23,7 +24,7 @@ namespace TDengineExample
|
|||
Console.WriteLine("fieldCount=" + fieldCount);
|
||||
|
||||
// print column names
|
||||
List<TDengineMeta> metas = TDengine.FetchFields(res);
|
||||
List<TDengineMeta> metas = LibTaos.GetMeta(res);
|
||||
for (int i = 0; i < metas.Count; i++)
|
||||
{
|
||||
Console.Write(metas[i].name + "\t");
|
||||
|
@ -31,98 +32,17 @@ namespace TDengineExample
|
|||
Console.WriteLine();
|
||||
|
||||
// print values
|
||||
IntPtr row;
|
||||
while ((row = TDengine.FetchRows(res)) != IntPtr.Zero)
|
||||
List<Object> resData = LibTaos.GetData(res);
|
||||
for (int i = 0; i < resData.Count; i++)
|
||||
{
|
||||
List<TDengineMeta> metaList = TDengine.FetchFields(res);
|
||||
int numOfFiled = TDengine.FieldCount(res);
|
||||
|
||||
List<String> dataRaw = new List<string>();
|
||||
|
||||
IntPtr colLengthPrt = TDengine.FetchLengths(res);
|
||||
int[] colLengthArr = new int[numOfFiled];
|
||||
Marshal.Copy(colLengthPrt, colLengthArr, 0, numOfFiled);
|
||||
|
||||
for (int i = 0; i < numOfFiled; i++)
|
||||
Console.Write($"|{resData[i].ToString()} \t");
|
||||
if (((i + 1) % metas.Count == 0))
|
||||
{
|
||||
TDengineMeta meta = metaList[i];
|
||||
IntPtr data = Marshal.ReadIntPtr(row, IntPtr.Size * i);
|
||||
|
||||
if (data == IntPtr.Zero)
|
||||
{
|
||||
Console.Write("NULL\t");
|
||||
continue;
|
||||
}
|
||||
switch ((TDengineDataType)meta.type)
|
||||
{
|
||||
case TDengineDataType.TSDB_DATA_TYPE_BOOL:
|
||||
bool v1 = Marshal.ReadByte(data) == 0 ? false : true;
|
||||
Console.Write(v1.ToString() + "\t");
|
||||
break;
|
||||
case TDengineDataType.TSDB_DATA_TYPE_TINYINT:
|
||||
sbyte v2 = (sbyte)Marshal.ReadByte(data);
|
||||
Console.Write(v2.ToString() + "\t");
|
||||
break;
|
||||
case TDengineDataType.TSDB_DATA_TYPE_SMALLINT:
|
||||
short v3 = Marshal.ReadInt16(data);
|
||||
Console.Write(v3.ToString() + "\t");
|
||||
break;
|
||||
case TDengineDataType.TSDB_DATA_TYPE_INT:
|
||||
int v4 = Marshal.ReadInt32(data);
|
||||
Console.Write(v4.ToString() + "\t");
|
||||
break;
|
||||
case TDengineDataType.TSDB_DATA_TYPE_BIGINT:
|
||||
long v5 = Marshal.ReadInt64(data);
|
||||
Console.Write(v5.ToString() + "\t");
|
||||
break;
|
||||
case TDengineDataType.TSDB_DATA_TYPE_FLOAT:
|
||||
float v6 = (float)Marshal.PtrToStructure(data, typeof(float));
|
||||
Console.Write(v6.ToString() + "\t");
|
||||
break;
|
||||
case TDengineDataType.TSDB_DATA_TYPE_DOUBLE:
|
||||
double v7 = (double)Marshal.PtrToStructure(data, typeof(double));
|
||||
Console.Write(v7.ToString() + "\t");
|
||||
break;
|
||||
case TDengineDataType.TSDB_DATA_TYPE_BINARY:
|
||||
string v8 = Marshal.PtrToStringUTF8(data, colLengthArr[i]);
|
||||
Console.Write(v8 + "\t");
|
||||
break;
|
||||
case TDengineDataType.TSDB_DATA_TYPE_TIMESTAMP:
|
||||
long v9 = Marshal.ReadInt64(data);
|
||||
Console.Write(v9.ToString() + "\t");
|
||||
break;
|
||||
case TDengineDataType.TSDB_DATA_TYPE_NCHAR:
|
||||
string v10 = Marshal.PtrToStringUTF8(data, colLengthArr[i]);
|
||||
Console.Write(v10 + "\t");
|
||||
break;
|
||||
case TDengineDataType.TSDB_DATA_TYPE_UTINYINT:
|
||||
byte v12 = Marshal.ReadByte(data);
|
||||
Console.Write(v12.ToString() + "\t");
|
||||
break;
|
||||
case TDengineDataType.TSDB_DATA_TYPE_USMALLINT:
|
||||
ushort v13 = (ushort)Marshal.ReadInt16(data);
|
||||
Console.Write(v13.ToString() + "\t");
|
||||
break;
|
||||
case TDengineDataType.TSDB_DATA_TYPE_UINT:
|
||||
uint v14 = (uint)Marshal.ReadInt32(data);
|
||||
Console.Write(v14.ToString() + "\t");
|
||||
break;
|
||||
case TDengineDataType.TSDB_DATA_TYPE_UBIGINT:
|
||||
ulong v15 = (ulong)Marshal.ReadInt64(data);
|
||||
Console.Write(v15.ToString() + "\t");
|
||||
break;
|
||||
case TDengineDataType.TSDB_DATA_TYPE_JSONTAG:
|
||||
string v16 = Marshal.PtrToStringUTF8(data, colLengthArr[i]);
|
||||
Console.Write(v16 + "\t");
|
||||
break;
|
||||
default:
|
||||
Console.Write("nonsupport data type value");
|
||||
break;
|
||||
}
|
||||
|
||||
Console.WriteLine("");
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
Console.WriteLine();
|
||||
|
||||
if (TDengine.ErrorNo(res) != 0)
|
||||
{
|
||||
Console.WriteLine($"Query is not complete, Error {TDengine.ErrorNo(res)} {TDengine.Error(res)}");
|
||||
|
|
|
@ -15,10 +15,10 @@ namespace TDengineExample
|
|||
CheckRes(conn, res, "failed to change database");
|
||||
res = TDengine.Query(conn, "CREATE STABLE power.meters (ts TIMESTAMP, current FLOAT, voltage INT, phase FLOAT) TAGS (location BINARY(64), groupId INT)");
|
||||
CheckRes(conn, res, "failed to create stable");
|
||||
var sql = "INSERT INTO d1001 USING meters TAGS(California.SanFrancisco, 2) VALUES ('2018-10-03 14:38:05.000', 10.30000, 219, 0.31000) ('2018-10-03 14:38:15.000', 12.60000, 218, 0.33000) ('2018-10-03 14:38:16.800', 12.30000, 221, 0.31000) " +
|
||||
"d1002 USING power.meters TAGS(California.SanFrancisco, 3) VALUES('2018-10-03 14:38:16.650', 10.30000, 218, 0.25000) " +
|
||||
"d1003 USING power.meters TAGS(California.LosAngeles, 2) VALUES('2018-10-03 14:38:05.500', 11.80000, 221, 0.28000)('2018-10-03 14:38:16.600', 13.40000, 223, 0.29000) " +
|
||||
"d1004 USING power.meters TAGS(California.LosAngeles, 3) VALUES('2018-10-03 14:38:05.000', 10.80000, 223, 0.29000)('2018-10-03 14:38:06.500', 11.50000, 221, 0.35000)";
|
||||
var sql = "INSERT INTO d1001 USING meters TAGS('California.SanFrancisco', 2) VALUES ('2018-10-03 14:38:05.000', 10.30000, 219, 0.31000) ('2018-10-03 14:38:15.000', 12.60000, 218, 0.33000) ('2018-10-03 14:38:16.800', 12.30000, 221, 0.31000) " +
|
||||
"d1002 USING power.meters TAGS('California.SanFrancisco', 3) VALUES('2018-10-03 14:38:16.650', 10.30000, 218, 0.25000) " +
|
||||
"d1003 USING power.meters TAGS('California.LosAngeles', 2) VALUES('2018-10-03 14:38:05.500', 11.80000, 221, 0.28000)('2018-10-03 14:38:16.600', 13.40000, 223, 0.29000) " +
|
||||
"d1004 USING power.meters TAGS('California.LosAngeles', 3) VALUES('2018-10-03 14:38:05.000', 10.80000, 223, 0.29000)('2018-10-03 14:38:06.500', 11.50000, 221, 0.35000)";
|
||||
res = TDengine.Query(conn, sql);
|
||||
CheckRes(conn, res, "failed to insert data");
|
||||
int affectedRows = TDengine.AffectRows(res);
|
||||
|
|
|
@ -21,7 +21,7 @@ namespace TDengineExample
|
|||
CheckStmtRes(res, "failed to prepare stmt");
|
||||
|
||||
// 2. bind table name and tags
|
||||
TAOS_BIND[] tags = new TAOS_BIND[2] { TaosBind.BindBinary("California.SanFrancisco"), TaosBind.BindInt(2) };
|
||||
TAOS_MULTI_BIND[] tags = new TAOS_MULTI_BIND[2] { TaosMultiBind.MultiBindBinary(new string[]{"California.SanFrancisco"}), TaosMultiBind.MultiBindInt(new int?[] {2}) };
|
||||
res = TDengine.StmtSetTbnameTags(stmt, "d1001", tags);
|
||||
CheckStmtRes(res, "failed to bind table name and tags");
|
||||
|
||||
|
@ -44,7 +44,7 @@ namespace TDengineExample
|
|||
CheckStmtRes(res, "faild to execute");
|
||||
|
||||
// 6. free
|
||||
TaosBind.FreeTaosBind(tags);
|
||||
TaosMultiBind.FreeTaosBind(tags);
|
||||
TaosMultiBind.FreeTaosBind(values);
|
||||
TDengine.Close(conn);
|
||||
TDengine.Cleanup();
|
||||
|
|
|
@ -1,12 +1,100 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using TDengineTMQ;
|
||||
using TDengineDriver;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace csharp
|
||||
namespace TMQExample
|
||||
{
|
||||
internal class SubscribeDemo
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
IntPtr conn = GetConnection();
|
||||
string topic = "topic_example";
|
||||
Console.WriteLine($"create topic if not exist {topic} as select * from meters");
|
||||
//create topic
|
||||
IntPtr res = TDengine.Query(conn, $"create topic if not exists {topic} as select * from meters");
|
||||
|
||||
if (res == IntPtr.Zero)
|
||||
{
|
||||
throw new Exception($"create topic failed, reason:{TDengine.Error(res)}");
|
||||
}
|
||||
|
||||
var cfg = new ConsumerConfig
|
||||
{
|
||||
GourpId = "group_1",
|
||||
TDConnectUser = "root",
|
||||
TDConnectPasswd = "taosdata",
|
||||
MsgWithTableName = "true",
|
||||
TDConnectIp = "127.0.0.1",
|
||||
};
|
||||
|
||||
// create consumer
|
||||
var consumer = new ConsumerBuilder(cfg)
|
||||
.Build();
|
||||
|
||||
// subscribe
|
||||
consumer.Subscribe(topic);
|
||||
|
||||
// consume
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
var consumeRes = consumer.Consume(300);
|
||||
// print consumeResult
|
||||
foreach (KeyValuePair<TopicPartition, TaosResult> kv in consumeRes.Message)
|
||||
{
|
||||
Console.WriteLine("topic partitions:\n{0}", kv.Key.ToString());
|
||||
|
||||
kv.Value.Metas.ForEach(meta =>
|
||||
{
|
||||
Console.Write("{0} {1}({2}) \t|", meta.name, meta.TypeName(), meta.size);
|
||||
});
|
||||
Console.WriteLine("");
|
||||
kv.Value.Datas.ForEach(data =>
|
||||
{
|
||||
Console.WriteLine(data.ToString());
|
||||
});
|
||||
}
|
||||
|
||||
consumer.Commit(consumeRes);
|
||||
Console.WriteLine("\n================ {0} done ", i);
|
||||
|
||||
}
|
||||
|
||||
// retrieve topic list
|
||||
List<string> topics = consumer.Subscription();
|
||||
topics.ForEach(t => Console.WriteLine("topic name:{0}", t));
|
||||
|
||||
|
||||
// unsubscribe
|
||||
consumer.Unsubscribe();
|
||||
|
||||
// close consumer after use.Otherwise will lead memory leak.
|
||||
consumer.Close();
|
||||
TDengine.Close(conn);
|
||||
|
||||
|
||||
}
|
||||
|
||||
static IntPtr GetConnection()
|
||||
{
|
||||
string host = "localhost";
|
||||
short port = 6030;
|
||||
string username = "root";
|
||||
string password = "taosdata";
|
||||
string dbname = "power";
|
||||
var conn = TDengine.Connect(host, username, password, dbname, port);
|
||||
if (conn == IntPtr.Zero)
|
||||
{
|
||||
Console.WriteLine("Connect to TDengine failed");
|
||||
System.Environment.Exit(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Connect to TDengine success");
|
||||
}
|
||||
return conn;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="TDengine.Connector" Version="1.0.6" />
|
||||
<PackageReference Include="TDengine.Connector" Version="3.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="TDengine.Connector" Version="1.0.6" />
|
||||
<PackageReference Include="TDengine.Connector" Version="3.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="TDengine.Connector" Version="1.0.6" />
|
||||
<PackageReference Include="TDengine.Connector" Version="3.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="TDengine.Connector" Version="1.0.6" />
|
||||
<PackageReference Include="TDengine.Connector" Version="3.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="TDengine.Connector" Version="1.0.6" />
|
||||
<PackageReference Include="TDengine.Connector" Version="3.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="TDengine.Connector" Version="1.0.6" />
|
||||
<PackageReference Include="TDengine.Connector" Version="3.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="TDengine.Connector" Version="1.0.6" />
|
||||
<PackageReference Include="TDengine.Connector" Version="3.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="TDengine.Connector" Version="1.0.6" />
|
||||
<PackageReference Include="TDengine.Connector" Version="3.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -5,11 +5,11 @@
|
|||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<StartupObject>TDengineExample.SubscribeDemo</StartupObject>
|
||||
<StartupObject>TMQExample.SubscribeDemo</StartupObject>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="TDengine.Connector" Version="1.0.6" />
|
||||
<PackageReference Include="TDengine.Connector" Version="3.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -2,6 +2,7 @@ package main
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/taosdata/driver-go/v3/af"
|
||||
)
|
||||
|
@ -10,7 +11,7 @@ func main() {
|
|||
conn, err := af.Open("localhost", "root", "taosdata", "", 6030)
|
||||
defer conn.Close()
|
||||
if err != nil {
|
||||
fmt.Println("failed to connect, err:", err)
|
||||
log.Fatalln("failed to connect, err:", err)
|
||||
} else {
|
||||
fmt.Println("connected")
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package main
|
|||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
_ "github.com/taosdata/driver-go/v3/taosSql"
|
||||
)
|
||||
|
@ -11,7 +12,7 @@ func main() {
|
|||
var taosDSN = "root:taosdata@tcp(localhost:6030)/"
|
||||
taos, err := sql.Open("taosSql", taosDSN)
|
||||
if err != nil {
|
||||
fmt.Println("failed to connect TDengine, err:", err)
|
||||
log.Fatalln("failed to connect TDengine, err:", err)
|
||||
return
|
||||
}
|
||||
fmt.Println("Connected")
|
||||
|
|
|
@ -3,6 +3,7 @@ package main
|
|||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
_ "github.com/taosdata/driver-go/v3/taosRestful"
|
||||
)
|
||||
|
@ -11,7 +12,7 @@ func main() {
|
|||
var taosDSN = "root:taosdata@http(localhost:6041)/"
|
||||
taos, err := sql.Open("taosRestful", taosDSN)
|
||||
if err != nil {
|
||||
fmt.Println("failed to connect TDengine, err:", err)
|
||||
log.Fatalln("failed to connect TDengine, err:", err)
|
||||
return
|
||||
}
|
||||
fmt.Println("Connected")
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/taosdata/driver-go/v3/wrapper"
|
||||
)
|
||||
|
||||
func main() {
|
||||
conn, err := wrapper.TaosConnect("localhost", "root", "taosdata", "", 6030)
|
||||
defer wrapper.TaosClose(conn)
|
||||
if err != nil {
|
||||
fmt.Println("fail to connect, err:", err)
|
||||
} else {
|
||||
fmt.Println("connected")
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/taosdata/driver-go/v3/af"
|
||||
)
|
||||
|
@ -20,7 +20,7 @@ func prepareDatabase(conn *af.Connector) {
|
|||
func main() {
|
||||
conn, err := af.Open("localhost", "root", "taosdata", "", 6030)
|
||||
if err != nil {
|
||||
fmt.Println("fail to connect, err:", err)
|
||||
log.Fatalln("fail to connect, err:", err)
|
||||
}
|
||||
defer conn.Close()
|
||||
prepareDatabase(conn)
|
||||
|
@ -32,6 +32,6 @@ func main() {
|
|||
|
||||
err = conn.OpenTSDBInsertJsonPayload(payload)
|
||||
if err != nil {
|
||||
fmt.Println("insert error:", err)
|
||||
log.Fatalln("insert error:", err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package main
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/taosdata/driver-go/v3/af"
|
||||
)
|
||||
|
@ -33,6 +34,6 @@ func main() {
|
|||
|
||||
err = conn.InfluxDBInsertLines(lines, "ms")
|
||||
if err != nil {
|
||||
fmt.Println("insert error:", err)
|
||||
log.Fatalln("insert error:", err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package main
|
|||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
_ "github.com/taosdata/driver-go/v3/taosRestful"
|
||||
)
|
||||
|
@ -10,28 +11,26 @@ import (
|
|||
func createStable(taos *sql.DB) {
|
||||
_, err := taos.Exec("CREATE DATABASE power")
|
||||
if err != nil {
|
||||
fmt.Println("failed to create database, err:", err)
|
||||
log.Fatalln("failed to create database, err:", err)
|
||||
}
|
||||
_, err = taos.Exec("CREATE STABLE power.meters (ts TIMESTAMP, current FLOAT, voltage INT, phase FLOAT) TAGS (location BINARY(64), groupId INT)")
|
||||
if err != nil {
|
||||
fmt.Println("failed to create stable, err:", err)
|
||||
log.Fatalln("failed to create stable, err:", err)
|
||||
}
|
||||
}
|
||||
|
||||
func insertData(taos *sql.DB) {
|
||||
sql := `INSERT INTO power.d1001 USING power.meters TAGS(California.SanFrancisco, 2) VALUES ('2018-10-03 14:38:05.000', 10.30000, 219, 0.31000) ('2018-10-03 14:38:15.000', 12.60000, 218, 0.33000) ('2018-10-03 14:38:16.800', 12.30000, 221, 0.31000)
|
||||
power.d1002 USING power.meters TAGS(California.SanFrancisco, 3) VALUES ('2018-10-03 14:38:16.650', 10.30000, 218, 0.25000)
|
||||
power.d1003 USING power.meters TAGS(California.LosAngeles, 2) VALUES ('2018-10-03 14:38:05.500', 11.80000, 221, 0.28000) ('2018-10-03 14:38:16.600', 13.40000, 223, 0.29000)
|
||||
power.d1004 USING power.meters TAGS(California.LosAngeles, 3) VALUES ('2018-10-03 14:38:05.000', 10.80000, 223, 0.29000) ('2018-10-03 14:38:06.500', 11.50000, 221, 0.35000)`
|
||||
sql := `INSERT INTO power.d1001 USING power.meters TAGS('California.SanFrancisco', 2) VALUES ('2018-10-03 14:38:05.000', 10.30000, 219, 0.31000) ('2018-10-03 14:38:15.000', 12.60000, 218, 0.33000) ('2018-10-03 14:38:16.800', 12.30000, 221, 0.31000)
|
||||
power.d1002 USING power.meters TAGS('California.SanFrancisco', 3) VALUES ('2018-10-03 14:38:16.650', 10.30000, 218, 0.25000)
|
||||
power.d1003 USING power.meters TAGS('California.LosAngeles', 2) VALUES ('2018-10-03 14:38:05.500', 11.80000, 221, 0.28000) ('2018-10-03 14:38:16.600', 13.40000, 223, 0.29000)
|
||||
power.d1004 USING power.meters TAGS('California.LosAngeles', 3) VALUES ('2018-10-03 14:38:05.000', 10.80000, 223, 0.29000) ('2018-10-03 14:38:06.500', 11.50000, 221, 0.35000)`
|
||||
result, err := taos.Exec(sql)
|
||||
if err != nil {
|
||||
fmt.Println("failed to insert, err:", err)
|
||||
return
|
||||
log.Fatalln("failed to insert, err:", err)
|
||||
}
|
||||
rowsAffected, err := result.RowsAffected()
|
||||
if err != nil {
|
||||
fmt.Println("failed to get affected rows, err:", err)
|
||||
return
|
||||
log.Fatalln("failed to get affected rows, err:", err)
|
||||
}
|
||||
fmt.Println("RowsAffected", rowsAffected)
|
||||
}
|
||||
|
@ -40,8 +39,7 @@ func main() {
|
|||
var taosDSN = "root:taosdata@http(localhost:6041)/"
|
||||
taos, err := sql.Open("taosRestful", taosDSN)
|
||||
if err != nil {
|
||||
fmt.Println("failed to connect TDengine, err:", err)
|
||||
return
|
||||
log.Fatalln("failed to connect TDengine, err:", err)
|
||||
}
|
||||
defer taos.Close()
|
||||
createStable(taos)
|
||||
|
|
|
@ -5,8 +5,8 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/taosdata/driver-go/v3/af"
|
||||
"github.com/taosdata/driver-go/v3/af/param"
|
||||
"github.com/taosdata/driver-go/v3/common"
|
||||
"github.com/taosdata/driver-go/v3/common/param"
|
||||
)
|
||||
|
||||
func checkErr(err error, prompt string) {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/taosdata/driver-go/v3/af"
|
||||
)
|
||||
|
@ -20,7 +20,7 @@ func prepareDatabase(conn *af.Connector) {
|
|||
func main() {
|
||||
conn, err := af.Open("localhost", "root", "taosdata", "", 6030)
|
||||
if err != nil {
|
||||
fmt.Println("fail to connect, err:", err)
|
||||
log.Fatalln("fail to connect, err:", err)
|
||||
}
|
||||
defer conn.Close()
|
||||
prepareDatabase(conn)
|
||||
|
@ -37,6 +37,6 @@ func main() {
|
|||
|
||||
err = conn.OpenTSDBInsertTelnetLines(lines)
|
||||
if err != nil {
|
||||
fmt.Println("insert error:", err)
|
||||
log.Fatalln("insert error:", err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ package main
|
|||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
_ "github.com/taosdata/driver-go/v3/taosRestful"
|
||||
|
@ -12,14 +12,12 @@ func main() {
|
|||
var taosDSN = "root:taosdata@http(localhost:6041)/power"
|
||||
taos, err := sql.Open("taosRestful", taosDSN)
|
||||
if err != nil {
|
||||
fmt.Println("failed to connect TDengine, err:", err)
|
||||
return
|
||||
log.Fatalln("failed to connect TDengine, err:", err)
|
||||
}
|
||||
defer taos.Close()
|
||||
rows, err := taos.Query("SELECT ts, current FROM meters LIMIT 2")
|
||||
if err != nil {
|
||||
fmt.Println("failed to select from table, err:", err)
|
||||
return
|
||||
log.Fatalln("failed to select from table, err:", err)
|
||||
}
|
||||
|
||||
defer rows.Close()
|
||||
|
@ -30,9 +28,9 @@ func main() {
|
|||
}
|
||||
err := rows.Scan(&r.ts, &r.current)
|
||||
if err != nil {
|
||||
fmt.Println("scan error:\n", err)
|
||||
log.Fatalln("scan error:\n", err)
|
||||
return
|
||||
}
|
||||
fmt.Println(r.ts, r.current)
|
||||
log.Fatalln(r.ts, r.current)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
const taos = require("td2.0-connector");
|
||||
const taos = require("@tdengine/client");
|
||||
const conn = taos.connect({ host: "localhost", database: "power" });
|
||||
const cursor = conn.cursor();
|
||||
|
||||
|
@ -18,4 +18,3 @@ try {
|
|||
conn.close();
|
||||
}, 2000);
|
||||
}
|
||||
// bug here: jira 14506
|
||||
|
|
|
@ -1,13 +1,20 @@
|
|||
const taos = require("td2.0-connector");
|
||||
const { options, connect } = require("@tdengine/rest");
|
||||
|
||||
var conn = taos.connect({
|
||||
host: "localhost",
|
||||
port: 6030,
|
||||
user: "root",
|
||||
password: "taosdata",
|
||||
});
|
||||
conn.close();
|
||||
async function test() {
|
||||
options.path = "/rest/sql";
|
||||
options.host = "localhost";
|
||||
let conn = connect(options);
|
||||
let cursor = conn.cursor();
|
||||
try {
|
||||
let res = await cursor.query("SELECT server_version()");
|
||||
res.toString();
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
}
|
||||
}
|
||||
test();
|
||||
|
||||
// run with: node connect.js
|
||||
// output:
|
||||
// Successfully connected to TDengine
|
||||
// server_version() |
|
||||
// ===================
|
||||
// 3.0.0.0 |
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
const taos = require("td2.0-connector");
|
||||
const taos = require("@tdengine/client");
|
||||
|
||||
const conn = taos.connect({
|
||||
host: "localhost",
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
const taos = require("td2.0-connector");
|
||||
const taos = require("@tdengine/client");
|
||||
|
||||
const conn = taos.connect({
|
||||
host: "localhost",
|
||||
|
@ -11,11 +11,11 @@ try {
|
|||
cursor.execute(
|
||||
"CREATE STABLE meters (ts TIMESTAMP, current FLOAT, voltage INT, phase FLOAT) TAGS (location BINARY(64), groupId INT)"
|
||||
);
|
||||
var sql = `INSERT INTO power.d1001 USING power.meters TAGS(California.SanFrancisco, 2) VALUES ('2018-10-03 14:38:05.000', 10.30000, 219, 0.31000) ('2018-10-03 14:38:15.000', 12.60000, 218, 0.33000) ('2018-10-03 14:38:16.800', 12.30000, 221, 0.31000)
|
||||
power.d1002 USING power.meters TAGS(California.SanFrancisco, 3) VALUES ('2018-10-03 14:38:16.650', 10.30000, 218, 0.25000)
|
||||
power.d1003 USING power.meters TAGS(California.LosAngeles, 2) VALUES ('2018-10-03 14:38:05.500', 11.80000, 221, 0.28000) ('2018-10-03 14:38:16.600', 13.40000, 223, 0.29000)
|
||||
power.d1004 USING power.meters TAGS(California.LosAngeles, 3) VALUES ('2018-10-03 14:38:05.000', 10.80000, 223, 0.29000) ('2018-10-03 14:38:06.500', 11.50000, 221, 0.35000)`;
|
||||
cursor.execute(sql);
|
||||
var sql = `INSERT INTO power.d1001 USING power.meters TAGS('California.SanFrancisco', 2) VALUES ('2018-10-03 14:38:05.000', 10.30000, 219, 0.31000) ('2018-10-03 14:38:15.000', 12.60000, 218, 0.33000) ('2018-10-03 14:38:16.800', 12.30000, 221, 0.31000)
|
||||
power.d1002 USING power.meters TAGS('California.SanFrancisco', 3) VALUES ('2018-10-03 14:38:16.650', 10.30000, 218, 0.25000)
|
||||
power.d1003 USING power.meters TAGS('California.LosAngeles', 2) VALUES ('2018-10-03 14:38:05.500', 11.80000, 221, 0.28000) ('2018-10-03 14:38:16.600', 13.40000, 223, 0.29000)
|
||||
power.d1004 USING power.meters TAGS('California.LosAngeles', 3) VALUES ('2018-10-03 14:38:05.000', 10.80000, 223, 0.29000) ('2018-10-03 14:38:06.500', 11.50000, 221, 0.35000)`;
|
||||
cursor.execute(sql,{'quiet':false});
|
||||
} finally {
|
||||
cursor.close();
|
||||
conn.close();
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
const taos = require("td2.0-connector");
|
||||
const taos = require("@tdengine/client");
|
||||
|
||||
const conn = taos.connect({
|
||||
host: "localhost",
|
||||
|
@ -24,10 +24,10 @@ function insertData() {
|
|||
);
|
||||
|
||||
// bind table name and tags
|
||||
let tagBind = new taos.TaosBind(2);
|
||||
tagBind.bindBinary("California.SanFrancisco");
|
||||
tagBind.bindInt(2);
|
||||
cursor.stmtSetTbnameTags("d1001", tagBind.getBind());
|
||||
let tagBind = new taos.TaosMultiBindArr(2);
|
||||
tagBind.multiBindBinary(["California.SanFrancisco"]);
|
||||
tagBind.multiBindInt([2]);
|
||||
cursor.stmtSetTbnameTags("d1001", tagBind.getMultiBindArr());
|
||||
|
||||
// bind values
|
||||
let valueBind = new taos.TaosMultiBindArr(4);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
const taos = require("td2.0-connector");
|
||||
const taos = require("@tdengine/client");
|
||||
|
||||
const conn = taos.connect({
|
||||
host: "localhost",
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
const taos = require("td2.0-connector");
|
||||
const taos = require("@tdengine/client");
|
||||
|
||||
const conn = taos.connect({
|
||||
host: "localhost",
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
const taos = require("td2.0-connector");
|
||||
const taos = require("@tdengine/client");
|
||||
|
||||
const conn = taos.connect({
|
||||
host: "localhost",
|
||||
|
@ -23,25 +23,22 @@ function insertData() {
|
|||
);
|
||||
|
||||
// bind table name and tags
|
||||
let tagBind = new taos.TaosBind(2);
|
||||
tagBind.bindBinary("California.SanFrancisco");
|
||||
tagBind.bindInt(2);
|
||||
cursor.stmtSetTbnameTags("d1001", tagBind.getBind());
|
||||
let tagBind = new taos.TaosMultiBindArr(2);
|
||||
tagBind.multiBindBinary(["California.SanFrancisco"]);
|
||||
tagBind.multiBindInt([2]);
|
||||
cursor.stmtSetTbnameTags("d1001", tagBind.getMultiBindArr());
|
||||
|
||||
// bind values
|
||||
let rows = [
|
||||
[1648432611249, 10.3, 219, 0.31],
|
||||
[1648432611749, 12.6, 218, 0.33],
|
||||
];
|
||||
for (let row of rows) {
|
||||
let valueBind = new taos.TaosBind(4);
|
||||
valueBind.bindTimestamp(row[0]);
|
||||
valueBind.bindFloat(row[1]);
|
||||
valueBind.bindInt(row[2]);
|
||||
valueBind.bindFloat(row[3]);
|
||||
cursor.stmtBindParam(valueBind.getBind());
|
||||
cursor.stmtAddBatch();
|
||||
}
|
||||
let rows = [[1648432611249, 1648432611749], [10.3, 12.6], [219, 218], [0.31, 0.33]];
|
||||
|
||||
let valueBind = new taos.TaosMultiBindArr(4);
|
||||
valueBind.multiBindTimestamp(rows[0]);
|
||||
valueBind.multiBindFloat(rows[1]);
|
||||
valueBind.multiBindInt(rows[2]);
|
||||
valueBind.multiBindFloat(rows[3]);
|
||||
cursor.stmtBindParamBatch(valueBind.getMultiBindArr());
|
||||
cursor.stmtAddBatch();
|
||||
|
||||
|
||||
// execute
|
||||
cursor.stmtExecute();
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
const taos = require("td2.0-connector");
|
||||
const taos = require("@tdengine/client");
|
||||
|
||||
const conn = taos.connect({ host: "localhost", database: "power" });
|
||||
const cursor = conn.cursor();
|
||||
|
@ -9,8 +9,6 @@ query.execute().then(function (result) {
|
|||
|
||||
// output:
|
||||
// Successfully connected to TDengine
|
||||
// Query OK, 2 row(s) in set (0.00317767s)
|
||||
|
||||
// ts | current |
|
||||
// =======================================================
|
||||
// 2018-10-03 14:38:05.000 | 10.3 |
|
||||
|
|
|
@ -1,4 +1,51 @@
|
|||
const taos = require("td2.0-connector");
|
||||
const taos = require("@tdengine/client");
|
||||
|
||||
const conn = taos.connect({ host: "localhost", database: "power" });
|
||||
// 未完成
|
||||
var cursor = conn.cursor();
|
||||
|
||||
function runConsumer() {
|
||||
|
||||
// create topic
|
||||
cursor.execute("create topic topic_name_example as select * from meters");
|
||||
|
||||
let consumer = taos.consumer({
|
||||
'group.id': 'tg2',
|
||||
'td.connect.user': 'root',
|
||||
'td.connect.pass': 'taosdata',
|
||||
'msg.with.table.name': 'true',
|
||||
'enable.auto.commit': 'true'
|
||||
});
|
||||
|
||||
// subscribe the topic just created.
|
||||
consumer.subscribe("topic_name_example");
|
||||
|
||||
// get subscribe topic list
|
||||
let topicList = consumer.subscription();
|
||||
console.log(topicList);
|
||||
|
||||
for (let i = 0; i < 5; i++) {
|
||||
let msg = consumer.consume(100);
|
||||
console.log(msg.topicPartition);
|
||||
console.log(msg.block);
|
||||
console.log(msg.fields)
|
||||
consumer.commit(msg);
|
||||
console.log(`=======consumer ${i} done`)
|
||||
}
|
||||
|
||||
consumer.unsubscribe();
|
||||
consumer.close();
|
||||
|
||||
// drop topic
|
||||
cursor.execute("drop topic topic_name_example");
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
runConsumer();
|
||||
} finally {
|
||||
|
||||
setTimeout(() => {
|
||||
cursor.close();
|
||||
conn.close();
|
||||
}, 2000);
|
||||
}
|
|
@ -4,7 +4,7 @@
|
|||
"main": "index.js",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"td2.0-connector": "^2.0.12",
|
||||
"td2.0-rest-connector": "^1.0.0"
|
||||
"@tdengine/client": "^3.0.0",
|
||||
"@tdengine/rest": "^3.0.0"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
const { options, connect } = require("td2.0-rest-connector");
|
||||
const { options, connect } = require("@tdengine/rest");
|
||||
|
||||
async function test() {
|
||||
options.path = "/rest/sqlt";
|
||||
|
@ -17,4 +17,4 @@ test();
|
|||
// output:
|
||||
// server_version() |
|
||||
// ===================
|
||||
// 2.4.0.12 |
|
||||
// 3.0.0.0 |
|
||||
|
|
|
@ -11,7 +11,7 @@ import TabItem from "@theme/TabItem";
|
|||
|
||||
:::
|
||||
|
||||
TDengine 开源版本提供 deb 和 rpm 格式安装包,用户可以根据自己的运行环境选择合适的安装包。其中 deb 支持 Debian/Ubuntu 及衍生系统,rpm 支持 CentOS/RHEL/SUSE 及衍生系统。同时我们也为企业用户提供 tar.gz 格式安装包。
|
||||
TDengine 开源版本提供 deb 和 rpm 格式安装包,用户可以根据自己的运行环境选择合适的安装包。其中 deb 支持 Debian/Ubuntu 及衍生系统,rpm 支持 CentOS/RHEL/SUSE 及衍生系统。同时我们也为企业用户提供 tar.gz 格式安装包。也支持通过 `apt-get` 工具从线上进行安装。
|
||||
|
||||
## 安装
|
||||
|
||||
|
@ -293,4 +293,4 @@ taos> select avg(current), max(voltage), min(phase) from test.meters where group
|
|||
|
||||
```sql
|
||||
taos> select avg(current), max(voltage), min(phase) from test.d10 interval(10s);
|
||||
```
|
||||
```
|
||||
|
|
|
@ -3,6 +3,6 @@
|
|||
```
|
||||
|
||||
:::tip
|
||||
driver-go 的模块 `github.com/taosdata/driver-go/v2/wrapper` 是 C 接口的底层封装。使用这个模块也可以实现参数绑定写入。
|
||||
driver-go 的模块 `github.com/taosdata/driver-go/v3/wrapper` 是 C 接口的底层封装。使用这个模块也可以实现参数绑定写入。
|
||||
|
||||
:::
|
||||
|
|
|
@ -25,6 +25,7 @@ TDengine 采用 SQL 作为查询语言。应用程序可以通过 REST API 或
|
|||
- 单列、多列数据查询
|
||||
- 标签和数值的多种过滤条件:>, <, =, <\>, like 等
|
||||
- 聚合结果的分组(Group by)、排序(Order by)、约束输出(Limit/Offset)
|
||||
- 时间窗口(Interval)、会话窗口(Session)和状态窗口(State_window)等窗口切分聚合查询
|
||||
- 数值列及聚合结果的四则运算
|
||||
- 时间戳对齐的连接查询(Join Query: 隐式连接)操作
|
||||
- 多种聚合/计算函数: count, max, min, avg, sum, twa, stddev, leastsquares, top, bottom, first, last, percentile, apercentile, last_row, spread, diff 等
|
||||
|
@ -40,7 +41,7 @@ taos> select * from d1001 where voltage > 215 order by ts desc limit 2;
|
|||
Query OK, 2 row(s) in set (0.001100s)
|
||||
```
|
||||
|
||||
为满足物联网场景的需求,TDengine 支持几个特殊的函数,比如 twa(时间加权平均),spread (最大值与最小值的差),last_row(最后一条记录)等,更多与物联网场景相关的函数将添加进来。TDengine 还支持连续查询。
|
||||
为满足物联网场景的需求,TDengine 支持几个特殊的函数,比如 twa(时间加权平均),spread (最大值与最小值的差),last_row(最后一条记录)等,更多与物联网场景相关的函数将添加进来。
|
||||
|
||||
具体的查询语法请看 [TAOS SQL 的数据查询](/taos-sql/select) 章节。
|
||||
|
||||
|
@ -73,7 +74,7 @@ taos> SELECT count(*), max(current) FROM meters where groupId = 2 and ts > now -
|
|||
Query OK, 1 row(s) in set (0.002136s)
|
||||
```
|
||||
|
||||
TDengine 仅容许对属于同一个超级表的表之间进行聚合查询,不同超级表之间的聚合查询不支持。在 [TAOS SQL 的数据查询](/taos-sql/select) 一章,查询类操作都会注明是否支持超级表。
|
||||
在 [TAOS SQL 的数据查询](/taos-sql/select) 一章,查询类操作都会注明是否支持超级表。
|
||||
|
||||
## 降采样查询、插值
|
||||
|
||||
|
|
|
@ -1,254 +1,246 @@
|
|||
---
|
||||
sidebar_label: 数据订阅
|
||||
description: "轻量级的数据订阅与推送服务。连续写入到 TDengine 中的时序数据能够被自动推送到订阅客户端。"
|
||||
title: 数据订阅
|
||||
---
|
||||
|
||||
import Tabs from "@theme/Tabs";
|
||||
import TabItem from "@theme/TabItem";
|
||||
import Java from "./_sub_java.mdx";
|
||||
import Python from "./_sub_python.mdx";
|
||||
import Go from "./_sub_go.mdx";
|
||||
import Rust from "./_sub_rust.mdx";
|
||||
import Node from "./_sub_node.mdx";
|
||||
import CSharp from "./_sub_cs.mdx";
|
||||
import CDemo from "./_sub_c.mdx";
|
||||
|
||||
基于数据天然的时间序列特性,TDengine 的数据写入(insert)与消息系统的数据发布(pub)逻辑上一致,均可视为系统中插入一条带时间戳的新记录。同时,TDengine 在内部严格按照数据时间序列单调递增的方式保存数据。本质上来说,TDengine 中每一张表均可视为一个标准的消息队列。
|
||||
|
||||
TDengine 内嵌支持轻量级的消息订阅与推送服务。使用系统提供的 API,用户可使用普通查询语句订阅数据库中的一张或多张表。订阅的逻辑和操作状态的维护均是由客户端完成,客户端定时轮询服务器是否有新的记录到达,有新的记录到达就会将结果反馈到客户。
|
||||
|
||||
TDengine 的订阅与推送服务的状态是由客户端维持,TDengine 服务端并不维持。因此如果应用重启,从哪个时间点开始获取最新数据,由应用决定。
|
||||
|
||||
TDengine 的 API 中,与订阅相关的主要有以下三个:
|
||||
|
||||
```c
|
||||
taos_subscribe
|
||||
taos_consume
|
||||
taos_unsubscribe
|
||||
```
|
||||
|
||||
这些 API 的文档请见 [C/C++ Connector](/reference/connector/cpp),下面仍以智能电表场景为例介绍一下它们的具体用法(超级表和子表结构请参考上一节“连续查询”),完整的示例代码可以在 [这里](https://github.com/taosdata/TDengine/blob/master/examples/c/subscribe.c) 找到。
|
||||
|
||||
如果我们希望当某个电表的电流超过一定限制(比如 10A)后能得到通知并进行一些处理, 有两种方法:一是分别对每张子表进行查询,每次查询后记录最后一条数据的时间戳,后续只查询这个时间戳之后的数据:
|
||||
|
||||
```sql
|
||||
select * from D1001 where ts > {last_timestamp1} and current > 10;
|
||||
select * from D1002 where ts > {last_timestamp2} and current > 10;
|
||||
...
|
||||
```
|
||||
|
||||
这确实可行,但随着电表数量的增加,查询数量也会增加,客户端和服务端的性能都会受到影响,当电表数增长到一定的程度,系统就无法承受了。
|
||||
|
||||
另一种方法是对超级表进行查询。这样,无论有多少电表,都只需一次查询:
|
||||
|
||||
```sql
|
||||
select * from meters where ts > {last_timestamp} and current > 10;
|
||||
```
|
||||
|
||||
但是,如何选择 `last_timestamp` 就成了一个新的问题。因为,一方面数据的产生时间(也就是数据时间戳)和数据入库的时间一般并不相同,有时偏差还很大;另一方面,不同电表的数据到达 TDengine 的时间也会有差异。所以,如果我们在查询中使用最慢的那台电表的数据的时间戳作为 `last_timestamp`,就可能重复读入其它电表的数据;如果使用最快的电表的时间戳,其它电表的数据就可能被漏掉。
|
||||
|
||||
TDengine 的订阅功能为上面这个问题提供了一个彻底的解决方案。
|
||||
|
||||
首先是使用 `taos_subscribe` 创建订阅:
|
||||
|
||||
```c
|
||||
TAOS_SUB* tsub = NULL;
|
||||
if (async) {
|
||||
// create an asynchronized subscription, the callback function will be called every 1s
|
||||
tsub = taos_subscribe(taos, restart, topic, sql, subscribe_callback, &blockFetch, 1000);
|
||||
} else {
|
||||
// create an synchronized subscription, need to call 'taos_consume' manually
|
||||
tsub = taos_subscribe(taos, restart, topic, sql, NULL, NULL, 0);
|
||||
}
|
||||
```
|
||||
|
||||
TDengine 中的订阅既可以是同步的,也可以是异步的,上面的代码会根据从命令行获取的参数 `async` 的值来决定使用哪种方式。这里,同步的意思是用户程序要直接调用 `taos_consume` 来拉取数据,而异步则由 API 在内部的另一个线程中调用 `taos_consume`,然后把拉取到的数据交给回调函数 `subscribe_callback`去处理。(注意,`subscribe_callback` 中不宜做较为耗时的操作,否则有可能导致客户端阻塞等不可控的问题。)
|
||||
|
||||
参数 `taos` 是一个已经建立好的数据库连接,在同步模式下无特殊要求。但在异步模式下,需要注意它不会被其它线程使用,否则可能导致不可预计的错误,因为回调函数在 API 的内部线程中被调用,而 TDengine 的部分 API 不是线程安全的。
|
||||
|
||||
参数 `sql` 是查询语句,可以在其中使用 where 子句指定过滤条件。在我们的例子中,如果只想订阅电流超过 10A 时的数据,可以这样写:
|
||||
|
||||
```sql
|
||||
select * from meters where current > 10;
|
||||
```
|
||||
|
||||
注意,这里没有指定起始时间,所以会读到所有时间的数据。如果只想从一天前的数据开始订阅,而不需要更早的历史数据,可以再加上一个时间条件:
|
||||
|
||||
```sql
|
||||
select * from meters where ts > now - 1d and current > 10;
|
||||
```
|
||||
|
||||
订阅的 `topic` 实际上是它的名字,因为订阅功能是在客户端 API 中实现的,所以没必要保证它全局唯一,但需要它在一台客户端机器上唯一。
|
||||
|
||||
如果名为 `topic` 的订阅不存在,参数 `restart` 没有意义;但如果用户程序创建这个订阅后退出,当它再次启动并重新使用这个 `topic` 时,`restart` 就会被用于决定是从头开始读取数据,还是接续上次的位置进行读取。本例中,如果 `restart` 是 **true**(非零值),用户程序肯定会读到所有数据。但如果这个订阅之前就存在了,并且已经读取了一部分数据,且 `restart` 是 **false**(**0**),用户程序就不会读到之前已经读取的数据了。
|
||||
|
||||
`taos_subscribe`的最后一个参数是以毫秒为单位的轮询周期。在同步模式下,如果前后两次调用 `taos_consume` 的时间间隔小于此时间,`taos_consume` 会阻塞,直到间隔超过此时间。异步模式下,这个时间是两次调用回调函数的最小时间间隔。
|
||||
|
||||
`taos_subscribe` 的倒数第二个参数用于用户程序向回调函数传递附加参数,订阅 API 不对其做任何处理,只原样传递给回调函数。此参数在同步模式下无意义。
|
||||
|
||||
订阅创建以后,就可以消费其数据了,同步模式下,示例代码是下面的 else 部分:
|
||||
|
||||
```c
|
||||
if (async) {
|
||||
getchar();
|
||||
} else while(1) {
|
||||
TAOS_RES* res = taos_consume(tsub);
|
||||
if (res == NULL) {
|
||||
printf("failed to consume data.");
|
||||
break;
|
||||
} else {
|
||||
print_result(res, blockFetch);
|
||||
getchar();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
这里是一个 **while** 循环,用户每按一次回车键就调用一次 `taos_consume`,而 `taos_consume` 的返回值是查询到的结果集,与 `taos_use_result` 完全相同,例子中使用这个结果集的代码是函数 `print_result`:
|
||||
|
||||
```c
|
||||
void print_result(TAOS_RES* res, int blockFetch) {
|
||||
TAOS_ROW row = NULL;
|
||||
int num_fields = taos_num_fields(res);
|
||||
TAOS_FIELD* fields = taos_fetch_fields(res);
|
||||
int nRows = 0;
|
||||
if (blockFetch) {
|
||||
nRows = taos_fetch_block(res, &row);
|
||||
for (int i = 0; i < nRows; i++) {
|
||||
char temp[256];
|
||||
taos_print_row(temp, row + i, fields, num_fields);
|
||||
puts(temp);
|
||||
}
|
||||
} else {
|
||||
while ((row = taos_fetch_row(res))) {
|
||||
char temp[256];
|
||||
taos_print_row(temp, row, fields, num_fields);
|
||||
puts(temp);
|
||||
nRows++;
|
||||
}
|
||||
}
|
||||
printf("%d rows consumed.\n", nRows);
|
||||
}
|
||||
```
|
||||
|
||||
其中的 `taos_print_row` 用于处理订阅到数据,在我们的例子中,它会打印出所有符合条件的记录。而异步模式下,消费订阅到的数据则显得更为简单:
|
||||
|
||||
```c
|
||||
void subscribe_callback(TAOS_SUB* tsub, TAOS_RES *res, void* param, int code) {
|
||||
print_result(res, *(int*)param);
|
||||
}
|
||||
```
|
||||
|
||||
当要结束一次数据订阅时,需要调用 `taos_unsubscribe`:
|
||||
|
||||
```c
|
||||
taos_unsubscribe(tsub, keep);
|
||||
```
|
||||
|
||||
其第二个参数,用于决定是否在客户端保留订阅的进度信息。如果这个参数是**false**(**0**),那无论下次调用 `taos_subscribe` 时的 `restart` 参数是什么,订阅都只能重新开始。另外,进度信息的保存位置是 _{DataDir}/subscribe/_ 这个目录下(注:`taos.cfg` 配置文件中 `DataDir` 参数值默认为 **/var/lib/taos/**,但是 Windows 服务器上本身不存在该目录,所以需要在 Windows 的配置文件中修改 `DataDir` 参数值为相应的已存在目录"),每个订阅有一个与其 `topic` 同名的文件,删掉某个文件,同样会导致下次创建其对应的订阅时只能重新开始。
|
||||
|
||||
代码介绍完毕,我们来看一下实际的运行效果。假设:
|
||||
|
||||
- 示例代码已经下载到本地
|
||||
- TDengine 也已经在同一台机器上安装好
|
||||
- 示例所需的数据库、超级表、子表已经全部创建好
|
||||
|
||||
则可以在示例代码所在目录执行以下命令来编译并启动示例程序:
|
||||
|
||||
```bash
|
||||
make
|
||||
./subscribe -sql='select * from meters where current > 10;'
|
||||
```
|
||||
|
||||
示例程序启动后,打开另一个终端窗口,启动 TDengine CLI 向 **D1001** 插入一条电流为 12A 的数据:
|
||||
|
||||
```sql
|
||||
$ taos
|
||||
> use test;
|
||||
> insert into D1001 values(now, 12, 220, 1);
|
||||
```
|
||||
|
||||
这时,因为电流超过了 10A,您应该可以看到示例程序将它输出到了屏幕上。您可以继续插入一些数据观察示例程序的输出。
|
||||
|
||||
## 示例程序
|
||||
|
||||
下面的示例程序展示是如何使用连接器订阅所有电流超过 10A 的记录。
|
||||
|
||||
### 准备数据
|
||||
|
||||
```
|
||||
# create database "power"
|
||||
taos> create database power;
|
||||
# use "power" as the database in following operations
|
||||
taos> use power;
|
||||
# create super table "meters"
|
||||
taos> create table meters(ts timestamp, current float, voltage int, phase int) tags(location binary(64), groupId int);
|
||||
# create tabes using the schema defined by super table "meters"
|
||||
taos> create table d1001 using meters tags ("California.SanFrancisco", 2);
|
||||
taos> create table d1002 using meters tags ("California.LosAngeles", 2);
|
||||
# insert some rows
|
||||
taos> insert into d1001 values("2020-08-15 12:00:00.000", 12, 220, 1),("2020-08-15 12:10:00.000", 12.3, 220, 2),("2020-08-15 12:20:00.000", 12.2, 220, 1);
|
||||
taos> insert into d1002 values("2020-08-15 12:00:00.000", 9.9, 220, 1),("2020-08-15 12:10:00.000", 10.3, 220, 1),("2020-08-15 12:20:00.000", 11.2, 220, 1);
|
||||
# filter out the rows in which current is bigger than 10A
|
||||
taos> select * from meters where current > 10;
|
||||
ts | current | voltage | phase | location | groupid |
|
||||
===========================================================================================================
|
||||
2020-08-15 12:10:00.000 | 10.30000 | 220 | 1 | California.LosAngeles | 2 |
|
||||
2020-08-15 12:20:00.000 | 11.20000 | 220 | 1 | California.LosAngeles | 2 |
|
||||
2020-08-15 12:00:00.000 | 12.00000 | 220 | 1 | California.SanFrancisco | 2 |
|
||||
2020-08-15 12:10:00.000 | 12.30000 | 220 | 2 | California.SanFrancisco | 2 |
|
||||
2020-08-15 12:20:00.000 | 12.20000 | 220 | 1 | California.SanFrancisco | 2 |
|
||||
Query OK, 5 row(s) in set (0.004896s)
|
||||
```
|
||||
|
||||
### 示例代码
|
||||
|
||||
<Tabs defaultValue="java" groupId="lang">
|
||||
<TabItem label="Java" value="java">
|
||||
<Java />
|
||||
</TabItem>
|
||||
<TabItem label="Python" value="Python">
|
||||
<Python />
|
||||
</TabItem>
|
||||
{/* <TabItem label="Go" value="go">
|
||||
<Go/>
|
||||
</TabItem> */}
|
||||
<TabItem label="Rust" value="rust">
|
||||
<Rust />
|
||||
</TabItem>
|
||||
{/* <TabItem label="Node.js" value="nodejs">
|
||||
<Node/>
|
||||
</TabItem>
|
||||
<TabItem label="C#" value="csharp">
|
||||
<CSharp/>
|
||||
</TabItem> */}
|
||||
<TabItem label="C" value="c">
|
||||
<CDemo />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
### 运行示例程序
|
||||
|
||||
示例程序会先消费符合查询条件的所有历史数据:
|
||||
|
||||
```bash
|
||||
ts: 1597464000000 current: 12.0 voltage: 220 phase: 1 location: California.SanFrancisco groupid : 2
|
||||
ts: 1597464600000 current: 12.3 voltage: 220 phase: 2 location: California.SanFrancisco groupid : 2
|
||||
ts: 1597465200000 current: 12.2 voltage: 220 phase: 1 location: California.SanFrancisco groupid : 2
|
||||
ts: 1597464600000 current: 10.3 voltage: 220 phase: 1 location: California.LosAngeles groupid : 2
|
||||
ts: 1597465200000 current: 11.2 voltage: 220 phase: 1 location: California.LosAngeles groupid : 2
|
||||
```
|
||||
|
||||
接着,使用 TDengine CLI 向表中新增一条数据:
|
||||
|
||||
```
|
||||
# taos
|
||||
taos> use power;
|
||||
taos> insert into d1001 values(now, 12.4, 220, 1);
|
||||
```
|
||||
|
||||
因为这条数据的电流大于 10A,示例程序会将其消费:
|
||||
|
||||
```
|
||||
ts: 1651146662805 current: 12.4 voltage: 220 phase: 1 location: California.SanFrancisco groupid: 2
|
||||
```
|
||||
---
|
||||
sidebar_label: 数据订阅
|
||||
description: "数据订阅与推送服务。写入到 TDengine 中的时序数据能够被自动推送到订阅客户端。"
|
||||
title: 数据订阅
|
||||
---
|
||||
|
||||
为了帮助应用实时获取写入 TDengine 的数据,或者以事件到达顺序处理数据,TDengine提供了类似消息队列产品的数据订阅、消费接口。这样在很多场景下,采用 TDengine 的时序数据处理系统不再需要集成消息队列产品,比如 kafka, 从而简化系统设计的复杂度,降低运营维护成本。
|
||||
|
||||
与 kafka 一样,你需要定义 topic, 但 TDengine 的 topic 是基于一个已经存在的超级表、子表或普通表的查询条件,即一个 SELECT 语句。你可以使用 SQL 对标签、表名、列、表达式等条件进行过滤,以及对数据进行标量函数与 UDF 计算(不包括数据聚合)。与其他消息队列软件相比,这是 TDengine 数据订阅功能的最大的优势,它提供了更大的灵活性,数据的颗粒度可以由应用随时调整,而且数据的过滤与预处理交给 TDengine,而不是应用完成,有效的减少传输的数据量与应用的复杂度。
|
||||
|
||||
消费者订阅 topic 后,可以实时获得最新的数据。多个消费者可以组成一个消费者组 (consumer group), 一个消费者组里的多个消费者共享消费进度,便于多线程、分布式地消费数据,提高消费速度。但不同消费者组中的消费者即使消费同一个topic, 并不共享消费进度。一个消费者可以订阅多个 topic。如果订阅的是超级表,数据可能会分布在多个不同的 vnode 上,也就是多个 shard 上,这样一个消费组里有多个消费者可以提高消费效率。TDengine 的消息队列提供了消息的ACK机制,在宕机、重启等复杂环境下确保 at least once 消费。
|
||||
|
||||
为了实现上述功能,TDengine 会为 WAL (Write-Ahead-Log) 文件自动创建索引以支持快速随机访问,并提供了灵活可配置的文件切换与保留机制:用户可以按需指定 WAL 文件保留的时间以及大小(详见 create database 语句)。通过以上方式将 WAL 改造成了一个保留事件到达顺序的、可持久化的存储引擎(但由于 TSDB 具有远比 WAL 更高的压缩率,我们不推荐保留太长时间,一般来说,不超过几天)。 对于以 topic 形式创建的查询,TDengine 将对接 WAL 而不是 TSDB 作为其存储引擎。在消费时,TDengine 根据当前消费进度从 WAL 直接读取数据,并使用统一的查询引擎实现过滤、变换等操作,将数据推送给消费者。
|
||||
|
||||
本文档不对消息队列本身的基础知识做介绍,如果需要了解,请自行搜索。
|
||||
|
||||
## 主要数据结构和API
|
||||
|
||||
TMQ 的 API 中,与订阅相关的主要数据结构和API如下:
|
||||
|
||||
```c
|
||||
typedef struct tmq_t tmq_t;
|
||||
typedef struct tmq_conf_t tmq_conf_t;
|
||||
typedef struct tmq_list_t tmq_list_t;
|
||||
|
||||
typedef void(tmq_commit_cb(tmq_t *, int32_t code, void *param));
|
||||
|
||||
DLL_EXPORT tmq_list_t *tmq_list_new();
|
||||
DLL_EXPORT int32_t tmq_list_append(tmq_list_t *, const char *);
|
||||
DLL_EXPORT void tmq_list_destroy(tmq_list_t *);
|
||||
DLL_EXPORT tmq_t *tmq_consumer_new(tmq_conf_t *conf, char *errstr, int32_t errstrLen);
|
||||
DLL_EXPORT const char *tmq_err2str(int32_t code);
|
||||
|
||||
DLL_EXPORT int32_t tmq_subscribe(tmq_t *tmq, const tmq_list_t *topic_list);
|
||||
DLL_EXPORT int32_t tmq_unsubscribe(tmq_t *tmq);
|
||||
DLL_EXPORT TAOS_RES *tmq_consumer_poll(tmq_t *tmq, int64_t timeout);
|
||||
DLL_EXPORT int32_t tmq_consumer_close(tmq_t *tmq);
|
||||
DLL_EXPORT int32_t tmq_commit_sync(tmq_t *tmq, const TAOS_RES *msg);
|
||||
DLL_EXPORT void tmq_commit_async(tmq_t *tmq, const TAOS_RES *msg, tmq_commit_cb *cb, void *param);
|
||||
|
||||
enum tmq_conf_res_t {
|
||||
TMQ_CONF_UNKNOWN = -2,
|
||||
TMQ_CONF_INVALID = -1,
|
||||
TMQ_CONF_OK = 0,
|
||||
};
|
||||
typedef enum tmq_conf_res_t tmq_conf_res_t;
|
||||
|
||||
DLL_EXPORT tmq_conf_t *tmq_conf_new();
|
||||
DLL_EXPORT tmq_conf_res_t tmq_conf_set(tmq_conf_t *conf, const char *key, const char *value);
|
||||
DLL_EXPORT void tmq_conf_destroy(tmq_conf_t *conf);
|
||||
DLL_EXPORT void tmq_conf_set_auto_commit_cb(tmq_conf_t *conf, tmq_commit_cb *cb, void *param);
|
||||
```
|
||||
|
||||
这些 API 的文档请见 [C/C++ Connector](/reference/connector/cpp),下面介绍一下它们的具体用法(超级表和子表结构请参考“数据建模”一节),完整的示例代码可以在 [tmq.c](https://github.com/taosdata/TDengine/blob/3.0/examples/c/tmq.c) 看到。
|
||||
|
||||
## 写入数据
|
||||
|
||||
首先完成建库、建一张超级表和多张子表操作,然后就可以写入数据了,比如:
|
||||
|
||||
```sql
|
||||
drop database if exists tmqdb;
|
||||
create database tmqdb;
|
||||
create table tmqdb.stb (ts timestamp, c1 int, c2 float, c3 varchar(16) tags(t1 int, t3 varchar(16));
|
||||
create table tmqdb.ctb0 using tmqdb.stb tags(0, "subtable0");
|
||||
create table tmqdb.ctb1 using tmqdb.stb tags(1, "subtable1");
|
||||
create table tmqdb.ctb2 using tmqdb.stb tags(2, "subtable2");
|
||||
create table tmqdb.ctb3 using tmqdb.stb tags(3, "subtable3");
|
||||
insert into tmqdb.ctb0 values(now, 0, 0, 'a0')(now+1s, 0, 0, 'a00');
|
||||
insert into tmqdb.ctb1 values(now, 1, 1, 'a1')(now+1s, 11, 11, 'a11');
|
||||
insert into tmqdb.ctb2 values(now, 2, 2, 'a1')(now+1s, 22, 22, 'a22');
|
||||
insert into tmqdb.ctb3 values(now, 3, 3, 'a1')(now+1s, 33, 33, 'a33');
|
||||
```
|
||||
|
||||
## 创建topic:
|
||||
|
||||
```sql
|
||||
create topic topicName as select ts, c1, c2, c3 from tmqdb.stb where c1 > 1;
|
||||
```
|
||||
|
||||
TMQ支持多种订阅类型:
|
||||
|
||||
### 列订阅
|
||||
|
||||
语法:CREATE TOPIC topic_name as subquery
|
||||
通过select语句订阅(包括select *,或select ts, c1等指定列描述订阅,可以带条件过滤、标量函数计算,但不支持聚合函数、不支持时间窗口聚合)
|
||||
|
||||
- TOPIC一旦创建则schema确定
|
||||
- 被订阅或用于计算的column和tag不可被删除、修改
|
||||
- 若发生schema变更,新增的column不出现在结果中
|
||||
|
||||
### 超级表订阅
|
||||
语法:CREATE TOPIC topic_name AS STABLE stbName
|
||||
|
||||
与select * from stbName订阅的区别是:
|
||||
- 不会限制用户的schema变更
|
||||
- 返回的是非结构化的数据:返回数据的schema会随之超级表的schema变化而变化
|
||||
- 用户对于要处理的每一个数据块都可能有不同的schema,因此,必须重新获取schema
|
||||
- 返回数据不带有tag
|
||||
|
||||
## 创建 consumer 以及consumer group
|
||||
|
||||
对于consumer, 目前支持的config包括:
|
||||
|
||||
| 参数名称 | 参数值 | 备注 |
|
||||
| ---------------------------- | ------------------------------ | ------------------------------------------------------ |
|
||||
| group.id | 最大长度:192 | |
|
||||
| enable.auto.commit | 合法值:true, false | |
|
||||
| auto.commit.interval.ms | | |
|
||||
| auto.offset.reset | 合法值:earliest, latest, none | |
|
||||
| td.connect.ip | 用于连接,同taos_connect的参数 | |
|
||||
| td.connect.user | 用于连接,同taos_connect的参数 | |
|
||||
| td.connect.pass | 用于连接,同taos_connect的参数 | |
|
||||
| td.connect.port | 用于连接,同taos_connect的参数 | |
|
||||
| enable.heartbeat.background | 合法值:true, false | 开启后台心跳,即consumer不会因为长时间不poll而认为离线 |
|
||||
| experimental.snapshot.enable | 合法值:true, false | 从wal开始消费,还是从tsbs开始消费 |
|
||||
| msg.with.table.name | 合法值:true, false | 从消息中能否解析表名 |
|
||||
|
||||
```sql
|
||||
/* 根据需要,设置消费组(group.id)、自动提交(enable.auto.commit)、自动提交时间间隔(auto.commit.interval.ms)、用户名(td.connect.user)、密码(td.connect.pass)等参数 */
|
||||
tmq_conf_t* conf = tmq_conf_new();
|
||||
tmq_conf_set(conf, "enable.auto.commit", "true");
|
||||
tmq_conf_set(conf, "auto.commit.interval.ms", "1000");
|
||||
tmq_conf_set(conf, "group.id", "cgrpName");
|
||||
tmq_conf_set(conf, "td.connect.user", "root");
|
||||
tmq_conf_set(conf, "td.connect.pass", "taosdata");
|
||||
tmq_conf_set(conf, "auto.offset.reset", "earliest");
|
||||
tmq_conf_set(conf, "experimental.snapshot.enable", "true");
|
||||
tmq_conf_set(conf, "msg.with.table.name", "true");
|
||||
tmq_conf_set_auto_commit_cb(conf, tmq_commit_cb_print, NULL);
|
||||
|
||||
tmq_t* tmq = tmq_consumer_new(conf, NULL, 0);
|
||||
tmq_conf_destroy(conf);
|
||||
return tmq;
|
||||
```
|
||||
|
||||
上述配置中包括consumer group ID,如果多个 consumer 指定的 consumer group ID一样,则自动形成一个consumer group,共享消费进度。
|
||||
|
||||
|
||||
## 创建 topic 列表
|
||||
|
||||
单个consumer支持同时订阅多个topic。
|
||||
|
||||
```sql
|
||||
tmq_list_t* topicList = tmq_list_new();
|
||||
tmq_list_append(topicList, "topicName");
|
||||
return topicList;
|
||||
```
|
||||
|
||||
## 启动订阅并开始消费
|
||||
|
||||
```sql
|
||||
/* 启动订阅 */
|
||||
tmq_subscribe(tmq, topicList);
|
||||
tmq_list_destroy(topicList);
|
||||
|
||||
/* 循环poll消息 */
|
||||
int32_t totalRows = 0;
|
||||
int32_t msgCnt = 0;
|
||||
int32_t timeOut = 5000;
|
||||
while (running) {
|
||||
TAOS_RES* tmqmsg = tmq_consumer_poll(tmq, timeOut);
|
||||
if (tmqmsg) {
|
||||
msgCnt++;
|
||||
totalRows += msg_process(tmqmsg);
|
||||
taos_free_result(tmqmsg);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "%d msg consumed, include %d rows\n", msgCnt, totalRows);
|
||||
```
|
||||
|
||||
这里是一个 **while** 循环,每调用一次tmq_consumer_poll(),获取一个消息,该消息与普通查询返回的结果集完全相同,可以使用相同的解析API完成消息内容的解析:
|
||||
|
||||
```sql
|
||||
static int32_t msg_process(TAOS_RES* msg) {
|
||||
char buf[1024];
|
||||
int32_t rows = 0;
|
||||
|
||||
const char* topicName = tmq_get_topic_name(msg);
|
||||
const char* dbName = tmq_get_db_name(msg);
|
||||
int32_t vgroupId = tmq_get_vgroup_id(msg);
|
||||
|
||||
printf("topic: %s\n", topicName);
|
||||
printf("db: %s\n", dbName);
|
||||
printf("vgroup id: %d\n", vgroupId);
|
||||
|
||||
while (1) {
|
||||
TAOS_ROW row = taos_fetch_row(msg);
|
||||
if (row == NULL) break;
|
||||
|
||||
TAOS_FIELD* fields = taos_fetch_fields(msg);
|
||||
int32_t numOfFields = taos_field_count(msg);
|
||||
int32_t* length = taos_fetch_lengths(msg);
|
||||
int32_t precision = taos_result_precision(msg);
|
||||
const char* tbName = tmq_get_table_name(msg);
|
||||
rows++;
|
||||
taos_print_row(buf, row, fields, numOfFields);
|
||||
printf("row content from %s: %s\n", (tbName != NULL ? tbName : "null table"), buf);
|
||||
}
|
||||
|
||||
return rows;
|
||||
}
|
||||
```
|
||||
|
||||
## 结束消费
|
||||
|
||||
```sql
|
||||
/* 取消订阅 */
|
||||
tmq_unsubscribe(tmq);
|
||||
|
||||
/* 关闭消费 */
|
||||
tmq_consumer_close(tmq);
|
||||
```
|
||||
|
||||
## 删除topic
|
||||
|
||||
如果不再需要,可以删除创建topic,但注意:只有没有被订阅的topic才能别删除。
|
||||
|
||||
```sql
|
||||
/* 删除topic */
|
||||
drop topic topicName;
|
||||
```
|
||||
|
||||
## 状态查看
|
||||
|
||||
1、topics:查询已经创建的topic
|
||||
|
||||
```sql
|
||||
show topics;
|
||||
```
|
||||
|
||||
2、consumers:查询consumer的状态及其订阅的topic
|
||||
|
||||
```sql
|
||||
show consumers;
|
||||
```
|
||||
|
||||
3、subscriptions:查询consumer与vgroup之间的分配关系
|
||||
|
||||
```sql
|
||||
show subscriptions;
|
||||
```
|
||||
|
||||
|
||||
|
|
|
@ -124,52 +124,49 @@ gcc -g -O0 -fPIC -shared add_one.c -o add_one.so
|
|||
|
||||
用户可以通过 SQL 指令在系统中加载客户端所在主机上的 UDF 函数库(不能通过 RESTful 接口或 HTTP 管理界面来进行这一过程)。一旦创建成功,则当前 TDengine 集群的所有用户都可以在 SQL 指令中使用这些函数。UDF 存储在系统的 MNode 节点上,因此即使重启 TDengine 系统,已经创建的 UDF 也仍然可用。
|
||||
|
||||
在创建 UDF 时,需要区分标量函数和聚合函数。如果创建时声明了错误的函数类别,则可能导致通过 SQL 指令调用函数时出错。此外, UDF 支持输入与输出类型不一致,用户需要保证输入数据类型与 UDF 程序匹配,UDF 输出数据类型与 OUTPUTTYPE 匹配。
|
||||
在创建 UDF 时,需要区分标量函数和聚合函数。如果创建时声明了错误的函数类别,则可能导致通过 SQL 指令调用函数时出错。此外,用户需要保证输入数据类型与 UDF 程序匹配,UDF 输出数据类型与 OUTPUTTYPE 匹配。
|
||||
|
||||
- 创建标量函数
|
||||
```sql
|
||||
CREATE FUNCTION ids(X) AS ids(Y) OUTPUTTYPE typename(Z) [ BUFSIZE B ];
|
||||
CREATE FUNCTION function_name AS library_path OUTPUTTYPE output_type;
|
||||
```
|
||||
|
||||
- ids(X):标量函数未来在 SQL 指令中被调用时的函数名,必须与函数实现中 udfNormalFunc 的实际名称一致;
|
||||
- ids(Y):包含 UDF 函数实现的动态链接库的库文件绝对路径(指的是库文件在当前客户端所在主机上的保存路径,通常是指向一个 .so 文件),这个路径需要用英文单引号或英文双引号括起来;
|
||||
- typename(Z):此函数计算结果的数据类型,与上文中 udfNormalFunc 的 itype 参数不同,这里不是使用数字表示法,而是直接写类型名称即可;
|
||||
- B:中间计算结果的缓冲区大小,单位是字节,最小 0,最大 512,如果不使用可以不设置。
|
||||
- function_name:标量函数未来在 SQL 中被调用时的函数名,必须与函数实现中 udf 的实际名称一致;
|
||||
- library_path:包含 UDF 函数实现的动态链接库的库文件绝对路径(指的是库文件在当前客户端所在主机上的保存路径,通常是指向一个 .so 文件),这个路径需要用英文单引号或英文双引号括起来;
|
||||
- output_type:此函数计算结果的数据类型名称;
|
||||
|
||||
例如,如下语句可以把 add_one.so 创建为系统中可用的 UDF:
|
||||
例如,如下语句可以把 libbitand.so 创建为系统中可用的 UDF:
|
||||
|
||||
```sql
|
||||
CREATE FUNCTION add_one AS "/home/taos/udf_example/add_one.so" OUTPUTTYPE INT;
|
||||
CREATE FUNCTION bit_and AS "/home/taos/udf_example/libbitand.so" OUTPUTTYPE INT;
|
||||
```
|
||||
|
||||
- 创建聚合函数:
|
||||
```sql
|
||||
CREATE AGGREGATE FUNCTION ids(X) AS ids(Y) OUTPUTTYPE typename(Z) [ BUFSIZE B ];
|
||||
CREATE AGGREGATE FUNCTION function_name AS library_path OUTPUTTYPE output_type [ BUFSIZE buffer_size ];
|
||||
```
|
||||
|
||||
- ids(X):聚合函数未来在 SQL 指令中被调用时的函数名,必须与函数实现中 udfNormalFunc 的实际名称一致;
|
||||
- ids(Y):包含 UDF 函数实现的动态链接库的库文件绝对路径(指的是库文件在当前客户端所在主机上的保存路径,通常是指向一个 .so 文件),这个路径需要用英文单引号或英文双引号括起来;
|
||||
- typename(Z):此函数计算结果的数据类型,与上文中 udfNormalFunc 的 itype 参数不同,这里不是使用数字表示法,而是直接写类型名称即可;
|
||||
- B:中间计算结果的缓冲区大小,单位是字节,最小 0,最大 512,如果不使用可以不设置。
|
||||
- function_name:聚合函数未来在 SQL 中被调用时的函数名,必须与函数实现中 udfNormalFunc 的实际名称一致;
|
||||
- library_path:包含 UDF 函数实现的动态链接库的库文件绝对路径(指的是库文件在当前客户端所在主机上的保存路径,通常是指向一个 .so 文件),这个路径需要用英文单引号或英文双引号括起来;
|
||||
- output_type:此函数计算结果的数据类型,与上文中 udfNormalFunc 的 itype 参数不同,这里不是使用数字表示法,而是直接写类型名称即可;
|
||||
- buffer_size:中间计算结果的缓冲区大小,单位是字节。如果不使用可以不设置。
|
||||
|
||||
关于中间计算结果的使用,可以参考示例程序[demo.c](https://github.com/taosdata/TDengine/blob/develop/tests/script/sh/demo.c)
|
||||
|
||||
例如,如下语句可以把 demo.so 创建为系统中可用的 UDF:
|
||||
例如,如下语句可以把 libsqrsum.so 创建为系统中可用的 UDF:
|
||||
|
||||
```sql
|
||||
CREATE AGGREGATE FUNCTION demo AS "/home/taos/udf_example/demo.so" OUTPUTTYPE DOUBLE bufsize 14;
|
||||
CREATE AGGREGATE FUNCTION sqr_sum AS "/home/taos/udf_example/libsqrsum.so" OUTPUTTYPE DOUBLE bufsize 8;
|
||||
```
|
||||
|
||||
### 管理 UDF
|
||||
|
||||
- 删除指定名称的用户定义函数:
|
||||
```
|
||||
DROP FUNCTION ids(X);
|
||||
DROP FUNCTION function_name;
|
||||
```
|
||||
|
||||
- ids(X):此参数的含义与 CREATE 指令中的 ids(X) 参数一致,也即要删除的函数的名字,例如
|
||||
- function_name:此参数的含义与 CREATE 指令中的 function_name 参数一致,也即要删除的函数的名字,例如
|
||||
```sql
|
||||
DROP FUNCTION add_one;
|
||||
DROP FUNCTION bit_and;
|
||||
```
|
||||
- 显示系统中当前可用的所有 UDF:
|
||||
```sql
|
||||
|
@ -180,53 +177,32 @@ SHOW FUNCTIONS;
|
|||
|
||||
在 SQL 指令中,可以直接以在系统中创建 UDF 时赋予的函数名来调用用户定义函数。例如:
|
||||
```sql
|
||||
SELECT X(c) FROM table/stable;
|
||||
SELECT X(c1,c2) FROM table/stable;
|
||||
```
|
||||
|
||||
表示对名为 c 的数据列调用名为 X 的用户定义函数。SQL 指令中用户定义函数可以配合 WHERE 等查询特性来使用。
|
||||
表示对名为 c1, c2 的数据列调用名为 X 的用户定义函数。SQL 指令中用户定义函数可以配合 WHERE 等查询特性来使用。
|
||||
|
||||
## UDF 的一些使用限制
|
||||
|
||||
在当前版本下,使用 UDF 存在如下这些限制:
|
||||
|
||||
1. 在创建和调用 UDF 时,服务端和客户端都只支持 Linux 操作系统;
|
||||
2. UDF 不能与系统内建的 SQL 函数混合使用,暂不支持在一条 SQL 语句中使用多个不同名的 UDF ;
|
||||
3. UDF 只支持以单个数据列作为输入;
|
||||
4. UDF 只要创建成功,就会被持久化存储到 MNode 节点中;
|
||||
5. 无法通过 RESTful 接口来创建 UDF;
|
||||
6. UDF 在 SQL 中定义的函数名,必须与 .so 库文件实现中的接口函数名前缀保持一致,也即必须是 udfNormalFunc 的名称,而且不可与 TDengine 中已有的内建 SQL 函数重名。
|
||||
|
||||
## 示例代码
|
||||
|
||||
### 标量函数示例 [add_one](https://github.com/taosdata/TDengine/blob/develop/tests/script/sh/add_one.c)
|
||||
### 标量函数示例 [bit_and](https://github.com/taosdata/TDengine/blob/develop/tests/script/sh/bit_and.c)
|
||||
|
||||
<details>
|
||||
<summary>add_one.c</summary>
|
||||
<summary>bit_and.c</summary>
|
||||
|
||||
```c
|
||||
{{#include tests/script/sh/add_one.c}}
|
||||
{{#include tests/script/sh/bit_and.c}}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
### 向量函数示例 [abs_max](https://github.com/taosdata/TDengine/blob/develop/tests/script/sh/abs_max.c)
|
||||
### 聚合函数示例 [sqr_sum](https://github.com/taosdata/TDengine/blob/develop/tests/script/sh/sqr_sum.c)
|
||||
|
||||
<details>
|
||||
<summary>abs_max.c</summary>
|
||||
<summary>sqr_sum.c</summary>
|
||||
|
||||
```c
|
||||
{{#include tests/script/sh/abs_max.c}}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
### 使用中间计算结果示例 [demo](https://github.com/taosdata/TDengine/blob/develop/tests/script/sh/demo.c)
|
||||
|
||||
<details>
|
||||
<summary>demo.c</summary>
|
||||
|
||||
```c
|
||||
{{#include tests/script/sh/demo.c}}
|
||||
{{#include tests/script/sh/sqr_sum.c}}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
|
|
@ -0,0 +1,270 @@
|
|||
---
|
||||
sidebar_label: SHOW 命令
|
||||
title: 使用 SHOW 命令查看系统元数据
|
||||
---
|
||||
|
||||
除了使用 `select` 语句查询 `INFORMATION_SCHEMA` 数据库中的表获得系统中的各种元数据、系统信息和状态之外,也可以用 `SHOW` 命令来实现同样的目的。
|
||||
|
||||
## SHOW ACCOUNTS
|
||||
|
||||
```sql
|
||||
SHOW ACCOUNTS;
|
||||
```
|
||||
|
||||
显示当前系统中所有租户的信息。
|
||||
|
||||
注:企业版独有
|
||||
|
||||
## SHOW APPS
|
||||
|
||||
```sql
|
||||
SHOW APPS;
|
||||
```
|
||||
|
||||
显示接入集群的应用(客户端)信息。
|
||||
|
||||
## SHOW BNODES
|
||||
|
||||
```sql
|
||||
SHOW BNODES;
|
||||
```
|
||||
|
||||
显示当前系统中存在的 BNODE (backup node, 即备份节点)的信息。
|
||||
|
||||
## SHOW CLUSTER
|
||||
|
||||
```sql
|
||||
SHOW CLUSTER;
|
||||
```
|
||||
|
||||
显示当前集群的信息
|
||||
|
||||
## SHOW CONNECTIONS
|
||||
|
||||
```sql
|
||||
SHOW CONNECTIONS;
|
||||
```
|
||||
|
||||
显示当前系统中存在的连接的信息。
|
||||
|
||||
## SHOW CONSUMERS
|
||||
|
||||
```sql
|
||||
SHOW CONSUMERS;
|
||||
```
|
||||
|
||||
显示当前数据库下所有活跃的消费者的信息。
|
||||
|
||||
## SHOW CREATE DATABASE
|
||||
|
||||
```sql
|
||||
SHOW CREATE DATABASE db_name;
|
||||
```
|
||||
|
||||
显示 db_name 指定的数据库的创建语句。
|
||||
|
||||
## SHOW CREATE STABLE
|
||||
|
||||
```sql
|
||||
SHOW CREATE STABLE [db_name.]stb_name;
|
||||
```
|
||||
|
||||
显示 tb_name 指定的超级表的创建语句
|
||||
|
||||
## SHOW CREATE TABLE
|
||||
|
||||
```sql
|
||||
SHOW CREATE TABLE [db_name.]tb_name
|
||||
```
|
||||
|
||||
显示 tb_name 指定的表的创建语句。支持普通表、超级表和子表。
|
||||
|
||||
## SHOW DATABASES
|
||||
|
||||
```sql
|
||||
SHOW DATABASES;
|
||||
```
|
||||
|
||||
显示用户定义的所有数据库。
|
||||
|
||||
## SHOW DNODES
|
||||
|
||||
```sql
|
||||
SHOW DNODES;
|
||||
```
|
||||
|
||||
显示当前系统中 DNODE 的信息。
|
||||
|
||||
## SHOW FUNCTIONS
|
||||
|
||||
```sql
|
||||
SHOW FUNCTIONS;
|
||||
```
|
||||
|
||||
显示用户定义的自定义函数。
|
||||
|
||||
## SHOW LICENSE
|
||||
|
||||
```sql
|
||||
SHOW LICENSE;
|
||||
SHOW GRANTS;
|
||||
```
|
||||
|
||||
显示企业版许可授权的信息。
|
||||
|
||||
注:企业版独有
|
||||
|
||||
## SHOW INDEXES
|
||||
|
||||
```sql
|
||||
SHOW INDEXES FROM tbl_name [FROM db_name];
|
||||
```
|
||||
|
||||
显示已创建的索引。
|
||||
|
||||
## SHOW LOCAL VARIABLES
|
||||
|
||||
```sql
|
||||
SHOW LOCAL VARIABLES;
|
||||
```
|
||||
|
||||
显示当前客户端配置参数的运行值。
|
||||
|
||||
## SHOW MNODES
|
||||
|
||||
```sql
|
||||
SHOW MNODES;
|
||||
```
|
||||
|
||||
显示当前系统中 MNODE 的信息。
|
||||
|
||||
## SHOW MODULES
|
||||
|
||||
```sql
|
||||
SHOW MODULES;
|
||||
```
|
||||
|
||||
显示当前系统中所安装的组件的信息。
|
||||
|
||||
## SHOW QNODES
|
||||
|
||||
```sql
|
||||
SHOW QNODES;
|
||||
```
|
||||
|
||||
显示当前系统中 QNODE (查询节点)的信息。
|
||||
|
||||
## SHOW SCORES
|
||||
|
||||
```sql
|
||||
SHOW SCORES;
|
||||
```
|
||||
|
||||
显示系统被许可授权的容量的信息。
|
||||
|
||||
注:企业版独有
|
||||
|
||||
## SHOW SNODES
|
||||
|
||||
```sql
|
||||
SHOW SNODES;
|
||||
```
|
||||
|
||||
显示当前系统中 SNODE (流计算节点)的信息。
|
||||
|
||||
## SHOW STABLES
|
||||
|
||||
```sql
|
||||
SHOW [db_name.]STABLES [LIKE 'pattern'];
|
||||
```
|
||||
|
||||
显示当前数据库下的所有超级表的信息。可以使用 LIKE 对表名进行模糊匹配。
|
||||
|
||||
## SHOW STREAMS
|
||||
|
||||
```sql
|
||||
SHOW STREAMS;
|
||||
```
|
||||
|
||||
显示当前系统内所有流计算的信息。
|
||||
|
||||
## SHOW SUBSCRIPTIONS
|
||||
|
||||
```sql
|
||||
SHOW SUBSCRIPTIONS;
|
||||
```
|
||||
|
||||
显示当前数据库下的所有的订阅关系
|
||||
|
||||
## SHOW TABLES
|
||||
|
||||
```sql
|
||||
SHOW [db_name.]TABLES [LIKE 'pattern'];
|
||||
```
|
||||
|
||||
显示当前数据库下的所有普通表和子表的信息。可以使用 LIKE 对表名进行模糊匹配。
|
||||
|
||||
## SHOW TABLE DISTRIBUTED
|
||||
|
||||
```sql
|
||||
SHOW TABLE DISTRIBUTED table_name;
|
||||
```
|
||||
|
||||
显示表的数据分布信息。
|
||||
|
||||
## SHOW TAGS
|
||||
|
||||
```sql
|
||||
SHOW TAGS FROM child_table_name [FROM db_name];
|
||||
```
|
||||
|
||||
显示子表的标签信息。
|
||||
|
||||
## SHOW TOPICS
|
||||
|
||||
```sql
|
||||
SHOW TOPICS;
|
||||
```
|
||||
|
||||
显示当前数据库下的所有主题的信息。
|
||||
|
||||
## SHOW TRANSACTIONS
|
||||
|
||||
```sql
|
||||
SHOW TRANSACTIONS;
|
||||
```
|
||||
|
||||
显示当前系统中正在执行的事务的信息
|
||||
|
||||
## SHOW USERS
|
||||
|
||||
```sql
|
||||
SHOW USERS;
|
||||
```
|
||||
|
||||
显示当前系统中所有用户的信息。包括用户自定义的用户和系统默认用户。
|
||||
|
||||
## SHOW VARIABLES
|
||||
|
||||
```sql
|
||||
SHOW VARIABLES;
|
||||
SHOW DNODE dnode_id VARIABLES;
|
||||
```
|
||||
|
||||
显示当前系统中各节点需要相同的配置参数的运行值,也可以指定 DNODE 来查看其的配置参数。
|
||||
|
||||
## SHOW VGROUPS
|
||||
|
||||
```sql
|
||||
SHOW [db_name.]VGROUPS;
|
||||
```
|
||||
|
||||
显示当前系统中所有 VGROUP 或某个 db 的 VGROUPS 的信息。
|
||||
|
||||
## SHOW VNODES
|
||||
|
||||
```sql
|
||||
SHOW VNODES [dnode_name];
|
||||
```
|
||||
|
||||
显示当前系统中所有 VNODE 或某个 DNODE 的 VNODE 的信息。
|
|
@ -8,21 +8,30 @@ title: 用户自定义函数
|
|||
## 创建函数
|
||||
|
||||
```sql
|
||||
CREATE [AGGREGATE] FUNCTION func_name AS library_path OUTPUTTYPE type_name [BUFSIZE value]
|
||||
CREATE [AGGREGATE] FUNCTION func_name AS library_path OUTPUTTYPE type_name [BUFSIZE buffer_size]
|
||||
```
|
||||
|
||||
语法说明:
|
||||
|
||||
AGGREGATE:标识此函数是标量函数还是聚集函数。
|
||||
func_name:函数名,必须与函数实现中udfNormalFunc的实际名称一致。
|
||||
func_name:函数名,必须与函数实现中 udf 的实际名称一致。
|
||||
library_path:包含UDF函数实现的动态链接库的绝对路径,是在客户端侧主机上的绝对路径。
|
||||
OUTPUTTYPE:标识此函数的返回类型。
|
||||
BUFSIZE:中间结果的缓冲区大小,单位是字节。不设置则默认为0。最大不可超过512字节。
|
||||
type_name:标识此函数的返回类型。
|
||||
buffer_size:中间结果的缓冲区大小,单位是字节。不设置则默认为0。
|
||||
|
||||
关于如何开发自定义函数,请参考 [UDF使用说明](../../develop/udf)。
|
||||
|
||||
## 删除自定义函数
|
||||
|
||||
```
|
||||
DROP FUNCTION function_name;
|
||||
```
|
||||
|
||||
- function_name:此参数的含义与 CREATE 指令中的 function_name 参数一致,也即要删除的函数的名字,例如
|
||||
|
||||
|
||||
## 显示 UDF
|
||||
|
||||
```sql
|
||||
DROP FUNCTION func_name
|
||||
```
|
||||
SHOW FUNCTION;
|
||||
```
|
||||
|
|
|
@ -0,0 +1,481 @@
|
|||
---
|
||||
sidebar_label: 错误码
|
||||
title: TDengine C/C++ 连接器错误码
|
||||
---
|
||||
|
||||
本文中详细列举了在使用 TDengine C/C++ 连接器时客户端可能得到的错误码以及所要采取的相应动作。其它语言的连接器在使用原生连接方式时也会所得到的返回码返回给连接器的调用者。
|
||||
|
||||
| **Error Code** | **说明** | 如何处理错误 |
|
||||
| -------------- | ------------------ | ------------ |
|
||||
| 0 | 请求处理成功 | None |
|
||||
| -1 | 请求失败,未知原因 | TODO |
|
||||
| 0x0003 | RPC 认证失败 | TODO |
|
||||
| 0x0004 | RPC 重定向 |TODO|
|
||||
| 0x000B | 无法建立连接 |TODO|
|
||||
| 0x0015 | FQDN 解析失败 |检查各个dnode配置的FQDN是否正确,并且能够从其它节点 ping 到 |
|
||||
| 0x0017 | 端口已经被占用 | 检查所配置的端口被哪个进程占用,关闭该进程以释放端口;或者更改配置使用另一端口号 |
|
||||
| 0x0018 | 连接被断开 | 检查 dnode 进程是否还在,如果无异常检查网络情况 |
|
||||
| 0x0013 | 客户端和服务端的时间未同步 | 检查客户端和服务端的时间设置是否同步|
|
||||
| 0x0014 | 数据库不可用 |检查数据库是否存在,检查数据库的vgroups的状态 |
|
||||
| 0x0100 | 该操作不支持 | 参考SQL手册,使用正确的操作 |
|
||||
| 0x0102 | 无法分配内存,系统内存耗尽 | 检查系统中内存被耗尽的原因,采取措施释放内存。如果内存是被 dnode 耗尽的话重启该进程 |
|
||||
| 0x0104 | 文件被破坏 | TODO |
|
||||
| 0x0111 | 操作在进行中 | 等待该操作完成 |
|
||||
| 0x0115 | 无效的消息 | TODO |
|
||||
| 0x0116 | 无效的消息长度 | TODO |
|
||||
| 0x0117 | 无效指针 | TODO |
|
||||
| 0x0118 | 无效参数 | |
|
||||
| 0x0119 | 无效配置 | 检查配置参数的值是否在合法值域范围内 |
|
||||
| 0x011A | 无效选项 | 检查配置中是否有不支持的无效配置项 |
|
||||
| 0x011B | 无效的JSON 格式 | 修正插入数据中的JSON值|
|
||||
| 0x011C | 无效版本号 | 检查客户端版本是否匹配,更换正确的客户端 |
|
||||
| 0x011D | 无效版本信息 | 检查客户端版本是否匹配,更换正确的客户端 |
|
||||
| 0x011E | 版本不匹配 | TODO |
|
||||
| 0x011F | 校验和错误 | TODO |
|
||||
| 0x0120 | 数据压缩失败 | TODO |
|
||||
| 0x0121 | 消息未处理 | TODO |
|
||||
| 0x0122 | 配置未找到 | TODO|
|
||||
| 0x0123 | 重复初始化 | TODO |
|
||||
| 0x0124 | 无法将重复的key加入hash| TODO |
|
||||
| 0x0125 | 需要重试 | 重试 |
|
||||
| 0x0126 | RPC 队列内存耗尽 | TODO |
|
||||
| 0x0127 | 无效的时间戳 | 修正插入数据 |
|
||||
| 0x0128 | 消息解码失败 | 检查客户端版本是否匹配和兼容 |
|
||||
| 0x0129 | 磁盘耗尽 | TODO |
|
||||
| 0x012A | TODO | TODO |
|
||||
| 0x0200 | 无效操作 | 检查SQL命令,根据SQL手册使用正确的操作|
|
||||
| 0x0201 | 无效的查询句柄 | TODO |
|
||||
| 0x0202 | 无效的客户端/服务端时间组合 | TODO |
|
||||
| 0x0203 | 无效值 | TODO |
|
||||
| 0x0204 | 无效的客户端版本 | 检查客户端版本是否匹配,更换为正确的客户端版本 |
|
||||
| 0x0205 | TODO | TODO |
|
||||
| 0x0206 | 无效的 FQDN | 检查服务器 fqdn 配置是否正确,是否能够从其它服务器访问到该 fqdn |
|
||||
| 0x0207 | 用户名长度过长 | 检查用户名长度是否过长 |
|
||||
| 0x0208 | 密码长度过长 | 检查密码长度是否过长 |
|
||||
| 0x0209 | 数据库名字长度过长 | 检查数据库名是否过长 |
|
||||
| 0x020A | 表名长度过长 | 检查表名是否过长 |
|
||||
| 0x020B | 无效连接 | 检查该连接是否已经断开 |
|
||||
| 0x020C | 系统内存耗尽 | 检查系统中内存被耗尽的原因,尝试释放出内存 |
|
||||
| 0x020D | 磁盘空间耗尽 | 检查系统中磁盘耗尽的原因,尝试释放或增加磁盘空间 |
|
||||
| 0x020E | 查询缓存被清除 |TODO |
|
||||
| 0x020F | 查询已经被结束 | 尝试优化查询条件再重启查询 |
|
||||
| 0x0210 | 结果集过大无法存储 | 尝试优化查询条件,缩小结果集,再重启查询 |
|
||||
| 0x0211 | 数据库不可用 | 查看数据库是否存在,查看数据库的 vgroups 状态 |
|
||||
| 0x0212 | 操作正在进行中 | 等待操作完成 |
|
||||
| 0x0213 | 连接被服务端断开 | 查看服务端进程是否发生 crash 等异常终止情况 |
|
||||
| 0x0214 | 没有写权限 | 只进行读操作或者尝试获取写权限 |
|
||||
| 0x0215 | 连接被 kill | 重新建立连接 |
|
||||
| 0x0216 | SQL 语法错误 | 参考 SQL手册,纠正语法错误再重试 |
|
||||
| 0x0217 | 未指定数据库或者指定的数据库不可用 | 指定数据库,或者检查指定数据库的状态 |
|
||||
| 0x0218 | 所查询的表不存在 | 确认表名后纠正查询语句 |
|
||||
| 0x0219 | SQL 语句超长 | 根据 maxSQLLength 缩短SQL语句或者加大maxSQLLength (如果还未配置到上限)|
|
||||
| 0x021A | 空文件 | TODO |
|
||||
| 0x021B | Line 协议语法错误 | 纠正插入语句 |
|
||||
| 0x021C | 元数据未被缓存 | TODO |
|
||||
| 0x021D | 重复的列名 | 纠正SQL语句中的相应错误 |
|
||||
| 0x021E | tag 过长 | 纠正过长的 tag |
|
||||
| 0x021F | 列名过长 | 纠正过长的列名 |
|
||||
| 0x0220 | 重复的表名**TODO** | TODO|
|
||||
| 0x0221 | JSON 格式错误 | 纠正错误的 JSON 结构 |
|
||||
| 0x0222 | JSON 中使用了无效的数据类型 | 纠正 JSON 结构中的错误 |
|
||||
| 0x0224 | 超出了所支持的值域 | 纠正到值域范围内 |
|
||||
| 0x0229 | 无效的 tsc 输入 **TODO** | TODO |
|
||||
| 0x022A | stmt API 使用错误 | 根据参考手册正确使用 |
|
||||
| 0x022B | stmt 使用时未指定表名 | 指定表名 |
|
||||
| 0x022C | 不支持 stmt 子名 | 根据参考手册纠正错误用法 |
|
||||
| 0x022D | 查询被 kill | 优化查询语句,尽量减小计算量和结果集,然后重新启动查询 |
|
||||
| 0x022E | 在当前配置的查询策略下没有可用的计算节点 | 创建新的 qnode |
|
||||
| 0x022F | 所指定的表不是超级表 | 确认下该查询场景适用于超级表还是子表/普通表,如果是前者则纠正为超级表名 |
|
||||
| 0x0303 | 没有权限进行所发起的操作 | 申请权限或调整操作 |
|
||||
| 0x0304 | 管理节点内部错误 | TODO |
|
||||
| 0x0305 | 无效连接 | TODO |
|
||||
| 0x030B | 所要展示的操作其数据已经因为超时而被删除 | 更换想要展示操作或者放弃此次操作 |
|
||||
| 0x030C | 无效的查询ID| 确认正确的查询ID再重新发起 |
|
||||
| 0x030D | 无效的流ID| 确认正确的流ID再重新发起|
|
||||
| 0x030E | 无效的连接ID| 确认正确的连接ID再重新发起|
|
||||
| 0x0310 | mnode已经在运行 | 无须采取任何动作 |
|
||||
| 0x0311 | 配置同步失败 | TODO |
|
||||
| 0x0312 | 无法启动同步 | TODO |
|
||||
| 0x0313 | 无法创建 mnode 对应的目录 | 确认磁盘上是否有可用空间以及是否有相应的写权限 |
|
||||
| 0x0314 | 启动组件失败 | TODO |
|
||||
| 0x0315 | 用户帐号被禁用 | 联系管理员激活该帐号 |
|
||||
| 0x0320 | 元数据中已经存在所要创建的对象 | 检查所要创建的对象,比如超级表或表,是否已经存在 |
|
||||
| 0x0321 | 元数据库中非预期的一般性错误 | TODO |
|
||||
| 0x0322 | 无效的表类型 | TODO |
|
||||
| 0x0323 | 所要查找的对象不存在 | TODO |
|
||||
| 0x0325 | 无效的 key 类型 | TODO |
|
||||
| 0x0326 | 无效的动作类型 | TODO |
|
||||
| 0x0327 | 无效的状态类型 | TODO |
|
||||
| 0x0328 | 无效的原始数据版本 | TODO |
|
||||
| 0x0329 | 无效的原始数据长度 | TODO |
|
||||
| 0x032A | 无效的原始数据内容 | TODO |
|
||||
| 0x032B | 无效的 wal 版本 | TODO |
|
||||
| 0x032C | 对象创建中 | TODO |
|
||||
| 0x032D | 对象停止中 | TODO |
|
||||
| 0x0330 | dnode 已经存在 | 无需任何动作,放弃重复创建dnode的操作 |
|
||||
| 0x0331 | dnode 不存在 | 确认所要查询或者操作的dnode ID 或者 end point 是否正确 |
|
||||
| 0x0332 | vgroup 不存在 | 确认所要查询或者操作的vgroup ID 是否正确 |
|
||||
| 0x0333 | 系统拒绝 drop 其角色是 leader 的 mnode | 放弃该操作 |
|
||||
| 0x0334 | 没有足够的 dnode 创建所指定的 vgroups | 增加 dnode 或者修改现有dnode的配置参数 `supportVgroups` |
|
||||
| 0x0335 | 集群中各个dnode的配置不一致 | 检查各个dnode的配置参数确保其一致 |
|
||||
| 0x0338 | 所要查询或操作的vgroup不在所指定的dnode中| 检查vgroup ID 和 dnode ID是否正确 |
|
||||
| 0x0339 | 所要查询或操作的 vgroup 已经在所指定的dnode中 | 检查 vgroup ID 和 dnode ID是否正确 |
|
||||
| 0x033B | 集群 ID 不匹配 | TODO |
|
||||
| 0x0340 | 该帐户已经存在 | 放弃重复创建帐户的操作 |
|
||||
| 0x0342 | 无效的帐户选项 | 检查创建帐户时的参数选项是否正确 |
|
||||
| 0x0343 | 帐户授权已经过期 | 联系管理员重新授权 |
|
||||
| 0x0344 | 无效帐户 | 联系管理员确认帐户 |
|
||||
| 0x0345 | 操作的帐户过多,无法支持 | 减少同时操作的帐户数 |
|
||||
| 0x0350 | 用户已经存在 | 放弃重复创建用户的操作 |
|
||||
| 0x0351 | 无效用户 | 检查并确认正确用户 |
|
||||
| 0x0352 | 无效的用户名格式 | 查看参考手册修改用户名 |
|
||||
| 0x0353 | 无效的密码格式 | 查看参考手册修改密码 |
|
||||
| 0x0354 | 无法从连接中获取用户名 | 检查客户端环境初始化是否使用了正确的用户名 |
|
||||
| 0x0355 | 一次尝试操作的用户过多 | 查看参考手册减少同时操作的用户数 |
|
||||
| 0x0356 | 无效的修改操作 | 查看参考手册使用正确的操作 |
|
||||
| 0x0357 | 认证失败 | 使用正确的用户名和密码 |
|
||||
| 0x0360 | 要创建的超级表已经存在 | 放弃重复创建的操作或者删除该超级表再重新创建 |
|
||||
| 0x0362 | 所使用或查询的超级表不存在 | 确认超级表名是否正确,如果正确则需要先创建超级表 |
|
||||
| 0x0364 | 标签过多 | 查看参考手册减少标签数量 |
|
||||
| 0x0365 | 列过多 | 查看参考手册减少列数量 |
|
||||
| 0x0369 | 要添加的标签已经存在 | 修改标签名 |
|
||||
| 0x036A | 要查询或修改的标签不存在 | 确认标签名是否正确 |
|
||||
| 0x036B | 要添加的列已经存在 | 修改列名或者放弃该操作 |
|
||||
| 0x036C | 要查询或修改的列不存在 | 确认列名是否正确 |
|
||||
| 0x036E | 无效的超级表操作 | 查看参考手册进行正确的操作 |
|
||||
| 0x036F | 错误的行字节数 | TODO |
|
||||
| 0x0370 | 无效的函数名 | 确认函数名是否正确 |
|
||||
| 0x0372 | 无效的函数代码 | 无效的函数编码 |
|
||||
| 0x0373 | 该函数已经存在 | 修改函数名或者放弃该操作|
|
||||
| 0x0374 | 所引用的函数不存在 | 确认函数名是否正确 |
|
||||
| 0x0375 | 无效的 bufSize | 查看参考手册修改 bufSize |
|
||||
| 0x0378 | 无效的函数注释 | 查看参考手册修改函数注释 |
|
||||
| 0x0379 | 无效的函数检索消息 | TODO |
|
||||
| 0x0380 | 未指定数据库或者指定的数据库不可用 | 指定数据库,或者检查所指定的数据库的状态 |
|
||||
| 0x0381 | 数据库已经存在 | 放弃重复创建,或者修改数据库名 |
|
||||
| 0x0382 | 无效的数据库参数 | 查看参考手册使用正确的参数 |
|
||||
| 0x0383 | 无效的数据库名称 | 查看参考手册使用正确的数据库名 |
|
||||
| 0x0385 | 该帐号下的数据库过多 | 删除旧的数据库再尝试创建新数据库 |
|
||||
| 0x0388 | 数据库不存在 | 确认数据库名是否正确 |
|
||||
| 0x0389 | 无效的数据库帐户 | 确认帐户是否正确 |
|
||||
| 0x038A | 数据库参数未修改 | 查看参考手册确认修改的参数和值是否正确 |
|
||||
| 0x038B | 索引不存在 |确认索引名称是否正确 |
|
||||
| 0x039A | 无效的系统表名 | 查看参考手册确认表名是否正确 |
|
||||
| 0x03A0 | mnode 已经存在 | 放弃该操作 |
|
||||
| 0x03A1 | mnode 不存在 | 确认要查看或操作的 mnode ID |
|
||||
| 0x03A2 | qnode 已经存在 | 放弃该操作 |
|
||||
| 0x03A3 | qnode 不存在 | 确认要查看或操作的 qnode ID 是否正确 |
|
||||
| 0x03A8 | mnode 的 replica 不能小于1 | 停止 drop mnode |
|
||||
| 0x03A9 | mnode 的 replica 不能大于3 | 停止 create mnode |
|
||||
| 0x03B0 | dnode 数量过多 | 停止添加新的 dnode |
|
||||
| 0x03B1 | dnode 没有足够的可用内存 | 检查所在系统的内存使用情况 ,尝试释放出内存 |
|
||||
| 0x03B2 | 无效的 dnode 配置 | 查看参考手册纠正配置 |
|
||||
| 0x03B3 | 无效的 dnode 地址 | 确认 dnode 的 FQDN 和 serverPort参数是否正确 |
|
||||
| 0x03B4 | 无效的 dnode ID | 确认正确的 dnode ID |
|
||||
| 0x03B5 | vgroup 的分布未发生变化 | TODO |
|
||||
| 0x03B6 | 存在状态为 offline 的 dnode | drop 这些 dnode 或者启动相应的 dnode 使其状态为 ready |
|
||||
| 0x03B7 | 无效的 vgroup 副本 | TODO |
|
||||
| 0x03C0 | topic 与超级表冲突 | TODO |
|
||||
| 0x03C1 | 订阅了过多的超级表 | 查看参考手册减少超级表数量 |
|
||||
| 0x03C2 | 无效的 超级表修改参数 | 查看参考手册进行纠正 |
|
||||
| 0x03C3 | 超级表参数未被修改 | 查看参考手册确认参数是否正确 |
|
||||
| 0x03C4 | 该字段被某个主题所使用 | TODO |
|
||||
| 0x03C5 | 该数据库是单超级表模式 | 修改数据库为多超级表模式或者放弃创建新的超级表 |
|
||||
| 0x03C6 | 修改超级表使用了无效的 schema 版本 | TODO |
|
||||
| 0x03C7 | 修改超级表使用了无效的超级表 ID | 确认超级表使用是否正确 |
|
||||
| 0x03C8 | 该字段被 tsma 所使用 | TODO |
|
||||
| 0x03D0 | 该事务已经存在 | TODO |
|
||||
| 0x03D1 | 该事务不存在 | TODO |
|
||||
| 0x03D2 | 要 kill 的 stage 不存在 | TODO |
|
||||
| 0x03D3 | 冲突的事务没有完成 | TODO |
|
||||
| 0x03D4 | 未知的事务错误 | TODO |
|
||||
| 0x03D5 | 事务提交日志已满 | TODO |
|
||||
| 0x03DF | 在执行事务时无法建立连接 | 等待事务完成尝试重新建立连接 |
|
||||
| 0x03E0 | Topic 已经存在 | 修改 topic 名字或者放弃创建重复的 topic |
|
||||
| 0x03E1 | Topic 不存在 | 确认 Topic 名字是否正确 |
|
||||
| 0x03E2 | Topic 过多 | 尝试删除不用的 topic 再建立新的,或者放弃此次操作 |
|
||||
| 0x03E3 | 无效的 Topic | 确认 Topic 是否正确 |
|
||||
| 0x03E4 | 建立 Topic 的查询子名无效 | 查看参考手册纠正查询子名 |
|
||||
| 0x03E5 | 建立 Topic 的参数无效 | 查看参考手册使用正确的参数 |
|
||||
| 0x03E6 | 消费者不存在 | 确认正确的消费者 ID |
|
||||
| 0x03E7 | 消费者未修改 | TODO |
|
||||
| 0x03E8 | 订阅不存在 | 确认正确的订阅 ID |
|
||||
| 0x03E9 | 偏移量不存在 | 纠正偏移量 |
|
||||
| 0x03EA | 消费者不可用 | TODO |
|
||||
| 0x03EB | 无法删除已经被订阅的 Topic | 先取消订阅再尝试删除 |
|
||||
| 0x03EC | Consumer group正在被某些消费者使用 | TODO |
|
||||
| 0x03F0 | 流已经存在 | 修改流名称或者放弃创建该流 |
|
||||
| 0x03F1 | 要查询或操作的流不存在 | 确认正确的流 ID |
|
||||
| 0x03F2 | 无效的流参数 | 查看参考手册纠正错误的参数 |
|
||||
| 0x0480 | SMA 已经存在 | 修改 SMA 名称或者放弃创建 |
|
||||
| 0x0481 | SMA 不存在 | 确认正确的 SMA 名称或者 ID |
|
||||
| 0x0482 | SMA 参数错误 | 查看参考手册纠正参数 |
|
||||
| 0x0408 | 节点不在线 | TODO |
|
||||
| 0x0409 | 节点已经部署 | TODO |
|
||||
| 0x040A | 节点未部署 | TODO |
|
||||
| 0x0500 | 该动作作在进行中| TODO |
|
||||
| 0x0501 | 消息未被处理 | TODO |
|
||||
| 0x0502 | 该动作需要被重新处理 | TODO |
|
||||
| 0x0503 | 无效的 vgroup ID | 检查确认正确的 vgroups ID |
|
||||
| 0x0504 | vnode 初始化失败 | TODO |
|
||||
| 0x0505 | 系统磁盘空间耗尽 | 尝试释放或者增加磁盘空间 |
|
||||
| 0x0506 | 对磁盘文件没有写权限 | 检查启动 TDengine 的系统帐号的写权限 |
|
||||
| 0x0507 | 数据文件缺失 | TODO |
|
||||
| 0x0508 | vnode 没有可用内存 | TODO |
|
||||
| 0x0509 | vnode 中未预期的一般性错误 | TODO |
|
||||
| 0x050C | 数据库无空闲内存 | TODO |
|
||||
| 0x050D | 数据库正在删除中 | TODO |
|
||||
| 0x050E | 数据库正在更新中 | TODO |
|
||||
| 0x0510 | 数据库正在关闭中 | TODO |
|
||||
| 0x0511 | 数据库被暂停操作 | TODO |
|
||||
| 0x0512 | 数据库写操作被拒绝 | 检查用户权限,申请写操作授权 |
|
||||
| 0x0513 | 数据库正在同步中 | TODO |
|
||||
| 0x0514 | 无效的 tsdb 状态 | TODO |
|
||||
| 0x0520 | 指定的表不存在 | 检查确认正确的表名 |
|
||||
| 0x0521 | 指定的SMA 不存在 | 检查确认正确的 SMA名称 |
|
||||
| 0x0522 | Hash 值不匹配 | TODO |
|
||||
| 0x0523 | 指定的表不存在 | 检查确认正确的表名 |
|
||||
| 0x0524 | 无效的表动作 | TODO |
|
||||
| 0x0525 | 列名已经存在 | 修改列名或放弃操作 |
|
||||
| 0x0526 | 列名不存在 | 确认正确的列名 |
|
||||
| 0x0527 | 该列已经被订阅 | 先取消订阅再操作或者放弃操作 |
|
||||
| 0x0528 | 无效的配置文件 | 检查配置文件的路径和访问权限 |
|
||||
| 0x0529 | 无效的 term 文件 | TODO |
|
||||
| 0x0600 | 无效的表 ID | 确认表名是否正确 |
|
||||
| 0x0601 | 无效的表 类型 | TODO |
|
||||
| 0x0602 | 无效的 schema 版本 | TODO |
|
||||
| 0x0603 | 表已经存在 | 修改表名或放弃操作 |
|
||||
| 0x0604 | 配置无效 | 查看参考手册纠正配置 |
|
||||
| 0x0605 | TSDB 初始化失败 | TODO |
|
||||
| 0x0606 | 磁盘空间耗尽 | 查看磁盘空间耗尽的原因,尝试释放或增加磁盘空间 |
|
||||
| 0x0607 | 磁盘文件没有访问权限 | 确认启动集群的系统帐户是否有相应的写权限 |
|
||||
| 0x0608 | 数据文件被破坏 | TODO |
|
||||
| 0x0609 | 内存耗尽 | 检查内存被耗尽的原因,尝试释放内存 |
|
||||
| 0x060A | 标签版本过老 | TODO |
|
||||
| 0x060B | 时间戳不在允许范围内 | 查看参考手册了解允许写入的时间戳规则 |
|
||||
| 0x060C | 提交消息被破坏 | TODO |
|
||||
| 0x060D | 无效操作 | TODO |
|
||||
| 0x060E | 建表消息无效 | TODO |
|
||||
| 0x060F | 内存跳表中没有表的数据 | TODO |
|
||||
| 0x0610 | 文件已经存在 | TODO |
|
||||
| 0x0611 | 需要重新配置该表 | TODO |
|
||||
| 0x0612 | 建表的信息无效 | TODO |
|
||||
| 0x0613 | 磁盘空间耗尽 | 尝试释放或增加磁盘空间 |
|
||||
| 0x0614 | 消息被破坏 |TODO |
|
||||
| 0x0615 | 无效的标签值 | 修正标签值 |
|
||||
| 0x0616 | 未缓存最后一行的原始数据 | 修改数据库的 cacheModel 参数 |
|
||||
| 0x0618 | 该表不存在 | 检查表名是否正确 |
|
||||
| 0x0619 | 超级表已经存在 | 修改超级表名再次尝试 |
|
||||
| 0x061A | 超级表不存在 | 检查超级表名是否正确 |
|
||||
| 0x061B | 表被重新创建 | TODO |
|
||||
| 0x061C | TDB 环境打开错误 | N/A |
|
||||
| 0x0700 | 无效的查询句柄 | N/A |
|
||||
| 0x0701 | 无效的消息 | TODO |
|
||||
| 0x0702 | 磁盘空间耗尽 | 尝试释放或增加磁盘空间 |
|
||||
| 0x0703 | 系统内存耗尽 | 尝试释放内存 |
|
||||
| 0x0704 | 未知错误 | TODO |
|
||||
| 0x0705 | 重复的 Join Key | 修正查询语句中的 Join Key |
|
||||
| 0x0706 | 标签过滤条件过多 | 减小查询语句中的标签过滤条件 |
|
||||
| 0x0707 | 查询不可用 | TODO |
|
||||
| 0x0708 | TODO | TODO |
|
||||
| 0x0709 | TODO | TODO |
|
||||
| 0x070A | 查询中的时间窗口过多 | 修改查询语句以减小时间窗口的数量 |
|
||||
| 0x070B | 查询缓冲区达到上限 | TODO |
|
||||
| 0x070C | 多副本数据不一致 | TODO |
|
||||
| 0x070D | 系统错误 | TODO |
|
||||
| 0x070E | 无效的时间范围 | 修正查询语句中的时间范围 |
|
||||
| 0x070F | 无效输入 | 修正查询语句 |
|
||||
| 0x0720 | 调度器不存在 | TODO |
|
||||
| 0x0721 | 任务不存在 | TODO |
|
||||
| 0x0722 | 任务已经存在 | TODO |
|
||||
| 0x0723 | 任务上下文不存在 | TODO |
|
||||
| 0x0724 | 任务被取消 | TODO |
|
||||
| 0x0725 | 任务被停止 | TODO |
|
||||
| 0x0726 | 任务正在取消中 | TODO |
|
||||
| 0x0727 | 任务正在停止中 | TODO |
|
||||
| 0x0728 | 重复操作 | TODO |
|
||||
| 0x0729 | 任务消息错误 | TODO |
|
||||
| 0x072A | 作业已经被释放 | TODO |
|
||||
| 0x072B | 任务状态错误 | TODO |
|
||||
| 0x072C | in 和 not in 操作符不支持 JSON 类型 | 修正查询语句 |
|
||||
| 0x072D | 此处不支持 JSON |修正查询语句 |
|
||||
| 0x072E | group 和 partition by 不支持 JSON 类型 |
|
||||
| 0x072F | 查询作业不存在 | TODO |
|
||||
| 0x0800 | License 已经过期 | 重新激活或获取 License |
|
||||
| 0x0801 | 受限于 License 无法创建 dnode | 获取新的License |
|
||||
| 0x0802 | 受限于 License 无法创建帐户 | 获取新的 License |
|
||||
| 0x0803 | 受限于 License 无法创建表 | 获取新的 License |
|
||||
| 0x0804 | 受限于 License 无法创建数据库 | 获取新的 License |
|
||||
| 0x0805 | 受限于 License 无法创建用户 | 获取新的 License |
|
||||
| 0x0806 | 受限于 License 无法创建连接 | 获取新的 License |
|
||||
| 0x0807 | 受限于 License 无法创建流 | 获取新的 License |
|
||||
| 0x0808 | 写入速度受限于 License | 获取新的 License |
|
||||
| 0x0809 | 存储容量受限于 License | 获取新的 License |
|
||||
| 0x080A | 查询时间受限于 License | 获取新的 License |
|
||||
| 0x080B | CPU 核数受限于 License | 获取新的 License |
|
||||
| 0x080C | 受限于 License 无法创建超级表 | 获取新的 License |
|
||||
| 0x080D | 受限于 License 无法创建表 | 获取新的 License |
|
||||
| 0x0A00 | TQ 无效配置 | TODO |
|
||||
| 0x0A01 | TQ 初始化失败 | TODO |
|
||||
| 0x0A02 | TQ 磁盘空间耗尽 | 尝试释放或增加磁盘空间 |
|
||||
| 0x0A03 | TQ 没有写磁盘权限 | 确认启动集群的系统帐号是否具有写磁盘权限 |
|
||||
| 0x0A04 | TQ 文件被破坏 | TODO |
|
||||
| 0x0A05 | TQ 内存耗尽 | 尝试释放内存 |
|
||||
| 0x0A06 | TQ 文件已经存在 | TODO |
|
||||
| 0x0A07 | TQ 创建目录失败 | TODO |
|
||||
| 0x0A08 | TQ meta 中不存在该 key | TODO |
|
||||
| 0x0A09 | meta key在事务中不存在 | TODO |
|
||||
| 0x0A0A | meta key在事务中重复 | TODO |
|
||||
| 0x0A0B | 消费组不存在 | 指定正确的消费组 |
|
||||
| 0x0A0C | 该表的 schema 不存在 | 确认表名是否正确 |
|
||||
| 0x0A0D | 没有已经提交的 offset | TODO |
|
||||
| 0x1000 | WAL 未知错误 | TODO |
|
||||
| 0x1001 | WAL 文件被破坏 | TODO |
|
||||
| 0x1002 | WAL 大小超出上限 | TODO |
|
||||
| 0x1003 | WAL 使用了错误的版本号 | TODO |
|
||||
| 0x1004 | 系统内存耗尽 | 尝试释放内存 |
|
||||
| 0x1005 | WAL 日志不存在 | TODO |
|
||||
| 0x2201 | 无效的 mount 配置 | 修正 mount 配置参数 |
|
||||
| 0x2202 | mount 点过多 | TODO |
|
||||
| 0x2203 | 重复的 primary mount | TODO |
|
||||
| 0x2204 | primary mount 缺失 | TODO |
|
||||
| 0x2205 | no mount at tier: TODO | TODO |
|
||||
| 0x2206 | 文件已经存在 | 更改文件名或者删除该文件 |
|
||||
| 0x2207 | 无效的级别 | TODO |
|
||||
| 0x2208 | 没有可用磁盘 | TODO |
|
||||
| 0x220F | 系统内存耗尽 | TODO |
|
||||
| 0x2400 | catalog 内部错误 | TODO |
|
||||
| 0x2401 | 无效的 catalog 输入参数 | TODO |
|
||||
| 0x2402 | catalog 不可用 | TODO |
|
||||
| 0x2403 | catalog 系统错误 | TODO |
|
||||
| 0x2404 | 数据库被删除 | TODO |
|
||||
| 0x2405 | catalog 不可用 | TODO |
|
||||
| 0x2406 | 表元数据和 vgroup 不匹配 | TODO |
|
||||
| 0x2407 | catalog 不存在 | TODO |
|
||||
| 0x2550 | 无效的消息顺序 | TODO |
|
||||
| 0x2501 | 调度器状态错误 | TODO |
|
||||
| 0x2502 | 调度器内部错误 | TODO |
|
||||
| 0x2504 | 任务超时 | TODO |
|
||||
| 0x2505 | 作业正在停止中 | TODO |
|
||||
| 0x2600 | 语法错误 | 参考 SQL 手册纠正 |
|
||||
| 0x2601 | 不完整的 SQL 语句 | 参考 SQL 手册纠正 |
|
||||
| 0x2602 | 无效列名 | 使用正确的列名 |
|
||||
| 0x2603 | 表不存在 | 使用正确的表名 |
|
||||
| 0x2604 | 表名定义有二义性 | 参考 SQL 手册纠正 |
|
||||
| 0x2605 | 无效的值类型 | 参考 SQL 手册纠正 |
|
||||
| 0x2608 | 此处不能使用聚合查询 | 参考 SQL 手册纠正 |
|
||||
| 0x2609 | ORDER BY 只能用于查询语句中的结果列 | 参考 SQL 手册纠正 |
|
||||
| 0x260A | GROUP BY 缺失表达式 (TODO) | 参考 SQL 手册纠正 |
|
||||
| 0x260B | 不是 SELECT 表达式 | 参考 SQL 手册纠正 |
|
||||
| 0x260C | 不是单一分组的分组函数 (TODO) | 参考 SQL 手册纠正 |
|
||||
| 0x260D | 标签数量不匹配 | 参考 SQL 手册纠正 |
|
||||
| 0x260E | 无效的标签名 | 改用正确的标签名 |
|
||||
| 0x2610 | 名字或密码过长 | 参考 SQL 手册纠正 |
|
||||
| 0x2611 | 密码不能为空 | 提供非空密码 |
|
||||
| 0x2612 | 端口无效 | 端口号必须在 (0,65535) 范围内 |
|
||||
| 0x2613 | 地址格式错误 | 正确格式是 "fqdn: port" |
|
||||
| 0x2614 | 该语句不再支持 | 参考 SQL 手册纠正 |
|
||||
| 0x2615 | 时间窗口过小 | 参考 SQL 手册纠正 |
|
||||
| 0x2616 | 未指定数据库 | 在表名或超级表名前添加 "<dbname\>." 指定数据库 |
|
||||
| 0x2617 | 标识符无效 | 参考 SQL 手册纠正 |
|
||||
| 0x2618 | 该数据库中不存在对应的超级表 | 使用正确的数据库名或者超级表名 |
|
||||
| 0x2619 | 数据库参数无效 | 参考 SQL 手册纠正 |
|
||||
| 0x261A | 建表参数无效 | 参考 SQL 手册纠正 |
|
||||
| 0x2624 | GROUP BY 和 窗口子句不能共用 | 参考 SQL 手册纠正 |
|
||||
| 0x2627 | 聚合函数不支持嵌套 | 参考 SQL 手册纠正 |
|
||||
| 0x2628 | 在 integer/bool/varchar 类型的列上只支持 状态窗口 | 参考 SQL 手册纠正 |
|
||||
| 0x2629 | 标签列上不支持状态窗口 | 参考 SQL 手册纠正 |
|
||||
| 0x262A | 状态窗口查询不支持超级表 | 参考 SQL 手册纠正 |
|
||||
| 0x262B | 会话之间的 gap 应该是大于 0 的固定大小的窗口 | 参考 SQL 手册纠正 |
|
||||
| 0x262C | 只在主键时间戳列上支持会话 | 参考 SQL 手册纠正 |
|
||||
| 0x262D | 窗口偏移量不能是负值 | 参考 SQL 手册纠正 |
|
||||
| 0x262E | 当 interval 的单位是 "year" 时 offset 的单位不能是 "month" | 参考 SQL 手册纠正 |
|
||||
| 0x262F | offset 所指定的时间长度应该小于 interval 所指定的时间长度 | 参考 SQL 手册纠正 |
|
||||
| 0x2630 | 当 interval 是自然年/月时不能使用 slidig | 参考 SQL 手册纠正 |
|
||||
| 0x2631 | sliding 所指定的时间长度不能大于 interval 所指定的时间长度 | 参考 SQL 手册纠正 |
|
||||
| 0x2632 | sliding 不能小于 interval 的 1%% | 参考 SQL 手册纠正 |
|
||||
| 0x2633 | 当使用 JSON 类型的 tag 时只允许这一个 tag 的存在 | 去除其它 tag |
|
||||
| 0x2634 | 查询块中包含的结果列的数量不正确 | TODO |
|
||||
| 0x2635 | 时间戳不正确 | TODO |
|
||||
| 0x2637 | offset/soffset 不能小于 0 | 纠正 offset/soffset |
|
||||
| 0x2638 | offset/soffset 只能用于 partition by | 参考 SQL 手册纠正 |
|
||||
| 0x2639 | 无效的 topic 查询 | TODO |
|
||||
| 0x263A | 不能批量删除超级表 | 请逐个删除 |
|
||||
| 0x263B | 查询时间范围未指定起止时间或者时间范围过大 | 参考 SQL 手册纠正 |
|
||||
| 0x263C | 重复的列表 | 参考 SQL 手册纠正 |
|
||||
| 0x263D | 标签长度超过上限 | 参考 SQL 手册纠正 |
|
||||
| 0x263E | 行长度超过上限 | 参考 SQL 手册纠正 |
|
||||
| 0x263F | 不合法的列数量 | 参考 SQL 手册纠正 |
|
||||
| 0x2640 | 列数过多 | 参考 SQL 手册纠正 |
|
||||
| 0x2641 | 首列必须是时间戳 | 参考 SQL 手册纠正 |
|
||||
| 0x2642 | binary/nchar 类型的列长度无效 | 参考 SQL 手册纠正 |
|
||||
| 0x2643 | 标签列数量无效 | 参考 SQL 手册纠正 |
|
||||
| 0x2644 | 无权进行该操作 | 参考 SQL 手册纠正 |
|
||||
| 0x2645 | 无效的流查询 | 参考 SQL 手册纠正 |
|
||||
| 0x2646 | 无效的 _c0 或 _rowts 表达式 | 参考 SQL 手册纠正 |
|
||||
| 0x2647 | 无效的时间线函数 | 参考 SQL 手册纠正 |
|
||||
| 0x2648 | 无效的密码 | 参考 SQL 手册纠正 |
|
||||
| 0x2649 | 无效的 alter table 语句 | 参考 SQL 手册纠正 |
|
||||
| 0x264A | 不能删除时间戳主列 | 参考 SQL 手册纠正 |
|
||||
| 0x264B | 只有 binary/nchar 类型的列能够修改长度 | 参考 SQL 手册纠正 |
|
||||
| 0x264C | 无效的 tbname 伪列 | 参考 SQL 手册纠正 |
|
||||
| 0x264D | 无效的函数名 | 参考 SQL 手册纠正 |
|
||||
| 0x264E | 注释过长 | 参考 SQL 手册纠正 |
|
||||
| 0x264F | 有些函数只能用在查询的 SELECT 列表中,且不能与其它非标量函数或列混用 | 参考 SQL 手册纠正 |
|
||||
| 0x2650 | 不支持窗口查询,因为子查询的结果不包含时间戳列 | 参考 SQL 手册纠正 |
|
||||
| 0x2651 | 任何列都不能被删除 | 参考 SQL 手册纠正 |
|
||||
| 0x2652 | 只有 标签列可以是 JSON 类型 | 参考 SQL 手册纠正 |
|
||||
| 0x2653 | 列或标签的值过长 | 参考 SQL 手册纠正 |
|
||||
| 0x2655 | DELETE 语句必须有一个确定的时间范围 | 参考 SQL 手册纠正 |
|
||||
| 0x2656 | REDISTRIBUTE VGROUP 语句只支持 1 到 3 个 vgroup | 参考 SQL 手册纠正 |
|
||||
| 0x2657 | 不支持 Fill | 参考 SQL 手册纠正 |
|
||||
| 0x2658 | 无效的窗口伪列 | 参考 SQL 手册纠正 |
|
||||
| 0x2659 | 不允许做窗口查询: TODO | 参考 SQL 手册纠正 |
|
||||
| 0x265A | 不允许做流计算: TODO | 参考 SQL 手册纠正 |
|
||||
| 0x265B | 不允许做 Group By | 参考 SQL 手册纠正 |
|
||||
| 0x265D | interp 子句错误 | 参考 SQL 手册纠正 |
|
||||
| 0x265E | 窗口查询中不支持该函数 | 参考 SQL 手册纠正 |
|
||||
| 0x265F | 只支持单表 | 参考 SQL 手册纠正 |
|
||||
| 0x2660 | 无效的 SMA 索引 | 参考 SQL 手册纠正 |
|
||||
| 0x2661 | 无效的 SELECT 表达式 | 参考 SQL 手册纠正 |
|
||||
| 0x2662 | 获取表的元数据失败 | TODO |
|
||||
| 0x2663 | 表名/表名不唯一 | 参考 SQL 手册纠正 |
|
||||
| 0x266F | 解析器内部错误 | TODO |
|
||||
| 0x2700 | 计划器内部错误 | TODO |
|
||||
| 0x2701 | TODO | TODO |
|
||||
| 0x2702 | 不支持 cross join | 参考 SQL 手册纠正 |
|
||||
| 0x2800 | 函数内部错误 | 参考 SQL 手册纠正 |
|
||||
| 0x2801 | 函数参数个数错误 | 参考 SQL 手册纠正 |
|
||||
| 0x2802 | 函数参数类型错误 | 参考 SQL 手册纠正 |
|
||||
| 0x2803 | 函数参数值错误 | 参考 SQL 手册纠正 |
|
||||
| 0x2804 | 非内置函数 | 参考 SQL 手册纠正 |
|
||||
| 0x2901 | UDF 正在停止 | TODO |
|
||||
| 0x2902 | UDF 管道读取错误 | TODO |
|
||||
| 0x2903 | UDF 连接错误 | TODO |
|
||||
| 0x2904 | UDF 管道缺失 | TODO |
|
||||
| 0x2905 | UDF 加载失败 | TODO |
|
||||
| 0x2906 | UDF 无效状态 | TODO |
|
||||
| 0x2907 | UDF 无效输入 | TODO |
|
||||
| 0x2908 | UDF 没有函数句柄 | TODO |
|
||||
| 0x2909 | UDF 无效的 bufsize | TODO |
|
||||
| 0x290A | UDF 无效的输出类型 | TODO |
|
||||
| 0x3000 | 无效的行协议类型 | 修正数据中的协议类型 |
|
||||
| 0x3001 | 无效的时间戳精度类型 | 修正时间戳精度类型 |
|
||||
| 0x3002 | 无效的数据格式 | 修正数据格式 |
|
||||
| 0x3003 | 无效的无模式数据库配置 | 修改配置 |
|
||||
| 0x3004 | 写入类型与之前的不同 | 修正写入类型 |
|
||||
| 0x3100 | TSMA 初始化失败 | TODO |
|
||||
| 0x3101 | TSMA 已经存在 | 放弃重复建立 TSMA |
|
||||
| 0x3102 | 元数据中没有 TSMA 索引 | TODO |
|
||||
| 0x3103 | 无效的 TSMA 环境 | TODO |
|
||||
| 0x3104 | 无效的 TSMA 状态 | TODO |
|
||||
| 0x3105 | 无效的 TSMA 指针 | TODO |
|
||||
| 0x3106 | 无效的 TSMA 参数 | 参考 SQL 手册纠正 |
|
||||
| 0x3107 | cache 中没有该 TSMA 的索引 | TODO |
|
||||
| 0x3150 | 无效的 RSMA 索引 | TODO |
|
||||
| 0x3151 | 无效的 RSMA 状态 | TODO |
|
||||
| 0x3152 | RSMA 创建 qtaskinfo 失败 | TODO |
|
||||
| 0x3153 | RSMA 文件被破坏 | TODO |
|
||||
| 0x3200 | 索引正在重建中 |TODO |
|
||||
| 0x3201 | 无效的索引文件 | TODO |
|
||||
| 0x4000 | 无效消息 | TODO |
|
|
@ -22,7 +22,9 @@ import CSAsyncQuery from "../../07-develop/04-query-data/_cs_async.mdx"
|
|||
|
||||
本文介绍如何在 Linux 或 Windows 环境中安装 `TDengine.Connector`,并通过 `TDengine.Connector` 连接 TDengine 集群,进行数据写入、查询等基本操作。
|
||||
|
||||
`TDengine.Connector` 的源码托管在 [GitHub](https://github.com/taosdata/taos-connector-dotnet)。
|
||||
注意:`TDengine.Connector` 3.x 不兼容 TDengine 2.x,如果在运行 TDengine 2.x 版本的环境下需要使用 C# 连接器请使用 TDengine.Connector 的 1.x 版本 。
|
||||
|
||||
`TDengine.Connector` 的源码托管在 [GitHub](https://github.com/taosdata/taos-connector-dotnet/tree/3.0)。
|
||||
|
||||
## 支持的平台
|
||||
|
||||
|
@ -63,15 +65,15 @@ dotnet add package TDengine.Connector
|
|||
</TabItem>
|
||||
<TabItem value="source" label="使用源码获取 C# 驱动">
|
||||
|
||||
可以下载 TDengine 的源码,直接引用最新版本的 TDengine.Connector 库
|
||||
也可以[下载源码](https://github.com/taosdata/taos-connector-dotnet/tree/3.0),直接引用 TDengine.Connector 库
|
||||
|
||||
```bash
|
||||
git clone https://github.com/taosdata/TDengine.git
|
||||
cd TDengine/src/connector/C#/src/
|
||||
cp -r TDengineDriver/ myProject
|
||||
git clone -b 3.0 https://github.com/taosdata/taos-connector-dotnet.git
|
||||
cd taos-connector-dotnet
|
||||
cp -r src/ myProject
|
||||
|
||||
cd myProject
|
||||
dotnet add TDengineDriver/TDengineDriver.csproj
|
||||
dotnet add exmaple.csproj reference src/TDengine.csproj
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
@ -145,20 +147,19 @@ namespace TDengineExample
|
|||
|
||||
|示例程序 | 示例程序描述 |
|
||||
|--------------------------------------------------------------------------------------------------------------------|--------------------------------------------|
|
||||
| [C#checker](https://github.com/taosdata/TDengine/tree/develop/examples/C%23/C%23checker) | 使用 TDengine.Connector 可以通过 help 命令中提供的参数,测试C# Driver的同步写入和查询 |
|
||||
| [TDengineTest](https://github.com/taosdata/TDengine/tree/develop/examples/C%23/TDengineTest) | 使用 TDengine.Connector 实现的简单写入和查询的示例 |
|
||||
| [insertCn](https://github.com/taosdata/TDengine/tree/develop/examples/C%23/insertCn) | 使用 TDengine.Connector 实现的写入和查询中文字符的示例 |
|
||||
| [jsonTag](https://github.com/taosdata/TDengine/tree/develop/examples/C%23/jsonTag) | 使用 TDengine.Connector 实现的写入和查询 json tag 类型数据的示例 |
|
||||
| [stmt](https://github.com/taosdata/TDengine/tree/develop/examples/C%23/stmt) | 使用 TDengine.Connector 实现的参数绑定的示例 |
|
||||
| [schemaless](https://github.com/taosdata/TDengine/tree/develop/examples/C%23/schemaless) | 使用 TDengine.Connector 实现的使用 schemaless 写入的示例 |
|
||||
| [benchmark](https://github.com/taosdata/TDengine/tree/develop/examples/C%23/taosdemo) | 使用 TDengine.Connector 实现的简易 Benchmark |
|
||||
| [async query](https://github.com/taosdata/taos-connector-dotnet/blob/develop/examples/QueryAsyncSample.cs) | 使用 TDengine.Connector 实现的异步查询的示例 |
|
||||
| [subscribe](https://github.com/taosdata/taos-connector-dotnet/blob/develop/examples/SubscribeSample.cs) | 使用 TDengine.Connector 实现的订阅数据的示例 |
|
||||
| [CURD](https://github.com/taosdata/taos-connector-dotnet/blob/3.0/examples/Query/Query.cs) | 使用 TDengine.Connector 实现的建表、插入、查询示例 |
|
||||
| [JSON Tag](https://github.com/taosdata/taos-connector-dotnet/blob/3.0/examples/JSONTag) | 使用 TDengine.Connector 实现的写入和查询 JSON tag 类型数据的示例 |
|
||||
| [stmt](https://github.com/taosdata/taos-connector-dotnet/tree/3.0/examples/Stmt) | 使用 TDengine.Connector 实现的参数绑定插入和查询的示例 |
|
||||
| [schemaless](https://github.com/taosdata/taos-connector-dotnet/blob/3.0/examples/schemaless) | 使用 TDengine.Connector 实现的使用 schemaless 写入的示例 |
|
||||
| [async query](https://github.com/taosdata/taos-connector-dotnet/blob/3.0/examples/AsyncQuery/QueryAsync.cs) | 使用 TDengine.Connector 实现的异步查询的示例 |
|
||||
| [TMQ](https://github.com/taosdata/taos-connector-dotnet/blob/3.0/examples/TMQ/TMQ.cs) | 使用 TDengine.Connector 实现的订阅数据的示例 |
|
||||
|
||||
## 重要更新记录
|
||||
|
||||
| TDengine.Connector | 说明 |
|
||||
|--------------------|--------------------------------|
|
||||
| 3.0.0 | 支持 TDengine 3.0.0.0,不兼容 2.x。新增接口TDengine.Impl.GetData(),解析查询结果。 |
|
||||
| 1.0.7 | 修复 TDengine.Query()内存泄露。 |
|
||||
| 1.0.6 | 修复 schemaless 在 1.0.4 和 1.0.5 中失效 bug。 |
|
||||
| 1.0.5 | 修复 Windows 同步查询中文报错 bug。 |
|
||||
| 1.0.4 | 新增异步查询,订阅等功能。修复绑定参数 bug。 |
|
||||
|
|
|
@ -15,11 +15,11 @@ import NodeOpenTSDBTelnet from "../../07-develop/03-insert-data/_js_opts_telnet.
|
|||
import NodeOpenTSDBJson from "../../07-develop/03-insert-data/_js_opts_json.mdx";
|
||||
import NodeQuery from "../../07-develop/04-query-data/_js.mdx";
|
||||
|
||||
`td2.0-connector` 和 `td2.0-rest-connector` 是 TDengine 的官方 Node.js 语言连接器。Node.js 开发人员可以通过它开发可以存取 TDengine 集群数据的应用软件。
|
||||
`@tdengine/client` 和 `@tdengine/rest` 是 TDengine 的官方 Node.js 语言连接器。 Node.js 开发人员可以通过它开发可以存取 TDengine 集群数据的应用软件。注意:从 TDengine 3.0 开始 Node.js 原生连接器的包名由 `td2.0-connector` 改名为 `@tdengine/client` 而 rest 连接器的包名由 `td2.0-rest-connector` 改为 `@tdengine/rest`。并且不与 TDengine 2.x 兼容。
|
||||
|
||||
`td2.0-connector` 是**原生连接器**,它通过 TDengine 客户端驱动程序(taosc)连接 TDengine 运行实例,支持数据写入、查询、订阅、schemaless 接口和参数绑定接口等功能。`td2.0-rest-connector` 是 **REST 连接器**,它通过 taosAdapter 提供的 REST 接口连接 TDengine 的运行实例。REST 连接器可以在任何平台运行,但性能略为下降,接口实现的功能特性集合和原生接口有少量不同。
|
||||
`@tdengine/client` 是**原生连接器**,它通过 TDengine 客户端驱动程序(taosc)连接 TDengine 运行实例,支持数据写入、查询、订阅、schemaless 接口和参数绑定接口等功能。`@tdengine/rest` 是 **REST 连接器**,它通过 taosAdapter 提供的 REST 接口连接 TDengine 的运行实例。REST 连接器可以在任何平台运行,但性能略为下降,接口实现的功能特性集合和原生接口有少量不同。
|
||||
|
||||
Node.js 连接器源码托管在 [GitHub](https://github.com/taosdata/taos-connector-node)。
|
||||
Node.js 连接器源码托管在 [GitHub](https://github.com/taosdata/taos-connector-node/tree/3.0)。
|
||||
|
||||
## 支持的平台
|
||||
|
||||
|
@ -58,7 +58,7 @@ REST 连接器支持所有能运行 Node.js 的平台。
|
|||
<TabItem value="Linux" label="Linux 系统安装依赖工具">
|
||||
|
||||
- `python` (建议`v2.7` , `v3.x.x` 目前还不支持)
|
||||
- `td2.0-connector` 2.0.6 支持 Node.js LTS v10.9.0 或更高版本, Node.js LTS v12.8.0 或更高版本;2.0.5 及更早版本支持 Node.js LTS v10.x 版本。其他版本可能存在包兼容性的问题
|
||||
- `@tdengine/client` 3.0.0 支持 Node.js LTS v10.9.0 或更高版本, Node.js LTS v12.8.0 或更高版本;其他版本可能存在包兼容性的问题
|
||||
- `make`
|
||||
- C 语言编译器,[GCC](https://gcc.gnu.org) v4.8.5 或更高版本
|
||||
|
||||
|
@ -90,14 +90,14 @@ REST 连接器支持所有能运行 Node.js 的平台。
|
|||
<TabItem value="install_native" label="安装原生连接器">
|
||||
|
||||
```bash
|
||||
npm install td2.0-connector
|
||||
npm install @tdengine/client
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="install_rest" label="安装 REST 连接器">
|
||||
|
||||
```bash
|
||||
npm i td2.0-rest-connector
|
||||
npm install @tdengine/rest
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
|
@ -109,13 +109,13 @@ npm i td2.0-rest-connector
|
|||
|
||||
验证方法:
|
||||
|
||||
- 新建安装验证目录,例如:`~/tdengine-test`,下载 GitHub 上 [nodejsChecker.js 源代码](https://github.com/taosdata/TDengine/tree/develop/examples/nodejs/nodejsChecker.js)到本地。
|
||||
- 新建安装验证目录,例如:`~/tdengine-test`,下载 GitHub 上 [nodejsChecker.js 源代码](https://github.com/taosdata/taos-connector-node/blob/3.0/nodejs/examples/nodejsChecker.js)到本地。
|
||||
|
||||
- 在命令行中执行以下命令。
|
||||
|
||||
```bash
|
||||
npm init -y
|
||||
npm install td2.0-connector
|
||||
npm install @tdengine/client
|
||||
node nodejsChecker.js host=localhost
|
||||
```
|
||||
|
||||
|
@ -128,11 +128,11 @@ node nodejsChecker.js host=localhost
|
|||
<Tabs defaultValue="native">
|
||||
<TabItem value="native" label="原生连接">
|
||||
|
||||
安装并引用 `td2.0-connector` 包。
|
||||
安装并引用 `@tdengine/client` 包。
|
||||
|
||||
```javascript
|
||||
//A cursor also needs to be initialized in order to interact with TDengine from Node.js.
|
||||
const taos = require("td2.0-connector");
|
||||
const taos = require("@tdengine/client");
|
||||
var conn = taos.connect({
|
||||
host: "127.0.0.1",
|
||||
user: "root",
|
||||
|
@ -149,12 +149,12 @@ conn.close();
|
|||
</TabItem>
|
||||
<TabItem value="rest" label="REST 连接">
|
||||
|
||||
安装并引用 `td2.0-rest-connector` 包。
|
||||
安装并引用 `@tdengine/rest` 包。
|
||||
|
||||
```javascript
|
||||
//A cursor also needs to be initialized in order to interact with TDengine from Node.js.
|
||||
import { options, connect } from "td2.0-rest-connector";
|
||||
options.path = "/rest/sqlt";
|
||||
import { options, connect } from "@tdengine/rest";
|
||||
options.path = "/rest/sql";
|
||||
// set host
|
||||
options.host = "localhost";
|
||||
// set other options like user/passwd
|
||||
|
@ -190,26 +190,23 @@ let cursor = conn.cursor();
|
|||
|
||||
<NodeQuery />
|
||||
|
||||
|
||||
## 更多示例程序
|
||||
|
||||
| 示例程序 | 示例程序描述 |
|
||||
| ------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------- |
|
||||
| [connection](https://github.com/taosdata/taos-connector-node/tree/develop/nodejs/examples/cursorClose.js) | 建立连接的示例。 |
|
||||
| [stmtBindBatch](https://github.com/taosdata/taos-connector-node/tree/develop/nodejs/examples/stmtBindParamBatchSample.js) | 绑定多行参数插入的示例。 |
|
||||
| [stmtBind](https://github.com/taosdata/taos-connector-node/tree/develop/nodejs/examples/stmtBindParamSample.js) | 一行一行绑定参数插入的示例。 |
|
||||
| [stmtBindSingleParamBatch](https://github.com/taosdata/taos-connector-node/tree/develop/nodejs/examples/stmtBindSingleParamBatchSample.js) | 按列绑定参数插入的示例。 |
|
||||
| [stmtUseResult](https://github.com/taosdata/taos-connector-node/tree/develop/nodejs/examples/stmtUseResultSample.js) | 绑定参数查询的示例。 |
|
||||
| [json tag](https://github.com/taosdata/taos-connector-node/tree/develop/nodejs/examples/testJsonTag.js) | Json tag 的使用示例。 |
|
||||
| [Nanosecond](https://github.com/taosdata/taos-connector-node/tree/develop/nodejs/examples/testNanoseconds.js) | 时间戳为纳秒精度的使用的示例。 |
|
||||
| [Microsecond](https://github.com/taosdata/taos-connector-node/tree/develop/nodejs/examples/testMicroseconds.js) | 时间戳为微秒精度的使用的示例。 |
|
||||
| [schemless insert](https://github.com/taosdata/taos-connector-node/tree/develop/nodejs/examples/testSchemalessInsert.js) | schemless 插入的示例。 |
|
||||
| [subscribe](https://github.com/taosdata/taos-connector-node/tree/develop/nodejs/examples/testSubscribe.js) | 订阅的使用示例。 |
|
||||
| [asyncQuery](https://github.com/taosdata/taos-connector-node/tree/develop/nodejs/examples/tset.js) | 异步查询的使用示例。 |
|
||||
| [REST](https://github.com/taosdata/taos-connector-node/blob/develop/typescript-rest/example/example.ts) | 使用 REST 连接的 TypeScript 使用示例。 |
|
||||
| [basicUse](https://github.com/taosdata/taos-connector-node/blob/3.0/nodejs/examples/queryExample.js) | 基本的使用如如建立连接,执行 SQL 等操作。 |
|
||||
| [stmtBindBatch](https://github.com/taosdata/taos-connector-node/blob/3.0/nodejs/examples/bindParamBatch.js) | 绑定多行参数插入的示例。 | |
|
||||
| [stmtBindSingleParamBatch](https://github.com/taosdata/taos-connector-node/blob/3.0/nodejs/examples/bindSingleParamBatch.js) | 按列绑定参数插入的示例。 |
|
||||
| [stmtQuery](https://github.com/taosdata/taos-connector-node/blob/3.0/nodejs/examples/stmtQuery.js) | 绑定参数查询的示例。 |
|
||||
| [schemless insert](https://github.com/taosdata/taos-connector-node/blob/3.0/nodejs/examples/schemaless.js) | schemless 插入的示例。 |
|
||||
| [TMQ](https://github.com/taosdata/taos-connector-node/blob/3.0/nodejs/examples/tmq.js) | 订阅的使用示例。 |
|
||||
| [asyncQuery](https://github.com/taosdata/taos-connector-node/blob/3.0/nodejs/examples/asyncQueryExample.js) | 异步查询的使用示例。 |
|
||||
| [REST](https://github.com/taosdata/taos-connector-node/blob/3.0/typescript-rest/example/example.ts) | 使用 REST 连接的 TypeScript 使用示例。 |
|
||||
|
||||
## 使用限制
|
||||
|
||||
Node.js 连接器 >= v2.0.6 目前支持 node 的版本为:支持 >=v12.8.0 <= v12.9.1 || >=v10.20.0 <= v10.9.0 ;2.0.5 及更早版本支持 v10.x 版本,其他版本可能存在包兼容性的问题。
|
||||
native 连接器(`@tdengine/client`) >= v3.0.0 目前支持 node 的版本为:支持 >=v12.8.0 <= v12.9.1 || >=v10.20.0 <= v10.9.0 ;2.0.5 及更早版本支持 v10.x 版本,其他版本可能存在包兼容性的问题。
|
||||
|
||||
## 其他说明
|
||||
|
||||
|
@ -225,7 +222,7 @@ Node.js 连接器的使用参见[视频教程](https://www.taosdata.com/blog/202
|
|||
|
||||
2. Node.js 版本
|
||||
|
||||
连接器 >v2.0.6 目前兼容的 Node.js 版本为:>=v10.20.0 <= v10.9.0 || >=v12.8.0 <= v12.9.1
|
||||
原生连接器 `@tdengine/client` 目前兼容的 Node.js 版本为:>=v10.20.0 <= v10.9.0 || >=v12.8.0 <= v12.9.1
|
||||
|
||||
3. "Unable to establish connection","Unable to resolve FQDN"
|
||||
|
||||
|
@ -235,18 +232,22 @@ Node.js 连接器的使用参见[视频教程](https://www.taosdata.com/blog/202
|
|||
|
||||
### 原生连接器
|
||||
|
||||
| td2.0-connector 版本 | 说明 |
|
||||
| -------------------- | ---------------------------------------------------------------- |
|
||||
| 2.0.12 | 修复 cursor.close() 报错的 bug。 |
|
||||
| 2.0.11 | 支持绑定参数、json tag、schemaless 接口等功能。 |
|
||||
| 2.0.10 | 支持连接管理,普通查询、连续查询、获取系统信息、订阅功能等功能。 |
|
||||
|
||||
| package name | version | TDengine version | 说明 |
|
||||
|------------------|---------|---------------------|------------------------------------------------------------------|
|
||||
| @tdengine/client | 3.0.0 | 3.0.0 | 支持TDengine 3.0 且不与2.x 兼容。 |
|
||||
| td2.0-connector | 2.0.12 | 2.4.x;2.5.x;2.6.x | 修复 cursor.close() 报错的 bug。 |
|
||||
| td2.0-connector | 2.0.11 | 2.4.x;2.5.x;2.6.x | 支持绑定参数、json tag、schemaless 接口等功能。 |
|
||||
| td2.0-connector | 2.0.10 | 2.4.x;2.5.x;2.6.x | 支持连接管理,普通查询、连续查询、获取系统信息、订阅功能等功能。 |
|
||||
### REST 连接器
|
||||
|
||||
| td2.0-rest-connector 版本 | 说明 |
|
||||
| ------------------------- | ---------------------------------------------------------------- |
|
||||
| 1.0.3 | 支持连接管理、普通查询、获取系统信息、错误信息、连续查询等功能。 |
|
||||
| package name | version | TDengine version | 说明 |
|
||||
|----------------------|---------|---------------------|---------------------------------------------------------------------------|
|
||||
| @tdengine/rest | 3.0.0 | 3.0.0 | 支持 TDegnine 3.0,且不与2.x 兼容。 |
|
||||
| td2.0-rest-connector | 1.0.7 | 2.4.x;2.5.x;2.6.x | 移除默认端口 6041。 |
|
||||
| td2.0-rest-connector | 1.0.6 | 2.4.x;2.5.x;2.6.x | 修复create,insert,update,alter 等SQL 执行返回的 affectRows 错误的bug。 |
|
||||
| td2.0-rest-connector | 1.0.5 | 2.4.x;2.5.x;2.6.x | 支持云服务 cloud Token; |
|
||||
| td2.0-rest-connector | 1.0.3 | 2.4.x;2.5.x;2.6.x | 支持连接管理、普通查询、获取系统信息、错误信息、连续查询等功能。 |
|
||||
|
||||
## API 参考
|
||||
|
||||
[API 参考](https://docs.taosdata.com/api/td2.0-connector/)
|
||||
[API 参考](https://docs.taosdata.com/api/td2.0-connector/)
|
|
@ -227,45 +227,34 @@ taosBenchmark -A INT,DOUBLE,NCHAR,BINARY\(16\)
|
|||
|
||||
#### 数据库相关配置参数
|
||||
|
||||
创建数据库时的相关参数在 json 配置文件中的 `dbinfo` 中配置,具体参数如下。这些参数与 TDengine 中 `create database` 时所指定的数据库参数相对应。
|
||||
创建数据库时的相关参数在 json 配置文件中的 `dbinfo` 中配置,个别具体参数如下。其余参数均与 TDengine 中 `create database` 时所指定的数据库参数相对应,详见[../../taos-sql/database]
|
||||
|
||||
- **name** : 数据库名。
|
||||
|
||||
- **drop** : 插入前是否删除数据库,默认为 true。
|
||||
|
||||
- **replica** : 创建数据库时指定的副本数。
|
||||
#### 流式计算相关配置参数
|
||||
|
||||
- **days** : 单个数据文件中存储数据的时间跨度,默认值为 10。
|
||||
创建流式计算的相关参数在 json 配置文件中的 `stream` 中配置,具体参数如下。
|
||||
|
||||
- **cache** : 缓存块的大小,单位是 MB,默认值是 16。
|
||||
- **stream_name** : 流式计算的名称,必填项。
|
||||
|
||||
- **blocks** : 每个 vnode 中缓存块的数量,默认为 6。
|
||||
- **stream_stb** : 流式计算对应的超级表名称,必填项。
|
||||
|
||||
- **precision** : 数据库时间精度,默认值为 "ms"。
|
||||
- **stream_sql** : 流式计算的sql语句,必填项。
|
||||
|
||||
- **keep** : 保留数据的天数,默认值为 3650。
|
||||
- **trigger_mode** : 流式计算的触发模式,可选项。
|
||||
|
||||
- **minRows** : 文件块中的最小记录数,默认值为 100。
|
||||
- **watermark** : 流式计算的水印,可选项。
|
||||
|
||||
- **maxRows** : 文件块中的最大记录数,默认值为 4096。
|
||||
|
||||
- **comp** : 文件压缩标志,默认值为 2。
|
||||
|
||||
- **walLevel** : WAL 级别,默认为 1。
|
||||
|
||||
- **cacheLast** : 是否允许将每个表的最后一条记录保留在内存中,默认值为 0,可选值为 0,1,2,3。
|
||||
|
||||
- **quorum** : 多副本模式下的写确认数量,默认值为 1。
|
||||
|
||||
- **fsync** : 当 wal 设置为 2 时,fsync 的间隔时间,单位为 ms,默认值为 3000。
|
||||
|
||||
- **update** : 是否支持数据更新,默认值为 0, 可选值为 0, 1, 2。
|
||||
- **drop** : 是否创建流式计算,可选项为 "yes" 或者 "no", 为 "no" 时不创建。
|
||||
|
||||
#### 超级表相关配置参数
|
||||
|
||||
创建超级表时的相关参数在 json 配置文件中的 `super_tables` 中配置,具体参数如下表。
|
||||
创建超级表时的相关参数在 json 配置文件中的 `super_tables` 中配置,具体参数如下。
|
||||
|
||||
- **name**: 超级表名,必须配置,没有默认值。
|
||||
|
||||
- **child_table_exists** : 子表是否已经存在,默认值为 "no",可选值为 "yes" 或 "no"。
|
||||
|
||||
- **child_table_count** : 子表的数量,默认值为 10。
|
||||
|
@ -316,6 +305,22 @@ taosBenchmark -A INT,DOUBLE,NCHAR,BINARY\(16\)
|
|||
|
||||
- **tags_file** : 仅当 insert_mode 为 taosc, rest 的模式下生效。 最终的 tag 的数值与 childtable_count 有关,如果 csv 文件内的 tag 数据行小于给定的子表数量,那么会循环读取 csv 文件数据直到生成 childtable_count 指定的子表数量;否则则只会读取 childtable_count 行 tag 数据。也即最终生成的子表数量为二者取小。
|
||||
|
||||
#### tsma配置参数
|
||||
|
||||
指定tsma的配置参数在 `super_tables` 中的 `tsmas` 中,具体参数如下。
|
||||
|
||||
- **name** : 指定 tsma 的名字,必选项。
|
||||
|
||||
- **function** : 指定 tsma 的函数,必选项。
|
||||
|
||||
- **interval** : 指定 tsma 的时间间隔,必选项。
|
||||
|
||||
- **sliding** : 指定 tsma 的窗口时间位移,必选项。
|
||||
|
||||
- **custom** : 指定 tsma 的创建语句结尾追加的自定义配置,可选项。
|
||||
|
||||
- **start_when_inserted** : 指定当插入多少行时创建 tsma,可选项,默认为 0。
|
||||
|
||||
#### 标签列与数据列配置参数
|
||||
|
||||
指定超级表标签列与数据列的配置参数分别在 `super_tables` 中的 `columns` 和 `tag` 中。
|
||||
|
@ -335,6 +340,8 @@ taosBenchmark -A INT,DOUBLE,NCHAR,BINARY\(16\)
|
|||
|
||||
- **values** : nchar/binary 列/标签的值域,将从值中随机选择。
|
||||
|
||||
- **sma**: 将该列加入bsma中,值为 "yes" 或者 "no",默认为 "no"。
|
||||
|
||||
#### 插入行为配置参数
|
||||
|
||||
- **thread_count** : 插入数据的线程数量,默认为 8。
|
||||
|
|
|
@ -147,7 +147,7 @@ import (
|
|||
"fmt"
|
||||
"time"
|
||||
|
||||
_ "github.com/taosdata/driver-go/v2/taosSql"
|
||||
_ "github.com/taosdata/driver-go/v3/taosSql"
|
||||
)
|
||||
|
||||
type config struct {
|
||||
|
|
|
@ -1,131 +1,71 @@
|
|||
---
|
||||
title: 诊断及其他
|
||||
---
|
||||
|
||||
## 网络连接诊断
|
||||
|
||||
当出现客户端应用无法访问服务端时,需要确认客户端与服务端之间网络的各端口连通情况,以便有针对性地排除故障。
|
||||
|
||||
目前网络连接诊断支持在:Linux 与 Linux,Linux 与 Windows 之间进行诊断测试。
|
||||
|
||||
诊断步骤:
|
||||
|
||||
1. 如拟诊断的端口范围与服务器 taosd 实例的端口范围相同,须先停掉 taosd 实例
|
||||
2. 服务端命令行输入:`taos -n server -P <port> -l <pktlen>` 以服务端身份启动对端口 port 为基准端口的监听
|
||||
3. 客户端命令行输入:`taos -n client -h <fqdn of server> -P <port> -l <pktlen>` 以客户端身份启动对指定的服务器、指定的端口发送测试包
|
||||
|
||||
-l <pktlen\>: 测试网络包的大小(单位:字节)。最小值是 11、最大值是 64000,默认值为 1000。
|
||||
注:两端命令行中指定的测试包长度必须一致,否则测试显示失败。
|
||||
|
||||
服务端运行正常的话会输出以下信息:
|
||||
|
||||
```bash
|
||||
# taos -n server -P 6000
|
||||
12/21 14:50:13.522509 0x7f536f455200 UTL work as server, host:172.27.0.7 startPort:6000 endPort:6011 pkgLen:1000
|
||||
|
||||
12/21 14:50:13.522659 0x7f5352242700 UTL TCP server at port:6000 is listening
|
||||
12/21 14:50:13.522727 0x7f5351240700 UTL TCP server at port:6001 is listening
|
||||
...
|
||||
...
|
||||
...
|
||||
12/21 14:50:13.523954 0x7f5342fed700 UTL TCP server at port:6011 is listening
|
||||
12/21 14:50:13.523989 0x7f53437ee700 UTL UDP server at port:6010 is listening
|
||||
12/21 14:50:13.524019 0x7f53427ec700 UTL UDP server at port:6011 is listening
|
||||
12/21 14:50:22.192849 0x7f5352242700 UTL TCP: read:1000 bytes from 172.27.0.8 at 6000
|
||||
12/21 14:50:22.192993 0x7f5352242700 UTL TCP: write:1000 bytes to 172.27.0.8 at 6000
|
||||
12/21 14:50:22.237082 0x7f5351a41700 UTL UDP: recv:1000 bytes from 172.27.0.8 at 6000
|
||||
12/21 14:50:22.237203 0x7f5351a41700 UTL UDP: send:1000 bytes to 172.27.0.8 at 6000
|
||||
12/21 14:50:22.237450 0x7f5351240700 UTL TCP: read:1000 bytes from 172.27.0.8 at 6001
|
||||
12/21 14:50:22.237576 0x7f5351240700 UTL TCP: write:1000 bytes to 172.27.0.8 at 6001
|
||||
12/21 14:50:22.281038 0x7f5350a3f700 UTL UDP: recv:1000 bytes from 172.27.0.8 at 6001
|
||||
12/21 14:50:22.281141 0x7f5350a3f700 UTL UDP: send:1000 bytes to 172.27.0.8 at 6001
|
||||
...
|
||||
...
|
||||
...
|
||||
12/21 14:50:22.677443 0x7f5342fed700 UTL TCP: read:1000 bytes from 172.27.0.8 at 6011
|
||||
12/21 14:50:22.677576 0x7f5342fed700 UTL TCP: write:1000 bytes to 172.27.0.8 at 6011
|
||||
12/21 14:50:22.721144 0x7f53427ec700 UTL UDP: recv:1000 bytes from 172.27.0.8 at 6011
|
||||
12/21 14:50:22.721261 0x7f53427ec700 UTL UDP: send:1000 bytes to 172.27.0.8 at 6011
|
||||
```
|
||||
|
||||
客户端运行正常会输出以下信息:
|
||||
|
||||
```bash
|
||||
# taos -n client -h 172.27.0.7 -P 6000
|
||||
12/21 14:50:22.192434 0x7fc95d859200 UTL work as client, host:172.27.0.7 startPort:6000 endPort:6011 pkgLen:1000
|
||||
|
||||
12/21 14:50:22.192472 0x7fc95d859200 UTL server ip:172.27.0.7 is resolved from host:172.27.0.7
|
||||
12/21 14:50:22.236869 0x7fc95d859200 UTL successed to test TCP port:6000
|
||||
12/21 14:50:22.237215 0x7fc95d859200 UTL successed to test UDP port:6000
|
||||
...
|
||||
...
|
||||
...
|
||||
12/21 14:50:22.676891 0x7fc95d859200 UTL successed to test TCP port:6010
|
||||
12/21 14:50:22.677240 0x7fc95d859200 UTL successed to test UDP port:6010
|
||||
12/21 14:50:22.720893 0x7fc95d859200 UTL successed to test TCP port:6011
|
||||
12/21 14:50:22.721274 0x7fc95d859200 UTL successed to test UDP port:6011
|
||||
```
|
||||
|
||||
仔细阅读打印出来的错误信息,可以帮助管理员找到原因,以解决问题。
|
||||
|
||||
## 启动状态及 RPC 诊断
|
||||
|
||||
`taos -n startup -h <fqdn of server>`
|
||||
|
||||
判断 taosd 服务端是否成功启动,是数据库管理员经常遇到的一种情形。特别当若干台服务器组成集群时,判断每个服务端实例是否成功启动就会是一个重要问题。除检索 taosd 服务端日志文件进行问题定位、分析外,还可以通过 `taos -n startup -h <fqdn of server>` 来诊断一个 taosd 进程的启动状态。
|
||||
|
||||
针对多台服务器组成的集群,当服务启动过程耗时较长时,可通过该命令行来诊断每台服务器的 taosd 实例的启动状态,以准确定位问题。
|
||||
|
||||
`taos -n rpc -h <fqdn of server>`
|
||||
|
||||
该命令用来诊断已经启动的 taosd 实例的端口是否可正常访问。如果 taosd 程序异常或者失去响应,可以通过 `taos -n rpc -h <fqdn of server>` 来发起一个与指定 fqdn 的 rpc 通信,看看 taosd 是否能收到,以此来判定是网络问题还是 taosd 程序异常问题。
|
||||
|
||||
## sync 及 arbitrator 诊断
|
||||
|
||||
```
|
||||
taos -n sync -P 6040 -h <fqdn of server>
|
||||
taos -n sync -P 6042 -h <fqdn of server>
|
||||
```
|
||||
|
||||
用来诊断 sync 端口是否工作正常,判断服务端 sync 模块是否成功工作。另外,-P 6042 用来诊断 arbitrator 是否配置正常,判断指定服务器的 arbitrator 是否能正常工作。
|
||||
|
||||
## 网络速度诊断
|
||||
|
||||
`taos -n speed -h <fqdn of server> -P 6030 -N 10 -l 10000000 -S TCP`
|
||||
|
||||
从 2.2.0.0 版本开始,taos 工具新提供了一个网络速度诊断的模式,可以对一个正在运行中的 taosd 实例或者 `taos -n server` 方式模拟的一个服务端实例,以非压缩传输的方式进行网络测速。这个模式下可供调整的参数如下:
|
||||
|
||||
-n:设为“speed”时,表示对网络速度进行诊断。
|
||||
-h:所要连接的服务端的 FQDN 或 ip 地址。如果不设置这一项,会使用本机 taos.cfg 文件中 FQDN 参数的设置作为默认值。
|
||||
-P:所连接服务端的网络端口。默认值为 6030。
|
||||
-N:诊断过程中使用的网络包总数。最小值是 1、最大值是 10000,默认值为 100。
|
||||
-l:单个网络包的大小(单位:字节)。最小值是 1024、最大值是 1024 `*` 1024 `*` 1024,默认值为 1024。
|
||||
-S:网络封包的类型。可以是 TCP 或 UDP,默认值为 TCP。
|
||||
|
||||
## FQDN 解析速度诊断
|
||||
|
||||
`taos -n fqdn -h <fqdn of server>`
|
||||
|
||||
从 2.2.0.0 版本开始,taos 工具新提供了一个 FQDN 解析速度的诊断模式,可以对一个目标 FQDN 地址尝试解析,并记录解析过程中所消耗的时间。这个模式下可供调整的参数如下:
|
||||
|
||||
-n:设为“fqdn”时,表示对 FQDN 解析进行诊断。
|
||||
-h:所要解析的目标 FQDN 地址。如果不设置这一项,会使用本机 taos.cfg 文件中 FQDN 参数的设置作为默认值。
|
||||
|
||||
## 服务端日志
|
||||
|
||||
taosd 服务端日志文件标志位 debugflag 默认为 131,在 debug 时往往需要将其提升到 135 或 143 。
|
||||
|
||||
一旦设定为 135 或 143,日志文件增长很快,特别是写入、查询请求量较大时,增长速度惊人。如合并保存日志,很容易把日志内的关键信息(如配置信息、错误信息等)冲掉。为此,服务端将重要信息日志与其他日志分开存放:
|
||||
|
||||
- taosinfo 存放重要信息日志, 包括:INFO/ERROR/WARNING 级别的日志信息。不记录 DEBUG、TRACE 级别的日志。
|
||||
- taosdlog 服务器端生成的日志,记录 taosinfo 中全部信息外,还根据设置的日志输出级别,记录 DEBUG(日志级别 135)、TRACE(日志级别是 143)。
|
||||
|
||||
## 客户端日志
|
||||
|
||||
每个独立运行的客户端(一个进程)生成一个独立的客户端日志,其命名方式采用 taoslog+<序号> 的方式命名。文件标志位 debugflag 默认为 131,在 debug 时往往需要将其提升到 135 或 143 。
|
||||
|
||||
- taoslog 客户端(driver)生成的日志,默认记录客户端 INFO/ERROR/WARNING 级别日志,还根据设置的日志输出级别,记录 DEBUG(日志级别 135)、TRACE(日志级别是 143)。
|
||||
|
||||
其中,日志文件最大长度由 numOfLogLines 来进行配置,一个 taosd 实例最多保留两个文件。
|
||||
|
||||
taosd 服务端日志采用异步落盘写入机制,优点是可以避免硬盘写入压力太大,对性能造成很大影响。缺点是,在极端情况下,存在少量日志行数丢失的可能。
|
||||
---
|
||||
title: 诊断及其他
|
||||
---
|
||||
|
||||
## 网络连接诊断
|
||||
|
||||
当出现客户端应用无法访问服务端时,需要确认客户端与服务端之间网络的各端口连通情况,以便有针对性地排除故障。
|
||||
|
||||
目前网络连接诊断支持在:Linux 与 Linux,Linux 与 Windows 之间进行诊断测试。
|
||||
|
||||
诊断步骤:
|
||||
|
||||
1. 如拟诊断的端口范围与服务器 taosd 实例的端口范围相同,须先停掉 taosd 实例
|
||||
2. 服务端命令行输入:`taos -n server -P <port> -l <pktlen>` 以服务端身份启动对端口 port 为基准端口的监听
|
||||
3. 客户端命令行输入:`taos -n client -h <fqdn of server> -P <port> -l <pktlen>` 以客户端身份启动对指定的服务器、指定的端口发送测试包
|
||||
|
||||
-l <pktlen\>: 测试网络包的大小(单位:字节)。最小值是 11、最大值是 64000,默认值为 1000。
|
||||
注:两端命令行中指定的测试包长度必须一致,否则测试显示失败。
|
||||
|
||||
服务端运行正常的话会输出以下信息:
|
||||
|
||||
```bash
|
||||
# taos -n server -P 6030 -l 1000
|
||||
network test server is initialized, port:6030
|
||||
request is received, size:1000
|
||||
request is received, size:1000
|
||||
...
|
||||
...
|
||||
...
|
||||
request is received, size:1000
|
||||
request is received, size:1000
|
||||
```
|
||||
|
||||
客户端运行正常会输出以下信息:
|
||||
|
||||
```bash
|
||||
# taos -n client -h 172.27.0.7 -P 6000
|
||||
taos -n client -h v3s2 -P 6030 -l 1000
|
||||
network test client is initialized, the server is v3s2:6030
|
||||
request is sent, size:1000
|
||||
response is received, size:1000
|
||||
request is sent, size:1000
|
||||
response is received, size:1000
|
||||
...
|
||||
...
|
||||
...
|
||||
request is sent, size:1000
|
||||
response is received, size:1000
|
||||
request is sent, size:1000
|
||||
response is received, size:1000
|
||||
|
||||
total succ: 100/100 cost: 16.23 ms speed: 5.87 MB/s
|
||||
```
|
||||
|
||||
仔细阅读打印出来的错误信息,可以帮助管理员找到原因,以解决问题。
|
||||
|
||||
## 服务端日志
|
||||
|
||||
taosd 服务端日志文件标志位 debugflag 默认为 131,在 debug 时往往需要将其提升到 135 或 143 。
|
||||
|
||||
一旦设定为 135 或 143,日志文件增长很快,特别是写入、查询请求量较大时,增长速度惊人。请注意日志文件目录所在磁盘的空间大小。
|
||||
|
||||
## 客户端日志
|
||||
|
||||
每个独立运行的客户端(一个进程)生成一个独立的客户端日志,其命名方式采用 taoslog+<序号> 的方式命名。文件标志位 debugflag 默认为 131,在 debug 时往往需要将其提升到 135 或 143 。
|
||||
|
||||
- taoslog 客户端(driver)生成的日志,默认记录客户端 INFO/ERROR/WARNING 级别日志,还根据设置的日志输出级别,记录 DEBUG(日志级别 135)、TRACE(日志级别是 143)。
|
||||
|
||||
其中,日志文件最大长度由 numOfLogLines 来进行配置,一个 taosd 实例最多保留两个文件。
|
||||
|
||||
taosd 服务端日志采用异步落盘写入机制,优点是可以避免硬盘写入压力太大,对性能造成很大影响。缺点是,在极端情况下,存在少量日志行数丢失的可能。当问题分析需要的时候,可以考虑将 参数 asynclog 设置成 0,修改为同步落盘写入机制,保证日志不会丢失。
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
sidebar_label: 发布历史
|
||||
title: 发布历史
|
||||
---
|
||||
|
||||
import Release from "/components/Release";
|
||||
|
||||
|
||||
<Release versionPrefix="3.0" />
|
760
examples/c/tmq.c
760
examples/c/tmq.c
|
@ -1,473 +1,287 @@
|
|||
/*
|
||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
||||
*
|
||||
* This program is free software: you can use, redistribute, and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3
|
||||
* or later ("AGPL"), as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include "taos.h"
|
||||
|
||||
static int running = 1;
|
||||
static void msg_process(TAOS_RES* msg) {
|
||||
char buf[1024];
|
||||
/*memset(buf, 0, 1024);*/
|
||||
printf("topic: %s\n", tmq_get_topic_name(msg));
|
||||
printf("db: %s\n", tmq_get_db_name(msg));
|
||||
printf("vg: %d\n", tmq_get_vgroup_id(msg));
|
||||
if (tmq_get_res_type(msg) == TMQ_RES_TABLE_META) {
|
||||
tmq_raw_data raw = {0};
|
||||
int32_t code = tmq_get_raw(msg, &raw);
|
||||
if (code == 0) {
|
||||
TAOS* pConn = taos_connect("192.168.1.86", "root", "taosdata", NULL, 0);
|
||||
if (pConn == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
TAOS_RES* pRes = taos_query(pConn, "create database if not exists abc1 vgroups 5");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
printf("error in create db, reason:%s\n", taos_errstr(pRes));
|
||||
return;
|
||||
}
|
||||
taos_free_result(pRes);
|
||||
|
||||
pRes = taos_query(pConn, "use abc1");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
printf("error in use db, reason:%s\n", taos_errstr(pRes));
|
||||
return;
|
||||
}
|
||||
taos_free_result(pRes);
|
||||
|
||||
int32_t ret = tmq_write_raw(pConn, raw);
|
||||
printf("write raw data: %s\n", tmq_err2str(ret));
|
||||
taos_close(pConn);
|
||||
}
|
||||
char* result = tmq_get_json_meta(msg);
|
||||
if (result) {
|
||||
printf("meta result: %s\n", result);
|
||||
}
|
||||
tmq_free_json_meta(result);
|
||||
return;
|
||||
}
|
||||
while (1) {
|
||||
TAOS_ROW row = taos_fetch_row(msg);
|
||||
if (row == NULL) break;
|
||||
TAOS_FIELD* fields = taos_fetch_fields(msg);
|
||||
int32_t numOfFields = taos_field_count(msg);
|
||||
taos_print_row(buf, row, fields, numOfFields);
|
||||
printf("%s\n", buf);
|
||||
|
||||
const char* tbName = tmq_get_table_name(msg);
|
||||
if (tbName) {
|
||||
printf("from tb: %s\n", tbName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int32_t init_env() {
|
||||
TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0);
|
||||
if (pConn == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
TAOS_RES* pRes = taos_query(pConn, "create database if not exists abc1 vgroups 5");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
printf("error in create db, reason:%s\n", taos_errstr(pRes));
|
||||
return -1;
|
||||
}
|
||||
taos_free_result(pRes);
|
||||
|
||||
pRes = taos_query(pConn, "use abc1");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
printf("error in use db, reason:%s\n", taos_errstr(pRes));
|
||||
return -1;
|
||||
}
|
||||
taos_free_result(pRes);
|
||||
|
||||
pRes = taos_query(pConn,
|
||||
"create stable if not exists st1 (ts timestamp, c1 int, c2 float, c3 binary(16)) tags(t1 int, t3 "
|
||||
"nchar(8), t4 bool)");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
printf("failed to create super table st1, reason:%s\n", taos_errstr(pRes));
|
||||
return -1;
|
||||
}
|
||||
taos_free_result(pRes);
|
||||
|
||||
pRes = taos_query(pConn, "create table if not exists ct0 using st1 tags(1000, \"ttt\", true)");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
printf("failed to create child table tu1, reason:%s\n", taos_errstr(pRes));
|
||||
return -1;
|
||||
}
|
||||
taos_free_result(pRes);
|
||||
|
||||
pRes = taos_query(pConn, "insert into ct0 values(now, 1, 2, 'a')");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
printf("failed to insert into ct0, reason:%s\n", taos_errstr(pRes));
|
||||
return -1;
|
||||
}
|
||||
taos_free_result(pRes);
|
||||
|
||||
pRes = taos_query(pConn, "create table if not exists ct1 using st1(t1) tags(2000)");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
printf("failed to create child table ct1, reason:%s\n", taos_errstr(pRes));
|
||||
return -1;
|
||||
}
|
||||
taos_free_result(pRes);
|
||||
|
||||
pRes = taos_query(pConn, "create table if not exists ct2 using st1(t1) tags(NULL)");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
printf("failed to create child table ct2, reason:%s\n", taos_errstr(pRes));
|
||||
return -1;
|
||||
}
|
||||
taos_free_result(pRes);
|
||||
|
||||
pRes = taos_query(pConn, "insert into ct1 values(now, 3, 4, 'b')");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
printf("failed to insert into ct1, reason:%s\n", taos_errstr(pRes));
|
||||
return -1;
|
||||
}
|
||||
taos_free_result(pRes);
|
||||
|
||||
pRes = taos_query(pConn, "create table if not exists ct3 using st1(t1) tags(3000)");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
printf("failed to create child table ct3, reason:%s\n", taos_errstr(pRes));
|
||||
return -1;
|
||||
}
|
||||
taos_free_result(pRes);
|
||||
|
||||
pRes = taos_query(pConn, "insert into ct3 values(now, 5, 6, 'c')");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
printf("failed to insert into ct3, reason:%s\n", taos_errstr(pRes));
|
||||
return -1;
|
||||
}
|
||||
taos_free_result(pRes);
|
||||
|
||||
#if 0
|
||||
pRes = taos_query(pConn, "alter table st1 add column c4 bigint");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
printf("failed to alter super table st1, reason:%s\n", taos_errstr(pRes));
|
||||
return -1;
|
||||
}
|
||||
taos_free_result(pRes);
|
||||
|
||||
pRes = taos_query(pConn, "alter table st1 modify column c3 binary(64)");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
printf("failed to alter super table st1, reason:%s\n", taos_errstr(pRes));
|
||||
return -1;
|
||||
}
|
||||
taos_free_result(pRes);
|
||||
|
||||
pRes = taos_query(pConn, "alter table st1 add tag t2 binary(64)");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
printf("failed to alter super table st1, reason:%s\n", taos_errstr(pRes));
|
||||
return -1;
|
||||
}
|
||||
taos_free_result(pRes);
|
||||
|
||||
pRes = taos_query(pConn, "alter table ct3 set tag t1=5000");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
printf("failed to slter child table ct3, reason:%s\n", taos_errstr(pRes));
|
||||
return -1;
|
||||
}
|
||||
taos_free_result(pRes);
|
||||
|
||||
pRes = taos_query(pConn, "drop table ct3 ct1");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
printf("failed to drop child table ct3, reason:%s\n", taos_errstr(pRes));
|
||||
return -1;
|
||||
}
|
||||
taos_free_result(pRes);
|
||||
|
||||
pRes = taos_query(pConn, "drop table st1");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
printf("failed to drop super table st1, reason:%s\n", taos_errstr(pRes));
|
||||
return -1;
|
||||
}
|
||||
taos_free_result(pRes);
|
||||
|
||||
pRes = taos_query(pConn, "create table if not exists n1(ts timestamp, c1 int, c2 nchar(4))");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
printf("failed to create normal table n1, reason:%s\n", taos_errstr(pRes));
|
||||
return -1;
|
||||
}
|
||||
taos_free_result(pRes);
|
||||
|
||||
pRes = taos_query(pConn, "alter table n1 add column c3 bigint");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
printf("failed to alter normal table n1, reason:%s\n", taos_errstr(pRes));
|
||||
return -1;
|
||||
}
|
||||
taos_free_result(pRes);
|
||||
|
||||
pRes = taos_query(pConn, "alter table n1 modify column c2 nchar(8)");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
printf("failed to alter normal table n1, reason:%s\n", taos_errstr(pRes));
|
||||
return -1;
|
||||
}
|
||||
taos_free_result(pRes);
|
||||
|
||||
pRes = taos_query(pConn, "alter table n1 rename column c3 cc3");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
printf("failed to alter normal table n1, reason:%s\n", taos_errstr(pRes));
|
||||
return -1;
|
||||
}
|
||||
taos_free_result(pRes);
|
||||
|
||||
pRes = taos_query(pConn, "alter table n1 comment 'hello'");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
printf("failed to alter normal table n1, reason:%s\n", taos_errstr(pRes));
|
||||
return -1;
|
||||
}
|
||||
taos_free_result(pRes);
|
||||
|
||||
pRes = taos_query(pConn, "alter table n1 drop column c1");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
printf("failed to alter normal table n1, reason:%s\n", taos_errstr(pRes));
|
||||
return -1;
|
||||
}
|
||||
taos_free_result(pRes);
|
||||
|
||||
pRes = taos_query(pConn, "drop table n1");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
printf("failed to drop normal table n1, reason:%s\n", taos_errstr(pRes));
|
||||
return -1;
|
||||
}
|
||||
taos_free_result(pRes);
|
||||
|
||||
pRes = taos_query(pConn, "create table jt(ts timestamp, i int) tags(t json)");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
printf("failed to create super table jt, reason:%s\n", taos_errstr(pRes));
|
||||
return -1;
|
||||
}
|
||||
taos_free_result(pRes);
|
||||
|
||||
pRes = taos_query(pConn, "create table jt1 using jt tags('{\"k1\":1, \"k2\":\"hello\"}')");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
printf("failed to create super table jt, reason:%s\n", taos_errstr(pRes));
|
||||
return -1;
|
||||
}
|
||||
taos_free_result(pRes);
|
||||
|
||||
pRes = taos_query(pConn, "create table jt2 using jt tags('')");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
printf("failed to create super table jt2, reason:%s\n", taos_errstr(pRes));
|
||||
return -1;
|
||||
}
|
||||
taos_free_result(pRes);
|
||||
|
||||
pRes = taos_query(pConn,
|
||||
"create stable if not exists st1 (ts timestamp, c1 int, c2 float, c3 binary(16)) tags(t1 int, t3 "
|
||||
"nchar(8), t4 bool)");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
printf("failed to create super table st1, reason:%s\n", taos_errstr(pRes));
|
||||
return -1;
|
||||
}
|
||||
taos_free_result(pRes);
|
||||
|
||||
pRes = taos_query(pConn, "drop table st1");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
printf("failed to drop super table st1, reason:%s\n", taos_errstr(pRes));
|
||||
return -1;
|
||||
}
|
||||
taos_free_result(pRes);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t create_topic() {
|
||||
printf("create topic\n");
|
||||
TAOS_RES* pRes;
|
||||
TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0);
|
||||
if (pConn == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
pRes = taos_query(pConn, "use abc1");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
printf("error in use db, reason:%s\n", taos_errstr(pRes));
|
||||
return -1;
|
||||
}
|
||||
taos_free_result(pRes);
|
||||
|
||||
// pRes = taos_query(pConn, "create topic topic_ctb_column with meta as database abc1");
|
||||
pRes = taos_query(pConn, "create topic topic_ctb_column as select ts, c1, c2, c3 from st1");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
printf("failed to create topic topic_ctb_column, reason:%s\n", taos_errstr(pRes));
|
||||
return -1;
|
||||
}
|
||||
taos_free_result(pRes);
|
||||
|
||||
pRes = taos_query(pConn, "create topic topic2 as select ts, c1, c2, c3 from st1");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
printf("failed to create topic topic_ctb_column, reason:%s\n", taos_errstr(pRes));
|
||||
return -1;
|
||||
}
|
||||
taos_free_result(pRes);
|
||||
|
||||
#if 0
|
||||
pRes = taos_query(pConn, "insert into tu1 values(now, 1, 1.0, 'bi1')");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
printf("failed to insert, reason:%s\n", taos_errstr(pRes));
|
||||
return -1;
|
||||
}
|
||||
taos_free_result(pRes);
|
||||
pRes = taos_query(pConn, "insert into tu1 values(now+1d, 1, 1.0, 'bi1')");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
printf("failed to insert, reason:%s\n", taos_errstr(pRes));
|
||||
return -1;
|
||||
}
|
||||
taos_free_result(pRes);
|
||||
pRes = taos_query(pConn, "insert into tu2 values(now, 2, 2.0, 'bi2')");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
printf("failed to insert, reason:%s\n", taos_errstr(pRes));
|
||||
return -1;
|
||||
}
|
||||
taos_free_result(pRes);
|
||||
pRes = taos_query(pConn, "insert into tu2 values(now+1d, 2, 2.0, 'bi2')");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
printf("failed to insert, reason:%s\n", taos_errstr(pRes));
|
||||
return -1;
|
||||
}
|
||||
taos_free_result(pRes);
|
||||
#endif
|
||||
|
||||
taos_close(pConn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void tmq_commit_cb_print(tmq_t* tmq, int32_t code, void* param) {
|
||||
printf("commit %d tmq %p param %p\n", code, tmq, param);
|
||||
}
|
||||
|
||||
tmq_t* build_consumer() {
|
||||
#if 0
|
||||
TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0);
|
||||
assert(pConn != NULL);
|
||||
|
||||
TAOS_RES* pRes = taos_query(pConn, "use abc1");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
printf("error in use db, reason:%s\n", taos_errstr(pRes));
|
||||
}
|
||||
taos_free_result(pRes);
|
||||
#endif
|
||||
|
||||
tmq_conf_t* conf = tmq_conf_new();
|
||||
tmq_conf_set(conf, "group.id", "tg2");
|
||||
tmq_conf_set(conf, "client.id", "my app 1");
|
||||
tmq_conf_set(conf, "td.connect.user", "root");
|
||||
tmq_conf_set(conf, "td.connect.pass", "taosdata");
|
||||
tmq_conf_set(conf, "msg.with.table.name", "true");
|
||||
tmq_conf_set(conf, "enable.auto.commit", "true");
|
||||
|
||||
/*tmq_conf_set(conf, "experimental.snapshot.enable", "true");*/
|
||||
|
||||
tmq_conf_set_auto_commit_cb(conf, tmq_commit_cb_print, NULL);
|
||||
tmq_t* tmq = tmq_consumer_new(conf, NULL, 0);
|
||||
assert(tmq);
|
||||
tmq_conf_destroy(conf);
|
||||
return tmq;
|
||||
}
|
||||
|
||||
tmq_list_t* build_topic_list() {
|
||||
tmq_list_t* topic_list = tmq_list_new();
|
||||
tmq_list_append(topic_list, "topic_ctb_column");
|
||||
/*tmq_list_append(topic_list, "tmq_test_db_multi_insert_topic");*/
|
||||
return topic_list;
|
||||
}
|
||||
|
||||
void basic_consume_loop(tmq_t* tmq, tmq_list_t* topics) {
|
||||
int32_t code;
|
||||
|
||||
if ((code = tmq_subscribe(tmq, topics))) {
|
||||
fprintf(stderr, "%% Failed to start consuming topics: %s\n", tmq_err2str(code));
|
||||
printf("subscribe err\n");
|
||||
return;
|
||||
}
|
||||
int32_t cnt = 0;
|
||||
while (running) {
|
||||
TAOS_RES* tmqmessage = tmq_consumer_poll(tmq, -1);
|
||||
if (tmqmessage) {
|
||||
cnt++;
|
||||
msg_process(tmqmessage);
|
||||
/*if (cnt >= 2) break;*/
|
||||
/*printf("get data\n");*/
|
||||
taos_free_result(tmqmessage);
|
||||
/*} else {*/
|
||||
/*break;*/
|
||||
/*tmq_commit_sync(tmq, NULL);*/
|
||||
}
|
||||
}
|
||||
|
||||
code = tmq_consumer_close(tmq);
|
||||
if (code)
|
||||
fprintf(stderr, "%% Failed to close consumer: %s\n", tmq_err2str(code));
|
||||
else
|
||||
fprintf(stderr, "%% Consumer closed\n");
|
||||
}
|
||||
|
||||
void sync_consume_loop(tmq_t* tmq, tmq_list_t* topics) {
|
||||
static const int MIN_COMMIT_COUNT = 1;
|
||||
|
||||
int msg_count = 0;
|
||||
int32_t code;
|
||||
|
||||
if ((code = tmq_subscribe(tmq, topics))) {
|
||||
fprintf(stderr, "%% Failed to start consuming topics: %s\n", tmq_err2str(code));
|
||||
return;
|
||||
}
|
||||
|
||||
tmq_list_t* subList = NULL;
|
||||
tmq_subscription(tmq, &subList);
|
||||
char** subTopics = tmq_list_to_c_array(subList);
|
||||
int32_t sz = tmq_list_get_size(subList);
|
||||
printf("subscribed topics: ");
|
||||
for (int32_t i = 0; i < sz; i++) {
|
||||
printf("%s, ", subTopics[i]);
|
||||
}
|
||||
printf("\n");
|
||||
tmq_list_destroy(subList);
|
||||
|
||||
while (running) {
|
||||
TAOS_RES* tmqmessage = tmq_consumer_poll(tmq, 1000);
|
||||
if (tmqmessage) {
|
||||
msg_process(tmqmessage);
|
||||
taos_free_result(tmqmessage);
|
||||
|
||||
/*tmq_commit_sync(tmq, NULL);*/
|
||||
/*if ((++msg_count % MIN_COMMIT_COUNT) == 0) tmq_commit(tmq, NULL, 0);*/
|
||||
}
|
||||
}
|
||||
|
||||
code = tmq_consumer_close(tmq);
|
||||
if (code)
|
||||
fprintf(stderr, "%% Failed to close consumer: %s\n", tmq_err2str(code));
|
||||
else
|
||||
fprintf(stderr, "%% Consumer closed\n");
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
if (argc > 1) {
|
||||
printf("env init\n");
|
||||
if (init_env() < 0) {
|
||||
return -1;
|
||||
}
|
||||
create_topic();
|
||||
}
|
||||
tmq_t* tmq = build_consumer();
|
||||
tmq_list_t* topic_list = build_topic_list();
|
||||
basic_consume_loop(tmq, topic_list);
|
||||
/*sync_consume_loop(tmq, topic_list);*/
|
||||
}
|
||||
/*
|
||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
||||
*
|
||||
* This program is free software: you can use, redistribute, and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3
|
||||
* or later ("AGPL"), as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include "taos.h"
|
||||
|
||||
static int running = 1;
|
||||
static char dbName[64] = "tmqdb";
|
||||
static char stbName[64] = "stb";
|
||||
static char topicName[64] = "topicname";
|
||||
|
||||
static int32_t msg_process(TAOS_RES* msg) {
|
||||
char buf[1024];
|
||||
int32_t rows = 0;
|
||||
|
||||
const char* topicName = tmq_get_topic_name(msg);
|
||||
const char* dbName = tmq_get_db_name(msg);
|
||||
int32_t vgroupId = tmq_get_vgroup_id(msg);
|
||||
|
||||
printf("topic: %s\n", topicName);
|
||||
printf("db: %s\n", dbName);
|
||||
printf("vgroup id: %d\n", vgroupId);
|
||||
|
||||
while (1) {
|
||||
TAOS_ROW row = taos_fetch_row(msg);
|
||||
if (row == NULL) break;
|
||||
|
||||
TAOS_FIELD* fields = taos_fetch_fields(msg);
|
||||
int32_t numOfFields = taos_field_count(msg);
|
||||
int32_t* length = taos_fetch_lengths(msg);
|
||||
int32_t precision = taos_result_precision(msg);
|
||||
const char* tbName = tmq_get_table_name(msg);
|
||||
rows++;
|
||||
taos_print_row(buf, row, fields, numOfFields);
|
||||
printf("row content from %s: %s\n", (tbName != NULL ? tbName : "null table"), buf);
|
||||
}
|
||||
|
||||
return rows;
|
||||
}
|
||||
|
||||
static int32_t init_env() {
|
||||
TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0);
|
||||
if (pConn == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
TAOS_RES* pRes;
|
||||
// drop database if exists
|
||||
printf("create database\n");
|
||||
pRes = taos_query(pConn, "drop database if exists tmqdb");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
printf("error in drop tmqdb, reason:%s\n", taos_errstr(pRes));
|
||||
return -1;
|
||||
}
|
||||
taos_free_result(pRes);
|
||||
|
||||
// create database
|
||||
pRes = taos_query(pConn, "create database tmqdb");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
printf("error in create tmqdb, reason:%s\n", taos_errstr(pRes));
|
||||
return -1;
|
||||
}
|
||||
taos_free_result(pRes);
|
||||
|
||||
// create super table
|
||||
printf("create super table\n");
|
||||
pRes = taos_query(pConn, "create table tmqdb.stb (ts timestamp, c1 int, c2 float, c3 varchar(16)) tags(t1 int, t3 varchar(16))");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
printf("failed to create super table stb, reason:%s\n", taos_errstr(pRes));
|
||||
return -1;
|
||||
}
|
||||
taos_free_result(pRes);
|
||||
|
||||
// create sub tables
|
||||
printf("create sub tables\n");
|
||||
pRes = taos_query(pConn, "create table tmqdb.ctb0 using tmqdb.stb tags(0, 'subtable0')");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
printf("failed to create super table ctb0, reason:%s\n", taos_errstr(pRes));
|
||||
return -1;
|
||||
}
|
||||
taos_free_result(pRes);
|
||||
|
||||
pRes = taos_query(pConn, "create table tmqdb.ctb1 using tmqdb.stb tags(1, 'subtable1')");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
printf("failed to create super table ctb1, reason:%s\n", taos_errstr(pRes));
|
||||
return -1;
|
||||
}
|
||||
taos_free_result(pRes);
|
||||
|
||||
pRes = taos_query(pConn, "create table tmqdb.ctb2 using tmqdb.stb tags(2, 'subtable2')");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
printf("failed to create super table ctb2, reason:%s\n", taos_errstr(pRes));
|
||||
return -1;
|
||||
}
|
||||
taos_free_result(pRes);
|
||||
|
||||
pRes = taos_query(pConn, "create table tmqdb.ctb3 using tmqdb.stb tags(3, 'subtable3')");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
printf("failed to create super table ctb3, reason:%s\n", taos_errstr(pRes));
|
||||
return -1;
|
||||
}
|
||||
taos_free_result(pRes);
|
||||
|
||||
// insert data
|
||||
printf("insert data into sub tables\n");
|
||||
pRes = taos_query(pConn, "insert into tmqdb.ctb0 values(now, 0, 0, 'a0')(now+1s, 0, 0, 'a00')");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
printf("failed to insert into ctb0, reason:%s\n", taos_errstr(pRes));
|
||||
return -1;
|
||||
}
|
||||
taos_free_result(pRes);
|
||||
|
||||
pRes = taos_query(pConn, "insert into tmqdb.ctb1 values(now, 1, 1, 'a1')(now+1s, 11, 11, 'a11')");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
printf("failed to insert into ctb0, reason:%s\n", taos_errstr(pRes));
|
||||
return -1;
|
||||
}
|
||||
taos_free_result(pRes);
|
||||
|
||||
pRes = taos_query(pConn, "insert into tmqdb.ctb2 values(now, 2, 2, 'a1')(now+1s, 22, 22, 'a22')");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
printf("failed to insert into ctb0, reason:%s\n", taos_errstr(pRes));
|
||||
return -1;
|
||||
}
|
||||
taos_free_result(pRes);
|
||||
|
||||
pRes = taos_query(pConn, "insert into tmqdb.ctb3 values(now, 3, 3, 'a1')(now+1s, 33, 33, 'a33')");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
printf("failed to insert into ctb0, reason:%s\n", taos_errstr(pRes));
|
||||
return -1;
|
||||
}
|
||||
taos_free_result(pRes);
|
||||
|
||||
taos_close(pConn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t create_topic() {
|
||||
printf("create topic\n");
|
||||
TAOS_RES* pRes;
|
||||
TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0);
|
||||
if (pConn == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
pRes = taos_query(pConn, "use tmqdb");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
printf("error in use tmqdb, reason:%s\n", taos_errstr(pRes));
|
||||
return -1;
|
||||
}
|
||||
taos_free_result(pRes);
|
||||
|
||||
// pRes = taos_query(pConn, "create topic topic_ctb_column with meta as database abc1");
|
||||
pRes = taos_query(pConn, "create topic topicname as select ts, c1, c2, c3 from tmqdb.stb where c1 > 1");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
printf("failed to create topic topicname, reason:%s\n", taos_errstr(pRes));
|
||||
return -1;
|
||||
}
|
||||
taos_free_result(pRes);
|
||||
|
||||
taos_close(pConn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void tmq_commit_cb_print(tmq_t* tmq, int32_t code, void* param) {
|
||||
printf("tmq_commit_cb_print() code: %d, tmq: %p, param: %p\n", code, tmq, param);
|
||||
}
|
||||
|
||||
tmq_t* build_consumer() {
|
||||
tmq_conf_res_t code;
|
||||
tmq_conf_t* conf = tmq_conf_new();
|
||||
code = tmq_conf_set(conf, "enable.auto.commit", "true");
|
||||
if (TMQ_CONF_OK != code) return NULL;
|
||||
code = tmq_conf_set(conf, "auto.commit.interval.ms", "1000");
|
||||
if (TMQ_CONF_OK != code) return NULL;
|
||||
code = tmq_conf_set(conf, "group.id", "cgrpName");
|
||||
if (TMQ_CONF_OK != code) return NULL;
|
||||
code = tmq_conf_set(conf, "td.connect.user", "root");
|
||||
if (TMQ_CONF_OK != code) return NULL;
|
||||
code = tmq_conf_set(conf, "td.connect.pass", "taosdata");
|
||||
if (TMQ_CONF_OK != code) return NULL;
|
||||
code = tmq_conf_set(conf, "auto.offset.reset", "earliest");
|
||||
if (TMQ_CONF_OK != code) return NULL;
|
||||
code = tmq_conf_set(conf, "experimental.snapshot.enable", "true");
|
||||
if (TMQ_CONF_OK != code) return NULL;
|
||||
code = tmq_conf_set(conf, "msg.with.table.name", "true");
|
||||
if (TMQ_CONF_OK != code) return NULL;
|
||||
|
||||
tmq_conf_set_auto_commit_cb(conf, tmq_commit_cb_print, NULL);
|
||||
|
||||
tmq_t* tmq = tmq_consumer_new(conf, NULL, 0);
|
||||
tmq_conf_destroy(conf);
|
||||
return tmq;
|
||||
}
|
||||
|
||||
tmq_list_t* build_topic_list() {
|
||||
tmq_list_t* topicList = tmq_list_new();
|
||||
int32_t code = tmq_list_append(topicList, "topicname");
|
||||
if (code) {
|
||||
return NULL;
|
||||
}
|
||||
return topicList;
|
||||
}
|
||||
|
||||
void basic_consume_loop(tmq_t* tmq, tmq_list_t* topicList) {
|
||||
int32_t code;
|
||||
|
||||
if ((code = tmq_subscribe(tmq, topicList))) {
|
||||
fprintf(stderr, "%% Failed to tmq_subscribe(): %s\n", tmq_err2str(code));
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t totalRows = 0;
|
||||
int32_t msgCnt = 0;
|
||||
int32_t consumeDelay = 5000;
|
||||
while (running) {
|
||||
TAOS_RES* tmqmsg = tmq_consumer_poll(tmq, consumeDelay);
|
||||
if (tmqmsg) {
|
||||
msgCnt++;
|
||||
totalRows += msg_process(tmqmsg);
|
||||
taos_free_result(tmqmsg);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "%d msg consumed, include %d rows\n", msgCnt, totalRows);
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
int32_t code;
|
||||
|
||||
if (init_env() < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (create_topic() < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
tmq_t* tmq = build_consumer();
|
||||
if (NULL == tmq) {
|
||||
fprintf(stderr, "%% build_consumer() fail!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
tmq_list_t* topic_list = build_topic_list();
|
||||
if (NULL == topic_list) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
basic_consume_loop(tmq, topic_list);
|
||||
|
||||
code = tmq_unsubscribe(tmq);
|
||||
if (code) {
|
||||
fprintf(stderr, "%% Failed to unsubscribe: %s\n", tmq_err2str(code));
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "%% unsubscribe\n");
|
||||
}
|
||||
|
||||
code = tmq_consumer_close(tmq);
|
||||
if (code) {
|
||||
fprintf(stderr, "%% Failed to close consumer: %s\n", tmq_err2str(code));
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "%% Consumer closed\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -104,9 +104,11 @@ typedef struct SDataBlockInfo {
|
|||
uint32_t capacity;
|
||||
// TODO: optimize and remove following
|
||||
int64_t version; // used for stream, and need serialization
|
||||
int64_t ts; // used for stream, and need serialization
|
||||
int32_t childId; // used for stream, do not serialize
|
||||
EStreamType type; // used for stream, do not serialize
|
||||
STimeWindow calWin; // used for stream, do not serialize
|
||||
TSKEY watermark;// used for stream
|
||||
} SDataBlockInfo;
|
||||
|
||||
typedef struct SSDataBlock {
|
||||
|
|
|
@ -1370,6 +1370,7 @@ typedef struct {
|
|||
int64_t skey;
|
||||
int64_t ekey;
|
||||
int64_t version; // for stream
|
||||
TSKEY watermark;// for stream
|
||||
char data[];
|
||||
} SRetrieveTableRsp;
|
||||
|
||||
|
@ -2657,6 +2658,34 @@ typedef struct {
|
|||
SEpSet epSet;
|
||||
} SVgEpSet;
|
||||
|
||||
typedef struct {
|
||||
int64_t refId;
|
||||
int64_t suid;
|
||||
int8_t level;
|
||||
} SRSmaFetchMsg;
|
||||
|
||||
static FORCE_INLINE int32_t tEncodeSRSmaFetchMsg(SEncoder* pCoder, const SRSmaFetchMsg* pReq) {
|
||||
if (tStartEncode(pCoder) < 0) return -1;
|
||||
|
||||
if (tEncodeI64(pCoder, pReq->refId) < 0) return -1;
|
||||
if (tEncodeI64(pCoder, pReq->suid) < 0) return -1;
|
||||
if (tEncodeI8(pCoder, pReq->level) < 0) return -1;
|
||||
|
||||
tEndEncode(pCoder);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static FORCE_INLINE int32_t tDecodeSRSmaFetchMsg(SDecoder* pCoder, SRSmaFetchMsg* pReq) {
|
||||
if (tStartDecode(pCoder) < 0) return -1;
|
||||
|
||||
if (tDecodeI64(pCoder, &pReq->refId) < 0) return -1;
|
||||
if (tDecodeI64(pCoder, &pReq->suid) < 0) return -1;
|
||||
if (tDecodeI8(pCoder, &pReq->level) < 0) return -1;
|
||||
|
||||
tEndDecode(pCoder);
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
int8_t version; // for compatibility(default 0)
|
||||
int8_t intervalUnit; // MACRO: TIME_UNIT_XXX
|
||||
|
@ -3055,6 +3084,7 @@ int32_t tEncodeDeleteRes(SEncoder* pCoder, const SDeleteRes* pRes);
|
|||
int32_t tDecodeDeleteRes(SDecoder* pCoder, SDeleteRes* pRes);
|
||||
|
||||
typedef struct {
|
||||
int32_t msgIdx;
|
||||
int32_t msgType;
|
||||
int32_t msgLen;
|
||||
void* msg;
|
||||
|
@ -3068,12 +3098,13 @@ typedef struct {
|
|||
|
||||
typedef struct {
|
||||
int32_t reqType;
|
||||
int32_t msgIdx;
|
||||
int32_t msgLen;
|
||||
int32_t rspCode;
|
||||
void* msg;
|
||||
} SBatchRsp;
|
||||
|
||||
static FORCE_INLINE void tFreeSBatchRsp(void *p) {
|
||||
static FORCE_INLINE void tFreeSBatchRsp(void* p) {
|
||||
if (NULL == p) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -58,12 +58,17 @@ typedef struct SDbInfo {
|
|||
int64_t dbId;
|
||||
} SDbInfo;
|
||||
|
||||
typedef struct STablesReq {
|
||||
char dbFName[TSDB_DB_FNAME_LEN];
|
||||
SArray* pTables;
|
||||
} STablesReq;
|
||||
|
||||
typedef struct SCatalogReq {
|
||||
SArray* pDbVgroup; // element is db full name
|
||||
SArray* pDbCfg; // element is db full name
|
||||
SArray* pDbInfo; // element is db full name
|
||||
SArray* pTableMeta; // element is SNAME
|
||||
SArray* pTableHash; // element is SNAME
|
||||
SArray* pTableMeta; // element is STablesReq
|
||||
SArray* pTableHash; // element is STablesReq
|
||||
SArray* pUdf; // element is udf name
|
||||
SArray* pIndex; // element is index name
|
||||
SArray* pUser; // element is SUserAuthInfo
|
||||
|
|
|
@ -76,6 +76,13 @@ qTaskInfo_t qCreateQueueExecTaskInfo(void* msg, SReadHandle* readers, int32_t* n
|
|||
*/
|
||||
int32_t qSetMultiStreamInput(qTaskInfo_t tinfo, const void* pBlocks, size_t numOfBlocks, int32_t type);
|
||||
|
||||
/**
|
||||
* @brief Cleanup SSDataBlock for StreamScanInfo
|
||||
*
|
||||
* @param tinfo
|
||||
*/
|
||||
void tdCleanupStreamInputDataBlock(qTaskInfo_t tinfo);
|
||||
|
||||
/**
|
||||
* Update the table id list, add or remove.
|
||||
*
|
||||
|
@ -96,7 +103,7 @@ int32_t qUpdateQualifiedTableId(qTaskInfo_t tinfo, const SArray* tableIdList, bo
|
|||
* @return
|
||||
*/
|
||||
int32_t qCreateExecTask(SReadHandle* readHandle, int32_t vgId, uint64_t taskId, struct SSubplan* pPlan,
|
||||
qTaskInfo_t* pTaskInfo, DataSinkHandle* handle, const char* sql, EOPTR_EXEC_MODEL model);
|
||||
qTaskInfo_t* pTaskInfo, DataSinkHandle* handle, char* sql, EOPTR_EXEC_MODEL model);
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
|
@ -202,6 +202,7 @@ bool fmIsForbidStreamFunc(int32_t funcId);
|
|||
bool fmIsIntervalInterpoFunc(int32_t funcId);
|
||||
bool fmIsInterpFunc(int32_t funcId);
|
||||
bool fmIsLastRowFunc(int32_t funcId);
|
||||
bool fmIsNotNullOutputFunc(int32_t funcId);
|
||||
bool fmIsSelectValueFunc(int32_t funcId);
|
||||
bool fmIsSystemInfoFunc(int32_t funcId);
|
||||
bool fmIsImplicitTsFunc(int32_t funcId);
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "os.h"
|
||||
#include "query.h"
|
||||
#include "tdatablock.h"
|
||||
#include "tdbInt.h"
|
||||
#include "tmsg.h"
|
||||
#include "tmsgcb.h"
|
||||
#include "tqueue.h"
|
||||
|
@ -46,9 +47,10 @@ enum {
|
|||
};
|
||||
|
||||
enum {
|
||||
TASK_EXEC_STATUS__IDLE = 1,
|
||||
TASK_EXEC_STATUS__EXECUTING,
|
||||
TASK_EXEC_STATUS__CLOSING,
|
||||
TASK_SCHED_STATUS__INACTIVE = 1,
|
||||
TASK_SCHED_STATUS__WAITING,
|
||||
TASK_SCHED_STATUS__ACTIVE,
|
||||
TASK_SCHED_STATUS__FAILED,
|
||||
};
|
||||
|
||||
enum {
|
||||
|
@ -65,6 +67,31 @@ enum {
|
|||
TASK_OUTPUT_STATUS__BLOCKED,
|
||||
};
|
||||
|
||||
enum {
|
||||
TASK_TRIGGER_STATUS__INACTIVE = 1,
|
||||
TASK_TRIGGER_STATUS__ACTIVE,
|
||||
};
|
||||
|
||||
enum {
|
||||
TASK_LEVEL__SOURCE = 1,
|
||||
TASK_LEVEL__AGG,
|
||||
TASK_LEVEL__SINK,
|
||||
};
|
||||
|
||||
enum {
|
||||
TASK_OUTPUT__FIXED_DISPATCH = 1,
|
||||
TASK_OUTPUT__SHUFFLE_DISPATCH,
|
||||
TASK_OUTPUT__TABLE,
|
||||
TASK_OUTPUT__SMA,
|
||||
TASK_OUTPUT__FETCH,
|
||||
};
|
||||
|
||||
enum {
|
||||
STREAM_QUEUE__SUCESS = 1,
|
||||
STREAM_QUEUE__FAILED,
|
||||
STREAM_QUEUE__PROCESSING,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
int8_t type;
|
||||
} SStreamQueueItem;
|
||||
|
@ -103,12 +130,6 @@ typedef struct {
|
|||
SSDataBlock* pBlock;
|
||||
} SStreamTrigger;
|
||||
|
||||
enum {
|
||||
STREAM_QUEUE__SUCESS = 1,
|
||||
STREAM_QUEUE__FAILED,
|
||||
STREAM_QUEUE__PROCESSING,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
STaosQueue* queue;
|
||||
STaosQall* qall;
|
||||
|
@ -201,41 +222,6 @@ typedef struct {
|
|||
int8_t reserved;
|
||||
} STaskSinkFetch;
|
||||
|
||||
enum {
|
||||
TASK_SOURCE__SCAN = 1,
|
||||
TASK_SOURCE__PIPE,
|
||||
TASK_SOURCE__MERGE,
|
||||
};
|
||||
|
||||
enum {
|
||||
TASK_EXEC__NONE = 1,
|
||||
TASK_EXEC__PIPE,
|
||||
TASK_EXEC__MERGE,
|
||||
};
|
||||
|
||||
enum {
|
||||
TASK_DISPATCH__NONE = 1,
|
||||
TASK_DISPATCH__FIXED,
|
||||
TASK_DISPATCH__SHUFFLE,
|
||||
};
|
||||
|
||||
enum {
|
||||
TASK_SINK__NONE = 1,
|
||||
TASK_SINK__TABLE,
|
||||
TASK_SINK__SMA,
|
||||
TASK_SINK__FETCH,
|
||||
};
|
||||
|
||||
enum {
|
||||
TASK_INPUT_TYPE__SUMBIT_BLOCK = 1,
|
||||
TASK_INPUT_TYPE__DATA_BLOCK,
|
||||
};
|
||||
|
||||
enum {
|
||||
TASK_TRIGGER_STATUS__IN_ACTIVE = 1,
|
||||
TASK_TRIGGER_STATUS__ACTIVE,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
int32_t nodeId;
|
||||
int32_t childId;
|
||||
|
@ -248,28 +234,25 @@ typedef struct {
|
|||
typedef struct SStreamTask {
|
||||
int64_t streamId;
|
||||
int32_t taskId;
|
||||
int8_t isDataScan;
|
||||
int8_t execType;
|
||||
int8_t sinkType;
|
||||
int8_t dispatchType;
|
||||
int8_t isStreamDistributed;
|
||||
int32_t totalLevel;
|
||||
int8_t taskLevel;
|
||||
int8_t outputType;
|
||||
int16_t dispatchMsgType;
|
||||
|
||||
int8_t taskStatus;
|
||||
int8_t execStatus;
|
||||
int8_t schedStatus;
|
||||
|
||||
// node info
|
||||
int32_t selfChildId;
|
||||
int32_t nodeId;
|
||||
SEpSet epSet;
|
||||
|
||||
// used for semi or single task,
|
||||
// while final task should have processedVer for each child
|
||||
// used for task source and sink,
|
||||
// while task agg should have processedVer for each child
|
||||
int64_t recoverSnapVer;
|
||||
int64_t startVer;
|
||||
int64_t checkpointVer;
|
||||
int64_t processedVer;
|
||||
// int32_t numOfVgroups;
|
||||
|
||||
// children info
|
||||
SArray* childEpInfo; // SArray<SStreamChildEpInfo*>
|
||||
|
@ -277,19 +260,13 @@ typedef struct SStreamTask {
|
|||
// exec
|
||||
STaskExec exec;
|
||||
|
||||
// TODO: unify sink and dispatch
|
||||
|
||||
// local sink
|
||||
union {
|
||||
STaskSinkTb tbSink;
|
||||
STaskSinkSma smaSink;
|
||||
STaskSinkFetch fetchSink;
|
||||
};
|
||||
|
||||
// remote dispatcher
|
||||
// output
|
||||
union {
|
||||
STaskDispatcherFixedEp fixedEpDispatcher;
|
||||
STaskDispatcherShuffle shuffleDispatcher;
|
||||
STaskSinkTb tbSink;
|
||||
STaskSinkSma smaSink;
|
||||
STaskSinkFetch fetchSink;
|
||||
};
|
||||
|
||||
int8_t inputStatus;
|
||||
|
@ -303,9 +280,6 @@ typedef struct SStreamTask {
|
|||
int64_t triggerParam;
|
||||
void* timer;
|
||||
|
||||
// application storage
|
||||
// void* ahandle;
|
||||
|
||||
// msg handle
|
||||
SMsgCb* pMsgCb;
|
||||
} SStreamTask;
|
||||
|
@ -342,7 +316,7 @@ static FORCE_INLINE int32_t streamTaskInput(SStreamTask* pTask, SStreamQueueItem
|
|||
}
|
||||
|
||||
if (pItem->type != STREAM_INPUT__GET_RES && pItem->type != STREAM_INPUT__CHECKPOINT && pTask->triggerParam != 0) {
|
||||
atomic_val_compare_exchange_8(&pTask->triggerStatus, TASK_TRIGGER_STATUS__IN_ACTIVE, TASK_TRIGGER_STATUS__ACTIVE);
|
||||
atomic_val_compare_exchange_8(&pTask->triggerStatus, TASK_TRIGGER_STATUS__INACTIVE, TASK_TRIGGER_STATUS__ACTIVE);
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
@ -357,18 +331,15 @@ static FORCE_INLINE void streamTaskInputFail(SStreamTask* pTask) {
|
|||
}
|
||||
|
||||
static FORCE_INLINE int32_t streamTaskOutput(SStreamTask* pTask, SStreamDataBlock* pBlock) {
|
||||
if (pTask->sinkType == TASK_SINK__TABLE) {
|
||||
ASSERT(pTask->dispatchType == TASK_DISPATCH__NONE);
|
||||
if (pTask->outputType == TASK_OUTPUT__TABLE) {
|
||||
pTask->tbSink.tbSinkFunc(pTask, pTask->tbSink.vnode, 0, pBlock->blocks);
|
||||
taosArrayDestroyEx(pBlock->blocks, (FDelete)blockDataFreeRes);
|
||||
taosFreeQitem(pBlock);
|
||||
} else if (pTask->sinkType == TASK_SINK__SMA) {
|
||||
ASSERT(pTask->dispatchType == TASK_DISPATCH__NONE);
|
||||
} else if (pTask->outputType == TASK_OUTPUT__SMA) {
|
||||
pTask->smaSink.smaSink(pTask->smaSink.vnode, pTask->smaSink.smaId, pBlock->blocks);
|
||||
taosArrayDestroyEx(pBlock->blocks, (FDelete)blockDataFreeRes);
|
||||
taosFreeQitem(pBlock);
|
||||
} else {
|
||||
ASSERT(pTask->dispatchType != TASK_DISPATCH__NONE);
|
||||
taosWriteQitem(pTask->outputQueue->queue, pBlock);
|
||||
}
|
||||
return 0;
|
||||
|
@ -475,7 +446,6 @@ typedef struct {
|
|||
int32_t tDecodeStreamDispatchReq(SDecoder* pDecoder, SStreamDispatchReq* pReq);
|
||||
int32_t tDecodeStreamRetrieveReq(SDecoder* pDecoder, SStreamRetrieveReq* pReq);
|
||||
|
||||
int32_t streamLaunchByWrite(SStreamTask* pTask, int32_t vgId);
|
||||
int32_t streamSetupTrigger(SStreamTask* pTask);
|
||||
|
||||
int32_t streamProcessRunReq(SStreamTask* pTask);
|
||||
|
@ -487,13 +457,29 @@ int32_t streamProcessRecoverRsp(SStreamTask* pTask, SStreamTaskRecoverRsp* pRsp)
|
|||
int32_t streamProcessRetrieveReq(SStreamTask* pTask, SStreamRetrieveReq* pReq, SRpcMsg* pMsg);
|
||||
int32_t streamProcessRetrieveRsp(SStreamTask* pTask, SStreamRetrieveRsp* pRsp);
|
||||
|
||||
typedef struct SStreamMeta SStreamMeta;
|
||||
int32_t streamTryExec(SStreamTask* pTask);
|
||||
int32_t streamSchedExec(SStreamTask* pTask);
|
||||
|
||||
SStreamMeta* streamMetaOpen();
|
||||
typedef int32_t FTaskExpand(void* ahandle, SStreamTask* pTask);
|
||||
|
||||
typedef struct SStreamMeta {
|
||||
char* path;
|
||||
TDB* db;
|
||||
TTB* pTaskDb;
|
||||
TTB* pStateDb;
|
||||
SHashObj* pTasks;
|
||||
void* ahandle;
|
||||
TXN txn;
|
||||
FTaskExpand* expandFunc;
|
||||
} SStreamMeta;
|
||||
|
||||
SStreamMeta* streamMetaOpen(const char* path, void* ahandle, FTaskExpand expandFunc);
|
||||
void streamMetaClose(SStreamMeta* streamMeta);
|
||||
|
||||
int32_t streamMetaAddTask(SStreamMeta* pMeta, SStreamTask* pTask);
|
||||
int32_t streamMetaRemoveTask(SStreamMeta* pMeta, int32_t taskId);
|
||||
int32_t streamMetaAddTask(SStreamMeta* pMeta, SStreamTask* pTask);
|
||||
int32_t streamMetaAddSerializedTask(SStreamMeta* pMeta, char* msg, int32_t msgLen);
|
||||
int32_t streamMetaRemoveTask(SStreamMeta* pMeta, int32_t taskId);
|
||||
SStreamTask* streamMetaGetTask(SStreamMeta* pMeta, int32_t taskId);
|
||||
|
||||
int32_t streamMetaBegin(SStreamMeta* pMeta);
|
||||
int32_t streamMetaCommit(SStreamMeta* pMeta);
|
||||
|
|
|
@ -41,12 +41,13 @@ typedef struct {
|
|||
|
||||
typedef struct SRpcHandleInfo {
|
||||
// rpc info
|
||||
void *handle; // rpc handle returned to app
|
||||
int64_t refId; // refid, used by server
|
||||
int32_t noResp; // has response or not(default 0, 0: resp, 1: no resp);
|
||||
int32_t persistHandle; // persist handle or not
|
||||
void *handle; // rpc handle returned to app
|
||||
int64_t refId; // refid, used by server
|
||||
int8_t noResp; // has response or not(default 0, 0: resp, 1: no resp)
|
||||
int8_t persistHandle; // persist handle or not
|
||||
int8_t hasEpSet;
|
||||
|
||||
STraceId traceId;
|
||||
int8_t hasEpSet;
|
||||
|
||||
// app info
|
||||
void *ahandle; // app handle set by client
|
||||
|
@ -69,8 +70,9 @@ typedef struct SRpcMsg {
|
|||
SRpcHandleInfo info;
|
||||
} SRpcMsg;
|
||||
|
||||
typedef void (*RpcCfp)(void *parent, SRpcMsg *, SEpSet *rf);
|
||||
typedef void (*RpcCfp)(void *parent, SRpcMsg *, SEpSet *epset);
|
||||
typedef bool (*RpcRfp)(int32_t code, tmsg_t msgType);
|
||||
typedef bool (*RpcTfp)(int32_t code, tmsg_t msgType);
|
||||
|
||||
typedef struct SRpcInit {
|
||||
char localFqdn[TSDB_FQDN_LEN];
|
||||
|
@ -84,12 +86,15 @@ typedef struct SRpcInit {
|
|||
// the following is for client app ecurity only
|
||||
char *user; // user name
|
||||
|
||||
// call back to process incoming msg, code shall be ignored by server app
|
||||
// call back to process incoming msg
|
||||
RpcCfp cfp;
|
||||
|
||||
// user defined retry func
|
||||
// retry not not for particular msg
|
||||
RpcRfp rfp;
|
||||
|
||||
// set up timeout for particular msg
|
||||
RpcTfp tfp;
|
||||
|
||||
void *parent;
|
||||
} SRpcInit;
|
||||
|
||||
|
|
|
@ -57,7 +57,7 @@ extern "C" {
|
|||
|
||||
#if defined(WINDOWS)
|
||||
char *stpcpy (char *dest, const char *src);
|
||||
char *stpncpy (char *dest, const char *src, size_t n);
|
||||
char *stpncpy (char *dest, const char *src, int n);
|
||||
|
||||
// specific
|
||||
#ifndef __COMPAR_FN_T
|
||||
|
@ -77,7 +77,7 @@ extern "C" {
|
|||
|
||||
char * strsep(char **stringp, const char *delim);
|
||||
char * getpass(const char *prefix);
|
||||
char * strndup(const char *s, size_t n);
|
||||
char * strndup(const char *s, int n);
|
||||
|
||||
// for send function in tsocket.c
|
||||
#define MSG_NOSIGNAL 0
|
||||
|
|
|
@ -46,6 +46,7 @@ int32_t* taosGetErrno();
|
|||
#define TSDB_CODE_RPC_FQDN_ERROR TAOS_DEF_ERROR_CODE(0, 0x0015)
|
||||
#define TSDB_CODE_RPC_PORT_EADDRINUSE TAOS_DEF_ERROR_CODE(0, 0x0017)
|
||||
#define TSDB_CODE_RPC_BROKEN_LINK TAOS_DEF_ERROR_CODE(0, 0x0018)
|
||||
#define TSDB_CODE_RPC_TIMEOUT TAOS_DEF_ERROR_CODE(0, 0x0019)
|
||||
|
||||
//common & util
|
||||
#define TSDB_CODE_TIME_UNSYNCED TAOS_DEF_ERROR_CODE(0, 0x0013)
|
||||
|
|
|
@ -25,9 +25,9 @@ extern "C" {
|
|||
// reference counting
|
||||
typedef void (*_ref_fn_t)(const void *pObj);
|
||||
|
||||
#define T_REF_DECLARE() \
|
||||
struct { \
|
||||
int32_t val; \
|
||||
#define T_REF_DECLARE() \
|
||||
struct { \
|
||||
volatile int32_t val; \
|
||||
} _ref;
|
||||
|
||||
#define T_REF_REGISTER_FUNC(s, e) \
|
||||
|
|
|
@ -2,61 +2,78 @@
|
|||
|
||||
set internal_dir=%~dp0\..\..\
|
||||
set community_dir=%~dp0\..
|
||||
cd %community_dir%
|
||||
git checkout -- .
|
||||
cd %community_dir%\packaging
|
||||
set package_dir=%cd%
|
||||
|
||||
:: %1 name %2 version
|
||||
if !%1==! GOTO USAGE
|
||||
if !%2==! GOTO USAGE
|
||||
if %1 == taos GOTO TAOS
|
||||
if %1 == power GOTO POWER
|
||||
if %1 == tq GOTO TQ
|
||||
if %1 == pro GOTO PRO
|
||||
if %1 == kh GOTO KH
|
||||
if %1 == jh GOTO JH
|
||||
GOTO USAGE
|
||||
|
||||
:TAOS
|
||||
goto RELEASE
|
||||
|
||||
:POWER
|
||||
call sed_power.bat %community_dir%
|
||||
goto RELEASE
|
||||
|
||||
:TQ
|
||||
call sed_tq.bat %community_dir%
|
||||
goto RELEASE
|
||||
|
||||
:PRO
|
||||
call sed_pro.bat %community_dir%
|
||||
goto RELEASE
|
||||
|
||||
:KH
|
||||
call sed_kh.bat %community_dir%
|
||||
goto RELEASE
|
||||
|
||||
:JH
|
||||
call sed_jh.bat %community_dir%
|
||||
goto RELEASE
|
||||
|
||||
:RELEASE
|
||||
echo release windows-client-64 for %1, version: %2
|
||||
if not exist %internal_dir%\debug\ver-%2-64bit-%1 (
|
||||
md %internal_dir%\debug\ver-%2-64bit-%1
|
||||
if "%1" == "cluster" (
|
||||
set work_dir=%internal_dir%
|
||||
set packagServerName_x64=TDengine-enterprise-server-%2-beta-Windows-x64
|
||||
set packagServerName_x86=TDengine-enterprise-server-%2-beta-Windows-x86
|
||||
set packagClientName_x64=TDengine-enterprise-client-%2-beta-Windows-x64
|
||||
set packagClientName_x86=TDengine-enterprise-client-%2-beta-Windows-x86
|
||||
) else (
|
||||
rd /S /Q %internal_dir%\debug\ver-%2-64bit-%1
|
||||
md %internal_dir%\debug\ver-%2-64bit-%1
|
||||
set work_dir=%community_dir%
|
||||
set packagServerName_x64=TDengine-server-%2-Windows-x64
|
||||
set packagServerName_x86=TDengine-server-%2-Windows-x86
|
||||
set packagClientName_x64=TDengine-client-%2-Windows-x64
|
||||
set packagClientName_x86=TDengine-client-%2-Windows-x86
|
||||
)
|
||||
cd %internal_dir%\debug\ver-%2-64bit-%1
|
||||
call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" amd64
|
||||
cmake ../../ -G "NMake Makefiles" -DVERNUMBER=%2 -DCPUTYPE=x64
|
||||
set CL=/MP4
|
||||
nmake install
|
||||
|
||||
echo release windows-client for %1, version: %2
|
||||
if not exist %work_dir%\debug (
|
||||
md %work_dir%\debug
|
||||
)
|
||||
if not exist %work_dir%\debug\ver-%2-x64 (
|
||||
md %work_dir%\debug\ver-%2-x64
|
||||
) else (
|
||||
rd /S /Q %work_dir%\debug\ver-%2-x64
|
||||
md %work_dir%\debug\ver-%2-x64
|
||||
)
|
||||
if not exist %work_dir%\debug\ver-%2-x86 (
|
||||
md %work_dir%\debug\ver-%2-x86
|
||||
) else (
|
||||
rd /S /Q %work_dir%\debug\ver-%2-x86
|
||||
md %work_dir%\debug\ver-%2-x86
|
||||
)
|
||||
cd %work_dir%\debug\ver-%2-x64
|
||||
call vcvarsall.bat x64
|
||||
cmake ../../ -G "NMake Makefiles JOM" -DCMAKE_MAKE_PROGRAM=jom -DBUILD_TOOLS=true -DBUILD_HTTP=false -DVERNUMBER=%2 -DCPUTYPE=x64
|
||||
cmake --build .
|
||||
rd /s /Q C:\TDengine
|
||||
cmake --install .
|
||||
if not %errorlevel% == 0 ( call :RUNFAILED build x64 failed & exit /b 1)
|
||||
cd %package_dir%
|
||||
iscc /DMyAppInstallName="%packagServerName_x64%" /DMyAppVersion="%2" /DMyAppExcludeSource="" tools\tdengine.iss /O..\release
|
||||
if not %errorlevel% == 0 ( call :RUNFAILED package %packagServerName_x64% failed & exit /b 1)
|
||||
iscc /DMyAppInstallName="%packagClientName_x64%" /DMyAppVersion="%2" /DMyAppExcludeSource="taosd.exe" tools\tdengine.iss /O..\release
|
||||
if not %errorlevel% == 0 ( call :RUNFAILED package %packagClientName_x64% failed & exit /b 1)
|
||||
|
||||
cd %work_dir%\debug\ver-%2-x86
|
||||
call vcvarsall.bat x86
|
||||
cmake ../../ -G "NMake Makefiles JOM" -DCMAKE_MAKE_PROGRAM=jom -DBUILD_TOOLS=true -DBUILD_HTTP=false -DVERNUMBER=%2 -DCPUTYPE=x86
|
||||
cmake --build .
|
||||
rd /s /Q C:\TDengine
|
||||
cmake --install .
|
||||
if not %errorlevel% == 0 ( call :RUNFAILED build x86 failed & exit /b 1)
|
||||
cd %package_dir%
|
||||
iscc /DMyAppInstallName="%packagServerName_x86%" /DMyAppVersion="%2" /DMyAppExcludeSource="" tools\tdengine.iss /O..\release
|
||||
if not %errorlevel% == 0 ( call :RUNFAILED package %packagServerName_x86% failed & exit /b 1)
|
||||
iscc /DMyAppInstallName="%packagClientName_x86%" /DMyAppVersion="%2" /DMyAppExcludeSource="taosd.exe" tools\tdengine.iss /O..\release
|
||||
if not %errorlevel% == 0 ( call :RUNFAILED package %packagClientName_x86% failed & exit /b 1)
|
||||
|
||||
goto EXIT0
|
||||
|
||||
:USAGE
|
||||
echo Usage: release.bat $productName $version
|
||||
echo Usage: release.bat $verMode $version
|
||||
goto EXIT0
|
||||
|
||||
:EXIT0
|
||||
:EXIT0
|
||||
exit /b
|
||||
|
||||
:RUNFAILED
|
||||
echo %*
|
||||
cd %package_dir%
|
||||
goto :eof
|
|
@ -26,7 +26,7 @@ soMode=dynamic # [static | dynamic]
|
|||
dbName=taos # [taos | ...]
|
||||
allocator=glibc # [glibc | jemalloc]
|
||||
verNumber=""
|
||||
verNumberComp="2.0.0.0"
|
||||
verNumberComp="3.0.0.0"
|
||||
httpdBuild=false
|
||||
|
||||
while getopts "hv:V:c:o:l:s:d:a:n:m:H:" arg; do
|
||||
|
@ -216,7 +216,7 @@ else
|
|||
fi
|
||||
|
||||
# check support cpu type
|
||||
if [[ "$cpuType" == "x64" ]] || [[ "$cpuType" == "aarch64" ]] || [[ "$cpuType" == "aarch32" ]] || [[ "$cpuType" == "mips64" ]]; then
|
||||
if [[ "$cpuType" == "x64" ]] || [[ "$cpuType" == "aarch64" ]] || [[ "$cpuType" == "aarch32" ]] || [[ "$cpuType" == "arm64" ]] || [[ "$cpuType" == "arm32" ]] || [[ "$cpuType" == "mips64" ]]; then
|
||||
if [ "$verMode" != "cluster" ]; then
|
||||
# community-version compile
|
||||
cmake ../ -DCPUTYPE=${cpuType} -DOSTYPE=${osType} -DSOMODE=${soMode} -DDBNAME=${dbName} -DVERTYPE=${verType} -DVERDATE="${build_time}" -DGITINFO=${gitinfo} -DGITINFOI=${gitinfoOfInternal} -DVERNUMBER=${verNumber} -DVERCOMPATIBLE=${verNumberComp} -DPAGMODE=${pagMode} -DBUILD_HTTP=${BUILD_HTTP} -DBUILD_TOOLS=${BUILD_TOOLS} ${allocator_macro}
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 4.2 KiB |
|
@ -30,7 +30,6 @@ configDir="/etc/taos"
|
|||
installDir="/usr/local/taos"
|
||||
adapterName="taosadapter"
|
||||
benchmarkName="taosBenchmark"
|
||||
tmqName="tmq_sim"
|
||||
dumpName="taosdump"
|
||||
demoName="taosdemo"
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@ if [ "$pagMode" == "lite" ]; then
|
|||
strip ${build_dir}/bin/${serverName}
|
||||
strip ${build_dir}/bin/${clientName}
|
||||
# lite version doesn't include taosadapter, which will lead to no restful interface
|
||||
bin_files="${build_dir}/bin/${serverName} ${build_dir}/bin/${clientName} ${script_dir}/remove.sh ${script_dir}/startPre.sh ${build_dir}/bin/taosBenchmark ${build_dir}/bin/tmq_sim"
|
||||
bin_files="${build_dir}/bin/${serverName} ${build_dir}/bin/${clientName} ${script_dir}/remove.sh ${script_dir}/startPre.sh ${build_dir}/bin/taosBenchmark "
|
||||
taostools_bin_files=""
|
||||
else
|
||||
|
||||
|
@ -78,7 +78,6 @@ else
|
|||
|
||||
taostools_bin_files=" ${build_dir}/bin/taosdump \
|
||||
${build_dir}/bin/taosBenchmark \
|
||||
${build_dir}/bin/tmq_sim \
|
||||
${build_dir}/bin/TDinsight.sh \
|
||||
$tdinsight_caches"
|
||||
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
@echo off
|
||||
cd C:\TDengine
|
||||
if not "%1" == "" (
|
||||
%1 --help
|
||||
@cmd /k
|
||||
)
|
|
@ -0,0 +1,81 @@
|
|||
#define MyAppName "TDengine"
|
||||
#define MyAppPublisher "taosdata"
|
||||
#define MyAppURL "http://www.taosdata.com/"
|
||||
#define MyAppBeforeInstallTxt "windows_before_install.txt"
|
||||
#define MyAppIco "favicon.ico"
|
||||
#define MyAppInstallDir "C:\TDengine"
|
||||
#define MyAppOutputDir "./"
|
||||
#define MyAppSourceDir "C:\TDengine"
|
||||
;#define MyAppAllFile "\*"
|
||||
#define MyAppCfgName "\cfg\*"
|
||||
#define MyAppDriverName "\driver\*"
|
||||
#define MyAppConnectorName "\connector\*"
|
||||
#define MyAppExamplesName "\examples\*"
|
||||
#define MyAppIncludeName "\include\*"
|
||||
#define MyAppExeName "\*.exe"
|
||||
#define MyAppTaosExeName "\taos.bat"
|
||||
#define MyAppTaosdemoExeName "\taosBenchmark.exe"
|
||||
#define MyAppDLLName "\driver\taos.dll"
|
||||
;#define MyAppVersion "3.0"
|
||||
;#define MyAppInstallName "TDengine"
|
||||
|
||||
[Setup]
|
||||
VersionInfoVersion={#MyAppVersion}
|
||||
AppId={{A0F7A93C-79C4-485D-B2B8-F0D03DF42FAB}
|
||||
AppName={#MyAppName}
|
||||
AppVersion={#MyAppVersion}
|
||||
;AppVerName={#MyAppName} {#MyAppVersion}
|
||||
AppPublisher={#MyAppPublisher}
|
||||
AppPublisherURL={#MyAppURL}
|
||||
AppSupportURL={#MyAppURL}
|
||||
AppUpdatesURL={#MyAppURL}
|
||||
DefaultDirName={#MyAppInstallDir}
|
||||
DefaultGroupName={#MyAppName}
|
||||
DisableProgramGroupPage=yes
|
||||
InfoBeforeFile={#MyAppBeforeInstallTxt}
|
||||
OutputDir={#MyAppOutputDir}
|
||||
OutputBaseFilename={#MyAppInstallName}
|
||||
SetupIconFile={#MyAppIco}
|
||||
Compression=lzma
|
||||
SolidCompression=yes
|
||||
DisableDirPage=yes
|
||||
Uninstallable=yes
|
||||
|
||||
[Languages]
|
||||
Name: "chinesesimp"; MessagesFile: "compiler:Default.isl"
|
||||
;Name: "english"; MessagesFile: "compiler:Languages\English.isl"
|
||||
|
||||
[Files]
|
||||
;Source: {#MyAppSourceDir}{#MyAppAllFile}; DestDir: "{app}"; Flags: igNoreversion recursesubdirs createallsubdirs
|
||||
Source: taos.bat; DestDir: "{app}\include"; Flags: igNoreversion;
|
||||
;Source: taosdemo.png; DestDir: "{app}\include"; Flags: igNoreversion;
|
||||
;Source: taosShell.png; DestDir: "{app}\include"; Flags: igNoreversion;
|
||||
Source: favicon.ico; DestDir: "{app}\include"; Flags: igNoreversion;
|
||||
Source: {#MyAppSourceDir}{#MyAppDLLName}; DestDir: "{win}\System32"; Flags: igNoreversion;
|
||||
Source: {#MyAppSourceDir}{#MyAppCfgName}; DestDir: "{app}\cfg"; Flags: igNoreversion recursesubdirs createallsubdirs onlyifdoesntexist uninsneveruninstall
|
||||
Source: {#MyAppSourceDir}{#MyAppDriverName}; DestDir: "{app}\driver"; Flags: igNoreversion recursesubdirs createallsubdirs
|
||||
;Source: {#MyAppSourceDir}{#MyAppConnectorName}; DestDir: "{app}\connector"; Flags: igNoreversion recursesubdirs createallsubdirs
|
||||
;Source: {#MyAppSourceDir}{#MyAppExamplesName}; DestDir: "{app}\examples"; Flags: igNoreversion recursesubdirs createallsubdirs
|
||||
Source: {#MyAppSourceDir}{#MyAppIncludeName}; DestDir: "{app}\include"; Flags: igNoreversion recursesubdirs createallsubdirs
|
||||
Source: {#MyAppSourceDir}{#MyAppExeName}; DestDir: "{app}"; Excludes: {#MyAppExcludeSource} ; Flags: igNoreversion recursesubdirs createallsubdirs
|
||||
Source: {#MyAppSourceDir}{#MyAppTaosdemoExeName}; DestDir: "{app}"; Flags: igNoreversion recursesubdirs createallsubdirs
|
||||
|
||||
[UninstallDelete]
|
||||
Name: {app}\driver; Type: filesandordirs
|
||||
Name: {app}\connector; Type: filesandordirs
|
||||
Name: {app}\examples; Type: filesandordirs
|
||||
Name: {app}\include; Type: filesandordirs
|
||||
|
||||
[Tasks]
|
||||
Name: "desktopicon";Description: "{cm:CreateDesktopIcon}"; GroupDescription:"{cm:AdditionalIcons}"; Flags: checkablealone
|
||||
|
||||
[Icons]
|
||||
Name:"{group}\Taos Shell"; Filename: "{app}\include\{#MyAppTaosExeName}" ; Parameters: "taos.exe" ; IconFilename: "{app}\include\{#MyAppIco}"
|
||||
Name:"{group}\Open TDengine Directory"; Filename: "{app}\"
|
||||
Name:"{group}\Taosdemo"; Filename: "{app}\include\{#MyAppTaosExeName}" ; Parameters: "taosdemo.exe" ; IconFilename: "{app}\include\{#MyAppIco}"
|
||||
Name: "{group}\{cm:UninstallProgram,{#MyAppName}}"; Filename: "{uninstallexe}" ; IconFilename: "{app}\include\{#MyAppIco}"
|
||||
Name:"{commondesktop}\Taos Shell"; Filename: "{app}\include\{#MyAppTaosExeName}" ; Parameters: "taos.exe" ; Tasks: desktopicon; WorkingDir: "{app}" ; IconFilename: "{app}\include\{#MyAppIco}"
|
||||
|
||||
|
||||
[Messages]
|
||||
ConfirmUninstall=Do you really want to uninstall TDengine from your computer?%n%nPress [Y] to completely delete %1 and all its components;%nPress [N] to keep the software on your computer.
|
|
@ -0,0 +1,3 @@
|
|||
TDengine is a high-efficient, scalable, high-available distributed time-series database, which makes a lot of optimizations on inserting and querying data, which is far more efficient than normal regular databases. So TDengine can meet the high requirements of IOT and other areas on storing and querying a large amount of data.
|
||||
|
||||
TDengine will be installed under C:\TDengine, users can modify configuration file C:\TDengine\cfg\taos.cfg, set the log file path or other parameters.
|
|
@ -60,7 +60,7 @@ static int32_t registerRequest(SRequestObj *pRequest, STscObj *pTscObj) {
|
|||
}
|
||||
|
||||
static void deregisterRequest(SRequestObj *pRequest) {
|
||||
const static int64_t SLOW_QUERY_INTERVAL = 3000000L; // todo configurable
|
||||
const static int64_t SLOW_QUERY_INTERVAL = 3000000L; // todo configurable
|
||||
assert(pRequest != NULL);
|
||||
|
||||
STscObj *pTscObj = pRequest->pTscObj;
|
||||
|
@ -77,13 +77,13 @@ static void deregisterRequest(SRequestObj *pRequest) {
|
|||
if (QUERY_NODE_VNODE_MODIF_STMT == pRequest->stmtType) {
|
||||
atomic_add_fetch_64((int64_t *)&pActivity->insertElapsedTime, duration);
|
||||
} else if (QUERY_NODE_SELECT_STMT == pRequest->stmtType) {
|
||||
atomic_add_fetch_64((int64_t *)&pActivity->queryElapsedTime, duration);
|
||||
atomic_add_fetch_64((int64_t *)&pActivity->queryElapsedTime, duration);
|
||||
}
|
||||
|
||||
|
||||
if (duration >= SLOW_QUERY_INTERVAL) {
|
||||
atomic_add_fetch_64((int64_t *)&pActivity->numOfSlowQueries, 1);
|
||||
}
|
||||
|
||||
|
||||
releaseTscObj(pTscObj->id);
|
||||
}
|
||||
|
||||
|
@ -109,6 +109,14 @@ static bool clientRpcRfp(int32_t code, tmsg_t msgType) {
|
|||
}
|
||||
}
|
||||
|
||||
// start timer for particular msgType
|
||||
static bool clientRpcTfp(int32_t code, tmsg_t msgType) {
|
||||
if (msgType == TDMT_VND_SUBMIT || msgType == TDMT_VND_CREATE_TABLE) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO refactor
|
||||
void *openTransporter(const char *user, const char *auth, int32_t numOfThread) {
|
||||
SRpcInit rpcInit;
|
||||
|
@ -118,6 +126,7 @@ void *openTransporter(const char *user, const char *auth, int32_t numOfThread) {
|
|||
rpcInit.numOfThreads = numOfThread;
|
||||
rpcInit.cfp = processMsgFromServer;
|
||||
rpcInit.rfp = clientRpcRfp;
|
||||
rpcInit.tfp = clientRpcTfp;
|
||||
rpcInit.sessions = 1024;
|
||||
rpcInit.connType = TAOS_CONN_CLIENT;
|
||||
rpcInit.user = (char *)user;
|
||||
|
@ -375,7 +384,7 @@ void taos_init_imp(void) {
|
|||
initQueryModuleMsgHandle();
|
||||
|
||||
taosConvInit();
|
||||
|
||||
|
||||
rpcInit();
|
||||
|
||||
SCatalogCfg cfg = {.maxDBCacheNum = 100, .maxTblCacheNum = 100};
|
||||
|
|
|
@ -286,6 +286,7 @@ static int32_t hbAsyncCallBack(void *param, SDataBuf *pMsg, int32_t code) {
|
|||
if (pInst == NULL || NULL == *pInst) {
|
||||
taosThreadMutexUnlock(&appInfo.mutex);
|
||||
tscError("cluster not exist, key:%s", key);
|
||||
taosMemoryFree(pMsg->pData);
|
||||
tFreeClientHbBatchRsp(&pRsp);
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -1308,8 +1308,8 @@ int32_t doProcessMsgFromServer(void* param) {
|
|||
char tbuf[40] = {0};
|
||||
TRACE_TO_STR(trace, tbuf);
|
||||
|
||||
tscDebug("processMsgFromServer handle %p, message: %s, code: %s, gtid: %s", pMsg->info.handle,
|
||||
TMSG_INFO(pMsg->msgType), tstrerror(pMsg->code), tbuf);
|
||||
tscDebug("processMsgFromServer handle %p, message: %s, size:%d, code: %s, gtid: %s", pMsg->info.handle,
|
||||
TMSG_INFO(pMsg->msgType), pMsg->contLen, tstrerror(pMsg->code), tbuf);
|
||||
|
||||
if (pSendInfo->requestObjRefId != 0) {
|
||||
SRequestObj* pRequest = (SRequestObj*)taosAcquireRef(clientReqRefPool, pSendInfo->requestObjRefId);
|
||||
|
@ -1937,7 +1937,7 @@ _OVER:
|
|||
return code;
|
||||
}
|
||||
|
||||
int32_t appendTbToReq(SArray* pList, int32_t pos1, int32_t len1, int32_t pos2, int32_t len2, const char* str,
|
||||
int32_t appendTbToReq(SHashObj* pHash, int32_t pos1, int32_t len1, int32_t pos2, int32_t len2, const char* str,
|
||||
int32_t acctId, char* db) {
|
||||
SName name;
|
||||
|
||||
|
@ -1972,20 +1972,33 @@ int32_t appendTbToReq(SArray* pList, int32_t pos1, int32_t len1, int32_t pos2, i
|
|||
return -1;
|
||||
}
|
||||
|
||||
taosArrayPush(pList, &name);
|
||||
char dbFName[TSDB_DB_FNAME_LEN];
|
||||
sprintf(dbFName, "%d.%.*s", acctId, dbLen, dbName);
|
||||
|
||||
STablesReq* pDb = taosHashGet(pHash, dbFName, strlen(dbFName));
|
||||
if (pDb) {
|
||||
taosArrayPush(pDb->pTables, &name);
|
||||
} else {
|
||||
STablesReq db;
|
||||
db.pTables = taosArrayInit(20, sizeof(SName));
|
||||
strcpy(db.dbFName, dbFName);
|
||||
taosArrayPush(db.pTables, &name);
|
||||
taosHashPut(pHash, dbFName, strlen(dbFName), &db, sizeof(db));
|
||||
}
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t transferTableNameList(const char* tbList, int32_t acctId, char* dbName, SArray** pReq) {
|
||||
*pReq = taosArrayInit(10, sizeof(SName));
|
||||
if (NULL == *pReq) {
|
||||
SHashObj* pHash = taosHashInit(3, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_NO_LOCK);
|
||||
if (NULL == pHash) {
|
||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||
return terrno;
|
||||
}
|
||||
|
||||
bool inEscape = false;
|
||||
int32_t code = 0;
|
||||
void *pIter = NULL;
|
||||
|
||||
int32_t vIdx = 0;
|
||||
int32_t vPos[2];
|
||||
|
@ -2000,7 +2013,7 @@ int32_t transferTableNameList(const char* tbList, int32_t acctId, char* dbName,
|
|||
vLen[vIdx] = i - vPos[vIdx];
|
||||
}
|
||||
|
||||
code = appendTbToReq(*pReq, vPos[0], vLen[0], vPos[1], vLen[1], tbList, acctId, dbName);
|
||||
code = appendTbToReq(pHash, vPos[0], vLen[0], vPos[1], vLen[1], tbList, acctId, dbName);
|
||||
if (code) {
|
||||
goto _return;
|
||||
}
|
||||
|
@ -2050,7 +2063,7 @@ int32_t transferTableNameList(const char* tbList, int32_t acctId, char* dbName,
|
|||
vLen[vIdx] = i - vPos[vIdx];
|
||||
}
|
||||
|
||||
code = appendTbToReq(*pReq, vPos[0], vLen[0], vPos[1], vLen[1], tbList, acctId, dbName);
|
||||
code = appendTbToReq(pHash, vPos[0], vLen[0], vPos[1], vLen[1], tbList, acctId, dbName);
|
||||
if (code) {
|
||||
goto _return;
|
||||
}
|
||||
|
@ -2082,14 +2095,31 @@ int32_t transferTableNameList(const char* tbList, int32_t acctId, char* dbName,
|
|||
goto _return;
|
||||
}
|
||||
|
||||
int32_t dbNum = taosHashGetSize(pHash);
|
||||
*pReq = taosArrayInit(dbNum, sizeof(STablesReq));
|
||||
pIter = taosHashIterate(pHash, NULL);
|
||||
while (pIter) {
|
||||
STablesReq* pDb = (STablesReq*)pIter;
|
||||
taosArrayPush(*pReq, pDb);
|
||||
pIter = taosHashIterate(pHash, pIter);
|
||||
}
|
||||
|
||||
taosHashCleanup(pHash);
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
|
||||
_return:
|
||||
|
||||
terrno = TSDB_CODE_TSC_INVALID_OPERATION;
|
||||
|
||||
taosArrayDestroy(*pReq);
|
||||
*pReq = NULL;
|
||||
pIter = taosHashIterate(pHash, NULL);
|
||||
while (pIter) {
|
||||
STablesReq* pDb = (STablesReq*)pIter;
|
||||
taosArrayDestroy(pDb->pTables);
|
||||
pIter = taosHashIterate(pHash, pIter);
|
||||
}
|
||||
|
||||
taosHashCleanup(pHash);
|
||||
|
||||
return terrno;
|
||||
}
|
||||
|
|
|
@ -189,20 +189,6 @@ typedef struct {
|
|||
tsem_t rspSem;
|
||||
} SMqPollCbParam;
|
||||
|
||||
#if 0
|
||||
typedef struct {
|
||||
tmq_t* tmq;
|
||||
int8_t async;
|
||||
int8_t automatic;
|
||||
int8_t freeOffsets;
|
||||
tmq_commit_cb* userCb;
|
||||
tsem_t rspSem;
|
||||
int32_t rspErr;
|
||||
SArray* offsets;
|
||||
void* userParam;
|
||||
} SMqCommitCbParam;
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
tmq_t* tmq;
|
||||
int8_t automatic;
|
||||
|
@ -385,29 +371,6 @@ static int32_t tmqMakeTopicVgKey(char* dst, const char* topicName, int32_t vg) {
|
|||
return sprintf(dst, "%s:%d", topicName, vg);
|
||||
}
|
||||
|
||||
#if 0
|
||||
int32_t tmqCommitCb(void* param, const SDataBuf* pMsg, int32_t code) {
|
||||
SMqCommitCbParam* pParam = (SMqCommitCbParam*)param;
|
||||
pParam->rspErr = code;
|
||||
if (pParam->async) {
|
||||
if (pParam->automatic && pParam->tmq->commitCb) {
|
||||
pParam->tmq->commitCb(pParam->tmq, pParam->rspErr, pParam->tmq->commitCbUserParam);
|
||||
} else if (!pParam->automatic && pParam->userCb) {
|
||||
pParam->userCb(pParam->tmq, pParam->rspErr, pParam->userParam);
|
||||
}
|
||||
|
||||
if (pParam->freeOffsets) {
|
||||
taosArrayDestroy(pParam->offsets);
|
||||
}
|
||||
|
||||
taosMemoryFree(pParam);
|
||||
} else {
|
||||
tsem_post(&pParam->rspSem);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int32_t tmqCommitCb2(void* param, SDataBuf* pBuf, int32_t code) {
|
||||
SMqCommitCbParam2* pParam = (SMqCommitCbParam2*)param;
|
||||
SMqCommitCbParamSet* pParamSet = (SMqCommitCbParamSet*)pParam->params;
|
||||
|
@ -660,123 +623,6 @@ int32_t tmqCommitInner2(tmq_t* tmq, const TAOS_RES* msg, int8_t automatic, int8_
|
|||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
int32_t tmqCommitInner(tmq_t* tmq, const TAOS_RES* msg, int8_t automatic, int8_t async,
|
||||
tmq_commit_cb* userCb, void* userParam) {
|
||||
SMqCMCommitOffsetReq req;
|
||||
SArray* pOffsets = NULL;
|
||||
void* buf = NULL;
|
||||
SMqCommitCbParam* pParam = NULL;
|
||||
SMsgSendInfo* sendInfo = NULL;
|
||||
int8_t freeOffsets;
|
||||
int32_t code = -1;
|
||||
|
||||
if (msg == NULL) {
|
||||
freeOffsets = 1;
|
||||
pOffsets = taosArrayInit(0, sizeof(SMqOffset));
|
||||
for (int32_t i = 0; i < taosArrayGetSize(tmq->clientTopics); i++) {
|
||||
SMqClientTopic* pTopic = taosArrayGet(tmq->clientTopics, i);
|
||||
for (int32_t j = 0; j < taosArrayGetSize(pTopic->vgs); j++) {
|
||||
SMqClientVg* pVg = taosArrayGet(pTopic->vgs, j);
|
||||
SMqOffset offset;
|
||||
tstrncpy(offset.topicName, pTopic->topicName, TSDB_TOPIC_FNAME_LEN);
|
||||
tstrncpy(offset.cgroup, tmq->groupId, TSDB_CGROUP_LEN);
|
||||
offset.vgId = pVg->vgId;
|
||||
offset.offset = pVg->currentOffset;
|
||||
taosArrayPush(pOffsets, &offset);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
freeOffsets = 0;
|
||||
pOffsets = (SArray*)&msg->container;
|
||||
}
|
||||
|
||||
req.num = (int32_t)pOffsets->size;
|
||||
req.offsets = pOffsets->pData;
|
||||
|
||||
SEncoder encoder;
|
||||
|
||||
tEncoderInit(&encoder, NULL, 0);
|
||||
code = tEncodeSMqCMCommitOffsetReq(&encoder, &req);
|
||||
if (code < 0) {
|
||||
goto END;
|
||||
}
|
||||
int32_t tlen = encoder.pos;
|
||||
buf = taosMemoryMalloc(tlen);
|
||||
if (buf == NULL) {
|
||||
tEncoderClear(&encoder);
|
||||
goto END;
|
||||
}
|
||||
tEncoderClear(&encoder);
|
||||
|
||||
tEncoderInit(&encoder, buf, tlen);
|
||||
tEncodeSMqCMCommitOffsetReq(&encoder, &req);
|
||||
tEncoderClear(&encoder);
|
||||
|
||||
pParam = taosMemoryCalloc(1, sizeof(SMqCommitCbParam));
|
||||
if (pParam == NULL) {
|
||||
goto END;
|
||||
}
|
||||
pParam->tmq = tmq;
|
||||
pParam->automatic = automatic;
|
||||
pParam->async = async;
|
||||
pParam->offsets = pOffsets;
|
||||
pParam->freeOffsets = freeOffsets;
|
||||
pParam->userCb = userCb;
|
||||
pParam->userParam = userParam;
|
||||
if (!async) tsem_init(&pParam->rspSem, 0, 0);
|
||||
|
||||
sendInfo = taosMemoryCalloc(1, sizeof(SMsgSendInfo));
|
||||
if (sendInfo == NULL) goto END;
|
||||
sendInfo->msgInfo = (SDataBuf){
|
||||
.pData = buf,
|
||||
.len = tlen,
|
||||
.handle = NULL,
|
||||
};
|
||||
|
||||
sendInfo->requestId = generateRequestId();
|
||||
sendInfo->requestObjRefId = 0;
|
||||
sendInfo->param = pParam;
|
||||
sendInfo->fp = tmqCommitCb;
|
||||
sendInfo->msgType = TDMT_MND_MQ_COMMIT_OFFSET;
|
||||
|
||||
SEpSet epSet = getEpSet_s(&tmq->pTscObj->pAppInfo->mgmtEp);
|
||||
|
||||
int64_t transporterId = 0;
|
||||
asyncSendMsgToServer(tmq->pTscObj->pAppInfo->pTransporter, &epSet, &transporterId, sendInfo);
|
||||
|
||||
if (!async) {
|
||||
tsem_wait(&pParam->rspSem);
|
||||
code = pParam->rspErr;
|
||||
tsem_destroy(&pParam->rspSem);
|
||||
taosMemoryFree(pParam);
|
||||
} else {
|
||||
code = 0;
|
||||
}
|
||||
|
||||
// avoid double free if msg is sent
|
||||
buf = NULL;
|
||||
|
||||
END:
|
||||
if (buf) taosMemoryFree(buf);
|
||||
/*if (pParam) taosMemoryFree(pParam);*/
|
||||
/*if (sendInfo) taosMemoryFree(sendInfo);*/
|
||||
|
||||
if (code != 0 && async) {
|
||||
if (automatic) {
|
||||
tmq->commitCb(tmq, code, (tmq_topic_vgroup_list_t*)pOffsets, tmq->commitCbUserParam);
|
||||
} else {
|
||||
userCb(tmq, code, (tmq_topic_vgroup_list_t*)pOffsets, userParam);
|
||||
}
|
||||
}
|
||||
|
||||
if (!async && freeOffsets) {
|
||||
taosArrayDestroy(pOffsets);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
#endif
|
||||
|
||||
void tmqAssignAskEpTask(void* param, void* tmrId) {
|
||||
tmq_t* tmq = (tmq_t*)param;
|
||||
int8_t* pTaskType = taosAllocateQitem(sizeof(int8_t), DEF_QITEM);
|
||||
|
@ -1161,7 +1007,7 @@ int32_t tmqPollCb(void* param, SDataBuf* pMsg, int32_t code) {
|
|||
taosMemoryFree(pParam);
|
||||
if (code != 0) {
|
||||
tscWarn("msg discard from vgId:%d, epoch %d, code:%x", vgId, epoch, code);
|
||||
if (pMsg->pData) taosMemoryFree(pMsg->pData);
|
||||
if (pMsg->pData) taosMemoryFreeClear(pMsg->pData);
|
||||
if (code == TSDB_CODE_TQ_NO_COMMITTED_OFFSET) {
|
||||
SMqPollRspWrapper* pRspWrapper = taosAllocateQitem(sizeof(SMqPollRspWrapper), DEF_QITEM);
|
||||
if (pRspWrapper == NULL) {
|
||||
|
@ -1839,13 +1685,22 @@ int32_t tmq_consumer_close(tmq_t* tmq) {
|
|||
return rsp;
|
||||
}
|
||||
|
||||
int32_t retryCnt = 0;
|
||||
tmq_list_t* lst = tmq_list_new();
|
||||
rsp = tmq_subscribe(tmq, lst);
|
||||
while (1) {
|
||||
rsp = tmq_subscribe(tmq, lst);
|
||||
if (rsp != TSDB_CODE_MND_CONSUMER_NOT_READY || retryCnt > 5) {
|
||||
break;
|
||||
} else {
|
||||
retryCnt++;
|
||||
taosMsleep(500);
|
||||
}
|
||||
}
|
||||
|
||||
tmq_list_destroy(lst);
|
||||
|
||||
if (rsp != 0) {
|
||||
return rsp;
|
||||
}
|
||||
/*return rsp;*/
|
||||
return 0;
|
||||
}
|
||||
// TODO: free resources
|
||||
return 0;
|
||||
|
|
|
@ -16,15 +16,15 @@
|
|||
#include "systable.h"
|
||||
#include "taos.h"
|
||||
#include "tdef.h"
|
||||
#include "types.h"
|
||||
#include "tgrant.h"
|
||||
#include "types.h"
|
||||
|
||||
#define SYSTABLE_SCH_TABLE_NAME_LEN ((TSDB_TABLE_NAME_LEN - 1) + VARSTR_HEADER_SIZE)
|
||||
#define SYSTABLE_SCH_DB_NAME_LEN ((TSDB_DB_NAME_LEN - 1) + VARSTR_HEADER_SIZE)
|
||||
#define SYSTABLE_SCH_COL_NAME_LEN ((TSDB_COL_NAME_LEN - 1) + VARSTR_HEADER_SIZE)
|
||||
|
||||
static const SSysDbTableSchema dnodesSchema[] = {
|
||||
{.name = "id", .bytes = 2, .type = TSDB_DATA_TYPE_SMALLINT},
|
||||
{.name = "id", .bytes = 4, .type = TSDB_DATA_TYPE_SMALLINT},
|
||||
{.name = "endpoint", .bytes = TSDB_EP_LEN + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR},
|
||||
{.name = "vnodes", .bytes = 2, .type = TSDB_DATA_TYPE_SMALLINT},
|
||||
{.name = "support_vnodes", .bytes = 2, .type = TSDB_DATA_TYPE_SMALLINT},
|
||||
|
@ -66,7 +66,7 @@ static const SSysDbTableSchema bnodesSchema[] = {
|
|||
};
|
||||
|
||||
static const SSysDbTableSchema clusterSchema[] = {
|
||||
{.name = "id", .bytes = 8, .type = TSDB_DATA_TYPE_BIGINT},
|
||||
{.name = "id", .bytes = 4, .type = TSDB_DATA_TYPE_BIGINT},
|
||||
{.name = "name", .bytes = TSDB_CLUSTER_ID_LEN + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR},
|
||||
{.name = "create_time", .bytes = 8, .type = TSDB_DATA_TYPE_TIMESTAMP},
|
||||
};
|
||||
|
@ -97,7 +97,7 @@ static const SSysDbTableSchema userDBSchema[] = {
|
|||
{.name = "wal_retention_period", .bytes = 4, .type = TSDB_DATA_TYPE_INT},
|
||||
{.name = "wal_retention_size", .bytes = 8, .type = TSDB_DATA_TYPE_BIGINT},
|
||||
{.name = "wal_roll_period", .bytes = 4, .type = TSDB_DATA_TYPE_INT},
|
||||
{.name = "wal_seg_size", .bytes = 8, .type = TSDB_DATA_TYPE_BIGINT},
|
||||
{.name = "wal_segment_size", .bytes = 8, .type = TSDB_DATA_TYPE_BIGINT},
|
||||
};
|
||||
|
||||
static const SSysDbTableSchema userFuncSchema[] = {
|
||||
|
@ -243,8 +243,8 @@ static const SSysTableMeta infosMeta[] = {
|
|||
{TSDB_INS_TABLE_MNODES, mnodesSchema, tListLen(mnodesSchema)},
|
||||
{TSDB_INS_TABLE_MODULES, modulesSchema, tListLen(modulesSchema)},
|
||||
{TSDB_INS_TABLE_QNODES, qnodesSchema, tListLen(qnodesSchema)},
|
||||
// {TSDB_INS_TABLE_SNODES, snodesSchema, tListLen(snodesSchema)},
|
||||
// {TSDB_INS_TABLE_BNODES, bnodesSchema, tListLen(bnodesSchema)},
|
||||
// {TSDB_INS_TABLE_SNODES, snodesSchema, tListLen(snodesSchema)},
|
||||
// {TSDB_INS_TABLE_BNODES, bnodesSchema, tListLen(bnodesSchema)},
|
||||
{TSDB_INS_TABLE_CLUSTER, clusterSchema, tListLen(clusterSchema)},
|
||||
{TSDB_INS_TABLE_DATABASES, userDBSchema, tListLen(userDBSchema)},
|
||||
{TSDB_INS_TABLE_FUNCTIONS, userFuncSchema, tListLen(userFuncSchema)},
|
||||
|
@ -308,9 +308,9 @@ static const SSysDbTableSchema offsetSchema[] = {
|
|||
};
|
||||
|
||||
static const SSysDbTableSchema querySchema[] = {
|
||||
{.name = "query_id", .bytes = TSDB_QUERY_ID_LEN + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR},
|
||||
{.name = "req_id", .bytes = 8, .type = TSDB_DATA_TYPE_UBIGINT},
|
||||
{.name = "connId", .bytes = 4, .type = TSDB_DATA_TYPE_UINT},
|
||||
{.name = "kill_id", .bytes = TSDB_QUERY_ID_LEN + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR},
|
||||
{.name = "query_id", .bytes = 8, .type = TSDB_DATA_TYPE_UBIGINT},
|
||||
{.name = "conn_id", .bytes = 4, .type = TSDB_DATA_TYPE_UINT},
|
||||
{.name = "app", .bytes = TSDB_APP_NAME_LEN + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR},
|
||||
{.name = "pid", .bytes = 4, .type = TSDB_DATA_TYPE_INT},
|
||||
{.name = "user", .bytes = TSDB_USER_LEN + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR},
|
||||
|
@ -354,11 +354,19 @@ static const SSysTableMeta perfsMeta[] = {
|
|||
{TSDB_PERFS_TABLE_APPS, appSchema, tListLen(appSchema)}};
|
||||
|
||||
void getInfosDbMeta(const SSysTableMeta** pInfosTableMeta, size_t* size) {
|
||||
*pInfosTableMeta = infosMeta;
|
||||
*size = tListLen(infosMeta);
|
||||
if (pInfosTableMeta) {
|
||||
*pInfosTableMeta = infosMeta;
|
||||
}
|
||||
if (size) {
|
||||
*size = tListLen(infosMeta);
|
||||
}
|
||||
}
|
||||
|
||||
void getPerfDbMeta(const SSysTableMeta** pPerfsTableMeta, size_t* size) {
|
||||
*pPerfsTableMeta = perfsMeta;
|
||||
*size = tListLen(perfsMeta);
|
||||
if (pPerfsTableMeta) {
|
||||
*pPerfsTableMeta = perfsMeta;
|
||||
}
|
||||
if (size) {
|
||||
*size = tListLen(perfsMeta);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1272,8 +1272,7 @@ int32_t assignOneDataBlock(SSDataBlock* dst, const SSDataBlock* src) {
|
|||
colDataAssign(pDst, pSrc, src->info.rows, &src->info);
|
||||
}
|
||||
|
||||
dst->info.rows = src->info.rows;
|
||||
dst->info.capacity = src->info.rows;
|
||||
dst->info = src->info;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -89,7 +89,7 @@ bool tsSmlDataFormat =
|
|||
|
||||
// query
|
||||
int32_t tsQueryPolicy = 1;
|
||||
int32_t tsQuerySmaOptimize = 1;
|
||||
int32_t tsQuerySmaOptimize = 0;
|
||||
|
||||
/*
|
||||
* denote if the server needs to compress response message at the application layer to client, including query rsp,
|
||||
|
@ -389,7 +389,7 @@ static int32_t taosAddServerCfg(SConfig *pCfg) {
|
|||
tsNumOfVnodeQueryThreads = TMAX(tsNumOfVnodeQueryThreads, 4);
|
||||
if (cfgAddInt32(pCfg, "numOfVnodeQueryThreads", tsNumOfVnodeQueryThreads, 4, 1024, 0) != 0) return -1;
|
||||
|
||||
tsNumOfVnodeStreamThreads = tsNumOfCores;
|
||||
tsNumOfVnodeStreamThreads = tsNumOfCores / 4;
|
||||
tsNumOfVnodeStreamThreads = TMAX(tsNumOfVnodeStreamThreads, 4);
|
||||
if (cfgAddInt32(pCfg, "numOfVnodeStreamThreads", tsNumOfVnodeStreamThreads, 4, 1024, 0) != 0) return -1;
|
||||
|
||||
|
@ -401,7 +401,8 @@ static int32_t taosAddServerCfg(SConfig *pCfg) {
|
|||
tsNumOfVnodeWriteThreads = TMAX(tsNumOfVnodeWriteThreads, 1);
|
||||
if (cfgAddInt32(pCfg, "numOfVnodeWriteThreads", tsNumOfVnodeWriteThreads, 1, 1024, 0) != 0) return -1;
|
||||
|
||||
tsNumOfVnodeSyncThreads = tsNumOfCores;
|
||||
// tsNumOfVnodeSyncThreads = tsNumOfCores;
|
||||
tsNumOfVnodeSyncThreads = 32;
|
||||
tsNumOfVnodeSyncThreads = TMAX(tsNumOfVnodeSyncThreads, 1);
|
||||
if (cfgAddInt32(pCfg, "numOfVnodeSyncThreads", tsNumOfVnodeSyncThreads, 1, 1024, 0) != 0) return -1;
|
||||
|
||||
|
|
|
@ -604,11 +604,11 @@ typedef struct {
|
|||
int64_t createTime;
|
||||
int64_t updateTime;
|
||||
int32_t version;
|
||||
int32_t totalLevel;
|
||||
int64_t smaId; // 0 for unused
|
||||
// info
|
||||
int64_t uid;
|
||||
int8_t status;
|
||||
int8_t isDistributed;
|
||||
// config
|
||||
int8_t igExpired;
|
||||
int8_t trigger;
|
||||
|
@ -647,7 +647,6 @@ typedef struct {
|
|||
typedef struct {
|
||||
int64_t uid;
|
||||
int64_t streamId;
|
||||
int8_t isDistributed;
|
||||
int8_t status;
|
||||
int8_t stage;
|
||||
} SStreamRecoverObj;
|
||||
|
|
|
@ -1691,13 +1691,17 @@ static int32_t mndRetrieveDbs(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBloc
|
|||
if (!pShow->sysDbRsp) {
|
||||
SDbObj infoschemaDb = {0};
|
||||
setInformationSchemaDbCfg(&infoschemaDb);
|
||||
dumpDbInfoData(pBlock, &infoschemaDb, pShow, numOfRows, 14, true, 0, 1);
|
||||
size_t numOfTables = 0;
|
||||
getInfosDbMeta(NULL, &numOfTables);
|
||||
dumpDbInfoData(pBlock, &infoschemaDb, pShow, numOfRows, numOfTables, true, 0, 1);
|
||||
|
||||
numOfRows += 1;
|
||||
|
||||
SDbObj perfschemaDb = {0};
|
||||
setPerfSchemaDbCfg(&perfschemaDb);
|
||||
dumpDbInfoData(pBlock, &perfschemaDb, pShow, numOfRows, 3, true, 0, 1);
|
||||
numOfTables = 0;
|
||||
getPerfDbMeta(NULL, &numOfTables);
|
||||
dumpDbInfoData(pBlock, &perfschemaDb, pShow, numOfRows, numOfTables, true, 0, 1);
|
||||
|
||||
numOfRows += 1;
|
||||
pShow->sysDbRsp = true;
|
||||
|
|
|
@ -23,11 +23,11 @@ int32_t tEncodeSStreamObj(SEncoder *pEncoder, const SStreamObj *pObj) {
|
|||
if (tEncodeI64(pEncoder, pObj->createTime) < 0) return -1;
|
||||
if (tEncodeI64(pEncoder, pObj->updateTime) < 0) return -1;
|
||||
if (tEncodeI32(pEncoder, pObj->version) < 0) return -1;
|
||||
if (tEncodeI32(pEncoder, pObj->totalLevel) < 0) return -1;
|
||||
if (tEncodeI64(pEncoder, pObj->smaId) < 0) return -1;
|
||||
|
||||
if (tEncodeI64(pEncoder, pObj->uid) < 0) return -1;
|
||||
if (tEncodeI8(pEncoder, pObj->status) < 0) return -1;
|
||||
if (tEncodeI8(pEncoder, pObj->isDistributed) < 0) return -1;
|
||||
|
||||
if (tEncodeI8(pEncoder, pObj->igExpired) < 0) return -1;
|
||||
if (tEncodeI8(pEncoder, pObj->trigger) < 0) return -1;
|
||||
|
@ -69,11 +69,11 @@ int32_t tDecodeSStreamObj(SDecoder *pDecoder, SStreamObj *pObj) {
|
|||
if (tDecodeI64(pDecoder, &pObj->createTime) < 0) return -1;
|
||||
if (tDecodeI64(pDecoder, &pObj->updateTime) < 0) return -1;
|
||||
if (tDecodeI32(pDecoder, &pObj->version) < 0) return -1;
|
||||
if (tDecodeI32(pDecoder, &pObj->totalLevel) < 0) return -1;
|
||||
if (tDecodeI64(pDecoder, &pObj->smaId) < 0) return -1;
|
||||
|
||||
if (tDecodeI64(pDecoder, &pObj->uid) < 0) return -1;
|
||||
if (tDecodeI8(pDecoder, &pObj->status) < 0) return -1;
|
||||
if (tDecodeI8(pDecoder, &pObj->isDistributed) < 0) return -1;
|
||||
|
||||
if (tDecodeI8(pDecoder, &pObj->igExpired) < 0) return -1;
|
||||
if (tDecodeI8(pDecoder, &pObj->trigger) < 0) return -1;
|
||||
|
|
|
@ -84,6 +84,9 @@ int32_t mndProcessBatchMetaMsg(SRpcMsg *pMsg) {
|
|||
}
|
||||
|
||||
for (int32_t i = 0; i < msgNum; ++i) {
|
||||
req.msgIdx = ntohl(*(int32_t*)((char*)pMsg->pCont + offset));
|
||||
offset += sizeof(req.msgIdx);
|
||||
|
||||
req.msgType = ntohl(*(int32_t*)((char*)pMsg->pCont + offset));
|
||||
offset += sizeof(req.msgType);
|
||||
|
||||
|
@ -111,6 +114,7 @@ int32_t mndProcessBatchMetaMsg(SRpcMsg *pMsg) {
|
|||
} else {
|
||||
rsp.rspCode = 0;
|
||||
}
|
||||
rsp.msgIdx = req.msgIdx;
|
||||
rsp.reqType = reqMsg.msgType;
|
||||
rsp.msgLen = reqMsg.info.rspLen;
|
||||
rsp.msg = reqMsg.info.rsp;
|
||||
|
@ -136,6 +140,8 @@ int32_t mndProcessBatchMetaMsg(SRpcMsg *pMsg) {
|
|||
|
||||
*(int32_t*)((char*)pRsp + offset) = htonl(p->reqType);
|
||||
offset += sizeof(p->reqType);
|
||||
*(int32_t*)((char*)pRsp + offset) = htonl(p->msgIdx);
|
||||
offset += sizeof(p->msgIdx);
|
||||
*(int32_t*)((char*)pRsp + offset) = htonl(p->msgLen);
|
||||
offset += sizeof(p->msgLen);
|
||||
*(int32_t*)((char*)pRsp + offset) = htonl(p->rspCode);
|
||||
|
|
|
@ -98,13 +98,11 @@ END:
|
|||
}
|
||||
|
||||
int32_t mndAddSinkToTask(SMnode* pMnode, SStreamObj* pStream, SStreamTask* pTask) {
|
||||
pTask->dispatchType = TASK_DISPATCH__NONE;
|
||||
// sink
|
||||
if (pStream->smaId != 0) {
|
||||
pTask->sinkType = TASK_SINK__SMA;
|
||||
pTask->outputType = TASK_OUTPUT__SMA;
|
||||
pTask->smaSink.smaId = pStream->smaId;
|
||||
} else {
|
||||
pTask->sinkType = TASK_SINK__TABLE;
|
||||
pTask->outputType = TASK_OUTPUT__TABLE;
|
||||
pTask->tbSink.stbUid = pStream->targetStbUid;
|
||||
memcpy(pTask->tbSink.stbFullName, pStream->targetSTbName, TSDB_TABLE_FNAME_LEN);
|
||||
pTask->tbSink.pSchemaWrapper = tCloneSSchemaWrapper(&pStream->outputSchema);
|
||||
|
@ -113,8 +111,6 @@ int32_t mndAddSinkToTask(SMnode* pMnode, SStreamObj* pStream, SStreamTask* pTask
|
|||
}
|
||||
|
||||
int32_t mndAddDispatcherToInnerTask(SMnode* pMnode, SStreamObj* pStream, SStreamTask* pTask) {
|
||||
pTask->sinkType = TASK_SINK__NONE;
|
||||
|
||||
bool isShuffle = false;
|
||||
|
||||
if (pStream->fixedSinkVgId == 0) {
|
||||
|
@ -122,7 +118,7 @@ int32_t mndAddDispatcherToInnerTask(SMnode* pMnode, SStreamObj* pStream, SStream
|
|||
ASSERT(pDb);
|
||||
if (pDb->cfg.numOfVgroups > 1) {
|
||||
isShuffle = true;
|
||||
pTask->dispatchType = TASK_DISPATCH__SHUFFLE;
|
||||
pTask->outputType = TASK_OUTPUT__SHUFFLE_DISPATCH;
|
||||
pTask->dispatchMsgType = TDMT_STREAM_TASK_DISPATCH;
|
||||
if (mndExtractDbInfo(pMnode, pDb, &pTask->shuffleDispatcher.dbInfo, NULL) < 0) {
|
||||
ASSERT(0);
|
||||
|
@ -152,7 +148,7 @@ int32_t mndAddDispatcherToInnerTask(SMnode* pMnode, SStreamObj* pStream, SStream
|
|||
}
|
||||
}
|
||||
} else {
|
||||
pTask->dispatchType = TASK_DISPATCH__FIXED;
|
||||
pTask->outputType = TASK_OUTPUT__FIXED_DISPATCH;
|
||||
pTask->dispatchMsgType = TDMT_STREAM_TASK_DISPATCH;
|
||||
SArray* pArray = taosArrayGetP(pStream->tasks, 0);
|
||||
// one sink only
|
||||
|
@ -178,7 +174,6 @@ int32_t mndAssignTaskToVg(SMnode* pMnode, SStreamTask* pTask, SSubplan* plan, co
|
|||
terrno = TSDB_CODE_QRY_INVALID_INPUT;
|
||||
return -1;
|
||||
}
|
||||
ASSERT(pTask->dispatchType != TASK_DISPATCH__NONE || pTask->sinkType != TASK_SINK__NONE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -249,26 +244,20 @@ int32_t mndAddShuffleSinkTasksToStream(SMnode* pMnode, SStreamObj* pStream) {
|
|||
pTask->nodeId = pVgroup->vgId;
|
||||
pTask->epSet = mndGetVgroupEpset(pMnode, pVgroup);
|
||||
|
||||
// source
|
||||
pTask->isDataScan = 0;
|
||||
|
||||
// exec
|
||||
pTask->execType = TASK_EXEC__NONE;
|
||||
// type
|
||||
pTask->taskLevel = TASK_LEVEL__SINK;
|
||||
|
||||
// sink
|
||||
if (pStream->smaId != 0) {
|
||||
pTask->sinkType = TASK_SINK__SMA;
|
||||
pTask->outputType = TASK_OUTPUT__SMA;
|
||||
pTask->smaSink.smaId = pStream->smaId;
|
||||
} else {
|
||||
pTask->sinkType = TASK_SINK__TABLE;
|
||||
pTask->outputType = TASK_OUTPUT__TABLE;
|
||||
pTask->tbSink.stbUid = pStream->targetStbUid;
|
||||
memcpy(pTask->tbSink.stbFullName, pStream->targetSTbName, TSDB_TABLE_FNAME_LEN);
|
||||
pTask->tbSink.pSchemaWrapper = tCloneSSchemaWrapper(&pStream->outputSchema);
|
||||
ASSERT(pTask->tbSink.pSchemaWrapper);
|
||||
}
|
||||
|
||||
// dispatch
|
||||
pTask->dispatchType = TASK_DISPATCH__NONE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -295,25 +284,19 @@ int32_t mndAddFixedSinkTaskToStream(SMnode* pMnode, SStreamObj* pStream) {
|
|||
#endif
|
||||
pTask->epSet = mndGetVgroupEpset(pMnode, &pStream->fixedSinkVg);
|
||||
|
||||
// source
|
||||
pTask->isDataScan = 0;
|
||||
|
||||
// exec
|
||||
pTask->execType = TASK_EXEC__NONE;
|
||||
pTask->taskLevel = TASK_LEVEL__SINK;
|
||||
|
||||
// sink
|
||||
if (pStream->smaId != 0) {
|
||||
pTask->sinkType = TASK_SINK__SMA;
|
||||
pTask->outputType = TASK_OUTPUT__SMA;
|
||||
pTask->smaSink.smaId = pStream->smaId;
|
||||
} else {
|
||||
pTask->sinkType = TASK_SINK__TABLE;
|
||||
pTask->outputType = TASK_OUTPUT__TABLE;
|
||||
pTask->tbSink.stbUid = pStream->targetStbUid;
|
||||
memcpy(pTask->tbSink.stbFullName, pStream->targetSTbName, TSDB_TABLE_FNAME_LEN);
|
||||
pTask->tbSink.pSchemaWrapper = tCloneSSchemaWrapper(&pStream->outputSchema);
|
||||
}
|
||||
|
||||
// dispatch
|
||||
pTask->dispatchType = TASK_DISPATCH__NONE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -324,10 +307,9 @@ int32_t mndScheduleStream(SMnode* pMnode, SStreamObj* pStream) {
|
|||
terrno = TSDB_CODE_QRY_INVALID_INPUT;
|
||||
return -1;
|
||||
}
|
||||
int32_t totLevel = LIST_LENGTH(pPlan->pSubplans);
|
||||
ASSERT(totLevel <= 2);
|
||||
pStream->tasks = taosArrayInit(totLevel, sizeof(void*));
|
||||
pStream->isDistributed = totLevel == 2;
|
||||
int32_t planTotLevel = LIST_LENGTH(pPlan->pSubplans);
|
||||
ASSERT(planTotLevel <= 2);
|
||||
pStream->tasks = taosArrayInit(planTotLevel, sizeof(void*));
|
||||
|
||||
bool hasExtraSink = false;
|
||||
bool externalTargetDB = strcmp(pStream->sourceDb, pStream->targetDb) != 0;
|
||||
|
@ -337,7 +319,8 @@ int32_t mndScheduleStream(SMnode* pMnode, SStreamObj* pStream) {
|
|||
|
||||
bool multiTarget = pDbObj->cfg.numOfVgroups > 1;
|
||||
|
||||
if (totLevel == 2 || externalTargetDB || multiTarget) {
|
||||
if (planTotLevel == 2 || externalTargetDB || multiTarget) {
|
||||
/*if (true) {*/
|
||||
SArray* taskOneLevel = taosArrayInit(0, sizeof(void*));
|
||||
taosArrayPush(pStream->tasks, &taskOneLevel);
|
||||
// add extra sink
|
||||
|
@ -354,8 +337,9 @@ int32_t mndScheduleStream(SMnode* pMnode, SStreamObj* pStream) {
|
|||
}
|
||||
}
|
||||
}
|
||||
pStream->totalLevel = planTotLevel + hasExtraSink;
|
||||
|
||||
if (totLevel > 1) {
|
||||
if (planTotLevel > 1) {
|
||||
SStreamTask* pInnerTask;
|
||||
// inner level
|
||||
{
|
||||
|
@ -376,8 +360,7 @@ int32_t mndScheduleStream(SMnode* pMnode, SStreamObj* pStream) {
|
|||
|
||||
pInnerTask->childEpInfo = taosArrayInit(0, sizeof(void*));
|
||||
|
||||
// source
|
||||
pInnerTask->isDataScan = 0;
|
||||
pInnerTask->taskLevel = TASK_LEVEL__AGG;
|
||||
|
||||
// trigger
|
||||
pInnerTask->triggerParam = pStream->triggerParam;
|
||||
|
@ -388,16 +371,6 @@ int32_t mndScheduleStream(SMnode* pMnode, SStreamObj* pStream) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
// exec
|
||||
pInnerTask->execType = TASK_EXEC__PIPE;
|
||||
|
||||
#if 0
|
||||
SDbObj* pSourceDb = mndAcquireDb(pMnode, pStream->sourceDb);
|
||||
ASSERT(pDbObj != NULL);
|
||||
sdbRelease(pSdb, pSourceDb);
|
||||
pInnerTask->numOfVgroups = pSourceDb->cfg.numOfVgroups;
|
||||
#endif
|
||||
|
||||
if (tsSchedStreamToSnode) {
|
||||
SSnodeObj* pSnode = mndSchedFetchOneSnode(pMnode);
|
||||
if (pSnode == NULL) {
|
||||
|
@ -452,19 +425,16 @@ int32_t mndScheduleStream(SMnode* pMnode, SStreamObj* pStream) {
|
|||
mndAddTaskToTaskSet(taskSourceLevel, pTask);
|
||||
|
||||
// source
|
||||
pTask->isDataScan = 1;
|
||||
pTask->taskLevel = TASK_LEVEL__SOURCE;
|
||||
|
||||
// add fixed vg dispatch
|
||||
pTask->sinkType = TASK_SINK__NONE;
|
||||
pTask->dispatchMsgType = TDMT_STREAM_TASK_DISPATCH;
|
||||
pTask->dispatchType = TASK_DISPATCH__FIXED;
|
||||
pTask->outputType = TASK_OUTPUT__FIXED_DISPATCH;
|
||||
|
||||
pTask->fixedEpDispatcher.taskId = pInnerTask->taskId;
|
||||
pTask->fixedEpDispatcher.nodeId = pInnerTask->nodeId;
|
||||
pTask->fixedEpDispatcher.epSet = pInnerTask->epSet;
|
||||
|
||||
// exec
|
||||
pTask->execType = TASK_EXEC__PIPE;
|
||||
if (mndAssignTaskToVg(pMnode, pTask, plan, pVgroup) < 0) {
|
||||
sdbRelease(pSdb, pVgroup);
|
||||
qDestroyQueryPlan(pPlan);
|
||||
|
@ -487,7 +457,7 @@ int32_t mndScheduleStream(SMnode* pMnode, SStreamObj* pStream) {
|
|||
}
|
||||
}
|
||||
|
||||
if (totLevel == 1) {
|
||||
if (planTotLevel == 1) {
|
||||
SArray* taskOneLevel = taosArrayInit(0, sizeof(void*));
|
||||
taosArrayPush(pStream->tasks, &taskOneLevel);
|
||||
|
||||
|
@ -515,7 +485,7 @@ int32_t mndScheduleStream(SMnode* pMnode, SStreamObj* pStream) {
|
|||
mndAddTaskToTaskSet(taskOneLevel, pTask);
|
||||
|
||||
// source
|
||||
pTask->isDataScan = 1;
|
||||
pTask->taskLevel = TASK_LEVEL__SOURCE;
|
||||
|
||||
// trigger
|
||||
pTask->triggerParam = pStream->triggerParam;
|
||||
|
@ -527,8 +497,6 @@ int32_t mndScheduleStream(SMnode* pMnode, SStreamObj* pStream) {
|
|||
mndAddSinkToTask(pMnode, pStream, pTask);
|
||||
}
|
||||
|
||||
// exec
|
||||
pTask->execType = TASK_EXEC__PIPE;
|
||||
if (mndAssignTaskToVg(pMnode, pTask, plan, pVgroup) < 0) {
|
||||
sdbRelease(pSdb, pVgroup);
|
||||
qDestroyQueryPlan(pPlan);
|
||||
|
|
|
@ -489,7 +489,7 @@ static int32_t mndCreateSma(SMnode *pMnode, SRpcMsg *pReq, SMCreateSmaReq *pCrea
|
|||
smaObj.uid = mndGenerateUid(pCreate->name, TSDB_TABLE_FNAME_LEN);
|
||||
ASSERT(smaObj.uid != 0);
|
||||
char resultTbName[TSDB_TABLE_FNAME_LEN + 16] = {0};
|
||||
snprintf(resultTbName, TSDB_TABLE_FNAME_LEN + 16, "td.tsma.rst.tb.%s", pCreate->name);
|
||||
snprintf(resultTbName, TSDB_TABLE_FNAME_LEN + 16, "%s_td_tsma_rst_tb",pCreate->name);
|
||||
memcpy(smaObj.dstTbName, resultTbName, TSDB_TABLE_FNAME_LEN);
|
||||
smaObj.dstTbUid = mndGenerateUid(smaObj.dstTbName, TSDB_TABLE_FNAME_LEN);
|
||||
smaObj.stbUid = pStb->uid;
|
||||
|
@ -603,6 +603,9 @@ static int32_t mndCreateSma(SMnode *pMnode, SRpcMsg *pReq, SMCreateSmaReq *pCrea
|
|||
if (mndPersistStream(pMnode, pTrans, &streamObj) != 0) goto _OVER;
|
||||
if (mndTransPrepare(pMnode, pTrans) != 0) goto _OVER;
|
||||
|
||||
mDebug("mndSma: create sma index %s %" PRIi64 " on stb:%" PRIi64 ", dstSuid:%" PRIi64 " dstTb:%s dstVg:%d",
|
||||
pCreate->name, smaObj.uid, smaObj.stbUid, smaObj.dstTbUid, smaObj.dstTbName, smaObj.dstVgId);
|
||||
|
||||
code = 0;
|
||||
|
||||
_OVER:
|
||||
|
@ -795,11 +798,12 @@ static int32_t mndDropSma(SMnode *pMnode, SRpcMsg *pReq, SDbObj *pDb, SSmaObj *p
|
|||
pStb = mndAcquireStb(pMnode, pSma->stb);
|
||||
if (pStb == NULL) goto _OVER;
|
||||
|
||||
pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_CONFLICT_DB, pReq);
|
||||
pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_DB, pReq);
|
||||
if (pTrans == NULL) goto _OVER;
|
||||
|
||||
mDebug("trans:%d, used to drop sma:%s", pTrans->id, pSma->name);
|
||||
mndTransSetDbName(pTrans, pDb->name, NULL);
|
||||
mndTransSetSerial(pTrans);
|
||||
|
||||
char streamName[TSDB_TABLE_FNAME_LEN] = {0};
|
||||
mndGetStreamNameFromSmaName(streamName, pSma->name);
|
||||
|
@ -812,12 +816,14 @@ static int32_t mndDropSma(SMnode *pMnode, SRpcMsg *pReq, SDbObj *pDb, SSmaObj *p
|
|||
if (mndDropStreamTasks(pMnode, pTrans, pStream) < 0) {
|
||||
mError("stream:%s, failed to drop task since %s", pStream->name, terrstr());
|
||||
sdbRelease(pMnode->pSdb, pStream);
|
||||
ASSERT(0);
|
||||
goto _OVER;
|
||||
}
|
||||
|
||||
// drop stream
|
||||
if (mndPersistDropStreamLog(pMnode, pTrans, pStream) < 0) {
|
||||
sdbRelease(pMnode->pSdb, pStream);
|
||||
ASSERT(0);
|
||||
goto _OVER;
|
||||
}
|
||||
}
|
||||
|
@ -850,6 +856,7 @@ int32_t mndDropSmasByStb(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SStbObj *p
|
|||
if (pIter == NULL) break;
|
||||
|
||||
if (pSma->stbUid == pStb->uid) {
|
||||
mndTransSetSerial(pTrans);
|
||||
pVgroup = mndAcquireVgroup(pMnode, pSma->dstVgId);
|
||||
if (pVgroup == NULL) goto _OVER;
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue