diff --git a/deps/win/x64/dm_static/dmodule.lib b/deps/win/x64/dm_static/dmodule.lib
index 36ce1d81d3..55afb81e3f 100644
Binary files a/deps/win/x64/dm_static/dmodule.lib and b/deps/win/x64/dm_static/dmodule.lib differ
diff --git a/docs/zh/06-advanced/05-data-in/index.md b/docs/zh/06-advanced/05-data-in/index.md
index 99dfbf098b..32d530acb5 100644
--- a/docs/zh/06-advanced/05-data-in/index.md
+++ b/docs/zh/06-advanced/05-data-in/index.md
@@ -1,276 +1,276 @@
----
-sidebar_label: 数据写入
-title: 零代码数据源接入
-toc_max_heading_level: 4
----
-
-## 概述
-
-TDengine Enterprise 配备了一个强大的可视化数据管理工具—taosExplorer。借助 taosExplorer,用户只须在浏览器中简单配置,就能轻松地向 TDengine 提交任务,实现以零代码方式将来自不同数据源的数据无缝导入 TDengine。在导入过程中,TDengine 会对数据进行自动提取、过滤和转换,以保证导入的数据质量。通过这种零代码数据源接入方式,TDengine 成功转型为一个卓越的时序大数据汇聚平台。用户无须部署额外的 ETL 工具,从而大大简化整体架构的设计,提高了数据处理效率。
-
-下图展示了零代码接入平台的系统架构。
-
-
-
-## 支持的数据源
-
-目前 TDengine 支持的数据源如下:
-
-1. Aveva PI System:一个工业数据管理和分析平台,前身为 OSIsoft PI System,它能够实时采集、整合、分析和可视化工业数据,助力企业实现智能化决策和精细化管理
-2. Aveva Historian:一个工业大数据分析软件,前身为 Wonderware Historian,专为工业环境设计,用于存储、管理和分析来自各种工业设备、传感器的实时和历史数据。
-3. OPC DA/UA:OPC 是 Open Platform Communications 的缩写,是一种开放式、标准化的通信协议,用于不同厂商的自动化设备之间进行数据交换。它最初由微软公司开发,旨在解决工业控制领域中不同设备之间互操作性差的问题。OPC 协议最初于 1996 年发布,当时称为 OPC DA (Data Access),主要用于实时数据采集和控制;2006 年,OPC 基金会发布了 OPC UA (Unified Architecture) 标准,它是一种基于服务的面向对象的协议,具有更高的灵活性和可扩展性,已成为 OPC 协议的主流版本。
-4. MQTT:Message Queuing Telemetry Transport 的缩写,一种基于发布/订阅模式的轻量级通讯协议,专为低开销、低带宽占用的即时通讯设计,广泛适用于物联网、小型设备、移动应用等领域。
-5. Kafka:由 Apache 软件基金会开发的一个开源流处理平台,主要用于处理实时数据,并提供一个统一、高通量、低延迟的消息系统。它具备高速度、可伸缩性、持久性和分布式设计等特点,使得它能够在每秒处理数十万次的读写操作,支持上千个客户端,同时保持数据的可靠性和可用性。
-6. OpenTSDB:基于 HBase 的分布式、可伸缩的时序数据库。它主要用于存储、索引和提供从大规模集群(包括网络设备、操作系统、应用程序等)中收集的指标数据,使这些数据更易于访问和图形化展示。
-7. CSV:Comma Separated Values 的缩写,是一种以逗号分隔的纯文本文件格式,通常用于电子表格或数据库软件。
-8. TDengine 2:泛指运行 TDengine 2.x 版本的 TDengine 实例。
-9. TDengine 3:泛指运行 TDengine 3.x 版本的 TDengine 实例。
-10. MySQL, PostgreSQL, Oracle 等关系型数据库。
-
-## 数据提取、过滤和转换
-
-因为数据源可以有多个,每个数据源的物理单位可能不一样,命名规则也不一样,时区也可能不同。为解决这个问题,TDengine 内置 ETL 功能,可以从数据源的数据包中解析、提取需要的数据,并进行过滤和转换,以保证写入数据的质量,提供统一的命名空间。具体的功能如下:
-
-1. 解析:使用 JSON Path 或正则表达式,从原始消息中解析字段
-2. 从列中提取或拆分:使用 split 或正则表达式,从一个原始字段中提取多个字段
-3. 过滤:只有表达式的值为 true 时,消息才会被写入 TDengine
-4. 转换:建立解析后的字段和 TDengine 超级表字段之间的转换与映射关系。
-
-下面详细讲解数据转换规则
-
-
-### 解析
-
-仅非结构化的数据源需要这个步骤,目前 MQTT 和 Kafka 数据源会使用这个步骤提供的规则来解析非结构化数据,以初步获取结构化数据,即可以以字段描述的行列数据。在 explorer 中您需要提供示例数据和解析规则,来预览解析出以表格呈现的结构化数据。
-
-#### 示例数据
-
-
-
-如图,textarea 输入框中就是示例数据,可以通过三种方式来获取示例数据:
-
-1. 直接在 textarea 中输入示例数据;
-2. 点击右侧按钮 “从服务器检索” 则从配置的服务器获取示例数据,并追加到示例数据 textarea 中;
-3. 上传文件,将文件内容追加到示例数据 textarea 中。
-
-#### 解析
-
-解析就是通过解析规则,将非结构化字符串解析为结构化数据。消息体的解析规则目前支持 JSON、Regex 和 UDT。
-
-##### JSON 解析
-
-如下 JSON 示例数据,可自动解析出字段:`groupid`、`voltage`、`current`、`ts`、`inuse`、`location`。
-
-``` json
-{"groupid": 170001, "voltage": "221V", "current": 12.3, "ts": "2023-12-18T22:12:00", "inuse": true, "location": "beijing.chaoyang.datun"}
-{"groupid": 170001, "voltage": "220V", "current": 12.2, "ts": "2023-12-18T22:12:02", "inuse": true, "location": "beijing.chaoyang.datun"}
-{"groupid": 170001, "voltage": "216V", "current": 12.5, "ts": "2023-12-18T22:12:04", "inuse": false, "location": "beijing.chaoyang.datun"}
-```
-
-如下嵌套结构的 JSON 数据,可自动解析出字段`groupid`、`data_voltage`、`data_current`、`ts`、`inuse`、`location_0_province`、`location_0_city`、`location_0_datun`,也可以选择要解析的字段,并设置解析的别名。
-
-``` json
-{"groupid": 170001, "data": { "voltage": "221V", "current": 12.3 }, "ts": "2023-12-18T22:12:00", "inuse": true, "location": [{"province": "beijing", "city":"chaoyang", "street": "datun"}]}
-```
-
-
-
-##### Regex 正则表达式
-
-可以使用正则表达式的**命名捕获组**从任何字符串(文本)字段中提取多个字段。如图所示,从 nginx 日志中提取访问ip、时间戳、访问的url等字段。
-
-``` re
-(?\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\b)\s-\s-\s\[(?\d{2}/\w{3}/\d{4}:\d{2}:\d{2}:\d{2}\s\+\d{4})\]\s"(?[A-Z]+)\s(?[^\s"]+).*(?\d{3})\s(?\d+)
-```
-
-
-
-##### UDT 自定义解析脚本
-
-自定义 rhai 语法脚本解析输入数据(参考 `https://rhai.rs/book/` ),脚本目前仅支持 json 格式原始数据。
-
-**输入**:脚本中可以使用参数 data, data 是原始数据 json 解析后的 Object Map;
-
-**输出**:输出的数据必须是数组。
-
-例如对于数据,一次上报三相电压值,分别入到三个子表中。则需要对这类数据做解析
-
-``` json
-{
- "ts": "2024-06-27 18:00:00",
- "voltage": "220.1,220.3,221.1",
- "dev_id": "8208891"
-}
-```
-
-那么可以使用如下脚本来提取三个电压数据。
-
-```
-let v3 = data["voltage"].split(",");
-
-[
-#{"ts": data["ts"], "val": v3[0], "dev_id": data["dev_id"]},
-#{"ts": data["ts"], "val": v3[1], "dev_id": data["dev_id"]},
-#{"ts": data["ts"], "val": v3[2], "dev_id": data["dev_id"]}
-]
-```
-
-最终解析结果如下所示:
-
-
-
-### 提取或拆分
-
-解析后的数据,可能还无法满足目标表的数据要求。比如智能表原始采集数据如下( json 格式):
-
-``` json
-{"groupid": 170001, "voltage": "221V", "current": 12.3, "ts": "2023-12-18T22:12:00", "inuse": true, "location": "beijing.chaoyang.datun"}
-{"groupid": 170001, "voltage": "220V", "current": 12.2, "ts": "2023-12-18T22:12:02", "inuse": true, "location": "beijing.chaoyang.datun"}
-{"groupid": 170001, "voltage": "216V", "current": 12.5, "ts": "2023-12-18T22:12:04", "inuse": false, "location": "beijing.chaoyang.datun"}
-```
-
-使用 json 规则解析出的电压是字符串表达的带单位形式,最终入库希望能使用 int 类型记录电压值和电流值,便于统计分析,此时就需要对电压进一步拆分;另外日期期望拆分为日期和时间入库。
-
-如下图所示可以对源字段`ts`使用 split 规则拆分成日期和时间,对字段`voltage`使用 regex 提取出电压值和电压单位。split 规则需要设置**分隔符**和**拆分数量**,拆分后的字段命名规则为`{原字段名}_{顺序号}`,Regex 规则同解析过程中的一样,使用**命名捕获组**命名提取字段。
-
-
-
-### 过滤
-
-过滤功能可以设置过滤条件,满足条件的数据行 才会被写入目标表。过滤条件表达式的结果必须是 boolean 类型。在编写过滤条件前,必须确定 解析字段的类型,根据解析字段的类型,可以使用判断函数、比较操作符(`>`、`>=`、`<=`、`<`、`==`、`!=`)来判断。
-
-#### 字段类型及转换
-
-只有明确解析出的每个字段的类型,才能使用正确的语法做数据过滤。
-
-使用 json 规则解析出的字段,按照属性值来自动设置类型:
-
-1. bool 类型:"inuse": true
-2. int 类型:"voltage": 220
-3. float 类型:"current" : 12.2
-4. String 类型:"location": "MX001"
-
-使用 regex 规则解析的数据都是 string 类型。
-使用 split 和 regex 提取或拆分的数据是 string 类型。
-
-如果提取出的数据类型不是预期中的类型,可以做数据类型转换。常用的数据类型转换就是把字符串转换成为数值类型。支持的转换函数如下:
-
-|Function|From type|To type|e.g.|
-|:----|:----|:----|:----|
-| parse_int | string | int | parse_int("56") // 结果为整数 56 |
-| parse_float | string | float | parse_float("12.3") // 结果为浮点数 12.3 |
-
-#### 判断表达式
-
-不同的数据类型有各自判断表达式的写法。
-
-##### BOOL 类型
-
-可以使用变量或者使用操作符`!`,比如对于字段 "inuse": true,可以编写以下表达式:
-
-> 1. inuse
-> 2. !inuse
-
-##### 数值类型(int/float)
-
-数值类型支持使用比较操作符`==`、`!=`、`>`、`>=`、`<`、`<=`。
-
-##### 字符串类型
-
-使用比较操作符,比较字符串。
-
-字符串函数
-
-|Function|Description|e.g.|
-|:----|:----|:----|
-| is_empty | returns true if the string is empty | s.is_empty() |
-| contains | checks if a certain character or sub-string occurs in the string | s.contains("substring") |
-| starts_with | returns true if the string starts with a certain string | s.starts_with("prefix") |
-| ends_with | returns true if the string ends with a certain string | s.ends_with("suffix") |
-| len | returns the number of characters (not number of bytes) in the string,must be used with comparison operator | s.len == 5 判断字符串长度是否为5;len作为属性返回 int ,和前四个函数有区别,前四个直接返回 bool。 |
-
-##### 复合表达式
-
-多个判断表达式,可以使用逻辑操作符(&&、||、!)来组合。
-比如下面的表达式表示获取北京市安装的并且电压值大于 200 的智能表数据。
-
-> location.starts_with("beijing") && voltage > 200
-
-### 映射
-
-映射是将解析、提取、拆分的**源字段**对应到**目标表字段**,可以直接对应,也可以通过一些规则计算后再映射到目标表。
-
-#### 选择目标超级表
-
-选择目标超级表后,会加载出超级表所有的 tags 和 columns。
-源字段根据名称自动使用 mapping 规则映射到目标超级表的 tag 和 column。
-例如有如下解析、提取、拆分后的预览数据:
-
-#### 映射规则
-
-支持的映射规则如下表所示:
-
-|rule|description|
-|:----|:----|
-| mapping | 直接映射,需要选择映射源字段。|
-| value | 常量,可以输入字符串常量,也可以是数值常量,输入的常量值直接入库。|
-| generator | 生成器,目前仅支持时间戳生成器 now,入库时会将当前时间入库。|
-| join | 字符串连接器,可指定连接字符拼接选择的多个源字段。|
-| format | **字符串格式化工具**,填写格式化字符串,比如有三个源字段 year, month, day 分别表示年月日,入库希望以yyyy-MM-dd的日期格式入库,则可以提供格式化字符串为 `${year}-${month}-${day}`。其中`${}`作为占位符,占位符中可以是一个源字段,也可以是 string 类型字段的函数处理|
-| sum | 选择多个数值型字段做加法计算。|
-| expr | **数值运算表达式**,可以对数值型字段做更加复杂的函数处理和数学运算。|
-
-##### format 中支持的字符串处理函数
-
-|Function|description|e.g.|
-|:----|:----|:----|
-| pad(len, pad_chars) | pads the string with a character or a string to at least a specified length | "1.2".pad(5, '0') // 结果为"1.200" |
-|trim|trims the string of whitespace at the beginning and end|" abc ee ".trim() // 结果为"abc ee"|
-|sub_string(start_pos, len)|extracts a sub-string,两个参数:
1. start position, counting from end if < 0
2. (optional) number of characters to extract, none if ≤ 0, to end if omitted|"012345678".sub_string(5) // "5678"
"012345678".sub_string(5, 2) // "56"
"012345678".sub_string(-2) // "78"|
-|replace(substring, replacement)|replaces a sub-string with another|"012345678".replace("012", "abc") // "abc345678"|
-
-##### expr 数学计算表达式
-
-基本数学运算支持加`+`、减`-`、乘`*`、除`/`。
-
-比如数据源采集数值以设置度为单位,目标库存储华氏度温度值。那么就需要对采集的温度数据做转换。
-
-解析的源字段为`temperature`,则需要使用表达式 `temperature * 1.8 + 32`。
-
-数值表达式中也支持使用数学函数,可用的数学函数如下表所示:
-
-|Function|description|e.g.|
-|:----|:----|:----|
-|sin、cos、tan、sinh、cosh|Trigonometry|a.sin() |
-|asin、acos、atan、 asinh、acosh|arc-trigonometry|a.asin()|
-|sqrt|Square root|a.sqrt() // 4.sqrt() == 2|
-|exp|Exponential|a.exp()|
-|ln、log|Logarithmic|a.ln() // e.ln() == 1
a.log() // 10.log() == 1|
-|floor、ceiling、round、int、fraction|rounding|a.floor() // (4.2).floor() == 4
a.ceiling() // (4.2).ceiling() == 5
a.round() // (4.2).round() == 4
a.int() // (4.2).int() == 4
a.fraction() // (4.2).fraction() == 0.2|
-
-#### 子表名映射
-
-子表名类型为字符串,可以使用映射规则中的字符串格式化 format 表达式定义子表名。
-
-## 任务的创建
-
-下面以 MQTT 数据源为例,介绍如何创建一个 MQTT 类型的任务,从 MQTT Broker 消费数据,并写入 TDengine。
-
-1. 登录至 taosExplorer 以后,点击左侧导航栏上的“数据写入”,即可进入任务列表页面
-2. 在任务列表页面,点击“+ 新增数据源”,即可进入任务创建页面
-3. 输入任务名称后,选择类型为 MQTT, 然后可以创建一个新的代理,或者选择已创建的代理
-4. 输入 MQTT broker 的 IP 地址和端口号,例如:192.168.1.100:1883
-5. 配置认证和 SSL 加密:
- - 如果 MQTT broker 开启了用户认证,则在认证部分,输入 MQTT broker 的用户名和密码;
- - 如果 MQTT broker 开启了 SSL 加密,则可以打开页面上的 SSL 证书开关,并上传 CA 的证书,以及客户端的证书和私钥文件;
-6. 在“采集配置“部分,可选择 MQTT 协议的版本,目前支持 3.1, 3.1.1, 5.0 三个版本;配置 Client ID 时要注意,如果对同一个 MQTT broker 创建了多个任务,Client ID 应不同,否则会造成 Client ID 冲突,导致任务无法正常运行;在对主题和 QoS 进行配置时,需要使用 `::` 的形式,即订阅的主题与 QoS 之间要使用两个冒号分隔,其中 QoS 的取值范围为 0, 1, 2, 分别代表 at most once, at lease once, exactly once;配置完成以上信息后,可以点击“检查连通性”按钮,对以上配置进行检查,如果连通性检查失败,请按照页面上返回的具体错误提示进行修改;
-7. 在从 MQTT broker 同步数据的过程中,taosX 还支持对消息体中的字段进行提取,过滤、映射等操作。在位于 “Payload 转换”下方的文本框中,可以直接输入输入消息体样例,或是以上传文件的方式导入,以后还会支持直接从所配置的服务器中检索样例消息;
-8. 对消息体字段的提取,目前支持 2 种方式:JSON 和正则表达式。对于简单的 key/value 格式的 JSON 数据,可以直接点击提取按钮,即可展示解析出的字段名;对于复杂的 JSON 数据,可以使用 JSON Path 提取感兴趣的字段;当使用正则表达式提取字段时,要保证正则表达式的正确性;
-9. 消息体中的字段被解析后,可以基于解析出的字段名设置过滤规则,只有满足过滤规则的数据,才会写入 TDengine,否则会忽略该消息;例如:可以配置过滤规则为 voltage > 200,即只有当电压大于 200V 的数据才会被同步至 TDengine;
-10. 最后,在配置完消息体中的字段和超级表中的字段的映射规则后,就可以提交任务了;除了基本的映射以外,在这里还可以对消息中字段的值进行转换,例如:可以通过表达式 (expr) 将原消息体中的电压和电流,计算为功率后再写入 TDengine;
-11. 任务提交后,会自动返回任务列表页面,如果提交成功,任务的状态会切换至“运行中”,如果提交失败,可通过查看该任务的活动日志,查找错误原因;
-12. 对于运行中的任务,点击指标的查看按钮,可以查看该任务的详细运行指标,弹出窗口划分为 2 个标签页,分别展示该任务多次运行的累计指标和本次运行的指标,这些指标每 2 秒钟会自动刷新一次。
-
-## 任务管理
-
+---
+sidebar_label: 数据接入
+title: 零代码第三方数据接入
+toc_max_heading_level: 4
+---
+
+## 概述
+
+TDengine Enterprise 配备了一个强大的可视化数据管理工具—taosExplorer。借助 taosExplorer,用户只须在浏览器中简单配置,就能轻松地向 TDengine 提交任务,实现以零代码方式将来自不同数据源的数据无缝导入 TDengine。在导入过程中,TDengine 会对数据进行自动提取、过滤和转换,以保证导入的数据质量。通过这种零代码数据源接入方式,TDengine 成功转型为一个卓越的时序大数据汇聚平台。用户无须部署额外的 ETL 工具,从而大大简化整体架构的设计,提高了数据处理效率。
+
+下图展示了零代码接入平台的系统架构。
+
+
+
+## 支持的数据源
+
+目前 TDengine 支持的数据源如下:
+
+1. Aveva PI System:一个工业数据管理和分析平台,前身为 OSIsoft PI System,它能够实时采集、整合、分析和可视化工业数据,助力企业实现智能化决策和精细化管理
+2. Aveva Historian:一个工业大数据分析软件,前身为 Wonderware Historian,专为工业环境设计,用于存储、管理和分析来自各种工业设备、传感器的实时和历史数据。
+3. OPC DA/UA:OPC 是 Open Platform Communications 的缩写,是一种开放式、标准化的通信协议,用于不同厂商的自动化设备之间进行数据交换。它最初由微软公司开发,旨在解决工业控制领域中不同设备之间互操作性差的问题。OPC 协议最初于 1996 年发布,当时称为 OPC DA (Data Access),主要用于实时数据采集和控制;2006 年,OPC 基金会发布了 OPC UA (Unified Architecture) 标准,它是一种基于服务的面向对象的协议,具有更高的灵活性和可扩展性,已成为 OPC 协议的主流版本。
+4. MQTT:Message Queuing Telemetry Transport 的缩写,一种基于发布/订阅模式的轻量级通讯协议,专为低开销、低带宽占用的即时通讯设计,广泛适用于物联网、小型设备、移动应用等领域。
+5. Kafka:由 Apache 软件基金会开发的一个开源流处理平台,主要用于处理实时数据,并提供一个统一、高通量、低延迟的消息系统。它具备高速度、可伸缩性、持久性和分布式设计等特点,使得它能够在每秒处理数十万次的读写操作,支持上千个客户端,同时保持数据的可靠性和可用性。
+6. OpenTSDB:基于 HBase 的分布式、可伸缩的时序数据库。它主要用于存储、索引和提供从大规模集群(包括网络设备、操作系统、应用程序等)中收集的指标数据,使这些数据更易于访问和图形化展示。
+7. CSV:Comma Separated Values 的缩写,是一种以逗号分隔的纯文本文件格式,通常用于电子表格或数据库软件。
+8. TDengine 2:泛指运行 TDengine 2.x 版本的 TDengine 实例。
+9. TDengine 3:泛指运行 TDengine 3.x 版本的 TDengine 实例。
+10. MySQL, PostgreSQL, Oracle 等关系型数据库。
+
+## 数据提取、过滤和转换
+
+因为数据源可以有多个,每个数据源的物理单位可能不一样,命名规则也不一样,时区也可能不同。为解决这个问题,TDengine 内置 ETL 功能,可以从数据源的数据包中解析、提取需要的数据,并进行过滤和转换,以保证写入数据的质量,提供统一的命名空间。具体的功能如下:
+
+1. 解析:使用 JSON Path 或正则表达式,从原始消息中解析字段
+2. 从列中提取或拆分:使用 split 或正则表达式,从一个原始字段中提取多个字段
+3. 过滤:只有表达式的值为 true 时,消息才会被写入 TDengine
+4. 转换:建立解析后的字段和 TDengine 超级表字段之间的转换与映射关系。
+
+下面详细讲解数据转换规则
+
+
+### 解析
+
+仅非结构化的数据源需要这个步骤,目前 MQTT 和 Kafka 数据源会使用这个步骤提供的规则来解析非结构化数据,以初步获取结构化数据,即可以以字段描述的行列数据。在 explorer 中您需要提供示例数据和解析规则,来预览解析出以表格呈现的结构化数据。
+
+#### 示例数据
+
+
+
+如图,textarea 输入框中就是示例数据,可以通过三种方式来获取示例数据:
+
+1. 直接在 textarea 中输入示例数据;
+2. 点击右侧按钮 “从服务器检索” 则从配置的服务器获取示例数据,并追加到示例数据 textarea 中;
+3. 上传文件,将文件内容追加到示例数据 textarea 中。
+
+#### 解析
+
+解析就是通过解析规则,将非结构化字符串解析为结构化数据。消息体的解析规则目前支持 JSON、Regex 和 UDT。
+
+##### JSON 解析
+
+如下 JSON 示例数据,可自动解析出字段:`groupid`、`voltage`、`current`、`ts`、`inuse`、`location`。
+
+``` json
+{"groupid": 170001, "voltage": "221V", "current": 12.3, "ts": "2023-12-18T22:12:00", "inuse": true, "location": "beijing.chaoyang.datun"}
+{"groupid": 170001, "voltage": "220V", "current": 12.2, "ts": "2023-12-18T22:12:02", "inuse": true, "location": "beijing.chaoyang.datun"}
+{"groupid": 170001, "voltage": "216V", "current": 12.5, "ts": "2023-12-18T22:12:04", "inuse": false, "location": "beijing.chaoyang.datun"}
+```
+
+如下嵌套结构的 JSON 数据,可自动解析出字段`groupid`、`data_voltage`、`data_current`、`ts`、`inuse`、`location_0_province`、`location_0_city`、`location_0_datun`,也可以选择要解析的字段,并设置解析的别名。
+
+``` json
+{"groupid": 170001, "data": { "voltage": "221V", "current": 12.3 }, "ts": "2023-12-18T22:12:00", "inuse": true, "location": [{"province": "beijing", "city":"chaoyang", "street": "datun"}]}
+```
+
+
+
+##### Regex 正则表达式
+
+可以使用正则表达式的**命名捕获组**从任何字符串(文本)字段中提取多个字段。如图所示,从 nginx 日志中提取访问ip、时间戳、访问的url等字段。
+
+``` re
+(?\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\b)\s-\s-\s\[(?\d{2}/\w{3}/\d{4}:\d{2}:\d{2}:\d{2}\s\+\d{4})\]\s"(?[A-Z]+)\s(?[^\s"]+).*(?\d{3})\s(?\d+)
+```
+
+
+
+##### UDT 自定义解析脚本
+
+自定义 rhai 语法脚本解析输入数据(参考 `https://rhai.rs/book/` ),脚本目前仅支持 json 格式原始数据。
+
+**输入**:脚本中可以使用参数 data, data 是原始数据 json 解析后的 Object Map;
+
+**输出**:输出的数据必须是数组。
+
+例如对于数据,一次上报三相电压值,分别入到三个子表中。则需要对这类数据做解析
+
+``` json
+{
+ "ts": "2024-06-27 18:00:00",
+ "voltage": "220.1,220.3,221.1",
+ "dev_id": "8208891"
+}
+```
+
+那么可以使用如下脚本来提取三个电压数据。
+
+```
+let v3 = data["voltage"].split(",");
+
+[
+#{"ts": data["ts"], "val": v3[0], "dev_id": data["dev_id"]},
+#{"ts": data["ts"], "val": v3[1], "dev_id": data["dev_id"]},
+#{"ts": data["ts"], "val": v3[2], "dev_id": data["dev_id"]}
+]
+```
+
+最终解析结果如下所示:
+
+
+
+### 提取或拆分
+
+解析后的数据,可能还无法满足目标表的数据要求。比如智能表原始采集数据如下( json 格式):
+
+``` json
+{"groupid": 170001, "voltage": "221V", "current": 12.3, "ts": "2023-12-18T22:12:00", "inuse": true, "location": "beijing.chaoyang.datun"}
+{"groupid": 170001, "voltage": "220V", "current": 12.2, "ts": "2023-12-18T22:12:02", "inuse": true, "location": "beijing.chaoyang.datun"}
+{"groupid": 170001, "voltage": "216V", "current": 12.5, "ts": "2023-12-18T22:12:04", "inuse": false, "location": "beijing.chaoyang.datun"}
+```
+
+使用 json 规则解析出的电压是字符串表达的带单位形式,最终入库希望能使用 int 类型记录电压值和电流值,便于统计分析,此时就需要对电压进一步拆分;另外日期期望拆分为日期和时间入库。
+
+如下图所示可以对源字段`ts`使用 split 规则拆分成日期和时间,对字段`voltage`使用 regex 提取出电压值和电压单位。split 规则需要设置**分隔符**和**拆分数量**,拆分后的字段命名规则为`{原字段名}_{顺序号}`,Regex 规则同解析过程中的一样,使用**命名捕获组**命名提取字段。
+
+
+
+### 过滤
+
+过滤功能可以设置过滤条件,满足条件的数据行 才会被写入目标表。过滤条件表达式的结果必须是 boolean 类型。在编写过滤条件前,必须确定 解析字段的类型,根据解析字段的类型,可以使用判断函数、比较操作符(`>`、`>=`、`<=`、`<`、`==`、`!=`)来判断。
+
+#### 字段类型及转换
+
+只有明确解析出的每个字段的类型,才能使用正确的语法做数据过滤。
+
+使用 json 规则解析出的字段,按照属性值来自动设置类型:
+
+1. bool 类型:"inuse": true
+2. int 类型:"voltage": 220
+3. float 类型:"current" : 12.2
+4. String 类型:"location": "MX001"
+
+使用 regex 规则解析的数据都是 string 类型。
+使用 split 和 regex 提取或拆分的数据是 string 类型。
+
+如果提取出的数据类型不是预期中的类型,可以做数据类型转换。常用的数据类型转换就是把字符串转换成为数值类型。支持的转换函数如下:
+
+|Function|From type|To type|e.g.|
+|:----|:----|:----|:----|
+| parse_int | string | int | parse_int("56") // 结果为整数 56 |
+| parse_float | string | float | parse_float("12.3") // 结果为浮点数 12.3 |
+
+#### 判断表达式
+
+不同的数据类型有各自判断表达式的写法。
+
+##### BOOL 类型
+
+可以使用变量或者使用操作符`!`,比如对于字段 "inuse": true,可以编写以下表达式:
+
+> 1. inuse
+> 2. !inuse
+
+##### 数值类型(int/float)
+
+数值类型支持使用比较操作符`==`、`!=`、`>`、`>=`、`<`、`<=`。
+
+##### 字符串类型
+
+使用比较操作符,比较字符串。
+
+字符串函数
+
+|Function|Description|e.g.|
+|:----|:----|:----|
+| is_empty | returns true if the string is empty | s.is_empty() |
+| contains | checks if a certain character or sub-string occurs in the string | s.contains("substring") |
+| starts_with | returns true if the string starts with a certain string | s.starts_with("prefix") |
+| ends_with | returns true if the string ends with a certain string | s.ends_with("suffix") |
+| len | returns the number of characters (not number of bytes) in the string,must be used with comparison operator | s.len == 5 判断字符串长度是否为5;len作为属性返回 int ,和前四个函数有区别,前四个直接返回 bool。 |
+
+##### 复合表达式
+
+多个判断表达式,可以使用逻辑操作符(&&、||、!)来组合。
+比如下面的表达式表示获取北京市安装的并且电压值大于 200 的智能表数据。
+
+> location.starts_with("beijing") && voltage > 200
+
+### 映射
+
+映射是将解析、提取、拆分的**源字段**对应到**目标表字段**,可以直接对应,也可以通过一些规则计算后再映射到目标表。
+
+#### 选择目标超级表
+
+选择目标超级表后,会加载出超级表所有的 tags 和 columns。
+源字段根据名称自动使用 mapping 规则映射到目标超级表的 tag 和 column。
+例如有如下解析、提取、拆分后的预览数据:
+
+#### 映射规则
+
+支持的映射规则如下表所示:
+
+|rule|description|
+|:----|:----|
+| mapping | 直接映射,需要选择映射源字段。|
+| value | 常量,可以输入字符串常量,也可以是数值常量,输入的常量值直接入库。|
+| generator | 生成器,目前仅支持时间戳生成器 now,入库时会将当前时间入库。|
+| join | 字符串连接器,可指定连接字符拼接选择的多个源字段。|
+| format | **字符串格式化工具**,填写格式化字符串,比如有三个源字段 year, month, day 分别表示年月日,入库希望以yyyy-MM-dd的日期格式入库,则可以提供格式化字符串为 `${year}-${month}-${day}`。其中`${}`作为占位符,占位符中可以是一个源字段,也可以是 string 类型字段的函数处理|
+| sum | 选择多个数值型字段做加法计算。|
+| expr | **数值运算表达式**,可以对数值型字段做更加复杂的函数处理和数学运算。|
+
+##### format 中支持的字符串处理函数
+
+|Function|description|e.g.|
+|:----|:----|:----|
+| pad(len, pad_chars) | pads the string with a character or a string to at least a specified length | "1.2".pad(5, '0') // 结果为"1.200" |
+|trim|trims the string of whitespace at the beginning and end|" abc ee ".trim() // 结果为"abc ee"|
+|sub_string(start_pos, len)|extracts a sub-string,两个参数:
1. start position, counting from end if < 0
2. (optional) number of characters to extract, none if ≤ 0, to end if omitted|"012345678".sub_string(5) // "5678"
"012345678".sub_string(5, 2) // "56"
"012345678".sub_string(-2) // "78"|
+|replace(substring, replacement)|replaces a sub-string with another|"012345678".replace("012", "abc") // "abc345678"|
+
+##### expr 数学计算表达式
+
+基本数学运算支持加`+`、减`-`、乘`*`、除`/`。
+
+比如数据源采集数值以设置度为单位,目标库存储华氏度温度值。那么就需要对采集的温度数据做转换。
+
+解析的源字段为`temperature`,则需要使用表达式 `temperature * 1.8 + 32`。
+
+数值表达式中也支持使用数学函数,可用的数学函数如下表所示:
+
+|Function|description|e.g.|
+|:----|:----|:----|
+|sin、cos、tan、sinh、cosh|Trigonometry|a.sin() |
+|asin、acos、atan、 asinh、acosh|arc-trigonometry|a.asin()|
+|sqrt|Square root|a.sqrt() // 4.sqrt() == 2|
+|exp|Exponential|a.exp()|
+|ln、log|Logarithmic|a.ln() // e.ln() == 1
a.log() // 10.log() == 1|
+|floor、ceiling、round、int、fraction|rounding|a.floor() // (4.2).floor() == 4
a.ceiling() // (4.2).ceiling() == 5
a.round() // (4.2).round() == 4
a.int() // (4.2).int() == 4
a.fraction() // (4.2).fraction() == 0.2|
+
+#### 子表名映射
+
+子表名类型为字符串,可以使用映射规则中的字符串格式化 format 表达式定义子表名。
+
+## 任务的创建
+
+下面以 MQTT 数据源为例,介绍如何创建一个 MQTT 类型的任务,从 MQTT Broker 消费数据,并写入 TDengine。
+
+1. 登录至 taosExplorer 以后,点击左侧导航栏上的“数据写入”,即可进入任务列表页面
+2. 在任务列表页面,点击“+ 新增数据源”,即可进入任务创建页面
+3. 输入任务名称后,选择类型为 MQTT, 然后可以创建一个新的代理,或者选择已创建的代理
+4. 输入 MQTT broker 的 IP 地址和端口号,例如:192.168.1.100:1883
+5. 配置认证和 SSL 加密:
+ - 如果 MQTT broker 开启了用户认证,则在认证部分,输入 MQTT broker 的用户名和密码;
+ - 如果 MQTT broker 开启了 SSL 加密,则可以打开页面上的 SSL 证书开关,并上传 CA 的证书,以及客户端的证书和私钥文件;
+6. 在“采集配置“部分,可选择 MQTT 协议的版本,目前支持 3.1, 3.1.1, 5.0 三个版本;配置 Client ID 时要注意,如果对同一个 MQTT broker 创建了多个任务,Client ID 应不同,否则会造成 Client ID 冲突,导致任务无法正常运行;在对主题和 QoS 进行配置时,需要使用 `::` 的形式,即订阅的主题与 QoS 之间要使用两个冒号分隔,其中 QoS 的取值范围为 0, 1, 2, 分别代表 at most once, at lease once, exactly once;配置完成以上信息后,可以点击“检查连通性”按钮,对以上配置进行检查,如果连通性检查失败,请按照页面上返回的具体错误提示进行修改;
+7. 在从 MQTT broker 同步数据的过程中,taosX 还支持对消息体中的字段进行提取,过滤、映射等操作。在位于 “Payload 转换”下方的文本框中,可以直接输入输入消息体样例,或是以上传文件的方式导入,以后还会支持直接从所配置的服务器中检索样例消息;
+8. 对消息体字段的提取,目前支持 2 种方式:JSON 和正则表达式。对于简单的 key/value 格式的 JSON 数据,可以直接点击提取按钮,即可展示解析出的字段名;对于复杂的 JSON 数据,可以使用 JSON Path 提取感兴趣的字段;当使用正则表达式提取字段时,要保证正则表达式的正确性;
+9. 消息体中的字段被解析后,可以基于解析出的字段名设置过滤规则,只有满足过滤规则的数据,才会写入 TDengine,否则会忽略该消息;例如:可以配置过滤规则为 voltage > 200,即只有当电压大于 200V 的数据才会被同步至 TDengine;
+10. 最后,在配置完消息体中的字段和超级表中的字段的映射规则后,就可以提交任务了;除了基本的映射以外,在这里还可以对消息中字段的值进行转换,例如:可以通过表达式 (expr) 将原消息体中的电压和电流,计算为功率后再写入 TDengine;
+11. 任务提交后,会自动返回任务列表页面,如果提交成功,任务的状态会切换至“运行中”,如果提交失败,可通过查看该任务的活动日志,查找错误原因;
+12. 对于运行中的任务,点击指标的查看按钮,可以查看该任务的详细运行指标,弹出窗口划分为 2 个标签页,分别展示该任务多次运行的累计指标和本次运行的指标,这些指标每 2 秒钟会自动刷新一次。
+
+## 任务管理
+
在任务列表页面,还可以对任务进行启动、停止、查看、删除、复制等操作,也可以查看各个任务的运行情况,包括写入的记录条数、流量等。
\ No newline at end of file
diff --git a/docs/zh/07-operation/05-monitor.md b/docs/zh/07-operation/05-monitor.md
index c5b4cbac06..cd8a9772cd 100644
--- a/docs/zh/07-operation/05-monitor.md
+++ b/docs/zh/07-operation/05-monitor.md
@@ -8,57 +8,13 @@ toc_max_heading_level: 4
至于如何获取和使用这些监控数据,用户可以使用第三方的监测工具比如 Zabbix 来获取这些保存的系统监测数据,进而将 TDengine 的运行状况无缝集成到现有的 IT 监控系统中。也可以使用 TDengine 提供的 TDinsight 插件,使用该插件用户可以通过 Grafana 平台直观地展示和管理这些监控信息,如下图所示。这为用户提供了灵活的监控选项,以满足不同场景下的运维需求。
-~[通过监控组件管理监控信息](./grafana.png)
+
## 配置 taosKeeper
因为 TDengine 的监控数据都通过 taosKeeper 上报并存储,所以本节先介绍 taosKeeper 的配置。
-taosKeeper 的配置文件默认位于 `/etc/taos/taoskeeper.toml`。 下面为一个示例配置文件,更多详细信息见参考手册。其中最为关键的一个配置项是 `database`,它决定了收集到的监控数据存储在目标系统的哪个数据库中。
-
-```toml
-# gin 框架是否启用 debug
-debug = false
-
-# 服务监听端口, 默认为 6043
-port = 6043
-
-# 日志级别,包含 panic、error、info、debug、trace等
-loglevel = "info"
-
-# 程序中使用协程池的大小
-gopoolsize = 50000
-
-# 查询 TDengine 监控数据轮询间隔
-RotationInterval = "15s"
-
-[tdengine]
-host = "127.0.0.1"
-port = 6041
-username = "root"
-password = "taosdata"
-
-# 需要被监控的 taosAdapter
-[taosAdapter]
-address = ["127.0.0.1:6041"]
-
-[metrics]
-# 监控指标前缀
-prefix = "taos"
-
-# 集群数据的标识符
-cluster = "production"
-
-# 存放监控数据的数据库
-database = "log"
-
-# 指定需要监控的普通表
-tables = []
-
-# database options for db storing metrics data
-[metrics.databaseoptions]
-cachemodel = "none"
-```
+taosKeeper 的配置文件默认位于 `/etc/taos/taoskeeper.toml`。 详细配置见 [参考手册](../../reference/components/taoskeeper/#配置文件)。其中最为关键的一个配置项是 `database`,它决定了收集到的监控数据存储在目标系统的哪个数据库中。
## 监控 taosd
@@ -66,9 +22,9 @@ cachemodel = "none"
为了简化用户在 TDengine 监控方面的配置工作,TDengine 提供了一个名为 TDinsight 的 Grafana 插件。该插件与 taosKeeper 协同工作,能够实时监控 TDengine 的各项性能指标。
-通过集成 Grafana 和 TDengine 数据源插件,TDinsight 能够读取 taosKeeper 收集并存储的监控数据。这使得用户可以在 Grafana 平台上直观地查看 TDengine 集群的状态、节点信息、读写请求以及资源使用情况等关键指标,实现数据的可视化展示。
+通过集成 Grafana 和 TDengine 数据源插件,TDinsight 能够读取 taosKeeper 收集的监控数据。这使得用户可以在 Grafana 平台上直观地查看 TDengine 集群的状态、节点信息、读写请求以及资源使用情况等关键指标,实现数据的可视化展示。
-此外,TDinsight 还具备针对 vnode、dnode 和 mnode 节点的异常状态告警功能,为开发者提供实时的集群运行状态监控,确保 TDengine 集群的稳定性和可靠性。以下是TDinsight 的详细使用说明,以帮助你充分利用这一强大工具。
+以下是TDinsight 的详细使用说明,以帮助你充分利用这一强大工具。
#### 前置条件
@@ -76,314 +32,31 @@ cachemodel = "none"
- TDengine 已安装并正常运行。
- taosAdapter 已经安装并正常运行。
- taosKeeper 已经安装并正常运行。
-- Grafana 已安装并正常运行,以下介绍以 Grafna 10.4.0 为例。
+- Grafana 已安装并正常运行,以下介绍以 Grafna 11.0.0 为例。
同时记录以下信息。
-- taosAdapter 的 RESTful 接口地址,如 http://www.example.com:6041。
+- taosAdapter 的 RESTful 接口地址,如 `http://www.example.com:6041`。
- TDengine 集群的认证信息,包括用户名及密码。
#### 导入仪表盘
TDengine 数据源插件已被提交至 Grafana 官网,完成插件的安装和数据源的创建后,可以进行 TDinsight 仪表盘的导入。
-在 Grafana 的 Home-Dashboards 页面,点击位于右上角的 New → mport 按钮,即可进入 Dashboard 的导入页面,它支持以下两种导入方式。
+在 Grafana 的 ”Home“ -> ”Dashboards“ 页面,点击位于右上角的 ”New“ -> ”import“ 按钮,即可进入 Dashboard 的导入页面,它支持以下两种导入方式。
- Dashboard ID:18180。
- Dashboard URL:https://grafana.com/grafana/dashboards/18180-tdinsight-for-3-x/
-填写以上 Dashboard ID 或 Dashboard URL 以后,点击 Load 按钮,按照向导操作,即可完成导入。导入成功后,Dashboards 列表页面会出现 TDinsight for 3.x 仪盘,点击进入后,就可以看到 TDinsight 中已创建的各个指标的面板,如下图所示:
+填写以上 Dashboard ID 或 Dashboard URL 以后,点击 ”Load“ 按钮,按照向导操作,即可完成导入。导入成功后,Dashboards 列表页面会出现 ”TDinsight for 3.x“ 仪表盘,点击进入后,就可以看到 TDinsight 中已创建的各个指标的面板,如下图所示:
-
+
-**注意** 在 TDinsight 界面左上角的 Log from 下拉列表中可以选择 log 数据库。
+**注意** 在 TDinsight 界面左上角的 ”Log from“ 下拉列表中可以选择 `log` 数据库。
-### taosd 监控数据
+### TDengine V3 监控数据
-TDinsight dashboard 数据来源于 log 库(存放监控数据的默认 db,可以在 taoskeeper 配置文件中修改。以下是由 taosd 上报由 taosKeeper 存储在 log 库中的数据。
-
-1. taosd\_cluster\_basic 表
-
-`taosd_cluster_basic` 表记录集群基础信息。
-
-|field|type|is\_tag|comment|
-|:----|:---|:-----|:------|
-|ts|TIMESTAMP||timestamp|
-|first\_ep|VARCHAR||集群 first ep|
-|first\_ep\_dnode\_id|INT||集群 first ep 的 dnode id|
-|cluster_version|VARCHAR||tdengine version。例如:3.0.4.0|
-|cluster\_id|VARCHAR|TAG|cluster id|
-
-2. taosd\_cluster\_info 表
-
-`taosd_cluster_info` 表记录集群信息。
-
-|field|type|is\_tag|comment|
-|:----|:---|:-----|:------|
-|ts|TIMESTAMP||timestamp|
-|cluster_uptime|DOUBLE||当前 master 节点的uptime。单位:秒|
-|dbs\_total|DOUBLE||database 总数|
-|tbs\_total|DOUBLE||当前集群 table 总数|
-|stbs\_total|DOUBLE||当前集群 stable 总数|
-|dnodes\_total|DOUBLE||当前集群 dnode 总数|
-|dnodes\_alive|DOUBLE||当前集群 dnode 存活总数|
-|mnodes\_total|DOUBLE||当前集群 mnode 总数|
-|mnodes\_alive|DOUBLE||当前集群 mnode 存活总数|
-|vgroups\_total|DOUBLE||当前集群 vgroup 总数|
-|vgroups\_alive|DOUBLE||当前集群 vgroup 存活总数|
-|vnodes\_total|DOUBLE||当前集群 vnode 总数|
-|vnodes\_alive|DOUBLE||当前集群 vnode 存活总数|
-|connections\_total|DOUBLE||当前集群连接总数|
-|topics\_total|DOUBLE||当前集群 topic 总数|
-|streams\_total|DOUBLE||当前集群 stream 总数|
-|grants_expire\_time|DOUBLE||认证过期时间,企业版有效,社区版为 DOUBLE 最大值|
-|grants_timeseries\_used|DOUBLE||已用测点数|
-|grants_timeseries\_total|DOUBLE||总测点数,开源版本为 DOUBLE 最大值|
-|cluster\_id|VARCHAR|TAG|cluster id|
-
-3. taosd\_vgroups\_info 表
-
-`taosd_vgroups_info` 表记录虚拟节点组信息。
-
-|field|type|is\_tag|comment|
-|:----|:---|:-----|:------|
-|ts|TIMESTAMP||timestamp|
-|tables\_num|DOUBLE||vgroup 中 table 数量|
-|status|DOUBLE||vgroup 状态, 取值范围:unsynced = 0, ready = 1|
-|vgroup\_id|VARCHAR|TAG|vgroup id|
-|database\_name|VARCHAR|TAG|vgroup 所属的 database 名字|
-|cluster\_id|VARCHAR|TAG|cluster id|
-
-4. taosd\_dnodes\_info 表
-
-`taosd_dnodes_info` 记录 dnode 信息。
-
-|field|type|is\_tag|comment|
-|:----|:---|:-----|:------|
-|ts|TIMESTAMP||timestamp|
-|uptime|DOUBLE||dnode uptime,单位:秒|
-|cpu\_engine|DOUBLE||taosd cpu 使用率,从 `/proc//stat` 读取|
-|cpu\_system|DOUBLE||服务器 cpu 使用率,从 `/proc/stat` 读取|
-|cpu\_cores|DOUBLE||服务器 cpu 核数|
-|mem\_engine|DOUBLE||taosd 内存使用率,从 `/proc//status` 读取|
-|mem\_free|DOUBLE||服务器可用内存,单位 KB|
-|mem\_total|DOUBLE||服务器内存总量,单位 KB|
-|disk\_used|DOUBLE||data dir 挂载的磁盘使用量,单位 bytes|
-|disk\_total|DOUBLE||data dir 挂载的磁盘总容量,单位 bytes|
-|system\_net\_in|DOUBLE||网络吞吐率,从 `/proc/net/dev` 中读取的 received bytes。单位 byte/s|
-|system\_net\_out|DOUBLE||网络吞吐率,从 `/proc/net/dev` 中读取的 transmit bytes。单位 byte/s|
-|io\_read|DOUBLE||io 吞吐率,从 `/proc//io` 中读取的 rchar 与上次数值计算之后,计算得到速度。单位 byte/s|
-|io\_write|DOUBLE||io 吞吐率,从 `/proc//io` 中读取的 wchar 与上次数值计算之后,计算得到速度。单位 byte/s|
-|io\_read\_disk|DOUBLE||磁盘 io 吞吐率,从 `/proc//io` 中读取的 read_bytes。单位 byte/s|
-|io\_write\_disk|DOUBLE||磁盘 io 吞吐率,从 `/proc//io` 中读取的 write_bytes。单位 byte/s|
-|vnodes\_num|DOUBLE||dnode 上 vnodes 数量|
-|masters|DOUBLE||dnode 上 master node 数量|
-|has\_mnode|DOUBLE||dnode 是否包含 mnode,取值范围:包含=1,不包含=0|
-|has\_qnode|DOUBLE||dnode 是否包含 qnode,取值范围:包含=1,不包含=0|
-|has\_snode|DOUBLE||dnode 是否包含 snode,取值范围:包含=1,不包含=0|
-|has\_bnode|DOUBLE||dnode 是否包含 bnode,取值范围:包含=1,不包含=0|
-|error\_log\_count|DOUBLE||error 总数|
-|info\_log\_count|DOUBLE||info 总数|
-|debug\_log\_count|DOUBLE||debug 总数|
-|trace\_log\_count|DOUBLE||trace 总数|
-|dnode\_id|VARCHAR|TAG|dnode id|
-|dnode\_ep|VARCHAR|TAG|dnode endpoint|
-|cluster\_id|VARCHAR|TAG|cluster id|
-
-5. taosd\_dnodes\_status 表
-
-`taosd_dnodes_status` 表记录 dnode 状态信息。
-
-|field|type|is\_tag|comment|
-|:----|:---|:-----|:------|
-|ts|TIMESTAMP||timestamp|
-|status|DOUBLE||dnode 状态,取值范围:ready=1,offline =0|
-|dnode\_id|VARCHAR|TAG|dnode id|
-|dnode\_ep|VARCHAR|TAG|dnode endpoint|
-|cluster\_id|VARCHAR|TAG|cluster id|
-
-6. taosd\_dnodes\_log\_dir 表
-
-`taosd_dnodes_log_dir` 表记录 log 目录信息。
-
-|field|type|is\_tag|comment|
-|:----|:---|:-----|:------|
-|ts|TIMESTAMP||timestamp|
-|avail|DOUBLE||log 目录可用空间。单位 byte|
-|used|DOUBLE||log 目录已使用空间。单位 byte|
-|total|DOUBLE||log 目录空间。单位 byte|
-|name|VARCHAR|TAG|log 目录名,一般为 `/var/log/taos/`|
-|dnode\_id|VARCHAR|TAG|dnode id|
-|dnode\_ep|VARCHAR|TAG|dnode endpoint|
-|cluster\_id|VARCHAR|TAG|cluster id|
-
-7. taosd\_dnodes\_data\_dir 表
-
-`taosd_dnodes_data_dir` 表记录 data 目录信息。
-
-|field|type|is\_tag|comment|
-|:----|:---|:-----|:------|
-|ts|TIMESTAMP||timestamp|
-|avail|DOUBLE||data 目录可用空间。单位 byte|
-|used|DOUBLE||data 目录已使用空间。单位 byte|
-|total|DOUBLE||data 目录空间。单位 byte|
-|level|VARCHAR|TAG|0、1、2 多级存储级别|
-|name|VARCHAR|TAG|data 目录,一般为 `/var/lib/taos`|
-|dnode\_id|VARCHAR|TAG|dnode id|
-|dnode\_ep|VARCHAR|TAG|dnode endpoint|
-|cluster\_id|VARCHAR|TAG|cluster id|
-
-8. taosd\_mnodes\_info 表
-
-`taosd_mnodes_info` 表记录 mnode 角色信息。
-
-|field|type|is\_tag|comment|
-|:----|:---|:-----|:------|
-|ts|TIMESTAMP||timestamp|
-|role|DOUBLE||mnode 角色, 取值范围:offline = 0,follower = 100,candidate = 101,leader = 102,error = 103,learner = 104|
-|mnode\_id|VARCHAR|TAG|master node id|
-|mnode\_ep|VARCHAR|TAG|master node endpoint|
-|cluster\_id|VARCHAR|TAG|cluster id|
-
-9. taosd\_vnodes\_role 表
-
-`taosd_vnodes_role` 表记录虚拟节点角色信息。
-
-|field|type|is\_tag|comment|
-|:----|:---|:-----|:------|
-|ts|TIMESTAMP||timestamp|
-|vnode\_role|DOUBLE||vnode 角色,取值范围:offline = 0,follower = 100,candidate = 101,leader = 102,error = 103,learner = 104|
-|vgroup\_id|VARCHAR|TAG|dnode id|
-|dnode\_id|VARCHAR|TAG|dnode id|
-|database\_name|VARCHAR|TAG|vgroup 所属的 database 名字|
-|cluster\_id|VARCHAR|TAG|cluster id|
-
-10. taosd\_sql\_req 表
-
-`taosd_sql_req` 记录授权信息。
-
-|field|type|is\_tag|comment|
-|:----|:---|:-----|:------|
-|ts|TIMESTAMP||timestamp|
-|count|DOUBLE||sql 数量|
-|result|VARCHAR|TAG|sql的执行结果,取值范围:Success, Failed|
-|username|VARCHAR|TAG|执行sql的user name|
-|sql\_type|VARCHAR|TAG|sql类型,取值范围:inserted_rows|
-|dnode\_id|VARCHAR|TAG|dnode id|
-|dnode\_ep|VARCHAR|TAG|dnode endpoint|
-|vgroup\_id|VARCHAR|TAG|dnode id|
-|cluster\_id|VARCHAR|TAG|cluster id|
-
-11. taos\_sql\_req 表
-
-`taos_sql_req` 记录授权信息。
-
-|field|type|is\_tag|comment|
-|:----|:---|:-----|:------|
-|ts|TIMESTAMP||timestamp|
-|count|DOUBLE||sql 数量|
-|result|VARCHAR|TAG|sql的执行结果,取值范围:Success, Failed|
-|username|VARCHAR|TAG|执行sql的user name|
-|sql\_type|VARCHAR|TAG|sql类型,取值范围:select, insert,delete|
-|cluster\_id|VARCHAR|TAG|cluster id|
-
-12. taos\_slow\_sql 表
-
-`taos_slow_sql` 记录授权信息。
-
-|field|type|is\_tag|comment|
-|:----|:---|:-----|:------|
-|ts|TIMESTAMP||timestamp|
-|count|DOUBLE||sql 数量|
-|result|VARCHAR|TAG|sql的执行结果,取值范围:Success, Failed|
-|username|VARCHAR|TAG|执行sql的user name|
-|duration|VARCHAR|TAG|sql执行耗时,取值范围:3-10s,10-100s,100-1000s,1000s-|
-|cluster\_id|VARCHAR|TAG|cluster id|
-
-13. keeper\_monitor 表
-
-`keeper_monitor` 记录 taoskeeper 监控数据。
-
-|field|type|is\_tag|comment|
-|:----|:---|:-----|:------|
-|ts|TIMESTAMP||timestamp|
-|cpu|DOUBLE||cpu 使用率|
-|mem|DOUBLE||内存使用率|
-|identify|NCHAR|TAG||
-
-14. taosadapter\_restful\_http\_request\_total 表
-
-`taosadapter_restful_http_request_total` 记录 taosadapter rest 请求信息,该表为 schemaless 方式创建的表,时间戳字段名为 `_ts`。
-
-|field|type|is\_tag|comment|
-|:----|:---|:-----|:------|
-|\_ts|TIMESTAMP||timestamp|
-|gauge|DOUBLE||监控指标值|
-|client\_ip|NCHAR|TAG|client ip|
-|endpoint|NCHAR|TAG|taosadpater endpoint|
-|request\_method|NCHAR|TAG|request method|
-|request\_uri|NCHAR|TAG|request uri|
-|status\_code|NCHAR|TAG|status code|
-
-15. taosadapter\_restful\_http\_request\_fail 表
-
-`taosadapter_restful_http_request_fail` 记录 taosadapter rest 请求失败信息,该表为 schemaless 方式创建的表,时间戳字段名为 `_ts`。
-
-|field|type|is\_tag|comment|
-|:----|:---|:-----|:------|
-|\_ts|TIMESTAMP||timestamp|
-|gauge|DOUBLE||监控指标值|
-|client\_ip|NCHAR|TAG|client ip|
-|endpoint|NCHAR|TAG|taosadpater endpoint|
-|request\_method|NCHAR|TAG|request method|
-|request\_uri|NCHAR|TAG|request uri|
-|status\_code|NCHAR|TAG|status code|
-
-16. taosadapter\_restful\_http\_request\_in\_flight 表
-
-`taosadapter_restful_http_request_in_flight` 记录 taosadapter rest 实时请求信息,该表为 schemaless 方式创建的表,时间戳字段名为 `_ts`。
-
-|field|type|is\_tag|comment|
-|:----|:---|:-----|:------|
-|\_ts|TIMESTAMP||timestamp|
-|gauge|DOUBLE||监控指标值|
-|endpoint|NCHAR|TAG|taosadpater endpoint|
-
-17. taosadapter\_restful\_http\_request\_summary\_milliseconds 表
-
-`taosadapter_restful_http_request_summary_milliseconds` 记录 taosadapter rest 请求汇总信息,该表为 schemaless 方式创建的表,时间戳字段名为 `_ts`。
-
-|field|type|is\_tag|comment|
-|:----|:---|:-----|:------|
-|\_ts|TIMESTAMP||timestamp|
-|count|DOUBLE|||
-|sum|DOUBLE|||
-|0.5|DOUBLE|||
-|0.9|DOUBLE|||
-|0.99|DOUBLE|||
-|0.1|DOUBLE|||
-|0.2|DOUBLE|||
-|endpoint|NCHAR|TAG|taosadpater endpoint|
-|request\_method|NCHAR|TAG|request method|
-|request\_uri|NCHAR|TAG|request uri|
-
-18. taosadapter\_system\_mem\_percent 表
-
-`taosadapter_system_mem_percent` 表记录 taosadapter 内存使用情况,该表为 schemaless 方式创建的表,时间戳字段名为 `_ts`。
-
-|field|type|is\_tag|comment|
-|:----|:---|:-----|:------|
-|\_ts|TIMESTAMP||timestamp|
-|gauge|DOUBLE||监控指标值|
-|endpoint|NCHAR|TAG|taosadpater endpoint|
-
-19. taosadapter\_system\_cpu\_percent 表
-
-`taosadapter_system_cpu_percent` 表记录 taosadapter cpu 使用情况,该表为 schemaless 方式创建的表,时间戳字段名为 `_ts`。
-
-|field|type|is\_tag|comment|
-|:----|:---|:-----|:------|
-|\_ts|TIMESTAMP||timestamp|
-|gauge|DOUBLE||监控指标值|
-|endpoint|NCHAR|TAG|taosadpater endpoint|
+TDinsight dashboard 数据来源于 `log` 库(存放监控数据的默认数据库,可以在 taoskeeper 配置文件中修改)。”TDinsight for 3.x“ 仪表盘查询了 taosd 和 TaosAdapter 的监控指标。
+- taosd 的监控指标请参考 [taosd 监控指标](../../reference/components/taosd/#taosd-监控指标)
+- taosAdapter 的监控指标请参考 [taosAdapter 监控指标](../../reference/components/taosadapter/#taosadapter-监控指标)
## 监控 taosX
@@ -396,13 +69,13 @@ taosX 是 TDengine 中提供零代码数据接入能力的核心组件,对它
### 版本支持
1. TDengine 企业版本 3.2.3.0 或以上版本包含的 taosX 才包含此功能。如果单独安装 taosX,需要 taosX 1.5.0 或以上版本。
-1. 需要安装 Grafana 插件 [TDengie Datasource v3.5.0](https://grafana.com/grafana/plugins/tdengine-datasource/) 或以上版本。
+2. 需要安装 Grafana 插件 [TDengie Datasource v3.5.0](https://grafana.com/grafana/plugins/tdengine-datasource/) 或以上版本。
### 准备工作
-假设你已经部署好了 taosd,taosAdapter 和 taosAdapter。 那么还需要:
-2. 启动 taosX 服务。
-3. 部署 Grafana ,安装 TDengine Datasource 插件,配置好数据源。
+假设你已经部署好了 taosd,taosAdapter 和 taosAdapter。 那么还需要:
+1. 启动 taosX 服务。
+2. 部署 Grafana ,安装 TDengine Datasource 插件,配置好数据源。
### 配置 taosX
@@ -426,52 +99,50 @@ toasX 的配置文件(默认 /etc/taos/taosx.toml) 中与 monitor 相关的配
| port | --monitor-port | MONITOR_PORT | taosKeeper 服务的端口 | | 6043 |
| interval | --monitor-interval | MONITTOR_INTERVAL | taosX 发送 metrics 数据到 taosKeeper 的时间间隔,单位秒 | 1-10 | 10 |
-TDinsight for taosX
-
-"TDinsight for taosX" 专门为 taosX 监控创建的 Grafana 面板。使用前需要先导入这个面板。
-
### 基于 TDinsight 监控 tasoX
+"TDinsight for taosX" 是专门为 taosX 监控创建的 Grafana 面板。使用前需要先导入这个面板。
+
#### 进入面板
-1. 选择 TDengine Datasource
- 
-2. 点击 “Dashboard”, 选择 TDinsight for taosX 面板。(第一次使用需要先导入)。
- 
+1. 在 Grafana 界面菜单中点击 ”Data sources“, 然后选择已经配置好的 TDengine 数据源。
+2. 在数据源配置界面选择 “Dashboard” Tab, 然后导入 ”TDinsight for taosX“ 面板(第一次使用需要先导入)。 下面是一个示例图:
+

- 该面板每一行代表一个或一类监控对象。最上面是 taosX 监控行,然后是 Agent 监控行, 最后是各类数据写入任务的监控。
- :::note
- 1. 如果打开这个面板后看不到任何数据,你很可能需要点击左上角的数据库列表(即 “Log from” 下拉菜单),切换到监控数据所在的数据库。
- 2. 数据库包含多少个 Agent 的数据就会自动创建多少个 Agent 行。(如上图)
-
- :::
+
+ 该面板每一行代表一个或一类监控对象。最上面是 taosX 监控行,然后是 Agent 监控行, 最后是各类数据写入任务的监控。
+ :::note
+ - 如果打开这个面板后看不到任何数据,你很可能需要点击左上角的数据库列表(即 “Log from” 下拉菜单),切换到监控数据所在的数据库。
+ - 数据库包含多少个 Agent 的数据就会自动创建多少个 Agent 行。(如上图)
+ :::
#### 监控示例
-1. taosX 监控示例
+1. taosX 监控示例图
-
+ 
-2. Agent 监控示例
+2. Agent 监控示例图
-
+ 
-3. TDengine2 数据源监控示例
+3. TDengine2 数据源监控示例图
-
+ 
-:::info
-监控面板只展示了数据写入任务的部分监控指标,在 Explorer 页面上有更全面的监控指标,且有每个指标的具体说明。
+ :::info
+ 监控面板只展示了数据写入任务的部分监控指标,在 Explorer 页面上有更全面的监控指标,且有每个指标的具体说明。
-:::
+ :::
-3. TDengine3 数据源监控示例
-
+4. TDengine3 数据源监控示例图
+
+ 
-4. 其它数据源监控示例
-
+5. 其它数据源监控示例图
+ 
#### 限制
diff --git a/docs/zh/07-operation/TDinsight-1-cluster-status.webp b/docs/zh/07-operation/TDinsight-1-cluster-status.webp
new file mode 100644
index 0000000000..7f7792b2e9
Binary files /dev/null and b/docs/zh/07-operation/TDinsight-1-cluster-status.webp differ
diff --git a/docs/zh/07-operation/tdinsight.png b/docs/zh/07-operation/tdinsight.png
deleted file mode 100644
index 0d90950318..0000000000
Binary files a/docs/zh/07-operation/tdinsight.png and /dev/null differ
diff --git a/docs/zh/08-develop/09-udf.md b/docs/zh/08-develop/09-udf.md
index 45e4ae6134..700bbb2ae0 100644
--- a/docs/zh/08-develop/09-udf.md
+++ b/docs/zh/08-develop/09-udf.md
@@ -6,29 +6,28 @@ toc_max_heading_level: 4
## UDF 简介
-在某些应用场景中,应用逻辑需要的查询功能无法直接使用TDengine内置的函数来实现。TDengine允许编写用户自定义函数(UDF),以便解决特殊应用场景中的使用需求。UDF在集群中注册成功后,可以像系统内置函数一样在SQL中调用,就使用角度而言没有任何区别。UDF分为标量函数和聚合函数。标量函数对每行数据输出一个值,如求绝对值abs、正弦函数sin、字符串拼接函数concat等。聚合函数对多行数据输出一个值,如求平均数avg、取最大值max等。
+在某些应用场景中,应用逻辑需要的查询功能无法直接使用内置函数来实现,TDengine 允许编写用户自定义函数(UDF),以便解决特殊应用场景中的使用需求。UDF 在集群中注册成功后,可以像系统内置函数一样在 SQL 中调用,就使用角度而言没有任何区别。UDF 分为标量函数和聚合函数。标量函数对每行数据输出一个值,如求绝对值(abs)、正弦函数(sin)、字符串拼接函数(concat)等。聚合函数对多行数据输出一个值,如求平均数(avg)、取最大值(max)等。
-TDengine支持用C和Python两种编程语言编写UDF。C语言编写的UDF与内置函数的性能几乎相同,Python语言编写的UDF可以利用丰富的Python运算库。为了避免UDF执行中发生异常影响数据库服务,TDengine使用了进程分离技术,把UDF的执行放到另一个进程中完成,即使用户编写的UDF崩溃,也不会影响TDengine的正常运行。
+TDengine 支持用 C 和 Python 两种编程语言编写 UDF。C 语言编写的 UDF 与内置函数的性能几乎相同,Python 语言编写的 UDF 可以利用丰富的 Python 运算库。为了避免 UDF 执行中发生异常影响数据库服务,TDengine 使用了进程分离技术,把 UDF 的执行放到另一个进程中完成,即使用户编写的 UDF 崩溃,也不会影响 TDengine 的正常运行。
## 用 C 语言开发 UDF
使用 C 语言实现 UDF 时,需要实现规定的接口函数
- 标量函数需要实现标量接口函数 scalarfn 。
-- 聚合函数需要实现聚合接口函数 aggfn_start , aggfn , aggfn_finish。
-- 如果需要初始化,实现 udf_init;如果需要清理工作,实现udf_destroy。
-
-接口函数的名称是 UDF 名称,或者是 UDF 名称和特定后缀(`_start`, `_finish`, `_init`, `_destroy`)的连接。列表中的scalarfn,aggfn, udf需要替换成udf函数名。
+- 聚合函数需要实现聚合接口函数 aggfn_start、aggfn、aggfn_finish。
+- 如果需要初始化,实现 udf_init。
+- 如果需要清理工作,实现 udf_destroy。
### 接口定义
-在TDengine中,UDF的接口函数名称可以是UDF名称,也可以是UDF名称和特定后缀(如_start、_finish、_init、_destroy)的连接。后面内容中描述的函数名称,例如scalarfn、aggfn,需要替换成UDF名称。。
+接口函数的名称是 UDF 名称,或者是 UDF 名称和特定后缀(_start、_finish、_init、_destroy)的连接。后面内容中描述的函数名称,例如 scalarfn、aggfn,需要替换成 UDF 名称。
#### 标量函数接口
标量函数是一种将输入数据转换为输出数据的函数,通常用于对单个数据值进行计算和转换。标量函数的接口函数原型如下。
```c
-int32_t scalarfn(SUdfDataBlock* inputDataBlock, SUdfColumn *resultColumn)
+int32_t scalarfn(SUdfDataBlock* inputDataBlock, SUdfColumn *resultColumn);
```
主要参数说明如下。
- inputDataBlock:输入的数据块。
@@ -37,23 +36,22 @@ int32_t scalarfn(SUdfDataBlock* inputDataBlock, SUdfColumn *resultColumn)
#### 聚合函数接口
聚合函数是一种特殊的函数,用于对数据进行分组和计算,从而生成汇总信息。聚合函数的工作原理如下。
-- 初始化结果缓冲区:首先调用aggfn_start函数,生成一个结果缓冲区(result buffer),用于存储中间结果。
+- 初始化结果缓冲区:首先调用 aggfn_start 函数,生成一个结果缓冲区(result buffer),用于存储中间结果。
- 分组数据:相关数据会被分为多个行数据块(row data block),每个行数据块包含一组具有相同分组键(grouping key)的数据。
-- 更新中间结果:对于每个数据块,调用aggfn函数更新中间结果。aggfn函数会根据聚合函数的类型(如sum、avg、count等)对数据进行相应的计算,并将计算结
+- 更新中间结果:对于每个数据块,调用 aggfn 函数更新中间结果。aggfn 函数会根据聚合函数的类型(如 sum、avg、count 等)对数据进行相应的计算,并将计算结
果存储在结果缓冲区中。
-- 生成最终结果:在所有数据块的中间结果更新完成后,调用aggfn_finish函数从结果缓冲区中提取最终结果。最终结果通常只包含0条或1条数据,具体取决于聚
+- 生成最终结果:在所有数据块的中间结果更新完成后,调用 aggfn_finish 函数从结果缓冲区中提取最终结果。最终结果只包含 0 条或 1 条数据,具体取决于聚
合函数的类型和输入数据。
聚合函数的接口函数原型如下。
```c
-int32_t aggfn_start(SUdfInterBuf *interBuf)
-int32_t aggfn(SUdfDataBlock* inputBlock, SUdfInterBuf *interBuf, SUdfInterBuf *newInterBuf)
-int32_t aggfn_finish(SUdfInterBuf* interBuf, SUdfInterBuf *result)
+int32_t aggfn_start(SUdfInterBuf *interBuf);
+int32_t aggfn(SUdfDataBlock* inputBlock, SUdfInterBuf *interBuf, SUdfInterBuf *newInterBuf);
+int32_t aggfn_finish(SUdfInterBuf* interBuf, SUdfInterBuf *result);
```
-
-其中 aggfn 是函数名的占位符。首先调用aggfn_start生成结果buffer,然后相关的数据会被分为多个行数据块,对每个数据块调用 aggfn 用数据块更新中间结果,最后再调用 aggfn_finish 从中间结果产生最终结果,最终结果只能含 0 或 1 条结果数据。
+其中 aggfn 是函数名的占位符。首先调用 aggfn_start 生成结果 buffer,然后相关的数据会被分为多个行数据块,对每个数据块调用 aggfn 用数据块更新中间结果,最后再调用 aggfn_finish 从中间结果产生最终结果,最终结果只能含 0 或 1 条结果数据。
主要参数说明如下。
- interBuf:中间结果缓存区。
@@ -61,29 +59,49 @@ int32_t aggfn_finish(SUdfInterBuf* interBuf, SUdfInterBuf *result)
- newInterBuf:新的中间结果缓冲区。
- result:最终结果。
-
#### 初始化和销毁接口
-初始化和销毁接口是标量函数和聚合函数共同使用的接口,相关API如下。
+初始化和销毁接口是标量函数和聚合函数共同使用的接口,相关 API 如下。
```c
int32_t udf_init()
int32_t udf_destroy()
```
-其中,udf_init函数完成初始化工作,udf_destroy函数完成清理工作。如果没有初始化工作,无须定义udf_init函数;如果没有清理工作,无须定义udf_destroy函数。
+其中,udf_init 函数完成初始化工作,udf_destroy 函数完成清理工作。如果没有初始化工作,无须定义 udf_init 函数;如果没有清理工作,无须定义 udf_destroy 函数。
### 标量函数模板
-用C语言开发标量函数的模板如下。
+用 C 语言开发标量函数的模板如下。
```c
+#include "taos.h"
+#include "taoserror.h"
+#include "taosudf.h"
+
+// Initialization function.
+// If no initialization, we can skip definition of it.
+// The initialization function shall be concatenation of the udf name and _init suffix.
+// @return error number defined in taoserror.h
int32_t scalarfn_init() {
+ // initialization.
return TSDB_CODE_SUCCESS;
}
+
+// Scalar function main computation function.
+// @param inputDataBlock, input data block composed of multiple columns with each column defined by SUdfColumn
+// @param resultColumn, output column
+// @return error number defined in taoserror.h
int32_t scalarfn(SUdfDataBlock* inputDataBlock, SUdfColumn* resultColumn) {
+ // read data from inputDataBlock and process, then output to resultColumn.
return TSDB_CODE_SUCCESS;
}
+
+// Cleanup function.
+// If no cleanup related processing, we can skip definition of it.
+// The destroy function shall be concatenation of the udf name and _destroy suffix.
+// @return error number defined in taoserror.h
int32_t scalarfn_destroy() {
+ // clean up
return TSDB_CODE_SUCCESS;
}
```
@@ -91,53 +109,211 @@ int32_t scalarfn_destroy() {
用C语言开发聚合函数的模板如下。
```c
+#include "taos.h"
+#include "taoserror.h"
+#include "taosudf.h"
+
+// Initialization function.
+// If no initialization, we can skip definition of it.
+// The initialization function shall be concatenation of the udf name and _init suffix.
+// @return error number defined in taoserror.h
int32_t aggfn_init() {
+ // initialization.
return TSDB_CODE_SUCCESS;
}
+
+// Aggregate start function.
+// The intermediate value or the state(@interBuf) is initialized in this function.
+// The function name shall be concatenation of udf name and _start suffix.
+// @param interbuf intermediate value to initialize
+// @return error number defined in taoserror.h
int32_t aggfn_start(SUdfInterBuf* interBuf) {
+ // initialize intermediate value in interBuf
return TSDB_CODE_SUCCESS;
}
+
+// Aggregate reduce function.
+// This function aggregate old state(@interbuf) and one data bock(inputBlock) and output a new state(@newInterBuf).
+// @param inputBlock input data block
+// @param interBuf old state
+// @param newInterBuf new state
+// @return error number defined in taoserror.h
int32_t aggfn(SUdfDataBlock* inputBlock, SUdfInterBuf *interBuf, SUdfInterBuf *newInterBuf) {
+ // read from inputBlock and interBuf and output to newInterBuf
return TSDB_CODE_SUCCESS;
}
+
+// Aggregate function finish function.
+// This function transforms the intermediate value(@interBuf) into the final output(@result).
+// The function name must be concatenation of aggfn and _finish suffix.
+// @interBuf : intermediate value
+// @result: final result
+// @return error number defined in taoserror.h
int32_t int32_t aggfn_finish(SUdfInterBuf* interBuf, SUdfInterBuf *result) {
+ // read data from inputDataBlock and process, then output to result
return TSDB_CODE_SUCCESS;
}
+
+// Cleanup function.
+// If no cleanup related processing, we can skip definition of it.
+// The destroy function shall be concatenation of the udf name and _destroy suffix.
+// @return error number defined in taoserror.h
int32_t aggfn_destroy() {
+ // clean up
return TSDB_CODE_SUCCESS;
}
```
### 编译
-在TDengine中,为了实现UDF,需要编写C语言源代码,并按照TDengine的规范编译为动态链接库文件。
-按照前面描述的规则,准备UDF的源代码bit_and.c。以Linux操作系统为例,执行如下指令,编译得到动态链接库文件。
+在 TDengine 中,为了实现 UDF,需要编写 C 语言源代码,并按照 TDengine 的规范编译为动态链接库文件。
+按照前面描述的规则,准备 UDF 的源代码 bit_and.c。以 Linux 操作系统为例,执行如下指令,编译得到动态链接库文件。
```shell
-gcc-g-O0-fPIC-sharedbit_and.c-olibbitand.so
+gcc -g -O0 -fPIC -shared bit_and.c -o libbitand.so
```
-为了保证可靠运行,推荐使用7.5及以上版本的GCC。
+为了保证可靠运行,推荐使用 7.5 及以上版本的 GCC。
+
+### C UDF 数据结构
+```c
+typedef struct SUdfColumnMeta {
+ int16_t type;
+ int32_t bytes;
+ uint8_t precision;
+ uint8_t scale;
+} SUdfColumnMeta;
+
+typedef struct SUdfColumnData {
+ int32_t numOfRows;
+ int32_t rowsAlloc;
+ union {
+ struct {
+ int32_t nullBitmapLen;
+ char *nullBitmap;
+ int32_t dataLen;
+ char *data;
+ } fixLenCol;
+
+ struct {
+ int32_t varOffsetsLen;
+ int32_t *varOffsets;
+ int32_t payloadLen;
+ char *payload;
+ int32_t payloadAllocLen;
+ } varLenCol;
+ };
+} SUdfColumnData;
+
+typedef struct SUdfColumn {
+ SUdfColumnMeta colMeta;
+ bool hasNull;
+ SUdfColumnData colData;
+} SUdfColumn;
+
+typedef struct SUdfDataBlock {
+ int32_t numOfRows;
+ int32_t numOfCols;
+ SUdfColumn **udfCols;
+} SUdfDataBlock;
+
+typedef struct SUdfInterBuf {
+ int32_t bufLen;
+ char *buf;
+ int8_t numOfResult; //zero or one
+} SUdfInterBuf;
+```
+数据结构说明如下:
+
+- SUdfDataBlock 数据块包含行数 numOfRows 和列数 numCols。udfCols[i] (0 \<= i \<= numCols-1)表示每一列数据,类型为SUdfColumn*。
+- SUdfColumn 包含列的数据类型定义 colMeta 和列的数据 colData。
+- SUdfColumnMeta 成员定义同 taos.h 数据类型定义。
+- SUdfColumnData 数据可以变长,varLenCol 定义变长数据,fixLenCol 定义定长数据。
+- SUdfInterBuf 定义中间结构 buffer,以及 buffer 中结果个数 numOfResult
+
+为了更好的操作以上数据结构,提供了一些便利函数,定义在 taosudf.h。
+
+
+### C UDF 示例代码
+
+#### 标量函数示例 [bit_and](https://github.com/taosdata/TDengine/blob/3.0/tests/script/sh/bit_and.c)
+
+bit_add 实现多列的按位与功能。如果只有一列,返回这一列。bit_add 忽略空值。
+
+
+bit_and.c
+
+```c
+{{#include tests/script/sh/bit_and.c}}
+```
+
+
+
+#### 聚合函数示例1 返回值为数值类型 [l2norm](https://github.com/taosdata/TDengine/blob/3.0/tests/script/sh/l2norm.c)
+
+l2norm 实现了输入列的所有数据的二阶范数,即对每个数据先平方,再累加求和,最后开方。
+
+
+l2norm.c
+
+```c
+{{#include tests/script/sh/l2norm.c}}
+```
+
+
+
+#### 聚合函数示例2 返回值为字符串类型 [max_vol](https://github.com/taosdata/TDengine/blob/3.0/tests/script/sh/max_vol.c)
+
+max_vol 实现了从多个输入的电压列中找到最大电压,返回由设备 ID + 最大电压所在(行,列)+ 最大电压值 组成的组合字符串值
+
+创建表:
+```bash
+create table battery(ts timestamp, vol1 float, vol2 float, vol3 float, deviceId varchar(16));
+```
+创建自定义函数:
+```bash
+create aggregate function max_vol as '/root/udf/libmaxvol.so' outputtype binary(64) bufsize 10240 language 'C';
+```
+使用自定义函数:
+```bash
+select max_vol(vol1, vol2, vol3, deviceid) from battery;
+```
+
+
+max_vol.c
+
+```c
+{{#include tests/script/sh/max_vol.c}}
+```
+
+
## 用 Python 语言开发 UDF
### 准备环境
准备环境的具体步骤如下:
-- 第1步,准备好Python运行环境。
-- 第2步,安装Python包taospyudf。命令如下。
+- 第1步,准备好 Python 运行环境。
+- 第2步,安装 Python 包 taospyudf。命令如下。
```shell
pip3 install taospyudf
```
-- 第3步,执行命令ldconfig。
-- 第4步,启动taosd服务。
+- 第3步,执行命令 ldconfig。
+- 第4步,启动 taosd 服务。
+
+安装过程中会编译 C++ 源码,因此系统上要有 cmake 和 gcc。编译生成的 libtaospyudf.so 文件自动会被复制到 /usr/local/lib/ 目录,因此如果是非 root 用户,安装时需加 sudo。安装完可以检查这个目录是否有了这个文件:
+
+```shell
+root@slave11 ~/udf $ ls -l /usr/local/lib/libtaos*
+-rw-r--r-- 1 root root 671344 May 24 22:54 /usr/local/lib/libtaospyudf.so
+```
### 接口定义
-当使用Python语言开发UDF时,需要实现规定的接口函数。具体要求如下。
-- 标量函数需要实现标量接口函数process。
-- 聚合函数需要实现聚合接口函数start、reduce、finish。
-- 如果需要初始化,则应实现函数init。
-- 如果需要清理工作,则实现函数destroy。
+当使用 Python 语言开发 UDF 时,需要实现规定的接口函数。具体要求如下。
+- 标量函数需要实现标量接口函数 process。
+- 聚合函数需要实现聚合接口函数 start、reduce、finish。
+- 如果需要初始化,则应实现函数 init。
+- 如果需要清理工作,则实现函数 destroy。
#### 标量函数接口
@@ -147,7 +323,7 @@ def process(input: datablock) -> tuple[output_type]:
```
主要参数说明如下:
-- input:datablock 类似二维矩阵,通过成员方法 data(row,col)返回位于 row 行,col 列的 python 对象
+- input:datablock 类似二维矩阵,通过成员方法 data(row, col) 读取位于 row 行、col 列的 python 对象
- 返回值是一个 Python 对象元组,每个元素类型为输出类型。
#### 聚合函数接口
@@ -159,13 +335,13 @@ def reduce(inputs: datablock, buf: bytes) -> bytes
def finish(buf: bytes) -> output_type:
```
-上述代码定义了3个函数,分别用于实现一个自定义的聚合函数。具体过程如下。
+上述代码定义了 3 个函数,分别用于实现一个自定义的聚合函数。具体过程如下。
-首先,调用start函数生成最初的结果缓冲区。这个结果缓冲区用于存储聚合函数的内部状态,随着输入数据的处理而不断更新。
+首先,调用 start 函数生成最初的结果缓冲区。这个结果缓冲区用于存储聚合函数的内部状态,随着输入数据的处理而不断更新。
-然后,输入数据会被分为多个行数据块。对于每个行数据块,调用reduce函数,并将当前行数据块(inputs)和当前的中间结果(buf)作为参数传递。reduce函数会根据输入数据和当前状态来更新聚合函数的内部状态,并返回新的中间结果
+然后,输入数据会被分为多个行数据块。对于每个行数据块,调用 reduce 函数,并将当前行数据块(inputs)和当前的中间结果(buf)作为参数传递。reduce 函数会根据输入数据和当前状态来更新聚合函数的内部状态,并返回新的中间结果。
-最后,当所有行数据块都处理完毕后,调用finish函数。这个函数接收最终的中间结果(buf)作为参数,并从中生成最终的输出。由于聚合函数的特性,最终输出只能包含0条或1条数据。这个输出结果将作为聚合函数的计算结果返回给调用者。
+最后,当所有行数据块都处理完毕后,调用 finish 函数。这个函数接收最终的中间结果(buf)作为参数,并从中生成最终的输出。由于聚合函数的特性,最终输出只能包含 0 条或 1 条数据。这个输出结果将作为聚合函数的计算结果返回给调用者。
#### 初始化和销毁接口
@@ -179,7 +355,7 @@ def destroy()
- init 完成初始化工作
- destroy 完成清理工作
-**注意** 用Python开发UDF时必须定义init函数和destroy函数
+**注意** 用 Python 开发 UDF 时必须定义 init 函数和 destroy 函数
### 标量函数模板
@@ -204,7 +380,7 @@ def start() -> bytes:
def reduce(inputs: datablock, buf: bytes) -> bytes
# deserialize buf to state
# reduce the inputs and state into new_state.
- # use inputs.data(i,j) to access python object of location(i,j)
+ # use inputs.data(i, j) to access python object of location(i, j)
# serialize new_state into new_state_bytes
return new_state_bytes
def finish(buf: bytes) -> output_type:
@@ -217,13 +393,13 @@ def finish(buf: bytes) -> output_type:
| **TDengine SQL数据类型** | **Python数据类型** |
| :-----------------------: | ------------ |
-|TINYINT / SMALLINT / INT / BIGINT | int |
-|TINYINT UNSIGNED / SMALLINT UNSIGNED / INT UNSIGNED / BIGINT UNSIGNED | int |
-|FLOAT / DOUBLE | float |
-|BOOL | bool |
-|BINARY / VARCHAR / NCHAR | bytes|
-|TIMESTAMP | int |
-|JSON and other types | 不支持 |
+| TINYINT / SMALLINT / INT / BIGINT | int |
+| TINYINT UNSIGNED / SMALLINT UNSIGNED / INT UNSIGNED / BIGINT UNSIGNED | int |
+| FLOAT / DOUBLE | float |
+| BOOL | bool |
+| BINARY / VARCHAR / NCHAR | bytes|
+| TIMESTAMP | int |
+| JSON and other types | 不支持 |
### 开发示例
@@ -262,7 +438,7 @@ create function myfun as '/root/udf/myfun.py' outputtype double language 'Python
其输出如下
```shell
- taos> create function myfun as '/root/udf/myfun.py' outputtype double language 'Python';
+taos> create function myfun as '/root/udf/myfun.py' outputtype double language 'Python';
Create OK, 0 row(s) affected (0.005202s)
```
@@ -460,7 +636,7 @@ def process(block):
for i in range(rows)]
```
-UDF 框架会将 TDengine 的 timestamp 类型映射为 Python 的 int 类型,所以这个函数只接受一个表示毫秒数的整数。process 方法先做参数检查,然后用 moment 包替换时间的星期为星期日,最后格式化输出。输出的字符串长度是固定的10个字符长,因此可以这样创建 UDF 函数:
+UDF 框架会将 TDengine 的 timestamp 类型映射为 Python 的 int 类型,所以这个函数只接受一个表示毫秒数的整数。process 方法先做参数检查,然后用 moment 包替换时间的星期为星期日,最后格式化输出。输出的字符串长度是固定的 10 个字符长,因此可以这样创建 UDF 函数:
```sql
create function nextsunday as '/root/udf/nextsunday.py' outputtype binary(10) language 'Python';
@@ -627,39 +803,77 @@ close log file: spread.log
通过这个示例,我们学会了如何定义聚合函数,并打印自定义的日志信息。
+### 更多 Python UDF 示例代码
+#### 标量函数示例 [pybitand](https://github.com/taosdata/TDengine/blob/3.0/tests/script/sh/pybitand.py)
+
+pybitand 实现多列的按位与功能。如果只有一列,返回这一列。pybitand 忽略空值。
+
+
+pybitand.py
+
+```Python
+{{#include tests/script/sh/pybitand.py}}
+```
+
+
+
+#### 聚合函数示例 [pyl2norm](https://github.com/taosdata/TDengine/blob/3.0/tests/script/sh/pyl2norm.py)
+
+pyl2norm 实现了输入列的所有数据的二阶范数,即对每个数据先平方,再累加求和,最后开方。
+
+
+pyl2norm.py
+
+```c
+{{#include tests/script/sh/pyl2norm.py}}
+```
+
+
+
+#### 聚合函数示例 [pycumsum](https://github.com/taosdata/TDengine/blob/3.0/tests/script/sh/pycumsum.py)
+
+pycumsum 使用 numpy 计算输入列所有数据的累积和。
+
+pycumsum.py
+
+```c
+{{#include tests/script/sh/pycumsum.py}}
+```
+
+
+
## 管理 UDF
-在集群中管理UDF的过程涉及创建、使用和维护这些函数。用户可以通过SQL在集群中创建和管理UDF,一旦创建成功,集群的所有用户都可以在SQL中使用这些函数。由于UDF存储在集群的mnode上,因此即使重启集群,已经创建的UDF也仍然可用。
+在集群中管理 UDF 的过程涉及创建、使用和维护这些函数。用户可以通过 SQL 在集群中创建和管理 UDF,一旦创建成功,集群的所有用户都可以在 SQL 中使用这些函数。由于 UDF 存储在集群的 mnode 上,因此即使重启集群,已经创建的 UDF 也仍然可用。
-在创建UDF时,需要区分标量函数和聚合函数。标量函数接受零个或多个输入参数,并返回一个单一的值。聚合函数接受一组输入值,并通过对这些值进行某种计算(如求和、计数等)来返回一个单一的值。如果创建时声明了错误的函数类别,则通过SQL调用函数时会报错。
+在创建 UDF 时,需要区分标量函数和聚合函数。标量函数接受零个或多个输入参数,并返回一个单一的值。聚合函数接受一组输入值,并通过对这些值进行某种计算(如求和、计数等)来返回一个单一的值。如果创建时声明了错误的函数类别,则通过 SQL 调用函数时会报错。
-此外,用户需要确保输入数据类型与UDF程序匹配,UDF输出的数据类型与outputtype匹配。这意味着在创建UDF时,需要为输入参数和输出值指定正确的数据类型。这有助于确保在调用UDF时,输入数据能够正确地传递给UDF,并且UDF的输出值与预期的数据类型相匹配。
+此外,用户需要确保输入数据类型与 UDF 程序匹配,UDF 输出的数据类型与 outputtype 匹配。这意味着在创建 UDF 时,需要为输入参数和输出值指定正确的数据类型。这有助于确保在调用 UDF 时,输入数据能够正确地传递给 UDF,并且 UDF 的输出值与预期的数据类型相匹配。
### 创建标量函数
-创建标量函数的SQL语法如下。
+创建标量函数的 SQL 语法如下。
```sql
-CREATE FUNCTION function_name AS library_path OUTPUTTYPE output_type LANGUAGE 'Python';
+CREATE OR REPLACE FUNCTION function_name AS library_path OUTPUTTYPE output_type LANGUAGE 'Python';
```
各参数说明如下。
- or replace:如果函数已经存在,则会修改已有的函数属性。
- function_name:标量函数在SQL中被调用时的函数名。
-- language:支持C语言和Python语言(3.7及以上版本),默认为C。
-- library_path:如果编程语言是C,则路径是包含UDF实现的动态链接库的库文件绝对路径,通常指向一个so文件。如果编程语言是Python,则路径是包含UDF
-实现的Python文件路径。路径需要用英文单引号或英文双引号括起来。
+- language:支持 C 语言和 Python 语言(3.7 及以上版本),默认为 C。
+- library_path:如果编程语言是 C,则路径是包含 UDF 实现的动态链接库的库文件绝对路径,通常指向一个 so 文件。如果编程语言是 Python,则路径是包含 UDF
+实现的 Python 文件路径。路径需要用英文单引号或英文双引号括起来。
- output_type:函数计算结果的数据类型名称。
-
### 创建聚合函数
-创建聚合函数的SQL语法如下。
+创建聚合函数的 SQL 语法如下。
```sql
-CREATE AGGREGATE FUNCTION function_name library_path OUTPUTTYPE output_type LANGUAGE 'Python';
+CREATE OR REPLACE AGGREGATE FUNCTION function_name library_path OUTPUTTYPE output_type LANGUAGE 'Python';
```
其中,buffer_size 表示中间计算结果的缓冲区大小,单位是字节。其他参数的含义与标量函数相同。
-如下SQL创建一个名为 l2norm 的UDF。
+如下 SQL 创建一个名为 l2norm 的 UDF。
```sql
CREATE AGGREGATE FUNCTION l2norm AS "/home/taos/udf_example/libl2norm.so" OUTPUTTYPE DOUBLE bufsize 8;
```
@@ -673,8 +887,15 @@ DROP FUNCTION function_name;
### 查看 UDF
-显示集群中当前可用的所有UDF的SQL如下。
+显示集群中当前可用的所有 UDF 的 SQL 如下。
```sql
show functions;
```
+### 查看函数信息
+
+同名的 UDF 每更新一次,版本号会增加 1。
+```sql
+select * from ins_functions \G;
+```
+
diff --git a/docs/zh/14-reference/01-components/01-taosd.md b/docs/zh/14-reference/01-components/01-taosd.md
index 0e9c4eb926..02cf2155a0 100644
--- a/docs/zh/14-reference/01-components/01-taosd.md
+++ b/docs/zh/14-reference/01-components/01-taosd.md
@@ -27,42 +27,42 @@ taosd 命令行参数如下
### 连接相关
-| 参数名称 | 参数说明 |
-|:-------------:|:----------------------------------------------------------------:|
-|firstEp | taosd 启动时,主动连接的集群中首个 dnode 的 end point,缺省值:localhost:6030 |
-|secondEp | taosd 启动时,如果 firstEp 连接不上,尝试连接集群中第二个 dnode 的 endpoint,缺省值:无|
-|fqdn | 启动 taosd 后所监听的服务地址,缺省值:所在服务器上配置的第一个 hostname |
-|serverPort | 启动 taosd 后所监听的端口,缺省值:6030 |
-|maxShellConns | 一个 dnode 容许的连接数,取值范围为 10-5000000,缺省值:5000 |
-|numOfRpcSessions | 允许一个客户端能创建的最大连接数,取值范围 100-100000,缺省值:30000 |
-|timeToGetAvailableConn | 获得可用连接的最长等待时间,取值范围 10-50000000,单位为毫秒,缺省值:500000 |
+| 参数名称 | 参数说明 |
+| :--------------------: | :-------------------------------------------------------------------------------------: |
+| firstEp | taosd 启动时,主动连接的集群中首个 dnode 的 end point,缺省值:localhost:6030 |
+| secondEp | taosd 启动时,如果 firstEp 连接不上,尝试连接集群中第二个 dnode 的 endpoint,缺省值:无 |
+| fqdn | 启动 taosd 后所监听的服务地址,缺省值:所在服务器上配置的第一个 hostname |
+| serverPort | 启动 taosd 后所监听的端口,缺省值:6030 |
+| maxShellConns | 一个 dnode 容许的连接数,取值范围为 10-5000000,缺省值:5000 |
+| numOfRpcSessions | 允许一个客户端能创建的最大连接数,取值范围 100-100000,缺省值:30000 |
+| timeToGetAvailableConn | 获得可用连接的最长等待时间,取值范围 10-50000000,单位为毫秒,缺省值:500000 |
### 监控相关
-| 参数名称 | 参数说明 |
-|:-------------:|:----------------------------------------------------------------:|
-|monitor | 是否收集监控数据并上报,0: 关闭;1:打开;缺省值:0 |
-|monitorFqdn | taosKeeper 服务所在服务器的 FQDN,缺省值:无 |
-|monitorPort | taosKeeper 服务所监听的端口号,缺省值:6043 |
-|monitorInternal | 监控数据库记录系统参数(CPU/内存)的时间间隔,单位是秒,取值范围 1-200000 ,缺省值:30|
-|telemetryReporting | 是否上传 telemetry,0: 不上传,1:上传,缺省值:1 |
-|crashReporting | 是否上传 crash 信息;0: 不上传,1: 上传;缺省值: 1|
+| 参数名称 | 参数说明 |
+| :----------------: | :------------------------------------------------------------------------------------: |
+| monitor | 是否收集监控数据并上报,0: 关闭;1:打开;缺省值:0 |
+| monitorFqdn | taosKeeper 服务所在服务器的 FQDN,缺省值:无 |
+| monitorPort | taosKeeper 服务所监听的端口号,缺省值:6043 |
+| monitorInternal | 监控数据库记录系统参数(CPU/内存)的时间间隔,单位是秒,取值范围 1-200000 ,缺省值:30 |
+| telemetryReporting | 是否上传 telemetry,0: 不上传,1:上传,缺省值:1 |
+| crashReporting | 是否上传 crash 信息;0: 不上传,1: 上传;缺省值: 1 |
### 查询相关
-| 参数名称 | 参数说明 |
-|:-------------:|:----------------------------------------------------------------:|
-|queryPolicy | 查询策略,1: 只使用 vnode,不使用 qnode; 2: 没有扫描算子的子任务在 qnode 执行,带扫描算子的子任务在 vnode 执行; 3: vnode 只运行扫描算子,其余算子均在 qnode 执行 ;缺省值:1 |
-|maxNumOfDistinctRes | 允许返回的 distinct 结果最大行数,默认值 10 万,最大允许值 1 亿 |
-|countAlwaysReturnValue | ount/hyperloglog函数在输入数据为空或者NULL的情况下是否返回值,0: 返回空行,1: 返回;该参数设置为 1 时,如果查询中含有 INTERVAL 子句或者该查询使用了TSMA时, 且相应的组或窗口内数据为空或者NULL, 对应的组或窗口将不返回查询结果. 注意此参数客户端和服务端值应保持一致.|
+| 参数名称 | 参数说明 |
+| :--------------------: | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
+| queryPolicy | 查询策略,1: 只使用 vnode,不使用 qnode; 2: 没有扫描算子的子任务在 qnode 执行,带扫描算子的子任务在 vnode 执行; 3: vnode 只运行扫描算子,其余算子均在 qnode 执行 ;缺省值:1 |
+| maxNumOfDistinctRes | 允许返回的 distinct 结果最大行数,默认值 10 万,最大允许值 1 亿 |
+| countAlwaysReturnValue | ount/hyperloglog函数在输入数据为空或者NULL的情况下是否返回值,0: 返回空行,1: 返回;该参数设置为 1 时,如果查询中含有 INTERVAL 子句或者该查询使用了TSMA时, 且相应的组或窗口内数据为空或者NULL, 对应的组或窗口将不返回查询结果. 注意此参数客户端和服务端值应保持一致. |
### 区域相关
-| 参数名称 | 参数说明 |
-|:-------------:|:----------------------------------------------------------------:|
-|timezone | 时区,缺省值:当前服务器所配置的时区 |
-|locale | 系统区位信息及编码格式 ,缺省值:系统中动态获取,如果自动获取失败,需要用户在配置文件设置或通过 API 设置 |
-|charset | 字符集编码,缺省值:系统自动获取 |
+| 参数名称 | 参数说明 |
+| :------: | :------------------------------------------------------------------------------------------------------: |
+| timezone | 时区,缺省值:当前服务器所配置的时区 |
+| locale | 系统区位信息及编码格式 ,缺省值:系统中动态获取,如果自动获取失败,需要用户在配置文件设置或通过 API 设置 |
+| charset | 字符集编码,缺省值:系统自动获取 |
:::info
1. 为应对多时区的数据写入和查询问题,TDengine 采用 Unix 时间戳(Unix Timestamp)来记录和存储时间戳。Unix 时间戳的特点决定了任一时刻不论在任何时区,产生的时间戳均一致。需要注意的是,Unix 时间戳是在客户端完成转换和记录。为了确保客户端其他形式的时间转换为正确的 Unix 时间戳,需要设置正确的时区。
@@ -141,64 +141,64 @@ charset 的有效值是 UTF-8。
### 存储相关
-| 参数名称 | 参数说明 |
-|:-------------:|:----------------------------------------------------------------:|
-|dataDir | 数据文件目录,所有的数据文件都将写入该目录,缺省值:/var/lib |
-|tempDir | 指定所有系统运行过程中的临时文件生成的目录,缺省值:/tmp |
-|minimalTmpDirGB | tempDir 所指定的临时文件目录所需要保留的最小空间,单位 GB,缺省值: 1|
-|minimalDataDirGB | dataDir 指定的时序数据存储目录所需要保留的最小空间,单位 GB,缺省值: 2 |
+| 参数名称 | 参数说明 |
+| :--------------: | :--------------------------------------------------------------------: |
+| dataDir | 数据文件目录,所有的数据文件都将写入该目录,缺省值:/var/lib |
+| tempDir | 指定所有系统运行过程中的临时文件生成的目录,缺省值:/tmp |
+| minimalTmpDirGB | tempDir 所指定的临时文件目录所需要保留的最小空间,单位 GB,缺省值: 1 |
+| minimalDataDirGB | dataDir 指定的时序数据存储目录所需要保留的最小空间,单位 GB,缺省值: 2 |
### 集群相关
-| 参数名称 | 参数说明 |
-|:-------------:|:----------------------------------------------------------------:|
-|supportVnodes | dnode 支持的最大 vnode 数目,取值范围:0-4096,缺省值: CPU 核数的 2 倍 + 5 |
+| 参数名称 | 参数说明 |
+| :-----------: | :-------------------------------------------------------------------------: |
+| supportVnodes | dnode 支持的最大 vnode 数目,取值范围:0-4096,缺省值: CPU 核数的 2 倍 + 5 |
### 性能调优
-| 参数名称 | 参数说明 |
-|:-------------:|:----------------------------------------------------------------:|
-|numOfCommitThreads | 写入线程的最大数量,取值范围 0-1024,缺省值为 4 |
+| 参数名称 | 参数说明 |
+| :----------------: | :---------------------------------------------: |
+| numOfCommitThreads | 写入线程的最大数量,取值范围 0-1024,缺省值为 4 |
### 日志相关
-| 参数名称 | 参数说明 |
-|:-------------:|:----------------------------------------------------------------:|
-|logDir | 日志文件目录,运行日志将写入该目录,缺省值:/var/log/taos |
-|minimalLogDirGB | 当日志文件夹所在磁盘可用空间大小小于该值时,停止写日志,单位GB,缺省值:1|
-|numOfLogLines | 单个日志文件允许的最大行数,缺省值:10,000,000 |
-|asyncLog | 日志写入模式,0: 同步,1: 异步,缺省值: 1 |
-|logKeepDays | 日志文件的最长保存时间 ,单位:天,缺省值:0,意味着无限保存;当设置为大于0 的值时,日志文件会被重命名为 taosdlog.xxx,其中 xxx 为日志文件最后修改的时间戳。 |
-|slowLogThreshold | 慢查询门限值,大于等于门限值认为是慢查询,单位秒,默认值: 3 |
-|slowLogScope | 定启动记录哪些类型的慢查询,可选值:ALL, QUERY, INSERT, OHTERS, NONE; 默认值:ALL |
-|debugFlag | 运行日志开关,131(输出错误和警告日志),135(输出错误、警告和调试日志),143(输出错误、警告、调试和跟踪日志); 默认值:131 或 135 (取决于不同模块)|
-|tmrDebugFlag | 定时器模块的日志开关,取值范围同上 |
-|uDebugFlag | 共用功能模块的日志开关,取值范围同上 |
-|rpcDebugFlag | rpc 模块的日志开关,取值范围同上 |
-|jniDebugFlag | jni 模块的日志开关,取值范围同上 |
-|qDebugFlag | query 模块的日志开关,取值范围同上 |
-|dDebugFlag | dnode 模块的日志开关,取值范围同上,缺省值 135 |
-|vDebugFlag | vnode 模块的日志开关,取值范围同上 |
-|mDebugFlag | mnode 模块的日志开关,取值范围同上 |
-|wDebugFlag | wal 模块的日志开关,取值范围同上 |
-|sDebugFlag | sync 模块的日志开关,取值范围同上 |
-|tsdbDebugFlag | tsdb 模块的日志开关,取值范围同上 |
-|tqDebugFlag | tq 模块的日志开关,取值范围同上 |
-|fsDebugFlag | fs 模块的日志开关,取值范围同上 |
-|udfDebugFlag | udf 模块的日志开关,取值范围同上 |
-|smaDebugFlag | sma 模块的日志开关,取值范围同上 |
-|idxDebugFlag | index 模块的日志开关,取值范围同上 |
-|tdbDebugFlag | tdb 模块的日志开关,取值范围同上 |
+| 参数名称 | 参数说明 |
+| :--------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------: |
+| logDir | 日志文件目录,运行日志将写入该目录,缺省值:/var/log/taos |
+| minimalLogDirGB | 当日志文件夹所在磁盘可用空间大小小于该值时,停止写日志,单位GB,缺省值:1 |
+| numOfLogLines | 单个日志文件允许的最大行数,缺省值:10,000,000 |
+| asyncLog | 日志写入模式,0: 同步,1: 异步,缺省值: 1 |
+| logKeepDays | 日志文件的最长保存时间 ,单位:天,缺省值:0,意味着无限保存;当设置为大于0 的值时,日志文件会被重命名为 taosdlog.xxx,其中 xxx 为日志文件最后修改的时间戳。 |
+| slowLogThreshold | 慢查询门限值,大于等于门限值认为是慢查询,单位秒,默认值: 3 |
+| slowLogScope | 定启动记录哪些类型的慢查询,可选值:ALL, QUERY, INSERT, OHTERS, NONE; 默认值:ALL |
+| debugFlag | 运行日志开关,131(输出错误和警告日志),135(输出错误、警告和调试日志),143(输出错误、警告、调试和跟踪日志); 默认值:131 或 135 (取决于不同模块) |
+| tmrDebugFlag | 定时器模块的日志开关,取值范围同上 |
+| uDebugFlag | 共用功能模块的日志开关,取值范围同上 |
+| rpcDebugFlag | rpc 模块的日志开关,取值范围同上 |
+| jniDebugFlag | jni 模块的日志开关,取值范围同上 |
+| qDebugFlag | query 模块的日志开关,取值范围同上 |
+| dDebugFlag | dnode 模块的日志开关,取值范围同上,缺省值 135 |
+| vDebugFlag | vnode 模块的日志开关,取值范围同上 |
+| mDebugFlag | mnode 模块的日志开关,取值范围同上 |
+| wDebugFlag | wal 模块的日志开关,取值范围同上 |
+| sDebugFlag | sync 模块的日志开关,取值范围同上 |
+| tsdbDebugFlag | tsdb 模块的日志开关,取值范围同上 |
+| tqDebugFlag | tq 模块的日志开关,取值范围同上 |
+| fsDebugFlag | fs 模块的日志开关,取值范围同上 |
+| udfDebugFlag | udf 模块的日志开关,取值范围同上 |
+| smaDebugFlag | sma 模块的日志开关,取值范围同上 |
+| idxDebugFlag | index 模块的日志开关,取值范围同上 |
+| tdbDebugFlag | tdb 模块的日志开关,取值范围同上 |
### 压缩参数
-| 参数名称 | 参数说明 |
-|:-------------:|:----------------------------------------------------------------:|
-| compressMsgSize | 是否对 RPC 消息进行压缩;-1: 所有消息都不压缩; 0: 所有消息都压缩; N (N>0): 只有大于 N 个字节的消息才压缩;缺省值 -1 |
-| fPrecision | 设置 float 类型浮点数压缩精度 ,取值范围:0.1 ~ 0.00000001 ,默认值 0.00000001 , 小于此值的浮点数尾数部分将被截断 |
-|dPrecision | 设置 double 类型浮点数压缩精度 , 取值范围:0.1 ~ 0.0000000000000001 , 缺省值 0.0000000000000001 , 小于此值的浮点数尾数部分将被截取 |
-|lossyColumn | 对 float 和/或 double 类型启用 TSZ 有损压缩;取值范围: float, double, none;缺省值: none,表示关闭无损压缩 |
-|ifAdtFse | 在启用 TSZ 有损压缩时,使用 FSE 算法替换 HUFFMAN 算法, FSE 算法压缩速度更快,但解压稍慢,追求压缩速度可选用此算法; 0: 关闭,1:打开;默认值为 0 |
+| 参数名称 | 参数说明 |
+| :-------------: | :----------------------------------------------------------------------------------------------------------------------------------------------: |
+| compressMsgSize | 是否对 RPC 消息进行压缩;-1: 所有消息都不压缩; 0: 所有消息都压缩; N (N>0): 只有大于 N 个字节的消息才压缩;缺省值 -1 |
+| fPrecision | 设置 float 类型浮点数压缩精度 ,取值范围:0.1 ~ 0.00000001 ,默认值 0.00000001 , 小于此值的浮点数尾数部分将被截断 |
+| dPrecision | 设置 double 类型浮点数压缩精度 , 取值范围:0.1 ~ 0.0000000000000001 , 缺省值 0.0000000000000001 , 小于此值的浮点数尾数部分将被截取 |
+| lossyColumn | 对 float 和/或 double 类型启用 TSZ 有损压缩;取值范围: float, double, none;缺省值: none,表示关闭无损压缩 |
+| ifAdtFse | 在启用 TSZ 有损压缩时,使用 FSE 算法替换 HUFFMAN 算法, FSE 算法压缩速度更快,但解压稍慢,追求压缩速度可选用此算法; 0: 关闭,1:打开;默认值为 0 |
**补充说明**
@@ -216,10 +216,214 @@ lossyColumns float|double
### 其他参数
-| 参数名称 | 参数说明 |
-|:-------------:|:----------------------------------------------------------------:|
-|enableCoreFile | crash 时是否生成 core 文件;0: 不生成,1:生成;默认值 为 1; 不同的启动方式,生成 core 文件的目录如下:1、systemctl start taosd 启动:生成的 core 在根目录下
2、手动启动,就在 taosd 执行目录下。|
-|udf | 是否启动 UDF 服务;0: 不启动,1:启动;默认值 为 0 |
-|ttlChangeOnWrite | ttl 到期时间是否伴随表的修改操作改变; 0: 不改变,1:改变 ;默认值 为 |
-| tmqMaxTopicNum| 订阅最多可建立的 topic 数量; 取值范围 1-10000;缺省值 为20 |
-|maxTsmaNum | 集群内可创建的TSMA个数;取值范围:0-3;缺省值: 3|
\ No newline at end of file
+| 参数名称 | 参数说明 |
+| :--------------: | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
+| enableCoreFile | crash 时是否生成 core 文件;0: 不生成,1:生成;默认值 为 1; 不同的启动方式,生成 core 文件的目录如下:1、systemctl start taosd 启动:生成的 core 在根目录下
2、手动启动,就在 taosd 执行目录下。 |
+| udf | 是否启动 UDF 服务;0: 不启动,1:启动;默认值 为 0 |
+| ttlChangeOnWrite | ttl 到期时间是否伴随表的修改操作改变; 0: 不改变,1:改变 ;默认值 为 |
+| tmqMaxTopicNum | 订阅最多可建立的 topic 数量; 取值范围 1-10000;缺省值 为20 |
+| maxTsmaNum | 集群内可创建的TSMA个数;取值范围:0-3;缺省值: 3 |
+
+
+## taosd 监控指标
+
+taosd 会将监控指标上报给 taosKeeper,这些监控指标会被 taosKeeper 写入监控数据库,默认是 `log` 库,可以在 taoskeeper 配置文件中修改。以下是这些监控指标的详细介绍。
+
+### taosd\_cluster\_basic 表
+
+`taosd_cluster_basic` 表记录集群基础信息。
+
+| field | type | is\_tag | comment |
+| :------------------- | :-------- | :------ | :------------------------------ |
+| ts | TIMESTAMP | | timestamp |
+| first\_ep | VARCHAR | | 集群 first ep |
+| first\_ep\_dnode\_id | INT | | 集群 first ep 的 dnode id |
+| cluster_version | VARCHAR | | tdengine version。例如:3.0.4.0 |
+| cluster\_id | VARCHAR | TAG | cluster id |
+
+### taosd\_cluster\_info 表
+
+`taosd_cluster_info` 表记录集群信息。
+
+| field | type | is\_tag | comment |
+| :----------------------- | :-------- | :------ | :----------------------------------------------- |
+| \_ts | TIMESTAMP | | timestamp |
+| cluster_uptime | DOUBLE | | 当前 master 节点的uptime。单位:秒 |
+| dbs\_total | DOUBLE | | database 总数 |
+| tbs\_total | DOUBLE | | 当前集群 table 总数 |
+| stbs\_total | DOUBLE | | 当前集群 stable 总数 |
+| dnodes\_total | DOUBLE | | 当前集群 dnode 总数 |
+| dnodes\_alive | DOUBLE | | 当前集群 dnode 存活总数 |
+| mnodes\_total | DOUBLE | | 当前集群 mnode 总数 |
+| mnodes\_alive | DOUBLE | | 当前集群 mnode 存活总数 |
+| vgroups\_total | DOUBLE | | 当前集群 vgroup 总数 |
+| vgroups\_alive | DOUBLE | | 当前集群 vgroup 存活总数 |
+| vnodes\_total | DOUBLE | | 当前集群 vnode 总数 |
+| vnodes\_alive | DOUBLE | | 当前集群 vnode 存活总数 |
+| connections\_total | DOUBLE | | 当前集群连接总数 |
+| topics\_total | DOUBLE | | 当前集群 topic 总数 |
+| streams\_total | DOUBLE | | 当前集群 stream 总数 |
+| grants_expire\_time | DOUBLE | | 认证过期时间,企业版有效,社区版为 DOUBLE 最大值 |
+| grants_timeseries\_used | DOUBLE | | 已用测点数 |
+| grants_timeseries\_total | DOUBLE | | 总测点数,开源版本为 DOUBLE 最大值 |
+| cluster\_id | VARCHAR | TAG | cluster id |
+
+### taosd\_vgroups\_info 表
+
+`taosd_vgroups_info` 表记录虚拟节点组信息。
+
+| field | type | is\_tag | comment |
+| :------------- | :-------- | :------ | :--------------------------------------------- |
+| \_ts | TIMESTAMP | | timestamp |
+| tables\_num | DOUBLE | | vgroup 中 table 数量 |
+| status | DOUBLE | | vgroup 状态, 取值范围:unsynced = 0, ready = 1 |
+| vgroup\_id | VARCHAR | TAG | vgroup id |
+| database\_name | VARCHAR | TAG | vgroup 所属的 database 名字 |
+| cluster\_id | VARCHAR | TAG | cluster id |
+
+### taosd\_dnodes\_info 表
+
+`taosd_dnodes_info` 记录 dnode 信息。
+
+| field | type | is\_tag | comment |
+| :---------------- | :-------- | :------ | :------------------------------------------------------------------------------------------------ |
+| \_ts | TIMESTAMP | | timestamp |
+| uptime | DOUBLE | | dnode uptime,单位:秒 |
+| cpu\_engine | DOUBLE | | taosd cpu 使用率,从 `/proc//stat` 读取 |
+| cpu\_system | DOUBLE | | 服务器 cpu 使用率,从 `/proc/stat` 读取 |
+| cpu\_cores | DOUBLE | | 服务器 cpu 核数 |
+| mem\_engine | DOUBLE | | taosd 内存使用率,从 `/proc//status` 读取 |
+| mem\_free | DOUBLE | | 服务器可用内存,单位 KB |
+| mem\_total | DOUBLE | | 服务器内存总量,单位 KB |
+| disk\_used | DOUBLE | | data dir 挂载的磁盘使用量,单位 bytes |
+| disk\_total | DOUBLE | | data dir 挂载的磁盘总容量,单位 bytes |
+| system\_net\_in | DOUBLE | | 网络吞吐率,从 `/proc/net/dev` 中读取的 received bytes。单位 byte/s |
+| system\_net\_out | DOUBLE | | 网络吞吐率,从 `/proc/net/dev` 中读取的 transmit bytes。单位 byte/s |
+| io\_read | DOUBLE | | io 吞吐率,从 `/proc//io` 中读取的 rchar 与上次数值计算之后,计算得到速度。单位 byte/s |
+| io\_write | DOUBLE | | io 吞吐率,从 `/proc//io` 中读取的 wchar 与上次数值计算之后,计算得到速度。单位 byte/s |
+| io\_read\_disk | DOUBLE | | 磁盘 io 吞吐率,从 `/proc//io` 中读取的 read_bytes。单位 byte/s |
+| io\_write\_disk | DOUBLE | | 磁盘 io 吞吐率,从 `/proc//io` 中读取的 write_bytes。单位 byte/s |
+| vnodes\_num | DOUBLE | | dnode 上 vnodes 数量 |
+| masters | DOUBLE | | dnode 上 master node 数量 |
+| has\_mnode | DOUBLE | | dnode 是否包含 mnode,取值范围:包含=1,不包含=0 |
+| has\_qnode | DOUBLE | | dnode 是否包含 qnode,取值范围:包含=1,不包含=0 |
+| has\_snode | DOUBLE | | dnode 是否包含 snode,取值范围:包含=1,不包含=0 |
+| has\_bnode | DOUBLE | | dnode 是否包含 bnode,取值范围:包含=1,不包含=0 |
+| error\_log\_count | DOUBLE | | error 总数 |
+| info\_log\_count | DOUBLE | | info 总数 |
+| debug\_log\_count | DOUBLE | | debug 总数 |
+| trace\_log\_count | DOUBLE | | trace 总数 |
+| dnode\_id | VARCHAR | TAG | dnode id |
+| dnode\_ep | VARCHAR | TAG | dnode endpoint |
+| cluster\_id | VARCHAR | TAG | cluster id |
+
+### taosd\_dnodes\_status 表
+
+`taosd_dnodes_status` 表记录 dnode 状态信息。
+
+| field | type | is\_tag | comment |
+| :---------- | :-------- | :------ | :--------------------------------------- |
+| \_ts | TIMESTAMP | | timestamp |
+| status | DOUBLE | | dnode 状态,取值范围:ready=1,offline =0 |
+| dnode\_id | VARCHAR | TAG | dnode id |
+| dnode\_ep | VARCHAR | TAG | dnode endpoint |
+| cluster\_id | VARCHAR | TAG | cluster id |
+
+### taosd\_dnodes\_log\_dir 表
+
+`taosd_dnodes_log_dir` 表记录 log 目录信息。
+
+| field | type | is\_tag | comment |
+| :---------- | :-------- | :------ | :---------------------------------- |
+| \_ts | TIMESTAMP | | timestamp |
+| avail | DOUBLE | | log 目录可用空间。单位 byte |
+| used | DOUBLE | | log 目录已使用空间。单位 byte |
+| total | DOUBLE | | log 目录空间。单位 byte |
+| name | VARCHAR | TAG | log 目录名,一般为 `/var/log/taos/` |
+| dnode\_id | VARCHAR | TAG | dnode id |
+| dnode\_ep | VARCHAR | TAG | dnode endpoint |
+| cluster\_id | VARCHAR | TAG | cluster id |
+
+### taosd\_dnodes\_data\_dir 表
+
+`taosd_dnodes_data_dir` 表记录 data 目录信息。
+
+| field | type | is\_tag | comment |
+| :---------- | :-------- | :------ | :-------------------------------- |
+| \_ts | TIMESTAMP | | timestamp |
+| avail | DOUBLE | | data 目录可用空间。单位 byte |
+| used | DOUBLE | | data 目录已使用空间。单位 byte |
+| total | DOUBLE | | data 目录空间。单位 byte |
+| level | VARCHAR | TAG | 0、1、2 多级存储级别 |
+| name | VARCHAR | TAG | data 目录,一般为 `/var/lib/taos` |
+| dnode\_id | VARCHAR | TAG | dnode id |
+| dnode\_ep | VARCHAR | TAG | dnode endpoint |
+| cluster\_id | VARCHAR | TAG | cluster id |
+
+### taosd\_mnodes\_info 表
+
+`taosd_mnodes_info` 表记录 mnode 角色信息。
+
+| field | type | is\_tag | comment |
+| :---------- | :-------- | :------ | :------------------------------------------------------------------------------------------------------- |
+| \_ts | TIMESTAMP | | timestamp |
+| role | DOUBLE | | mnode 角色, 取值范围:offline = 0,follower = 100,candidate = 101,leader = 102,error = 103,learner = 104 |
+| mnode\_id | VARCHAR | TAG | master node id |
+| mnode\_ep | VARCHAR | TAG | master node endpoint |
+| cluster\_id | VARCHAR | TAG | cluster id |
+
+### taosd\_vnodes\_role 表
+
+`taosd_vnodes_role` 表记录虚拟节点角色信息。
+
+| field | type | is\_tag | comment |
+| :------------- | :-------- | :------ | :------------------------------------------------------------------------------------------------------ |
+| \_ts | TIMESTAMP | | timestamp |
+| vnode\_role | DOUBLE | | vnode 角色,取值范围:offline = 0,follower = 100,candidate = 101,leader = 102,error = 103,learner = 104 |
+| vgroup\_id | VARCHAR | TAG | dnode id |
+| dnode\_id | VARCHAR | TAG | dnode id |
+| database\_name | VARCHAR | TAG | vgroup 所属的 database 名字 |
+| cluster\_id | VARCHAR | TAG | cluster id |
+
+### taosd\_sql\_req 表
+
+`taosd_sql_req` 记录服务端 sql 请求信息。
+
+| field | type | is\_tag | comment |
+| :---------- | :-------- | :------ | :--------------------------------------- |
+| \_ts | TIMESTAMP | | timestamp |
+| count | DOUBLE | | sql 数量 |
+| result | VARCHAR | TAG | sql的执行结果,取值范围:Success, Failed |
+| username | VARCHAR | TAG | 执行sql的user name |
+| sql\_type | VARCHAR | TAG | sql类型,取值范围:inserted_rows |
+| dnode\_id | VARCHAR | TAG | dnode id |
+| dnode\_ep | VARCHAR | TAG | dnode endpoint |
+| vgroup\_id | VARCHAR | TAG | dnode id |
+| cluster\_id | VARCHAR | TAG | cluster id |
+
+### taos\_sql\_req 表
+
+`taos_sql_req` 记录客户端 sql 请求信息。
+
+| field | type | is\_tag | comment |
+| :---------- | :-------- | :------ | :---------------------------------------- |
+| \_ts | TIMESTAMP | | timestamp |
+| count | DOUBLE | | sql 数量 |
+| result | VARCHAR | TAG | sql的执行结果,取值范围:Success, Failed |
+| username | VARCHAR | TAG | 执行sql的user name |
+| sql\_type | VARCHAR | TAG | sql类型,取值范围:select, insert,delete |
+| cluster\_id | VARCHAR | TAG | cluster id |
+
+### taos\_slow\_sql 表
+
+`taos_slow_sql` 记录客户端慢查询信息。
+
+| field | type | is\_tag | comment |
+| :---------- | :-------- | :------ | :---------------------------------------------------- |
+| \_ts | TIMESTAMP | | timestamp |
+| count | DOUBLE | | sql 数量 |
+| result | VARCHAR | TAG | sql的执行结果,取值范围:Success, Failed |
+| username | VARCHAR | TAG | 执行sql的user name |
+| duration | VARCHAR | TAG | sql执行耗时,取值范围:3-10s,10-100s,100-1000s,1000s- |
+| cluster\_id | VARCHAR | TAG | cluster id |
+
diff --git a/docs/zh/14-reference/01-components/03-taosadapter.md b/docs/zh/14-reference/01-components/03-taosadapter.md
index 06ba4a9a07..84facad093 100644
--- a/docs/zh/14-reference/01-components/03-taosadapter.md
+++ b/docs/zh/14-reference/01-components/03-taosadapter.md
@@ -289,31 +289,32 @@ http 返回内容:
## taosAdapter 监控指标
-taosAdapter 采集 http 相关指标、CPU 百分比和内存百分比。
+taosAdapter 采集 REST/Websocket 相关请求的监控指标。将监控指标上报给 taosKeeper,这些监控指标会被 taosKeeper 写入监控数据库,默认是 `log` 库,可以在 taoskeeper 配置文件中修改。以下是这些监控指标的详细介绍。
-### http 接口
+#### adapter\_requests 表
-提供符合 [OpenMetrics](https://github.com/OpenObservability/OpenMetrics/blob/main/specification/OpenMetrics.md) 接口:
+`adapter_requests` 记录 taosadapter 监控数据。
-```text
-http://:6041/metrics
-```
-
-### 写入 TDengine
-
-taosAdapter 支持将 http 监控、CPU 百分比和内存百分比写入 TDengine。
-
-有关配置参数
-
-| **配置项** | **描述** | **默认值** |
-|-------------------------|--------------------------------------------|----------|
-| monitor.collectDuration | CPU 和内存采集间隔 | 3s |
-| monitor.identity | 当前taosadapter 的标识符如果不设置将使用 'hostname:port' | |
-| monitor.incgroup | 是否是 cgroup 中运行(容器中运行设置为 true) | false |
-| monitor.writeToTD | 是否写入到 TDengine | false |
-| monitor.user | TDengine 连接用户名 | root |
-| monitor.password | TDengine 连接密码 | taosdata |
-| monitor.writeInterval | 写入TDengine 间隔 | 30s |
+| field | type | is\_tag | comment |
+| :----------------- | :----------- | :------ | :---------------------------------- |
+| ts | TIMESTAMP | | timestamp |
+| total | INT UNSIGNED | | 总请求数 |
+| query | INT UNSIGNED | | 查询请求数 |
+| write | INT UNSIGNED | | 写入请求数 |
+| other | INT UNSIGNED | | 其他请求数 |
+| in\_process | INT UNSIGNED | | 正在处理请求数 |
+| success | INT UNSIGNED | | 成功请求数 |
+| fail | INT UNSIGNED | | 失败请求数 |
+| query\_success | INT UNSIGNED | | 查询成功请求数 |
+| query\_fail | INT UNSIGNED | | 查询失败请求数 |
+| write\_success | INT UNSIGNED | | 写入成功请求数 |
+| write\_fail | INT UNSIGNED | | 写入失败请求数 |
+| other\_success | INT UNSIGNED | | 其他成功请求数 |
+| other\_fail | INT UNSIGNED | | 其他失败请求数 |
+| query\_in\_process | INT UNSIGNED | | 正在处理查询请求数 |
+| write\_in\_process | INT UNSIGNED | | 正在处理写入请求数 |
+| endpoint | VARCHAR | | 请求端点 |
+| req\_type | NCHAR | TAG | 请求类型:0 为 REST,1 为 Websocket |
## 结果返回条数限制
@@ -342,11 +343,11 @@ taosAdapter 从 3.0.4.0 版本开始,提供参数 `smlAutoCreateDB` 来控制
在 TDengine server 2.2.x.x 或更早期版本中,taosd 进程包含一个内嵌的 http 服务。如前面所述,taosAdapter 是一个使用 systemd 管理的独立软件,拥有自己的进程。并且两者有一些配置参数和行为是不同的,请见下表:
-| **#** | **embedded httpd** | **taosAdapter** | **comment** |
-|-------|---------------------|-------------------------------|------------------------------------------------------------------------------------------------|
-| 1 | httpEnableRecordSql | --logLevel=debug | |
-| 2 | httpMaxThreads | n/a | taosAdapter 自动管理线程池,无需此参数 |
+| **#** | **embedded httpd** | **taosAdapter** | **comment** |
+| ----- | ------------------- | ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------ |
+| 1 | httpEnableRecordSql | --logLevel=debug | |
+| 2 | httpMaxThreads | n/a | taosAdapter 自动管理线程池,无需此参数 |
| 3 | telegrafUseFieldNum | 请参考 taosAdapter telegraf 配置方法 |
-| 4 | restfulRowLimit | restfulRowLimit | 内嵌 httpd 默认输出 10240 行数据,最大允许值为 102400。taosAdapter 也提供 restfulRowLimit 但是默认不做限制。您可以根据实际场景需求进行配置 |
-| 5 | httpDebugFlag | 不适用 | httpdDebugFlag 对 taosAdapter 不起作用 |
-| 6 | httpDBNameMandatory | 不适用 | taosAdapter 要求 URL 中必须指定数据库名 |
+| 4 | restfulRowLimit | restfulRowLimit | 内嵌 httpd 默认输出 10240 行数据,最大允许值为 102400。taosAdapter 也提供 restfulRowLimit 但是默认不做限制。您可以根据实际场景需求进行配置 |
+| 5 | httpDebugFlag | 不适用 | httpdDebugFlag 对 taosAdapter 不起作用 |
+| 6 | httpDBNameMandatory | 不适用 | taosAdapter 要求 URL 中必须指定数据库名 |
diff --git a/docs/zh/14-reference/01-components/04-taosx.md b/docs/zh/14-reference/01-components/04-taosx.md
index 166b6ea760..e378c18800 100644
--- a/docs/zh/14-reference/01-components/04-taosx.md
+++ b/docs/zh/14-reference/01-components/04-taosx.md
@@ -90,11 +90,11 @@ taosx privileges -i ./user-pass-privileges-backup.json -t "taos:///"
可用参数列表:
-| 参数 | 说明 |
-| ---- | ---- |
-| -u | 包含用户基本信息(密码、是否启用等) |
-| -p | 包含权限信息 |
-| -w | 包含白名单信息 |
+| 参数 | 说明 |
+| ---- | ------------------------------------ |
+| -u | 包含用户基本信息(密码、是否启用等) |
+| -p | 包含权限信息 |
+| -w | 包含白名单信息 |
当 `-u`/`-p` 参数应用时,将仅包含指定的信息,不带参数时,表示所有信息(用户名、密码、权限和白名单)。
@@ -324,4 +324,131 @@ Linux 下 `journalctl` 查看日志的命令如下:
```bash
journalctl -u taosx [-f]
-```
\ No newline at end of file
+```
+
+## taosX 监控指标
+
+taosX 会将监控指标上报给 taosKeeper,这些监控指标会被 taosKeeper 写入监控数据库,默认是 `log` 库,可以在 taoskeeper 配置文件中修改。以下是这些监控指标的详细介绍。
+
+### taosX 服务
+
+| 字段 | 描述 |
+| -------------------------- | ----------------------------------------------------------------------------- |
+| sys_cpu_cores | 系统 CPU 核数 |
+| sys_total_memory | 系统总内存,单位:字节 |
+| sys_used_memory | 系统已用内存, 单位:字节 |
+| sys_available_memory | 系统可用内存, 单位:字节 |
+| process_uptime | taosX 运行时长,单位:秒 |
+| process_id | taosX 进程 ID |
+| running_tasks | taosX 当前执行任务数 |
+| completed_tasks | taosX 进程在一个监控周期(比如10s)内完成的任务数 |
+| failed_tasks | taosX 进程在一个监控周期(比如10s)内失败的任务数 |
+| process_cpu_percent | taosX 进程占用 CPU 百分比, 单位 % |
+| process_memory_percent | taosX 进程占用内存百分比, 单位 % |
+| process_disk_read_bytes | taosX 进程在一个监控周期(比如10s)内从硬盘读取的字节数的平均值,单位 bytes/s |
+| process_disk_written_bytes | taosX 进程在一个监控周期(比如10s)内写到硬盘的字节数的平均值,单位 bytres/s |
+
+
+### Agent
+
+| 字段 | 描述 |
+| -------------------------- | ----------------------------------------------------------------------------- |
+| sys_cpu_cores | 系统 CPU 核数 |
+| sys_total_memory | 系统总内存,单位:字节 |
+| sys_used_memory | 系统已用内存, 单位:字节 |
+| sys_available_memory | 系统可用内存, 单位:字节 |
+| process_uptime | agent 运行时长,单位:秒 |
+| process_id | agent 进程 id |
+| process_cpu_percent | agent 进程占用 CPU 百分比 |
+| process_memory_percent | agent 进程占用内存百分比 |
+| process_uptime | 进程启动时间,单位秒 |
+| process_disk_read_bytes | agent 进程在一个监控周期(比如10s)内从硬盘读取的字节数的平均值,单位 bytes/s |
+| process_disk_written_bytes | agent 进程在一个监控周期(比如10s)内写到硬盘的字节数的平均值,单位 bytes/s |
+
+### Connector
+
+| 字段 | 描述 |
+| -------------------------- | --------------------------------------------------------------------------------- |
+| process_id | connector 进程 id |
+| process_uptime | 进程启动时间,单位秒 |
+| process_cpu_percent | 进程占用 CPU 百分比, 单位 % |
+| process_memory_percent | 进程占用内存百分比, 单位 % |
+| process_disk_read_bytes | connector 进程在一个监控周期(比如10s)内从硬盘读取的字节数的平均值,单位 bytes/s |
+| process_disk_written_bytes | connector 进程在一个监控周期(比如10s)内写到硬盘的字节数的平均值,单位 bytes/s |
+
+### taosX 通用数据源任务
+
+| 字段 | 描述 |
+| -------------------- | --------------------------------------------------------------- |
+| total_execute_time | 任务累计运行时间,单位毫秒 |
+| total_written_rowsls | 成功写入 TDengine 的总行数(包括重复记录) |
+| total_written_points | 累计写入成功点数 (等于数据块包含的行数乘以数据块包含的列数) |
+| start_time | 任务启动时间 (每次重启任务会被重置) |
+| written_rows | 本次运行此任务成功写入 TDengine 的总行数(包括重复记录) |
+| written_points | 本次运行写入成功点数 (等于数据块包含的行数乘以数据块包含的列数) |
+| execute_time | 任务本次运行时间,单位秒 |
+
+### taosX TDengine V2 任务
+
+| 字段 | 描述 |
+| --------------------- | -------------------------------------------------------------------- |
+| read_concurrency | 并发读取数据源的数据 worker 数, 也等于并发写入 TDengine 的 worker 数 |
+| total_stables | 需要迁移的超级表数据数量 |
+| total_updated_tags | 累计更新 tag 数 |
+| total_created_tables | 累计创建子表数 |
+| total_tables | 需要迁移的子表数量 |
+| total_finished_tables | 完成数据迁移的子表数 (任务中断重启可能大于实际值) |
+| total_success_blocks | 累计写入成功的数据块数 |
+| finished_tables | 本次运行完成迁移子表数 |
+| success_blocks | 本次写入成功的数据块数 |
+| created_tables | 本次运行创建子表数 |
+| updated_tags | 本次运行更新 tag 数 |
+
+### taosX TDengine V3 任务
+
+| 字段 | 描述 |
+| ---------------------- | ------------------------------------------------------- |
+| total_messages | 通过 TMQ 累计收到的消息总数 |
+| total_messages_of_meta | 通过 TMQ 累计收到的 Meta 类型的消息总数 |
+| total_messages_of_data | 通过 TMQ 累计收到的 Data 和 MetaData 类型的消息总数 |
+| total_write_raw_fails | 累计写入 raw meta 失败的次数 |
+| total_success_blocks | 累计写入成功的数据块数 |
+| topics | 通过 TMQ 订阅的主题数 |
+| consumers | TMQ 消费者数 |
+| messages | 本次运行通过 TMQ 收到的消息总数 |
+| messages_of_meta | 本次运行通过 TMQ 收到的 Meta 类型的消息总数 |
+| messages_of_data | 本次运行通过 TMQ 收到的 Data 和 MetaData 类型的消息总数 |
+| write_raw_fails | 本次运行写入 raw meta 失败的次数 |
+| success_blocks | 本次写入成功的数据块数 |
+
+
+### taosX 其他数据源 任务
+
+这些数据源包括: InfluxDB,OpenTSDB,OPC UA,OPC DA,PI,CSV,MQTT,AVEVA Historian 和 Kafka。
+
+| 字段 | 描述 |
+| ----------------------- | ----------------------------------------------------------- |
+| total_received_batches | 通过 IPC Stream 收到的数据总批数 |
+| total_processed_batches | 已经处理的批数 |
+| total_processed_rows | 已经处理的总行数(等于每批包含数据行数之和) |
+| total_inserted_sqls | 执行的 INSERT SQL 总条数 |
+| total_failed_sqls | 执行失败的 INSERT SQL 总条数 |
+| total_created_stables | 创建的超级表总数(可能大于实际值) |
+| total_created_tables | 尝试创建子表总数(可能大于实际值) |
+| total_failed_rows | 写入失败的总行数 |
+| total_failed_point | 写入失败的总点数 |
+| total_written_blocks | 写入成功的 raw block 总数 |
+| total_failed_blocks | 写入失败的 raw block 总数 |
+| received_batches | 本次运行此任务通过 IPC Stream 收到的数据总批数 |
+| processed_batches | 本次运行已处理批数 |
+| processed_rows | 本次处理的总行数(等于包含数据的 batch 包含的数据行数之和) |
+| received_records | 本次运行此任务通过 IPC Stream 收到的数据总行数 |
+| inserted_sqls | 本次运行此任务执行的 INSERT SQL 总条数 |
+| failed_sqls | 本次运行此任务执行失败的 INSERT SQL 总条数 |
+| created_stables | 本次运行此任务尝试创建超级表数(可能大于实际值) |
+| created_tables | 本次运行此任务尝试创建子表数(可能大于实际值) |
+| failed_rows | 本次运行此任务写入失败的行数 |
+| failed_points | 本次运行此任务写入失败的点数 |
+| written_blocks | 本次运行此任务写人成功的 raw block 数 |
+| failed_blocks | 本次运行此任务写入失败的 raw block 数 |
+
diff --git a/docs/zh/14-reference/01-components/06-taoskeeper.md b/docs/zh/14-reference/01-components/06-taoskeeper.md
index a1297230c4..2877728077 100644
--- a/docs/zh/14-reference/01-components/06-taoskeeper.md
+++ b/docs/zh/14-reference/01-components/06-taoskeeper.md
@@ -317,3 +317,19 @@ scrape_configs:
在 Grafana Dashboard 菜单点击 `import`,dashboard ID 填写 `18587`,点击 `Load` 按钮即可导入 `TaosKeeper Prometheus Dashboard for 3.x` dashboard。
+
+
+## taosKeeper 监控指标
+
+taosKeeper 也会将自己采集的监控数据写入监控数据库,默认是 `log` 库,可以在 taoskeeper 配置文件中修改。
+
+### keeper\_monitor 表
+
+`keeper_monitor` 记录 taoskeeper 监控数据。
+
+| field | type | is\_tag | comment |
+| :------- | :-------- | :------ | :----------- |
+| ts | TIMESTAMP | | timestamp |
+| cpu | DOUBLE | | cpu 使用率 |
+| mem | DOUBLE | | 内存使用率 |
+| identify | NCHAR | TAG | 身份标识信息 |
diff --git a/docs/zh/14-reference/01-components/12-tdinsight/index.mdx b/docs/zh/14-reference/01-components/12-tdinsight/index.mdx
index 4058e579de..224fd5908d 100644
--- a/docs/zh/14-reference/01-components/12-tdinsight/index.mdx
+++ b/docs/zh/14-reference/01-components/12-tdinsight/index.mdx
@@ -15,8 +15,8 @@ TDengine 通过 taosKeeper 将服务器的 CPU、内存、硬盘空间、带宽
首先检查下面服务:
- TDengine 已经安装并正常运行,此仪表盘需要 TDengine 3.0.0.0 及以上,并开启监控上报配置,具体配置请参考:[TDengine 监控配置](../taosd/#监控相关)。
-- taosAdapter 已经安装并正常运行。具体细节请参考:[taosAdapter 使用手册](../taosadapter)
-- taosKeeper 已安装并正常运行。具体细节请参考:[taosKeeper 使用手册](../taoskeeper)
+- taosAdapter 已经安装并正常运行。具体细节请参考:[taosAdapter 参考手册](../taosadapter)
+- taosKeeper 已安装并正常运行。具体细节请参考:[taosKeeper 参考手册](../taoskeeper)
然后记录以下信息:
diff --git a/docs/zh/14-reference/01-components/index.md b/docs/zh/14-reference/01-components/index.md
index 4f26d202cc..65f3a10eca 100644
--- a/docs/zh/14-reference/01-components/index.md
+++ b/docs/zh/14-reference/01-components/index.md
@@ -1,6 +1,13 @@
----
-sidebar_label: 产品组件
-title: 产品组件
-toc_max_heading_level: 4
-description: TDengine 产品组件参考手册
----
\ No newline at end of file
+---
+title: 产品组件
+description: TDengine 产品组件参考手册
+---
+
+本节详细说明 TDengine 中的主要产品组件的功能、命令行参数、配置参数等。
+
+```mdx-code-block
+import DocCardList from '@theme/DocCardList';
+import {useCurrentSidebarCategory} from '@docusaurus/theme-common';
+
+
+```
\ No newline at end of file
diff --git a/docs/zh/14-reference/05-connector/index.md b/docs/zh/14-reference/05-connector/index.md
index be25521a30..1c051bf163 100644
--- a/docs/zh/14-reference/05-connector/index.md
+++ b/docs/zh/14-reference/05-connector/index.md
@@ -118,3 +118,9 @@ import VerifyMacOS from "./_verify_macos.mdx";
+```mdx-code-block
+import DocCardList from '@theme/DocCardList';
+import {useCurrentSidebarCategory} from '@docusaurus/theme-common';
+
+
+```
\ No newline at end of file
diff --git a/docs/zh/26-tdinternal/01-arch.md b/docs/zh/26-tdinternal/01-arch.md
index fdec606239..04e47797a8 100644
--- a/docs/zh/26-tdinternal/01-arch.md
+++ b/docs/zh/26-tdinternal/01-arch.md
@@ -301,7 +301,7 @@ TDengine 采用了一种数据驱动的策略来实现缓存数据的持久化
对于采集的数据,通常会有一定的保留期限,该期限由数据库参数 keep 指定。超出设定天数的数据文件将被集群自动移除,并释放相应的存储空间。
-当设置 duration 和 keep 两个参数后,一个处于典型工作状态的 vnode 中,总的数据文件数量应为向上取整 (keep/duration)+1 个。数据文件的总个数应保持在一个合理的范围内,不宜过多也不宜过少,通常介于 10 到 100 之间较为适宜。基于这一原则,可以合理设置 duration 参数。在本书编写时的版本中,可以调整参数 keep,但参数 duration 一旦设定,则无法更改。
+当设置 duration 和 keep 两个参数后,一个处于典型工作状态的 vnode 中,总的数据文件数量应为向上取整 (keep/duration)+1 个。数据文件的总个数应保持在一个合理的范围内,不宜过多也不宜过少,通常介于 10 到 100 之间较为适宜。基于这一原则,可以合理设置 duration 参数。可以调整参数 keep,但参数 duration 一旦设定,则无法更改。
在每个数据文件中,表的数据是以块的形式存储的。一张表可能包含一到多个数据文件块。在一个文件块内,数据采用列式存储,占据连续的存储空间,这有助于显著提高读取度。文件块的大小由数据库参数 maxRows(每块最大记录条数)控制,默认值为 4096。这个值应适中,过大可能导致定位特定时间段数据的搜索时间变长,影响读取速度;过小则可能导致数据文件块的索引过大,压缩效率降低,同样影响读取速度。
diff --git a/include/client/taos.h b/include/client/taos.h
index 1d2b3a913c..73ab52357a 100644
--- a/include/client/taos.h
+++ b/include/client/taos.h
@@ -270,7 +270,10 @@ DLL_EXPORT TAOS_RES *taos_schemaless_insert_raw_ttl(TAOS *taos, char *lines, int
int precision, int32_t ttl);
DLL_EXPORT TAOS_RES *taos_schemaless_insert_raw_ttl_with_reqid(TAOS *taos, char *lines, int len, int32_t *totalRows,
int protocol, int precision, int32_t ttl, int64_t reqid);
-
+DLL_EXPORT TAOS_RES *taos_schemaless_insert_raw_ttl_with_reqid_tbname_key(TAOS *taos, char *lines, int len, int32_t *totalRows,
+ int protocol, int precision, int32_t ttl, int64_t reqid, char *tbnameKey);
+DLL_EXPORT TAOS_RES *taos_schemaless_insert_ttl_with_reqid_tbname_key(TAOS *taos, char *lines[], int numLines, int protocol,
+ int precision, int32_t ttl, int64_t reqid, char *tbnameKey);
/* --------------------------TMQ INTERFACE------------------------------- */
typedef struct tmq_t tmq_t;
diff --git a/include/libs/executor/storageapi.h b/include/libs/executor/storageapi.h
index 06a0a0348f..0cf52faa4f 100644
--- a/include/libs/executor/storageapi.h
+++ b/include/libs/executor/storageapi.h
@@ -246,12 +246,12 @@ typedef struct SStoreSnapshotFn {
} SStoreSnapshotFn;
typedef struct SStoreMeta {
- SMTbCursor* (*openTableMetaCursor)(void* pVnode); // metaOpenTbCursor
- void (*closeTableMetaCursor)(SMTbCursor* pTbCur); // metaCloseTbCursor
- void (*pauseTableMetaCursor)(SMTbCursor* pTbCur); // metaPauseTbCursor
- void (*resumeTableMetaCursor)(SMTbCursor* pTbCur, int8_t first, int8_t move); // metaResumeTbCursor
- int32_t (*cursorNext)(SMTbCursor* pTbCur, ETableType jumpTableType); // metaTbCursorNext
- int32_t (*cursorPrev)(SMTbCursor* pTbCur, ETableType jumpTableType); // metaTbCursorPrev
+ SMTbCursor* (*openTableMetaCursor)(void* pVnode); // metaOpenTbCursor
+ void (*closeTableMetaCursor)(SMTbCursor* pTbCur); // metaCloseTbCursor
+ void (*pauseTableMetaCursor)(SMTbCursor* pTbCur); // metaPauseTbCursor
+ int32_t (*resumeTableMetaCursor)(SMTbCursor* pTbCur, int8_t first, int8_t move); // metaResumeTbCursor
+ int32_t (*cursorNext)(SMTbCursor* pTbCur, ETableType jumpTableType); // metaTbCursorNext
+ int32_t (*cursorPrev)(SMTbCursor* pTbCur, ETableType jumpTableType); // metaTbCursorPrev
int32_t (*getTableTags)(void* pVnode, uint64_t suid, SArray* uidList);
int32_t (*getTableTagsByUid)(void* pVnode, int64_t suid, SArray* uidList);
diff --git a/include/libs/function/taosudf.h b/include/libs/function/taosudf.h
index 04b92a897a..0b59d7c2f5 100644
--- a/include/libs/function/taosudf.h
+++ b/include/libs/function/taosudf.h
@@ -320,6 +320,30 @@ typedef int32_t (*TScriptUdfDestoryFunc)(void *udfCtx);
typedef int32_t (*TScriptOpenFunc)(SScriptUdfEnvItem *items, int numItems);
typedef int32_t (*TScriptCloseFunc)();
+// clang-format off
+#ifdef WINDOWS
+ #define fnFatal(...) {}
+ #define fnError(...) {}
+ #define fnWarn(...) {}
+ #define fnInfo(...) {}
+ #define fnDebug(...) {}
+ #define fnTrace(...) {}
+#else
+ DLL_EXPORT void taosPrintLog(const char *flags, int32_t level, int32_t dflag, const char *format, ...)
+#ifdef __GNUC__
+ __attribute__((format(printf, 4, 5)))
+#endif
+ ;
+ extern int32_t udfDebugFlag;
+ #define udfFatal(...) { if (udfDebugFlag & 1) { taosPrintLog("UDF FATAL ", 1, 255, __VA_ARGS__); }}
+ #define udfError(...) { if (udfDebugFlag & 1) { taosPrintLog("UDF ERROR ", 1, 255, __VA_ARGS__); }}
+ #define udfWarn(...) { if (udfDebugFlag & 2) { taosPrintLog("UDF WARN ", 2, 255, __VA_ARGS__); }}
+ #define udfInfo(...) { if (udfDebugFlag & 2) { taosPrintLog("UDF ", 2, 255, __VA_ARGS__); }}
+ #define udfDebug(...) { if (udfDebugFlag & 4) { taosPrintLog("UDF ", 4, udfDebugFlag, __VA_ARGS__); }}
+ #define udfTrace(...) { if (udfDebugFlag & 8) { taosPrintLog("UDF ", 8, udfDebugFlag, __VA_ARGS__); }}
+#endif
+// clang-format on
+
#ifdef __cplusplus
}
#endif
diff --git a/include/util/tcompare.h b/include/util/tcompare.h
index 80f992f646..c7a29cad57 100644
--- a/include/util/tcompare.h
+++ b/include/util/tcompare.h
@@ -49,6 +49,7 @@ int32_t InitRegexCache();
void DestroyRegexCache();
int32_t patternMatch(const char *pattern, size_t psize, const char *str, size_t ssize, const SPatternCompareInfo *pInfo);
int32_t checkRegexPattern(const char *pPattern);
+void DestoryThreadLocalRegComp();
int32_t wcsPatternMatch(const TdUcs4 *pattern, size_t psize, const TdUcs4 *str, size_t ssize, const SPatternCompareInfo *pInfo);
diff --git a/include/util/tlog.h b/include/util/tlog.h
index 67aafbfe44..b4dbbef532 100644
--- a/include/util/tlog.h
+++ b/include/util/tlog.h
@@ -74,13 +74,13 @@ void taosCloseLog();
void taosResetLog();
void taosDumpData(uint8_t *msg, int32_t len);
-void taosPrintLog(const char *flags, ELogLevel level, int32_t dflag, const char *format, ...)
+void taosPrintLog(const char *flags, int32_t level, int32_t dflag, const char *format, ...)
#ifdef __GNUC__
__attribute__((format(printf, 4, 5)))
#endif
;
-void taosPrintLongString(const char *flags, ELogLevel level, int32_t dflag, const char *format, ...)
+void taosPrintLongString(const char *flags, int32_t level, int32_t dflag, const char *format, ...)
#ifdef __GNUC__
__attribute__((format(printf, 4, 5)))
#endif
diff --git a/source/client/inc/clientSml.h b/source/client/inc/clientSml.h
index e901f86b41..209c376f30 100644
--- a/source/client/inc/clientSml.h
+++ b/source/client/inc/clientSml.h
@@ -204,6 +204,7 @@ typedef struct {
STableMeta *currSTableMeta;
STableDataCxt *currTableDataCtx;
bool needModifySchema;
+ char *tbnameKey;
} SSmlHandle;
extern int64_t smlFactorNS[];
@@ -219,9 +220,10 @@ bool smlParseNumberOld(SSmlKv *kvVal, SSmlMsgBuf *msg);
void smlBuildInvalidDataMsg(SSmlMsgBuf *pBuf, const char *msg1, const char *msg2);
int32_t smlParseNumber(SSmlKv *kvVal, SSmlMsgBuf *msg);
int64_t smlGetTimeValue(const char *value, int32_t len, uint8_t fromPrecision, uint8_t toPrecision);
-int32_t smlBuildTableInfo(int numRows, const char* measure, int32_t measureLen, SSmlTableInfo** tInfo);
+
+int32_t smlBuildTableInfo(int numRows, const char* measure, int32_t measureLen, SSmlTableInfo** tInfo);
int32_t smlBuildSTableMeta(bool isDataFormat, SSmlSTableMeta** sMeta);
-int32_t smlSetCTableName(SSmlTableInfo *oneTable);
+int32_t smlSetCTableName(SSmlTableInfo *oneTable, char *tbnameKey);
int32_t getTableUid(SSmlHandle *info, SSmlLineInfo *currElement, SSmlTableInfo *tinfo);
int32_t smlGetMeta(SSmlHandle *info, const void* measure, int32_t measureLen, STableMeta **pTableMeta);
int32_t is_same_child_table_telnet(const void *a, const void *b);
diff --git a/source/client/src/clientEnv.c b/source/client/src/clientEnv.c
index 35e6651c41..d63701c529 100644
--- a/source/client/src/clientEnv.c
+++ b/source/client/src/clientEnv.c
@@ -374,8 +374,8 @@ int32_t openTransporter(const char *user, const char *auth, int32_t numOfThread,
*pDnodeConn = rpcOpen(&rpcInit);
if (*pDnodeConn == NULL) {
- tscError("failed to init connection to server.");
- code = TSDB_CODE_FAILED;
+ tscError("failed to init connection to server since %s", tstrerror(terrno));
+ code = terrno;
}
return code;
@@ -526,19 +526,17 @@ int32_t createRequest(uint64_t connId, int32_t type, int64_t reqid, SRequestObj
int32_t code = TSDB_CODE_SUCCESS;
*pRequest = (SRequestObj *)taosMemoryCalloc(1, sizeof(SRequestObj));
if (NULL == *pRequest) {
- return TSDB_CODE_OUT_OF_MEMORY;
+ return terrno;
}
STscObj *pTscObj = acquireTscObj(connId);
if (pTscObj == NULL) {
- code = TSDB_CODE_TSC_DISCONNECTED;
- goto _return;
+ TSC_ERR_JRET(TSDB_CODE_TSC_DISCONNECTED);
}
SSyncQueryParam *interParam = taosMemoryCalloc(1, sizeof(SSyncQueryParam));
if (interParam == NULL) {
releaseTscObj(connId);
- code = TSDB_CODE_OUT_OF_MEMORY;
- goto _return;
+ TSC_ERR_JRET(terrno);
}
TSC_ERR_JRET(tsem_init(&interParam->sem, 0, 0));
interParam->pRequest = *pRequest;
@@ -566,7 +564,11 @@ int32_t createRequest(uint64_t connId, int32_t type, int64_t reqid, SRequestObj
return TSDB_CODE_SUCCESS;
_return:
- doDestroyRequest(*pRequest);
+ if ((*pRequest)->pTscObj) {
+ doDestroyRequest(*pRequest);
+ } else {
+ taosMemoryFree(*pRequest);
+ }
return code;
}
@@ -869,7 +871,7 @@ _return:
TSC_ERR_RET(terrno);
}
- return TSDB_CODE_SUCCESS;
+ return code;
}
void tscStopCrashReport() {
diff --git a/source/client/src/clientHb.c b/source/client/src/clientHb.c
index a174ae4b13..415c2d6685 100644
--- a/source/client/src/clientHb.c
+++ b/source/client/src/clientHb.c
@@ -1405,7 +1405,7 @@ _return:
TSC_ERR_RET(terrno);
}
- return TSDB_CODE_SUCCESS;
+ return code;
}
static void hbStopThread() {
diff --git a/source/client/src/clientImpl.c b/source/client/src/clientImpl.c
index 4aa78caa15..664de5619f 100644
--- a/source/client/src/clientImpl.c
+++ b/source/client/src/clientImpl.c
@@ -2467,7 +2467,8 @@ TSDB_SERVER_STATUS taos_check_server_status(const char* fqdn, int port, char* de
clientRpc = rpcOpen(&rpcInit);
if (clientRpc == NULL) {
- tscError("failed to init server status client");
+ code = terrno;
+ tscError("failed to init server status client since %s", tstrerror(code));
goto _OVER;
}
diff --git a/source/client/src/clientSml.c b/source/client/src/clientSml.c
index c244d36eb7..55be514e40 100644
--- a/source/client/src/clientSml.c
+++ b/source/client/src/clientSml.c
@@ -402,7 +402,7 @@ int32_t smlProcessChildTable(SSmlHandle *info, SSmlLineInfo *elements) {
if (kv->valueEscaped) kv->value = NULL;
}
- code = smlSetCTableName(tinfo);
+ code = smlSetCTableName(tinfo, info->tbnameKey);
if (code != TSDB_CODE_SUCCESS){
smlDestroyTableInfo(&tinfo);
return code;
@@ -486,10 +486,10 @@ int32_t smlParseEndLine(SSmlHandle *info, SSmlLineInfo *elements, SSmlKv *kvTs)
return TSDB_CODE_SUCCESS;
}
-static int32_t smlParseTableName(SArray *tags, char *childTableName) {
+static int32_t smlParseTableName(SArray *tags, char *childTableName, char *tbnameKey) {
bool autoChildName = false;
size_t delimiter = strlen(tsSmlAutoChildTableNameDelimiter);
- if (delimiter > 0) {
+ if(delimiter > 0 && tbnameKey == NULL){
size_t totalNameLen = delimiter * (taosArrayGetSize(tags) - 1);
for (int i = 0; i < taosArrayGetSize(tags); i++) {
SSmlKv *tag = (SSmlKv *)taosArrayGet(tags, i);
@@ -517,8 +517,11 @@ static int32_t smlParseTableName(SArray *tags, char *childTableName) {
if (tsSmlDot2Underline) {
smlStrReplace(childTableName, strlen(childTableName));
}
- } else {
- size_t childTableNameLen = strlen(tsSmlChildTableName);
+ }else{
+ if (tbnameKey == NULL){
+ tbnameKey = tsSmlChildTableName;
+ }
+ size_t childTableNameLen = strlen(tbnameKey);
if (childTableNameLen <= 0) return TSDB_CODE_SUCCESS;
for (int i = 0; i < taosArrayGetSize(tags); i++) {
@@ -527,7 +530,7 @@ static int32_t smlParseTableName(SArray *tags, char *childTableName) {
return TSDB_CODE_SML_INVALID_DATA;
}
// handle child table name
- if (childTableNameLen == tag->keyLen && strncmp(tag->key, tsSmlChildTableName, tag->keyLen) == 0) {
+ if (childTableNameLen == tag->keyLen && strncmp(tag->key, tbnameKey, tag->keyLen) == 0) {
(void)memset(childTableName, 0, TSDB_TABLE_NAME_LEN);
(void)strncpy(childTableName, tag->value, (tag->length < TSDB_TABLE_NAME_LEN ? tag->length : TSDB_TABLE_NAME_LEN));
if (tsSmlDot2Underline) {
@@ -542,8 +545,8 @@ static int32_t smlParseTableName(SArray *tags, char *childTableName) {
return TSDB_CODE_SUCCESS;
}
-int32_t smlSetCTableName(SSmlTableInfo *oneTable) {
- int32_t code = smlParseTableName(oneTable->tags, oneTable->childTableName);
+int32_t smlSetCTableName(SSmlTableInfo *oneTable, char *tbnameKey) {
+ int32_t code = smlParseTableName(oneTable->tags, oneTable->childTableName, tbnameKey);
if(code != TSDB_CODE_SUCCESS){
return code;
}
@@ -2127,7 +2130,7 @@ void smlSetReqSQL(SRequestObj *request, char *lines[], char *rawLine, char *rawL
}
TAOS_RES *taos_schemaless_insert_inner(TAOS *taos, char *lines[], char *rawLine, char *rawLineEnd, int numLines,
- int protocol, int precision, int32_t ttl, int64_t reqid) {
+ int protocol, int precision, int32_t ttl, int64_t reqid, char *tbnameKey) {
int32_t code = TSDB_CODE_SUCCESS;
if (NULL == taos) {
uError("SML:taos_schemaless_insert error taos is null");
@@ -2159,6 +2162,7 @@ TAOS_RES *taos_schemaless_insert_inner(TAOS *taos, char *lines[], char *rawLine,
info->msgBuf.buf = info->pRequest->msgBuf;
info->msgBuf.len = ERROR_MSG_BUF_DEFAULT_SIZE;
info->lineNum = numLines;
+ info->tbnameKey = tbnameKey;
smlSetReqSQL(request, lines, rawLine, rawLineEnd);
@@ -2237,9 +2241,14 @@ end:
* @return TAOS_RES
*/
+TAOS_RES *taos_schemaless_insert_ttl_with_reqid_tbname_key(TAOS *taos, char *lines[], int numLines, int protocol,
+ int precision, int32_t ttl, int64_t reqid, char *tbnameKey){
+ return taos_schemaless_insert_inner(taos, lines, NULL, NULL, numLines, protocol, precision, ttl, reqid, tbnameKey);
+}
+
TAOS_RES *taos_schemaless_insert_ttl_with_reqid(TAOS *taos, char *lines[], int numLines, int protocol, int precision,
int32_t ttl, int64_t reqid) {
- return taos_schemaless_insert_inner(taos, lines, NULL, NULL, numLines, protocol, precision, ttl, reqid);
+ return taos_schemaless_insert_ttl_with_reqid_tbname_key(taos, lines, numLines, protocol, precision, ttl, reqid, NULL);
}
TAOS_RES *taos_schemaless_insert(TAOS *taos, char *lines[], int numLines, int protocol, int precision) {
@@ -2272,10 +2281,15 @@ static void getRawLineLen(char *lines, int len, int32_t *totalRows, int protocol
}
}
+TAOS_RES *taos_schemaless_insert_raw_ttl_with_reqid_tbname_key(TAOS *taos, char *lines, int len, int32_t *totalRows,
+ int protocol, int precision, int32_t ttl, int64_t reqid, char *tbnameKey){
+ getRawLineLen(lines, len, totalRows, protocol);
+ return taos_schemaless_insert_inner(taos, NULL, lines, lines + len, *totalRows, protocol, precision, ttl, reqid, tbnameKey);
+}
+
TAOS_RES *taos_schemaless_insert_raw_ttl_with_reqid(TAOS *taos, char *lines, int len, int32_t *totalRows, int protocol,
int precision, int32_t ttl, int64_t reqid) {
- getRawLineLen(lines, len, totalRows, protocol);
- return taos_schemaless_insert_inner(taos, NULL, lines, lines + len, *totalRows, protocol, precision, ttl, reqid);
+ return taos_schemaless_insert_raw_ttl_with_reqid_tbname_key(taos, lines, len, totalRows, protocol, precision, ttl, reqid, NULL);
}
TAOS_RES *taos_schemaless_insert_raw_with_reqid(TAOS *taos, char *lines, int len, int32_t *totalRows, int protocol,
diff --git a/source/client/src/clientTmq.c b/source/client/src/clientTmq.c
index 8cf39a51b9..197a65add8 100644
--- a/source/client/src/clientTmq.c
+++ b/source/client/src/clientTmq.c
@@ -1275,7 +1275,7 @@ tmq_t* tmq_consumer_new(tmq_conf_t* conf, char* errstr, int32_t errstrLen) {
// init semaphore
if (tsem2_init(&pTmq->rspSem, 0, 0) != 0) {
- tscError("consumer:0x %" PRIx64 " setup failed since %s, consumer group %s", pTmq->consumerId, terrstr(),
+ tscError("consumer:0x %" PRIx64 " setup failed since %s, consumer group %s", pTmq->consumerId, tstrerror(TAOS_SYSTEM_ERROR(errno)),
pTmq->groupId);
SET_ERROR_MSG_TMQ("init t_sem failed")
goto _failed;
diff --git a/source/dnode/mgmt/node_mgmt/src/dmTransport.c b/source/dnode/mgmt/node_mgmt/src/dmTransport.c
index 9bbfdd18b0..6de9665db9 100644
--- a/source/dnode/mgmt/node_mgmt/src/dmTransport.c
+++ b/source/dnode/mgmt/node_mgmt/src/dmTransport.c
@@ -393,8 +393,8 @@ int32_t dmInitClient(SDnode *pDnode) {
pTrans->clientRpc = rpcOpen(&rpcInit);
if (pTrans->clientRpc == NULL) {
- dError("failed to init dnode rpc client");
- return -1;
+ dError("failed to init dnode rpc client since:%s", tstrerror(terrno));
+ return terrno;
}
dDebug("dnode rpc client is initialized");
@@ -437,8 +437,8 @@ int32_t dmInitStatusClient(SDnode *pDnode) {
pTrans->statusRpc = rpcOpen(&rpcInit);
if (pTrans->statusRpc == NULL) {
- dError("failed to init dnode rpc status client");
- return TSDB_CODE_OUT_OF_MEMORY;
+ dError("failed to init dnode rpc status client since %s", tstrerror(terrno));
+ return terrno;
}
dDebug("dnode rpc status client is initialized");
@@ -482,8 +482,8 @@ int32_t dmInitSyncClient(SDnode *pDnode) {
pTrans->syncRpc = rpcOpen(&rpcInit);
if (pTrans->syncRpc == NULL) {
- dError("failed to init dnode rpc sync client");
- return TSDB_CODE_OUT_OF_MEMORY;
+ dError("failed to init dnode rpc sync client since %s", tstrerror(terrno));
+ return terrno;
}
dDebug("dnode rpc sync client is initialized");
@@ -532,7 +532,7 @@ int32_t dmInitServer(SDnode *pDnode) {
(void)taosVersionStrToInt(version, &(rpcInit.compatibilityVer));
pTrans->serverRpc = rpcOpen(&rpcInit);
if (pTrans->serverRpc == NULL) {
- dError("failed to init dnode rpc server");
+ dError("failed to init dnode rpc server since:%s", tstrerror(terrno));
return terrno;
}
diff --git a/source/dnode/mnode/impl/inc/mndConsumer.h b/source/dnode/mnode/impl/inc/mndConsumer.h
index a773c61986..175730b91e 100644
--- a/source/dnode/mnode/impl/inc/mndConsumer.h
+++ b/source/dnode/mnode/impl/inc/mndConsumer.h
@@ -46,7 +46,7 @@ const char *mndConsumerStatusName(int status);
#define MND_TMQ_NULL_CHECK(c) \
do { \
if (c == NULL) { \
- code = TSDB_CODE_OUT_OF_MEMORY; \
+ code = TAOS_GET_TERRNO(TSDB_CODE_OUT_OF_MEMORY); \
goto END; \
} \
} while (0)
diff --git a/source/dnode/mnode/impl/src/mndSubscribe.c b/source/dnode/mnode/impl/src/mndSubscribe.c
index fe7c597e57..bff313dbaf 100644
--- a/source/dnode/mnode/impl/src/mndSubscribe.c
+++ b/source/dnode/mnode/impl/src/mndSubscribe.c
@@ -882,7 +882,7 @@ static int32_t buildRebOutput(SMnode *pMnode, SMqRebInputObj *rebInput, SMqRebOu
rebInput->oldConsumerNum = 0;
code = mndCreateSubscription(pMnode, pTopic, key, &rebOutput->pSub);
if (code != 0) {
- mError("[rebalance] mq rebalance %s failed create sub since %s, ignore", key, terrstr());
+ mError("[rebalance] mq rebalance %s failed create sub since %s, ignore", key, tstrerror(code));
taosRUnLockLatch(&pTopic->lock);
mndReleaseTopic(pMnode, pTopic);
return code;
@@ -1067,7 +1067,7 @@ static int32_t mndProcessDropCgroupReq(SRpcMsg *pMsg) {
return 0;
} else {
code = TSDB_CODE_MND_SUBSCRIBE_NOT_EXIST;
- mError("topic:%s, cgroup:%s, failed to drop since %s", dropReq.topic, dropReq.cgroup, terrstr());
+ mError("topic:%s, cgroup:%s, failed to drop since %s", dropReq.topic, dropReq.cgroup, tstrerror(code));
return code;
}
}
@@ -1075,7 +1075,7 @@ static int32_t mndProcessDropCgroupReq(SRpcMsg *pMsg) {
taosWLockLatch(&pSub->lock);
if (taosHashGetSize(pSub->consumerHash) != 0) {
code = TSDB_CODE_MND_CGROUP_USED;
- mError("cgroup:%s on topic:%s, failed to drop since %s", dropReq.cgroup, dropReq.topic, terrstr());
+ mError("cgroup:%s on topic:%s, failed to drop since %s", dropReq.cgroup, dropReq.topic, tstrerror(code));
goto END;
}
diff --git a/source/dnode/mnode/impl/src/mndTopic.c b/source/dnode/mnode/impl/src/mndTopic.c
index 4bca13508e..c27cc04ae8 100644
--- a/source/dnode/mnode/impl/src/mndTopic.c
+++ b/source/dnode/mnode/impl/src/mndTopic.c
@@ -574,7 +574,7 @@ static int32_t mndProcessCreateTopicReq(SRpcMsg *pReq) {
END:
if (code != 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) {
- mError("failed to create topic:%s since %s", createTopicReq.name, terrstr());
+ mError("failed to create topic:%s since %s", createTopicReq.name, tstrerror(code));
}
mndReleaseTopic(pMnode, pTopic);
@@ -699,7 +699,7 @@ static int32_t mndProcessDropTopicReq(SRpcMsg *pReq) {
tFreeSMDropTopicReq(&dropReq);
return 0;
} else {
- mError("topic:%s, failed to drop since %s", dropReq.name, terrstr());
+ mError("topic:%s, failed to drop since %s", dropReq.name, tstrerror(code));
tFreeSMDropTopicReq(&dropReq);
return code;
}
@@ -727,7 +727,7 @@ END:
mndReleaseTopic(pMnode, pTopic);
mndTransDrop(pTrans);
if (code != 0) {
- mError("topic:%s, failed to drop since %s", dropReq.name, terrstr());
+ mError("topic:%s, failed to drop since %s", dropReq.name, tstrerror(code));
tFreeSMDropTopicReq(&dropReq);
return code;
}
diff --git a/source/dnode/vnode/src/inc/vnodeInt.h b/source/dnode/vnode/src/inc/vnodeInt.h
index c45d6e6edf..416438b2ec 100644
--- a/source/dnode/vnode/src/inc/vnodeInt.h
+++ b/source/dnode/vnode/src/inc/vnodeInt.h
@@ -131,7 +131,7 @@ typedef SVCreateTSmaReq SSmaCfg;
SMTbCursor* metaOpenTbCursor(void* pVnode);
void metaCloseTbCursor(SMTbCursor* pTbCur);
void metaPauseTbCursor(SMTbCursor* pTbCur);
-void metaResumeTbCursor(SMTbCursor* pTbCur, int8_t first, int8_t move);
+int32_t metaResumeTbCursor(SMTbCursor* pTbCur, int8_t first, int8_t move);
int32_t metaTbCursorNext(SMTbCursor* pTbCur, ETableType jumpTableType);
int32_t metaTbCursorPrev(SMTbCursor* pTbCur, ETableType jumpTableType);
diff --git a/source/dnode/vnode/src/meta/metaQuery.c b/source/dnode/vnode/src/meta/metaQuery.c
index e5dc34f4ab..1d284aaf1f 100644
--- a/source/dnode/vnode/src/meta/metaQuery.c
+++ b/source/dnode/vnode/src/meta/metaQuery.c
@@ -231,6 +231,7 @@ _exit:
#if 1 // ===================================================
SMTbCursor *metaOpenTbCursor(void *pVnode) {
SMTbCursor *pTbCur = NULL;
+ int32_t code;
pTbCur = (SMTbCursor *)taosMemoryCalloc(1, sizeof(*pTbCur));
if (pTbCur == NULL) {
@@ -241,7 +242,12 @@ SMTbCursor *metaOpenTbCursor(void *pVnode) {
// tdbTbcMoveToFirst((TBC *)pTbCur->pDbc);
pTbCur->pMeta = pVnodeObj->pMeta;
pTbCur->paused = 1;
- metaResumeTbCursor(pTbCur, 1, 0);
+ code = metaResumeTbCursor(pTbCur, 1, 0);
+ if (code) {
+ terrno = code;
+ taosMemoryFree(pTbCur);
+ return NULL;
+ }
return pTbCur;
}
@@ -266,28 +272,39 @@ void metaPauseTbCursor(SMTbCursor *pTbCur) {
pTbCur->paused = 1;
}
}
-void metaResumeTbCursor(SMTbCursor *pTbCur, int8_t first, int8_t move) {
+int32_t metaResumeTbCursor(SMTbCursor *pTbCur, int8_t first, int8_t move) {
+ int32_t code = 0;
+ int32_t lino;
+
if (pTbCur->paused) {
metaReaderDoInit(&pTbCur->mr, pTbCur->pMeta, META_READER_LOCK);
- (void)tdbTbcOpen(((SMeta *)pTbCur->pMeta)->pUidIdx, (TBC **)&pTbCur->pDbc, NULL);
+ code = tdbTbcOpen(((SMeta *)pTbCur->pMeta)->pUidIdx, (TBC **)&pTbCur->pDbc, NULL);
+ TSDB_CHECK_CODE(code, lino, _exit);
if (first) {
- (void)tdbTbcMoveToFirst((TBC *)pTbCur->pDbc);
+ code = tdbTbcMoveToFirst((TBC *)pTbCur->pDbc);
+ TSDB_CHECK_CODE(code, lino, _exit);
} else {
int c = 1;
- (void)tdbTbcMoveTo(pTbCur->pDbc, pTbCur->pKey, pTbCur->kLen, &c);
+ code = tdbTbcMoveTo(pTbCur->pDbc, pTbCur->pKey, pTbCur->kLen, &c);
+ TSDB_CHECK_CODE(code, lino, _exit);
if (c == 0) {
if (move) tdbTbcMoveToNext(pTbCur->pDbc);
} else if (c < 0) {
- (void)tdbTbcMoveToPrev(pTbCur->pDbc);
+ code = tdbTbcMoveToPrev(pTbCur->pDbc);
+ TSDB_CHECK_CODE(code, lino, _exit);
} else {
- (void)tdbTbcMoveToNext(pTbCur->pDbc);
+ code = tdbTbcMoveToNext(pTbCur->pDbc);
+ TSDB_CHECK_CODE(code, lino, _exit);
}
}
pTbCur->paused = 0;
}
+
+_exit:
+ return code;
}
int32_t metaTbCursorNext(SMTbCursor *pTbCur, ETableType jumpTableType) {
@@ -355,7 +372,9 @@ _query:
version = ((SUidIdxVal *)pData)[0].version;
- (void)tdbTbGet(pMeta->pTbDb, &(STbDbKey){.uid = uid, .version = version}, sizeof(STbDbKey), &pData, &nData);
+ if (tdbTbGet(pMeta->pTbDb, &(STbDbKey){.uid = uid, .version = version}, sizeof(STbDbKey), &pData, &nData) != 0) {
+ goto _err;
+ }
SMetaEntry me = {0};
tDecoderInit(&dc, pData, nData);
@@ -385,7 +404,9 @@ _query:
}
tDecoderInit(&dc, pData, nData);
- (void)tDecodeSSchemaWrapperEx(&dc, &schema);
+ if (tDecodeSSchemaWrapperEx(&dc, &schema) != 0) {
+ goto _err;
+ }
pSchema = tCloneSSchemaWrapper(&schema);
tDecoderClear(&dc);
@@ -588,6 +609,7 @@ STSchema *metaGetTbTSchema(SMeta *pMeta, tb_uid_t uid, int32_t sver, int lock) {
int32_t metaGetTbTSchemaEx(SMeta *pMeta, tb_uid_t suid, tb_uid_t uid, int32_t sver, STSchema **ppTSchema) {
int32_t code = 0;
+ int32_t lino;
void *pData = NULL;
int nData = 0;
@@ -603,7 +625,8 @@ int32_t metaGetTbTSchemaEx(SMeta *pMeta, tb_uid_t suid, tb_uid_t uid, int32_t sv
skmDbKey.uid = suid ? suid : uid;
skmDbKey.sver = INT32_MAX;
- (void)tdbTbcOpen(pMeta->pSkmDb, &pSkmDbC, NULL);
+ code = tdbTbcOpen(pMeta->pSkmDb, &pSkmDbC, NULL);
+ TSDB_CHECK_CODE(code, lino, _exit);
metaRLock(pMeta);
if (tdbTbcMoveTo(pSkmDbC, &skmDbKey, sizeof(skmDbKey), &c) < 0) {
diff --git a/source/dnode/vnode/src/meta/metaTable.c b/source/dnode/vnode/src/meta/metaTable.c
index 2badeec2c9..596fbf70b0 100644
--- a/source/dnode/vnode/src/meta/metaTable.c
+++ b/source/dnode/vnode/src/meta/metaTable.c
@@ -306,12 +306,13 @@ _err:
}
int metaDropSTable(SMeta *pMeta, int64_t verison, SVDropStbReq *pReq, SArray *tbUidList) {
- void *pKey = NULL;
- int nKey = 0;
- void *pData = NULL;
- int nData = 0;
- int c = 0;
- int rc = 0;
+ void *pKey = NULL;
+ int nKey = 0;
+ void *pData = NULL;
+ int nData = 0;
+ int c = 0;
+ int rc = 0;
+ int32_t lino;
// check if super table exists
rc = tdbTbGet(pMeta->pNameIdx, pReq->name, strlen(pReq->name) + 1, &pData, &nData);
@@ -323,7 +324,11 @@ int metaDropSTable(SMeta *pMeta, int64_t verison, SVDropStbReq *pReq, SArray *tb
// drop all child tables
TBC *pCtbIdxc = NULL;
- (void)(void)tdbTbcOpen(pMeta->pCtbIdx, &pCtbIdxc, NULL);
+ rc = tdbTbcOpen(pMeta->pCtbIdx, &pCtbIdxc, NULL);
+ if (rc) {
+ return (terrno = rc);
+ }
+
rc = tdbTbcMoveTo(pCtbIdxc, &(SCtbIdxKey){.suid = pReq->suid, .uid = INT64_MIN}, sizeof(SCtbIdxKey), &c);
if (rc < 0) {
(void)tdbTbcClose(pCtbIdxc);
@@ -379,20 +384,20 @@ _exit:
return 0;
}
-static void metaGetSubtables(SMeta *pMeta, int64_t suid, SArray *uids) {
- if (!uids) return;
+static int32_t metaGetSubtables(SMeta *pMeta, int64_t suid, SArray *uids) {
+ if (!uids) return TSDB_CODE_INVALID_PARA;
int c = 0;
void *pKey = NULL;
int nKey = 0;
TBC *pCtbIdxc = NULL;
- (void)tdbTbcOpen(pMeta->pCtbIdx, &pCtbIdxc, NULL);
+ TAOS_CHECK_RETURN(tdbTbcOpen(pMeta->pCtbIdx, &pCtbIdxc, NULL));
int rc = tdbTbcMoveTo(pCtbIdxc, &(SCtbIdxKey){.suid = suid, .uid = INT64_MIN}, sizeof(SCtbIdxKey), &c);
if (rc < 0) {
(void)tdbTbcClose(pCtbIdxc);
metaWLock(pMeta);
- return;
+ return 0;
}
for (;;) {
@@ -405,12 +410,17 @@ static void metaGetSubtables(SMeta *pMeta, int64_t suid, SArray *uids) {
break;
}
- (void)taosArrayPush(uids, &(((SCtbIdxKey *)pKey)->uid));
+ if (taosArrayPush(uids, &(((SCtbIdxKey *)pKey)->uid)) == NULL) {
+ tdbFree(pKey);
+ (void)tdbTbcClose(pCtbIdxc);
+ return terrno;
+ }
}
tdbFree(pKey);
(void)tdbTbcClose(pCtbIdxc);
+ return 0;
}
int metaAlterSTable(SMeta *pMeta, int64_t version, SVCreateStbReq *pReq) {
@@ -425,7 +435,7 @@ int metaAlterSTable(SMeta *pMeta, int64_t version, SVCreateStbReq *pReq) {
int32_t ret;
int32_t c = -2;
- (void)tdbTbcOpen(pMeta->pUidIdx, &pUidIdxc, NULL);
+ TAOS_CHECK_RETURN(tdbTbcOpen(pMeta->pUidIdx, &pUidIdxc, NULL));
ret = tdbTbcMoveTo(pUidIdxc, &pReq->suid, sizeof(tb_uid_t), &c);
if (ret < 0 || c) {
(void)tdbTbcClose(pUidIdxc);
@@ -442,7 +452,7 @@ int metaAlterSTable(SMeta *pMeta, int64_t version, SVCreateStbReq *pReq) {
oversion = ((SUidIdxVal *)pData)[0].version;
- (void)tdbTbcOpen(pMeta->pTbDb, &pTbDbc, NULL);
+ TAOS_CHECK_RETURN(tdbTbcOpen(pMeta->pTbDb, &pTbDbc, NULL));
ret = tdbTbcMoveTo(pTbDbc, &((STbDbKey){.uid = pReq->suid, .version = oversion}), sizeof(STbDbKey), &c);
if (!(ret == 0 && c == 0)) {
(void)tdbTbcClose(pUidIdxc);
@@ -486,7 +496,7 @@ int metaAlterSTable(SMeta *pMeta, int64_t version, SVCreateStbReq *pReq) {
int16_t cid = pReq->schemaRow.pSchema[nCols - 1].colId;
int8_t col_type = pReq->schemaRow.pSchema[nCols - 1].type;
- metaGetSubtables(pMeta, pReq->suid, uids);
+ TAOS_CHECK_RETURN(metaGetSubtables(pMeta, pReq->suid, uids));
(void)tsdbCacheNewSTableColumn(pTsdb, uids, cid, col_type);
} else if (deltaCol == -1) {
int16_t cid = -1;
@@ -502,7 +512,7 @@ int metaAlterSTable(SMeta *pMeta, int64_t version, SVCreateStbReq *pReq) {
}
if (cid != -1) {
- metaGetSubtables(pMeta, pReq->suid, uids);
+ TAOS_CHECK_RETURN(metaGetSubtables(pMeta, pReq->suid, uids));
(void)tsdbCacheDropSTableColumn(pTsdb, uids, cid, hasPrimaryKey);
}
}
@@ -619,7 +629,7 @@ int metaAddIndexToSTable(SMeta *pMeta, int64_t version, SVCreateStbReq *pReq) {
* iterator all pTdDbc by uid and version
*/
TBC *pCtbIdxc = NULL;
- (void)tdbTbcOpen(pMeta->pCtbIdx, &pCtbIdxc, NULL);
+ TAOS_CHECK_RETURN(tdbTbcOpen(pMeta->pCtbIdx, &pCtbIdxc, NULL));
int rc = tdbTbcMoveTo(pCtbIdxc, &(SCtbIdxKey){.suid = suid, .uid = INT64_MIN}, sizeof(SCtbIdxKey), &c);
if (rc < 0) {
(void)tdbTbcClose(pCtbIdxc);
@@ -756,7 +766,7 @@ int metaDropIndexFromSTable(SMeta *pMeta, int64_t version, SDropIndexReq *pReq)
* iterator all pTdDbc by uid and version
*/
TBC *pCtbIdxc = NULL;
- (void)tdbTbcOpen(pMeta->pCtbIdx, &pCtbIdxc, NULL);
+ TAOS_CHECK_RETURN(tdbTbcOpen(pMeta->pCtbIdx, &pCtbIdxc, NULL));
int rc = tdbTbcMoveTo(pCtbIdxc, &(SCtbIdxKey){.suid = suid, .uid = INT64_MIN}, sizeof(SCtbIdxKey), &c);
if (rc < 0) {
(void)tdbTbcClose(pCtbIdxc);
@@ -1424,7 +1434,7 @@ static int metaAlterTableColumn(SMeta *pMeta, int64_t version, SVAlterTbReq *pAl
// search uid index
TBC *pUidIdxc = NULL;
- (void)tdbTbcOpen(pMeta->pUidIdx, &pUidIdxc, NULL);
+ TAOS_CHECK_RETURN(tdbTbcOpen(pMeta->pUidIdx, &pUidIdxc, NULL));
(void)tdbTbcMoveTo(pUidIdxc, &uid, sizeof(uid), &c);
if (c != 0) {
(void)tdbTbcClose(pUidIdxc);
@@ -1438,7 +1448,7 @@ static int metaAlterTableColumn(SMeta *pMeta, int64_t version, SVAlterTbReq *pAl
// search table.db
TBC *pTbDbc = NULL;
- (void)tdbTbcOpen(pMeta->pTbDb, &pTbDbc, NULL);
+ TAOS_CHECK_RETURN(tdbTbcOpen(pMeta->pTbDb, &pTbDbc, NULL));
(void)tdbTbcMoveTo(pTbDbc, &((STbDbKey){.uid = uid, .version = oversion}), sizeof(STbDbKey), &c);
if (c != 0) {
(void)tdbTbcClose(pUidIdxc);
@@ -1689,7 +1699,7 @@ static int metaUpdateTableTagVal(SMeta *pMeta, int64_t version, SVAlterTbReq *pA
// search uid index
TBC *pUidIdxc = NULL;
- (void)tdbTbcOpen(pMeta->pUidIdx, &pUidIdxc, NULL);
+ TAOS_CHECK_RETURN(tdbTbcOpen(pMeta->pUidIdx, &pUidIdxc, NULL));
(void)tdbTbcMoveTo(pUidIdxc, &uid, sizeof(uid), &c);
if (c != 0) {
(void)tdbTbcClose(pUidIdxc);
@@ -1706,7 +1716,7 @@ static int metaUpdateTableTagVal(SMeta *pMeta, int64_t version, SVAlterTbReq *pA
SDecoder dc2 = {0};
/* get ctbEntry */
- (void)tdbTbcOpen(pMeta->pTbDb, &pTbDbc, NULL);
+ TAOS_CHECK_RETURN(tdbTbcOpen(pMeta->pTbDb, &pTbDbc, NULL));
(void)tdbTbcMoveTo(pTbDbc, &((STbDbKey){.uid = uid, .version = oversion}), sizeof(STbDbKey), &c);
if (c != 0) {
(void)tdbTbcClose(pUidIdxc);
@@ -1869,7 +1879,7 @@ static int metaUpdateTableOptions(SMeta *pMeta, int64_t version, SVAlterTbReq *p
// search uid index
TBC *pUidIdxc = NULL;
- (void)tdbTbcOpen(pMeta->pUidIdx, &pUidIdxc, NULL);
+ TAOS_CHECK_RETURN(tdbTbcOpen(pMeta->pUidIdx, &pUidIdxc, NULL));
(void)tdbTbcMoveTo(pUidIdxc, &uid, sizeof(uid), &c);
if (c != 0) {
(void)tdbTbcClose(pUidIdxc);
@@ -1883,7 +1893,7 @@ static int metaUpdateTableOptions(SMeta *pMeta, int64_t version, SVAlterTbReq *p
// search table.db
TBC *pTbDbc = NULL;
- (void)tdbTbcOpen(pMeta->pTbDb, &pTbDbc, NULL);
+ TAOS_CHECK_RETURN(tdbTbcOpen(pMeta->pTbDb, &pTbDbc, NULL));
(void)tdbTbcMoveTo(pTbDbc, &((STbDbKey){.uid = uid, .version = oversion}), sizeof(STbDbKey), &c);
if (c != 0) {
(void)tdbTbcClose(pUidIdxc);
@@ -2018,7 +2028,7 @@ static int metaAddTagIndex(SMeta *pMeta, int64_t version, SVAlterTbReq *pAlterTb
* iterator all pTdDbc by uid and version
*/
TBC *pCtbIdxc = NULL;
- (void)tdbTbcOpen(pMeta->pCtbIdx, &pCtbIdxc, NULL);
+ TAOS_CHECK_RETURN(tdbTbcOpen(pMeta->pCtbIdx, &pCtbIdxc, NULL));
int rc = tdbTbcMoveTo(pCtbIdxc, &(SCtbIdxKey){.suid = suid, .uid = INT64_MIN}, sizeof(SCtbIdxKey), &c);
if (rc < 0) {
(void)tdbTbcClose(pCtbIdxc);
@@ -2157,7 +2167,7 @@ static int metaDropTagIndex(SMeta *pMeta, int64_t version, SVAlterTbReq *pAlterT
SArray *tagIdxList = taosArrayInit(512, sizeof(SMetaPair));
TBC *pTagIdxc = NULL;
- (void)tdbTbcOpen(pMeta->pTagIdx, &pTagIdxc, NULL);
+ TAOS_CHECK_RETURN(tdbTbcOpen(pMeta->pTagIdx, &pTagIdxc, NULL));
int rc =
tdbTbcMoveTo(pTagIdxc, &(STagIdxKey){.suid = suid, .cid = INT32_MIN, .type = pCol->type}, sizeof(STagIdxKey), &c);
for (;;) {
diff --git a/source/dnode/vnode/src/tq/tqScan.c b/source/dnode/vnode/src/tq/tqScan.c
index d072d7199c..4357456790 100644
--- a/source/dnode/vnode/src/tq/tqScan.c
+++ b/source/dnode/vnode/src/tq/tqScan.c
@@ -101,6 +101,7 @@ int32_t tqScanData(STQ* pTq, STqHandle* pHandle, SMqDataRsp* pRsp, STqOffsetVal*
TSDB_CHECK_CODE(code, line, END);
qStreamSetSourceExcluded(task, pRequest->sourceExcluded);
+ uint64_t st = taosGetTimestampMs();
while (1) {
SSDataBlock* pDataBlock = NULL;
code = getDataBlock(task, pHandle, vgId, &pDataBlock);
@@ -160,7 +161,7 @@ int32_t tqScanData(STQ* pTq, STqHandle* pHandle, SMqDataRsp* pRsp, STqOffsetVal*
pRsp->common.blockNum++;
totalRows += pDataBlock->info.rows;
- if (totalRows >= tmqRowSize) {
+ if (totalRows >= tmqRowSize || (taosGetTimestampMs() - st > 1000)) {
break;
}
}
diff --git a/source/libs/command/src/command.c b/source/libs/command/src/command.c
index 2811402ea1..11ddc89d4c 100644
--- a/source/libs/command/src/command.c
+++ b/source/libs/command/src/command.c
@@ -38,7 +38,7 @@ static int32_t buildRetrieveTableRsp(SSDataBlock* pBlock, int32_t numOfCols, SRe
size_t rspSize = sizeof(SRetrieveTableRsp) + blockGetEncodeSize(pBlock) + PAYLOAD_PREFIX_LEN;
*pRsp = taosMemoryCalloc(1, rspSize);
if (NULL == *pRsp) {
- return TSDB_CODE_OUT_OF_MEMORY;
+ return terrno;
}
(*pRsp)->useconds = 0;
@@ -289,7 +289,7 @@ static int32_t buildRetension(SArray* pRetension, char **ppRetentions ) {
char* p1 = taosMemoryCalloc(1, 100);
if(NULL == p1) {
- return TSDB_CODE_OUT_OF_MEMORY;
+ return terrno;
}
int32_t len = 0;
@@ -849,7 +849,7 @@ _return:
static int32_t buildLocalVariablesResultDataBlock(SSDataBlock** pOutput) {
SSDataBlock* pBlock = taosMemoryCalloc(1, sizeof(SSDataBlock));
if (NULL == pBlock) {
- return TSDB_CODE_OUT_OF_MEMORY;
+ return terrno;
}
pBlock->info.hasVarCol = true;
diff --git a/source/libs/command/src/explain.c b/source/libs/command/src/explain.c
index 8d9f1fb9cc..3a73c05de2 100644
--- a/source/libs/command/src/explain.c
+++ b/source/libs/command/src/explain.c
@@ -227,7 +227,7 @@ int32_t qExplainGenerateResNode(SPhysiNode *pNode, SExplainGroup *group, SExplai
SExplainResNode *resNode = taosMemoryCalloc(1, sizeof(SExplainResNode));
if (NULL == resNode) {
qError("calloc SPhysiNodeExplainRes failed");
- return TSDB_CODE_OUT_OF_MEMORY;
+ return terrno;
}
int32_t code = 0;
diff --git a/source/libs/executor/src/aggregateoperator.c b/source/libs/executor/src/aggregateoperator.c
index af10bf8e49..093555c9c5 100644
--- a/source/libs/executor/src/aggregateoperator.c
+++ b/source/libs/executor/src/aggregateoperator.c
@@ -147,7 +147,10 @@ _error:
if (pInfo != NULL) {
destroyAggOperatorInfo(pInfo);
}
- destroyOperator(pOperator);
+ if (pOperator != NULL) {
+ pOperator->info = NULL;
+ destroyOperator(pOperator);
+ }
pTaskInfo->code = code;
return code;
}
@@ -340,6 +343,7 @@ int32_t doAggregateImpl(SOperatorInfo* pOperator, SqlFunctionCtx* pCtx) {
static int32_t createDataBlockForEmptyInput(SOperatorInfo* pOperator, SSDataBlock** ppBlock) {
int32_t code = TSDB_CODE_SUCCESS;
int32_t lino = 0;
+ SSDataBlock* pBlock = NULL;
if (!tsCountAlwaysReturnValue) {
return TSDB_CODE_SUCCESS;
}
@@ -363,7 +367,6 @@ static int32_t createDataBlockForEmptyInput(SOperatorInfo* pOperator, SSDataBloc
return TSDB_CODE_SUCCESS;
}
- SSDataBlock* pBlock = NULL;
code = createDataBlock(&pBlock);
if (code) {
return code;
@@ -411,6 +414,7 @@ static int32_t createDataBlockForEmptyInput(SOperatorInfo* pOperator, SSDataBloc
_end:
if (code != TSDB_CODE_SUCCESS) {
+ blockDataDestroy(pBlock);
qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code));
}
return code;
diff --git a/source/libs/executor/src/cachescanoperator.c b/source/libs/executor/src/cachescanoperator.c
index 652ebc0f9a..5c8ca49813 100644
--- a/source/libs/executor/src/cachescanoperator.c
+++ b/source/libs/executor/src/cachescanoperator.c
@@ -247,7 +247,10 @@ _error:
}
pInfo->pTableList = NULL;
destroyCacheScanOperator(pInfo);
- destroyOperator(pOperator);
+ if (pOperator != NULL) {
+ pOperator->info = NULL;
+ destroyOperator(pOperator);
+ }
return code;
}
@@ -448,7 +451,7 @@ void destroyCacheScanOperator(void* param) {
taosArrayDestroy(pInfo->matchInfo.pList);
tableListDestroy(pInfo->pTableList);
- if (pInfo->pLastrowReader != NULL) {
+ if (pInfo->pLastrowReader != NULL && pInfo->readHandle.api.cacheFn.closeReader != NULL) {
pInfo->readHandle.api.cacheFn.closeReader(pInfo->pLastrowReader);
pInfo->pLastrowReader = NULL;
}
diff --git a/source/libs/executor/src/countwindowoperator.c b/source/libs/executor/src/countwindowoperator.c
index 63c0c5fe87..9019fa0fef 100644
--- a/source/libs/executor/src/countwindowoperator.c
+++ b/source/libs/executor/src/countwindowoperator.c
@@ -294,10 +294,11 @@ int32_t createCountwindowOperatorInfo(SOperatorInfo* downstream, SPhysiNode* phy
SSDataBlock* pResBlock = createDataBlockFromDescNode(pCountWindowNode->window.node.pOutputDataBlockDesc);
QUERY_CHECK_NULL(pResBlock, code, lino, _error, terrno);
+ initBasicInfo(&pInfo->binfo, pResBlock);
+
code = blockDataEnsureCapacity(pResBlock, pOperator->resultInfo.capacity);
QUERY_CHECK_CODE(code, lino, _error);
- initBasicInfo(&pInfo->binfo, pResBlock);
initResultRowInfo(&pInfo->binfo.resultRowInfo);
pInfo->binfo.inputTsOrder = physiNode->inputTsOrder;
pInfo->binfo.outputTsOrder = physiNode->outputTsOrder;
@@ -341,7 +342,10 @@ _error:
destroyCountWindowOperatorInfo(pInfo);
}
- destroyOperator(pOperator);
+ if (pOperator != NULL) {
+ pOperator->info = NULL;
+ destroyOperator(pOperator);
+ }
pTaskInfo->code = code;
return code;
}
diff --git a/source/libs/executor/src/eventwindowoperator.c b/source/libs/executor/src/eventwindowoperator.c
index f9ae8be84f..d4e5dedd20 100644
--- a/source/libs/executor/src/eventwindowoperator.c
+++ b/source/libs/executor/src/eventwindowoperator.c
@@ -110,11 +110,11 @@ int32_t createEventwindowOperatorInfo(SOperatorInfo* downstream, SPhysiNode* phy
SSDataBlock* pResBlock = createDataBlockFromDescNode(pEventWindowNode->window.node.pOutputDataBlockDesc);
QUERY_CHECK_NULL(pResBlock, code, lino, _error, terrno);
+ initBasicInfo(&pInfo->binfo, pResBlock);
code = blockDataEnsureCapacity(pResBlock, pOperator->resultInfo.capacity);
QUERY_CHECK_CODE(code, lino, _error);
- initBasicInfo(&pInfo->binfo, pResBlock);
initResultRowInfo(&pInfo->binfo.resultRowInfo);
pInfo->binfo.inputTsOrder = physiNode->inputTsOrder;
pInfo->binfo.outputTsOrder = physiNode->outputTsOrder;
@@ -145,7 +145,10 @@ _error:
destroyEWindowOperatorInfo(pInfo);
}
- destroyOperator(pOperator);
+ if (pOperator != NULL) {
+ pOperator->info = NULL;
+ destroyOperator(pOperator);
+ }
pTaskInfo->code = code;
return code;
}
diff --git a/source/libs/executor/src/exchangeoperator.c b/source/libs/executor/src/exchangeoperator.c
index 22bb6524f1..e4ebb74252 100644
--- a/source/libs/executor/src/exchangeoperator.c
+++ b/source/libs/executor/src/exchangeoperator.c
@@ -452,7 +452,10 @@ _error:
doDestroyExchangeOperatorInfo(pInfo);
}
- destroyOperator(pOperator);
+ if (pOperator != NULL) {
+ pOperator->info = NULL;
+ destroyOperator(pOperator);
+ }
pTaskInfo->code = code;
return code;
}
@@ -707,8 +710,9 @@ void updateLoadRemoteInfo(SLoadRemoteDataInfo* pInfo, int64_t numOfRows, int32_t
}
int32_t extractDataBlockFromFetchRsp(SSDataBlock* pRes, char* pData, SArray* pColList, char** pNextStart) {
- int32_t code = TSDB_CODE_SUCCESS;
- int32_t lino = 0;
+ int32_t code = TSDB_CODE_SUCCESS;
+ int32_t lino = 0;
+ SSDataBlock* pBlock = NULL;
if (pColList == NULL) { // data from other sources
blockDataCleanup(pRes);
code = blockDecode(pRes, pData, (const char**)pNextStart);
@@ -731,7 +735,7 @@ int32_t extractDataBlockFromFetchRsp(SSDataBlock* pRes, char* pData, SArray* pCo
pStart += sizeof(SSysTableSchema);
}
- SSDataBlock* pBlock = NULL;
+ pBlock = NULL;
code = createDataBlock(&pBlock);
QUERY_CHECK_CODE(code, lino, _end);
@@ -756,10 +760,12 @@ int32_t extractDataBlockFromFetchRsp(SSDataBlock* pRes, char* pData, SArray* pCo
QUERY_CHECK_CODE(code, lino, _end);
blockDataDestroy(pBlock);
+ pBlock = NULL;
}
_end:
if (code != TSDB_CODE_SUCCESS) {
+ blockDataDestroy(pBlock);
qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
}
return code;
diff --git a/source/libs/executor/src/executil.c b/source/libs/executor/src/executil.c
index ae6351ab53..01d2ecd3c4 100644
--- a/source/libs/executor/src/executil.c
+++ b/source/libs/executor/src/executil.c
@@ -278,7 +278,7 @@ SSDataBlock* createDataBlockFromDescNode(SDataBlockDescNode* pNode) {
qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code));
blockDataDestroy(pBlock);
pBlock = NULL;
- terrno = code;
+ terrno = TSDB_CODE_INVALID_PARA;
break;
}
SColumnInfoData idata =
@@ -1094,7 +1094,7 @@ SSDataBlock* createTagValBlockForFilter(SArray* pColList, int32_t numOfTables, S
code = blockDataEnsureCapacity(pResBlock, numOfTables);
if (code != TSDB_CODE_SUCCESS) {
terrno = code;
- taosMemoryFree(pResBlock);
+ blockDataDestroy(pResBlock);
return NULL;
}
@@ -1166,7 +1166,7 @@ SSDataBlock* createTagValBlockForFilter(SArray* pColList, int32_t numOfTables, S
_end:
if (code != TSDB_CODE_SUCCESS) {
- taosMemoryFree(pResBlock);
+ blockDataDestroy(pResBlock);
qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
terrno = code;
return NULL;
diff --git a/source/libs/executor/src/filloperator.c b/source/libs/executor/src/filloperator.c
index 882a0dc4b6..f61b514626 100644
--- a/source/libs/executor/src/filloperator.c
+++ b/source/libs/executor/src/filloperator.c
@@ -567,7 +567,10 @@ _error:
}
pTaskInfo->code = code;
- destroyOperator(pOperator);
+ if (pOperator != NULL) {
+ pOperator->info = NULL;
+ destroyOperator(pOperator);
+ }
return code;
}
diff --git a/source/libs/executor/src/groupcacheoperator.c b/source/libs/executor/src/groupcacheoperator.c
index f2e24f160c..00b8c3b9ae 100644
--- a/source/libs/executor/src/groupcacheoperator.c
+++ b/source/libs/executor/src/groupcacheoperator.c
@@ -1504,7 +1504,10 @@ _error:
destroyGroupCacheOperator(pInfo);
}
- destroyOperator(pOperator);
+ if (pOperator != NULL) {
+ pOperator->info = NULL;
+ destroyOperator(pOperator);
+ }
pTaskInfo->code = code;
return code;
}
diff --git a/source/libs/executor/src/groupoperator.c b/source/libs/executor/src/groupoperator.c
index 309fb4b52f..69a9045004 100644
--- a/source/libs/executor/src/groupoperator.c
+++ b/source/libs/executor/src/groupoperator.c
@@ -1246,7 +1246,10 @@ _error:
destroyPartitionOperatorInfo(pInfo);
}
pTaskInfo->code = code;
- destroyOperator(pOperator);
+ if (pOperator != NULL) {
+ pOperator->info = NULL;
+ destroyOperator(pOperator);
+ }
TAOS_RETURN(code);
}
@@ -1792,7 +1795,10 @@ int32_t createStreamPartitionOperatorInfo(SOperatorInfo* downstream, SStreamPart
_error:
pTaskInfo->code = code;
if (pInfo != NULL) destroyStreamPartitionOperatorInfo(pInfo);
- destroyOperator(pOperator);
+ if (pOperator != NULL) {
+ pOperator->info = NULL;
+ destroyOperator(pOperator);
+ }
qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
return code;
}
diff --git a/source/libs/executor/src/operator.c b/source/libs/executor/src/operator.c
index 376890771c..c2913108b0 100644
--- a/source/libs/executor/src/operator.c
+++ b/source/libs/executor/src/operator.c
@@ -652,7 +652,7 @@ void destroyOperator(SOperatorInfo* pOperator) {
freeResetOperatorParams(pOperator, OP_GET_PARAM, true);
freeResetOperatorParams(pOperator, OP_NOTIFY_PARAM, true);
- if (pOperator->fpSet.closeFn != NULL) {
+ if (pOperator->fpSet.closeFn != NULL && pOperator->info != NULL) {
pOperator->fpSet.closeFn(pOperator->info);
}
diff --git a/source/libs/executor/src/projectoperator.c b/source/libs/executor/src/projectoperator.c
index 7c9f242a63..3f1eb43578 100644
--- a/source/libs/executor/src/projectoperator.c
+++ b/source/libs/executor/src/projectoperator.c
@@ -180,7 +180,10 @@ int32_t createProjectOperatorInfo(SOperatorInfo* downstream, SProjectPhysiNode*
_error:
destroyProjectOperatorInfo(pInfo);
- destroyOperator(pOperator);
+ if (pOperator != NULL) {
+ pOperator->info = NULL;
+ destroyOperator(pOperator);
+ }
pTaskInfo->code = code;
return code;
}
@@ -529,7 +532,10 @@ int32_t createIndefinitOutputOperatorInfo(SOperatorInfo* downstream, SPhysiNode*
_error:
destroyIndefinitOperatorInfo(pInfo);
- destroyOperator(pOperator);
+ if (pOperator != NULL) {
+ pOperator->info = NULL;
+ destroyOperator(pOperator);
+ }
pTaskInfo->code = code;
return code;
}
diff --git a/source/libs/executor/src/scanoperator.c b/source/libs/executor/src/scanoperator.c
index 9a50d3987f..c98f716ef2 100644
--- a/source/libs/executor/src/scanoperator.c
+++ b/source/libs/executor/src/scanoperator.c
@@ -1466,7 +1466,10 @@ _error:
destroyTableScanOperatorInfo(pInfo);
}
- destroyOperator(pOperator);
+ if (pOperator != NULL) {
+ pOperator->info = NULL;
+ destroyOperator(pOperator);
+ }
pTaskInfo->code = code;
return code;
}
@@ -3935,7 +3938,7 @@ static void destroyStreamScanOperatorInfo(void* param) {
destroyOperator(pStreamScan->pTableScanOp);
}
- if (pStreamScan->tqReader) {
+ if (pStreamScan->tqReader != NULL && pStreamScan->readerFn.tqReaderClose != NULL) {
pStreamScan->readerFn.tqReaderClose(pStreamScan->tqReader);
}
if (pStreamScan->matchInfo.pList) {
@@ -4306,7 +4309,10 @@ _error:
destroyStreamScanOperatorInfo(pInfo);
}
- destroyOperator(pOperator);
+ if (pOperator != NULL) {
+ pOperator->info = NULL;
+ destroyOperator(pOperator);
+ }
pTaskInfo->code = code;
return code;
}
@@ -4472,11 +4478,12 @@ static int32_t tagScanFilterByTagCond(SArray* aUidTags, SNode* pTagCond, SArray*
int32_t code = TSDB_CODE_SUCCESS;
int32_t lino = 0;
int32_t numOfTables = taosArrayGetSize(aUidTags);
+ SArray* pBlockList = NULL;
SSDataBlock* pResBlock = createTagValBlockForFilter(pInfo->filterCtx.cInfoList, numOfTables, aUidTags, pVnode, pAPI);
QUERY_CHECK_NULL(pResBlock, code, lino, _end, terrno);
- SArray* pBlockList = taosArrayInit(1, POINTER_BYTES);
+ pBlockList = taosArrayInit(1, POINTER_BYTES);
QUERY_CHECK_NULL(pBlockList, code, lino, _end, terrno);
void* tmp = taosArrayPush(pBlockList, &pResBlock);
@@ -4766,7 +4773,7 @@ static SSDataBlock* doTagScanFromMetaEntry(SOperatorInfo* pOperator) {
static void destroyTagScanOperatorInfo(void* param) {
STagScanInfo* pInfo = (STagScanInfo*)param;
- if (pInfo->pCtbCursor != NULL) {
+ if (pInfo->pCtbCursor != NULL && pInfo->pStorageAPI != NULL) {
pInfo->pStorageAPI->metaFn.closeCtbCursor(pInfo->pCtbCursor);
}
taosHashCleanup(pInfo->filterCtx.colHash);
@@ -4863,7 +4870,10 @@ _error:
}
if (pInfo != NULL) destroyTagScanOperatorInfo(pInfo);
- destroyOperator(pOperator);
+ if (pOperator != NULL) {
+ pOperator->info = NULL;
+ destroyOperator(pOperator);
+ }
return code;
}
@@ -5928,8 +5938,10 @@ void destroyTableMergeScanOperatorInfo(void* param) {
STableMergeScanInfo* pTableScanInfo = (STableMergeScanInfo*)param;
// start one reader variable
- pTableScanInfo->base.readerAPI.tsdReaderClose(pTableScanInfo->base.dataReader);
- pTableScanInfo->base.dataReader = NULL;
+ if (pTableScanInfo->base.readerAPI.tsdReaderClose != NULL) {
+ pTableScanInfo->base.readerAPI.tsdReaderClose(pTableScanInfo->base.dataReader);
+ pTableScanInfo->base.dataReader = NULL;
+ }
for (int32_t i = 0; i < pTableScanInfo->numNextDurationBlocks; ++i) {
if (pTableScanInfo->nextDurationBlocks[i] != NULL) {
@@ -5984,7 +5996,8 @@ int32_t createTableMergeScanOperatorInfo(STableScanPhysiNode* pTableScanNode, SR
SOperatorInfo** pOptrInfo) {
QRY_OPTR_CHECK(pOptrInfo);
- int32_t code = 0;
+ int32_t code = TSDB_CODE_SUCCESS;
+ int32_t lino = 0;
STableMergeScanInfo* pInfo = taosMemoryCalloc(1, sizeof(STableMergeScanInfo));
SOperatorInfo* pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
if (pInfo == NULL || pOperator == NULL) {
@@ -5997,16 +6010,10 @@ int32_t createTableMergeScanOperatorInfo(STableScanPhysiNode* pTableScanNode, SR
int32_t numOfCols = 0;
code = extractColMatchInfo(pTableScanNode->scan.pScanCols, pDescNode, &numOfCols, COL_MATCH_FROM_COL_ID,
&pInfo->base.matchInfo);
- int32_t lino = 0;
- if (code != TSDB_CODE_SUCCESS) {
- goto _error;
- }
+ QUERY_CHECK_CODE(code, lino, _error);
code = initQueryTableDataCond(&pInfo->base.cond, pTableScanNode, readHandle);
- if (code != TSDB_CODE_SUCCESS) {
- taosArrayDestroy(pInfo->base.matchInfo.pList);
- goto _error;
- }
+ QUERY_CHECK_CODE(code, lino, _error);
if (pTableScanNode->scan.pScanPseudoCols != NULL) {
SExprSupp* pSup = &pInfo->base.pseudoSup;
@@ -6021,10 +6028,7 @@ int32_t createTableMergeScanOperatorInfo(STableScanPhysiNode* pTableScanNode, SR
pInfo->scanInfo = (SScanInfo){.numOfAsc = pTableScanNode->scanSeq[0], .numOfDesc = pTableScanNode->scanSeq[1]};
pInfo->base.metaCache.pTableMetaEntryCache = taosLRUCacheInit(1024 * 128, -1, .5);
- if (pInfo->base.metaCache.pTableMetaEntryCache == NULL) {
- code = terrno;
- goto _error;
- }
+ QUERY_CHECK_NULL(pInfo->base.metaCache.pTableMetaEntryCache, code, lino, _error, terrno);
pInfo->base.readerAPI = pTaskInfo->storageAPI.tsdReader;
pInfo->base.dataBlockLoadFlag = FUNC_DATA_REQUIRED_DATA_LOAD;
@@ -6041,9 +6045,7 @@ int32_t createTableMergeScanOperatorInfo(STableScanPhysiNode* pTableScanNode, SR
pInfo->sample.seed = taosGetTimestampSec();
code = filterInitFromNode((SNode*)pTableScanNode->scan.node.pConditions, &pOperator->exprSupp.pFilterInfo, 0);
- if (code != TSDB_CODE_SUCCESS) {
- goto _error;
- }
+ QUERY_CHECK_CODE(code, lino, _error);
initLimitInfo(pTableScanNode->scan.node.pLimit, pTableScanNode->scan.node.pSlimit, &pInfo->limitInfo);
@@ -6105,10 +6107,16 @@ int32_t createTableMergeScanOperatorInfo(STableScanPhysiNode* pTableScanNode, SR
return code;
_error:
+ if (code != TSDB_CODE_SUCCESS) {
+ qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
+ }
pTaskInfo->code = code;
pInfo->base.pTableListInfo = NULL;
if (pInfo != NULL) destroyTableMergeScanOperatorInfo(pInfo);
- destroyOperator(pOperator);
+ if (pOperator != NULL) {
+ pOperator->info = NULL;
+ destroyOperator(pOperator);
+ }
return code;
}
@@ -6265,7 +6273,10 @@ _error:
if (pInfo != NULL) {
destoryTableCountScanOperator(pInfo);
}
- destroyOperator(pOperator);
+ if (pOperator != NULL) {
+ pOperator->info = NULL;
+ destroyOperator(pOperator);
+ }
pTaskInfo->code = code;
return code;
}
diff --git a/source/libs/executor/src/sortoperator.c b/source/libs/executor/src/sortoperator.c
index 2a1b4f3e23..59b4e1cbbb 100644
--- a/source/libs/executor/src/sortoperator.c
+++ b/source/libs/executor/src/sortoperator.c
@@ -164,7 +164,10 @@ _error:
destroySortOperatorInfo(pInfo);
}
- destroyOperator(pOperator);
+ if (pOperator != NULL) {
+ pOperator->info = NULL;
+ destroyOperator(pOperator);
+ }
pTaskInfo->code = code;
return code;
}
@@ -836,6 +839,9 @@ _error:
if (pInfo != NULL) {
destroyGroupSortOperatorInfo(pInfo);
}
- destroyOperator(pOperator);
+ if (pOperator != NULL) {
+ pOperator->info = NULL;
+ destroyOperator(pOperator);
+ }
return code;
}
diff --git a/source/libs/executor/src/streamcountwindowoperator.c b/source/libs/executor/src/streamcountwindowoperator.c
index 6a22269266..bbaf84a4cb 100644
--- a/source/libs/executor/src/streamcountwindowoperator.c
+++ b/source/libs/executor/src/streamcountwindowoperator.c
@@ -927,7 +927,10 @@ _error:
destroyStreamCountAggOperatorInfo(pInfo);
}
- destroyOperator(pOperator);
+ if (pOperator != NULL) {
+ pOperator->info = NULL;
+ destroyOperator(pOperator);
+ }
pTaskInfo->code = code;
qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
return code;
diff --git a/source/libs/executor/src/streameventwindowoperator.c b/source/libs/executor/src/streameventwindowoperator.c
index c31047757e..3e4ffdda6e 100644
--- a/source/libs/executor/src/streameventwindowoperator.c
+++ b/source/libs/executor/src/streameventwindowoperator.c
@@ -982,7 +982,10 @@ int32_t createStreamEventAggOperatorInfo(SOperatorInfo* downstream, SPhysiNode*
_error:
if (pInfo != NULL) destroyStreamEventOperatorInfo(pInfo);
- destroyOperator(pOperator);
+ if (pOperator != NULL) {
+ pOperator->info = NULL;
+ destroyOperator(pOperator);
+ }
pTaskInfo->code = code;
qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
return code;
diff --git a/source/libs/executor/src/streamfilloperator.c b/source/libs/executor/src/streamfilloperator.c
index 4cfacb03b4..29f96849ac 100644
--- a/source/libs/executor/src/streamfilloperator.c
+++ b/source/libs/executor/src/streamfilloperator.c
@@ -1458,7 +1458,10 @@ _error:
qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
}
if (pInfo != NULL) destroyStreamFillOperatorInfo(pInfo);
- destroyOperator(pOperator);
+ if (pOperator != NULL) {
+ pOperator->info = NULL;
+ destroyOperator(pOperator);
+ }
pTaskInfo->code = code;
return code;
}
diff --git a/source/libs/executor/src/streamtimewindowoperator.c b/source/libs/executor/src/streamtimewindowoperator.c
index f328aa15b9..6f5e17f5ab 100644
--- a/source/libs/executor/src/streamtimewindowoperator.c
+++ b/source/libs/executor/src/streamtimewindowoperator.c
@@ -2025,7 +2025,10 @@ int32_t createStreamFinalIntervalOperatorInfo(SOperatorInfo* downstream, SPhysiN
_error:
if (pInfo != NULL) destroyStreamFinalIntervalOperatorInfo(pInfo);
- destroyOperator(pOperator);
+ if (pOperator != NULL) {
+ pOperator->info = NULL;
+ destroyOperator(pOperator);
+ }
pTaskInfo->code = code;
return code;
}
@@ -3851,7 +3854,10 @@ _error:
destroyStreamSessionAggOperatorInfo(pInfo);
}
- destroyOperator(pOperator);
+ if (pOperator != NULL) {
+ pOperator->info = NULL;
+ destroyOperator(pOperator);
+ }
pTaskInfo->code = code;
qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
return code;
@@ -4107,7 +4113,10 @@ _error:
if (pInfo != NULL) {
destroyStreamSessionAggOperatorInfo(pInfo);
}
- destroyOperator(pOperator);
+ if (pOperator != NULL) {
+ pOperator->info = NULL;
+ destroyOperator(pOperator);
+ }
pTaskInfo->code = code;
if (code != TSDB_CODE_SUCCESS) {
qError("%s failed at line %d since %s. task:%s", __func__, lino, tstrerror(code), GET_TASKID(pTaskInfo));
@@ -4998,7 +5007,10 @@ int32_t createStreamStateAggOperatorInfo(SOperatorInfo* downstream, SPhysiNode*
_error:
if (pInfo != NULL) destroyStreamStateOperatorInfo(pInfo);
- destroyOperator(pOperator);
+ if (pOperator != NULL) {
+ pOperator->info = NULL;
+ destroyOperator(pOperator);
+ }
pTaskInfo->code = code;
qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
return code;
@@ -5211,6 +5223,8 @@ int32_t createStreamIntervalOperatorInfo(SOperatorInfo* downstream, SPhysiNode*
SSDataBlock* pResBlock = createDataBlockFromDescNode(pPhyNode->pOutputDataBlockDesc);
QUERY_CHECK_NULL(pResBlock, code, lino, _error, terrno);
+ initBasicInfo(&pInfo->binfo, pResBlock);
+
pInfo->interval = (SInterval){
.interval = pIntervalPhyNode->interval,
.sliding = pIntervalPhyNode->sliding,
@@ -5238,7 +5252,6 @@ int32_t createStreamIntervalOperatorInfo(SOperatorInfo* downstream, SPhysiNode*
SExprSupp* pSup = &pOperator->exprSupp;
pSup->hasWindowOrGroup = true;
- initBasicInfo(&pInfo->binfo, pResBlock);
code = initExecTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &pTaskInfo->window);
QUERY_CHECK_CODE(code, lino, _error);
@@ -5333,7 +5346,10 @@ int32_t createStreamIntervalOperatorInfo(SOperatorInfo* downstream, SPhysiNode*
_error:
if (pInfo != NULL) destroyStreamFinalIntervalOperatorInfo(pInfo);
- destroyOperator(pOperator);
+ if (pOperator != NULL) {
+ pOperator->info = NULL;
+ destroyOperator(pOperator);
+ }
pTaskInfo->code = code;
return code;
}
diff --git a/source/libs/executor/src/sysscanoperator.c b/source/libs/executor/src/sysscanoperator.c
index cdd22c2adc..e11ee6b0dc 100644
--- a/source/libs/executor/src/sysscanoperator.c
+++ b/source/libs/executor/src/sysscanoperator.c
@@ -568,7 +568,7 @@ static SSDataBlock* sysTableScanUserCols(SOperatorInfo* pOperator) {
if (pInfo->pCur == NULL) {
pInfo->pCur = pAPI->metaFn.openTableMetaCursor(pInfo->readHandle.vnode);
} else {
- pAPI->metaFn.resumeTableMetaCursor(pInfo->pCur, 0, 0);
+ (void)pAPI->metaFn.resumeTableMetaCursor(pInfo->pCur, 0, 0);
}
if (pInfo->pSchema == NULL) {
@@ -672,6 +672,7 @@ static SSDataBlock* sysTableScanUserCols(SOperatorInfo* pOperator) {
}
blockDataDestroy(pDataBlock);
+ pDataBlock = NULL;
if (ret != 0) {
pAPI->metaFn.closeTableMetaCursor(pInfo->pCur);
pInfo->pCur = NULL;
@@ -683,6 +684,7 @@ static SSDataBlock* sysTableScanUserCols(SOperatorInfo* pOperator) {
_end:
if (code != TSDB_CODE_SUCCESS) {
+ blockDataDestroy(pDataBlock);
qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
pTaskInfo->code = code;
T_LONG_JMP(pTaskInfo->env, code);
@@ -695,6 +697,7 @@ static SSDataBlock* sysTableScanUserTags(SOperatorInfo* pOperator) {
int32_t lino = 0;
SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
SStorageAPI* pAPI = &pTaskInfo->storageAPI;
+ SSDataBlock* dataBlock = NULL;
SSysTableScanInfo* pInfo = pOperator->info;
if (pOperator->status == OP_EXEC_DONE) {
@@ -704,7 +707,7 @@ static SSDataBlock* sysTableScanUserTags(SOperatorInfo* pOperator) {
blockDataCleanup(pInfo->pRes);
int32_t numOfRows = 0;
- SSDataBlock* dataBlock = buildInfoSchemaTableMetaBlock(TSDB_INS_TABLE_TAGS);
+ dataBlock = buildInfoSchemaTableMetaBlock(TSDB_INS_TABLE_TAGS);
code = blockDataEnsureCapacity(dataBlock, pOperator->resultInfo.capacity);
QUERY_CHECK_CODE(code, lino, _end);
@@ -777,8 +780,9 @@ static SSDataBlock* sysTableScanUserTags(SOperatorInfo* pOperator) {
int32_t ret = 0;
if (pInfo->pCur == NULL) {
pInfo->pCur = pAPI->metaFn.openTableMetaCursor(pInfo->readHandle.vnode);
+ QUERY_CHECK_NULL(pInfo->pCur, code, lino, _end, terrno);
} else {
- pAPI->metaFn.resumeTableMetaCursor(pInfo->pCur, 0, 0);
+ (void)pAPI->metaFn.resumeTableMetaCursor(pInfo->pCur, 0, 0);
}
while ((ret = pAPI->metaFn.cursorNext(pInfo->pCur, TSDB_SUPER_TABLE)) == 0) {
@@ -826,6 +830,7 @@ static SSDataBlock* sysTableScanUserTags(SOperatorInfo* pOperator) {
}
blockDataDestroy(dataBlock);
+ dataBlock = NULL;
if (ret != 0) {
pAPI->metaFn.closeTableMetaCursor(pInfo->pCur);
pInfo->pCur = NULL;
@@ -837,6 +842,7 @@ static SSDataBlock* sysTableScanUserTags(SOperatorInfo* pOperator) {
_end:
if (code != TSDB_CODE_SUCCESS) {
qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
+ blockDataDestroy(dataBlock);
pAPI->metaFn.closeTableMetaCursor(pInfo->pCur);
pInfo->pCur = NULL;
pTaskInfo->code = code;
@@ -1196,7 +1202,7 @@ static SSDataBlock* buildInfoSchemaTableMetaBlock(char* tableName) {
}
SSDataBlock* pBlock = NULL;
- int32_t code = createDataBlock(&pBlock);
+ int32_t code = createDataBlock(&pBlock);
if (code) {
terrno = code;
return NULL;
@@ -1310,9 +1316,11 @@ int32_t buildSysDbTableInfo(const SSysTableScanInfo* pInfo, int32_t capacity) {
QUERY_CHECK_CODE(code, lino, _end);
blockDataDestroy(p);
+ p = NULL;
_end:
if (code != TSDB_CODE_SUCCESS) {
+ blockDataDestroy(p);
qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
}
return code;
@@ -1325,6 +1333,7 @@ static SSDataBlock* sysTableBuildUserTablesByUids(SOperatorInfo* pOperator) {
SStorageAPI* pAPI = &pTaskInfo->storageAPI;
SSysTableScanInfo* pInfo = pOperator->info;
SSysTableIndex* pIdx = pInfo->pIdx;
+ SSDataBlock* p = NULL;
blockDataCleanup(pInfo->pRes);
int32_t numOfRows = 0;
@@ -1344,7 +1353,7 @@ static SSDataBlock* sysTableBuildUserTablesByUids(SOperatorInfo* pOperator) {
varDataSetLen(dbname, strlen(varDataVal(dbname)));
- SSDataBlock* p = buildInfoSchemaTableMetaBlock(TSDB_INS_TABLE_TABLES);
+ p = buildInfoSchemaTableMetaBlock(TSDB_INS_TABLE_TABLES);
code = blockDataEnsureCapacity(p, pOperator->resultInfo.capacity);
QUERY_CHECK_CODE(code, lino, _end);
@@ -1366,7 +1375,7 @@ static SSDataBlock* sysTableBuildUserTablesByUids(SOperatorInfo* pOperator) {
// table name
SColumnInfoData* pColInfoData = taosArrayGet(p->pDataBlock, 0);
QUERY_CHECK_NULL(pColInfoData, code, lino, _end, terrno);
-
+
code = colDataSetVal(pColInfoData, numOfRows, n, false);
QUERY_CHECK_CODE(code, lino, _end);
@@ -1545,12 +1554,14 @@ static SSDataBlock* sysTableBuildUserTablesByUids(SOperatorInfo* pOperator) {
}
blockDataDestroy(p);
+ p = NULL;
pInfo->loadInfo.totalRows += pInfo->pRes->info.rows;
_end:
if (code != TSDB_CODE_SUCCESS) {
qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
+ blockDataDestroy(p);
pTaskInfo->code = code;
T_LONG_JMP(pTaskInfo->env, code);
}
@@ -1563,14 +1574,16 @@ static SSDataBlock* sysTableBuildUserTables(SOperatorInfo* pOperator) {
SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
SStorageAPI* pAPI = &pTaskInfo->storageAPI;
int8_t firstMetaCursor = 0;
+ SSDataBlock* p = NULL;
SSysTableScanInfo* pInfo = pOperator->info;
if (pInfo->pCur == NULL) {
pInfo->pCur = pAPI->metaFn.openTableMetaCursor(pInfo->readHandle.vnode);
+ QUERY_CHECK_NULL(pInfo->pCur, code, lino, _end, terrno);
firstMetaCursor = 1;
}
if (!firstMetaCursor) {
- pAPI->metaFn.resumeTableMetaCursor(pInfo->pCur, 0, 1);
+ (void)pAPI->metaFn.resumeTableMetaCursor(pInfo->pCur, 0, 1);
}
blockDataCleanup(pInfo->pRes);
@@ -1590,7 +1603,7 @@ static SSDataBlock* sysTableBuildUserTables(SOperatorInfo* pOperator) {
varDataSetLen(dbname, strlen(varDataVal(dbname)));
- SSDataBlock* p = buildInfoSchemaTableMetaBlock(TSDB_INS_TABLE_TABLES);
+ p = buildInfoSchemaTableMetaBlock(TSDB_INS_TABLE_TABLES);
QUERY_CHECK_NULL(p, code, lino, _end, terrno);
code = blockDataEnsureCapacity(p, pOperator->resultInfo.capacity);
@@ -1783,6 +1796,7 @@ static SSDataBlock* sysTableBuildUserTables(SOperatorInfo* pOperator) {
}
blockDataDestroy(p);
+ p = NULL;
// todo temporarily free the cursor here, the true reason why the free is not valid needs to be found
if (ret != 0) {
@@ -1796,6 +1810,7 @@ static SSDataBlock* sysTableBuildUserTables(SOperatorInfo* pOperator) {
_end:
if (code != TSDB_CODE_SUCCESS) {
qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
+ blockDataDestroy(p);
pTaskInfo->code = code;
T_LONG_JMP(pTaskInfo->env, code);
}
@@ -2021,7 +2036,7 @@ static void sysTableScanFillTbName(SOperatorInfo* pOperator, const SSysTableScan
if (pInfo->tbnameSlotId != -1) {
SColumnInfoData* pColumnInfoData = (SColumnInfoData*)taosArrayGet(pBlock->pDataBlock, pInfo->tbnameSlotId);
QUERY_CHECK_NULL(pColumnInfoData, code, lino, _end, terrno);
- char varTbName[TSDB_TABLE_FNAME_LEN - 1 + VARSTR_HEADER_SIZE] = {0};
+ char varTbName[TSDB_TABLE_FNAME_LEN - 1 + VARSTR_HEADER_SIZE] = {0};
STR_TO_VARSTR(varTbName, name);
code = colDataSetNItems(pColumnInfoData, 0, varTbName, pBlock->info.rows, true);
@@ -2138,8 +2153,8 @@ static SSDataBlock* sysTableScanFromMNode(SOperatorInfo* pOperator, SSysTableSca
}
}
-int32_t createSysTableScanOperatorInfo(void* readHandle, SSystemTableScanPhysiNode* pScanPhyNode,
- const char* pUser, SExecTaskInfo* pTaskInfo, SOperatorInfo** pOptrInfo) {
+int32_t createSysTableScanOperatorInfo(void* readHandle, SSystemTableScanPhysiNode* pScanPhyNode, const char* pUser,
+ SExecTaskInfo* pTaskInfo, SOperatorInfo** pOptrInfo) {
QRY_OPTR_CHECK(pOptrInfo);
int32_t code = TSDB_CODE_SUCCESS;
@@ -2148,7 +2163,7 @@ int32_t createSysTableScanOperatorInfo(void* readHandle, SSystemTableScanPhysiNo
SOperatorInfo* pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
if (pInfo == NULL || pOperator == NULL) {
code = TSDB_CODE_OUT_OF_MEMORY;
- lino = __LINE__;
+ lino = __LINE__;
goto _error;
}
@@ -2209,7 +2224,10 @@ _error:
if (code != TSDB_CODE_SUCCESS) {
qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
}
- destroyOperator(pOperator);
+ if (pOperator != NULL) {
+ pOperator->info = NULL;
+ destroyOperator(pOperator);
+ }
pTaskInfo->code = code;
return code;
}
@@ -2244,7 +2262,7 @@ void destroySysScanOperator(void* param) {
if (strncasecmp(name, TSDB_INS_TABLE_TABLES, TSDB_TABLE_FNAME_LEN) == 0 ||
strncasecmp(name, TSDB_INS_TABLE_TAGS, TSDB_TABLE_FNAME_LEN) == 0 ||
strncasecmp(name, TSDB_INS_TABLE_COLS, TSDB_TABLE_FNAME_LEN) == 0 || pInfo->pCur != NULL) {
- if (pInfo->pAPI->metaFn.closeTableMetaCursor != NULL) {
+ if (pInfo->pAPI != NULL && pInfo->pAPI->metaFn.closeTableMetaCursor != NULL) {
pInfo->pAPI->metaFn.closeTableMetaCursor(pInfo->pCur);
}
@@ -2437,10 +2455,10 @@ static FORCE_INLINE int optSysBinarySearch(SArray* arr, int s, int e, uint64_t k
}
int32_t optSysIntersection(SArray* in, SArray* out) {
- int32_t code = TSDB_CODE_SUCCESS;
- int32_t lino = 0;
+ int32_t code = TSDB_CODE_SUCCESS;
+ int32_t lino = 0;
MergeIndex* mi = NULL;
- int32_t sz = (int32_t)taosArrayGetSize(in);
+ int32_t sz = (int32_t)taosArrayGetSize(in);
if (sz <= 0) {
goto _end;
}
@@ -2678,7 +2696,6 @@ static int32_t doBlockInfoScanNext(SOperatorInfo* pOperator, SSDataBlock** ppRes
int32_t slotId = pOperator->exprSupp.pExprInfo->base.resSchema.slotId;
SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, slotId);
QUERY_CHECK_NULL(pColInfo, code, lino, _end, terrno);
-
int32_t len = tSerializeBlockDistInfo(NULL, 0, &blockDistInfo);
char* p = taosMemoryCalloc(1, len + VARSTR_HEADER_SIZE);
@@ -2700,7 +2717,7 @@ static int32_t doBlockInfoScanNext(SOperatorInfo* pOperator, SSDataBlock** ppRes
if (slotId != 0) {
SColumnInfoData* p1 = taosArrayGet(pBlock->pDataBlock, 0);
QUERY_CHECK_NULL(p1, code, lino, _end, terrno);
- int64_t v = 0;
+ int64_t v = 0;
colDataSetInt64(p1, 0, &v);
}
@@ -2726,7 +2743,9 @@ static SSDataBlock* doBlockInfoScan(SOperatorInfo* pOperator) {
static void destroyBlockDistScanOperatorInfo(void* param) {
SBlockDistInfo* pDistInfo = (SBlockDistInfo*)param;
blockDataDestroy(pDistInfo->pResBlock);
- pDistInfo->readHandle.api.tsdReader.tsdReaderClose(pDistInfo->pHandle);
+ if (pDistInfo->readHandle.api.tsdReader.tsdReaderClose != NULL) {
+ pDistInfo->readHandle.api.tsdReader.tsdReaderClose(pDistInfo->pHandle);
+ }
tableListDestroy(pDistInfo->pTableListInfo);
taosMemoryFreeClear(param);
}
@@ -2760,11 +2779,12 @@ static int32_t initTableblockDistQueryCond(uint64_t uid, SQueryTableDataCond* pC
}
int32_t createDataBlockInfoScanOperator(SReadHandle* readHandle, SBlockDistScanPhysiNode* pBlockScanNode,
- STableListInfo* pTableListInfo, SExecTaskInfo* pTaskInfo, SOperatorInfo** pOptrInfo) {
+ STableListInfo* pTableListInfo, SExecTaskInfo* pTaskInfo,
+ SOperatorInfo** pOptrInfo) {
QRY_OPTR_CHECK(pOptrInfo);
- int32_t code = 0;
- int32_t lino = 0;
+ int32_t code = 0;
+ int32_t lino = 0;
SBlockDistInfo* pInfo = taosMemoryCalloc(1, sizeof(SBlockDistInfo));
SOperatorInfo* pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
if (pInfo == NULL || pOperator == NULL) {
@@ -2815,6 +2835,9 @@ _error:
pInfo->pTableListInfo = NULL;
destroyBlockDistScanOperatorInfo(pInfo);
}
- destroyOperator(pOperator);
+ if (pOperator != NULL) {
+ pOperator->info = NULL;
+ destroyOperator(pOperator);
+ }
return code;
}
diff --git a/source/libs/executor/src/timesliceoperator.c b/source/libs/executor/src/timesliceoperator.c
index d3d7a51cbe..30569db738 100644
--- a/source/libs/executor/src/timesliceoperator.c
+++ b/source/libs/executor/src/timesliceoperator.c
@@ -1208,7 +1208,10 @@ _error:
qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
}
if (pInfo != NULL) destroyTimeSliceOperatorInfo(pInfo);
- destroyOperator(pOperator);
+ if (pOperator != NULL) {
+ pOperator->info = NULL;
+ destroyOperator(pOperator);
+ }
pTaskInfo->code = code;
return code;
}
diff --git a/source/libs/executor/src/timewindowoperator.c b/source/libs/executor/src/timewindowoperator.c
index 99fa941071..ca6b89f7c5 100644
--- a/source/libs/executor/src/timewindowoperator.c
+++ b/source/libs/executor/src/timewindowoperator.c
@@ -1414,7 +1414,10 @@ _error:
if (pInfo != NULL) {
destroyIntervalOperatorInfo(pInfo);
}
- destroyOperator(pOperator);
+ if (pOperator != NULL) {
+ pOperator->info = NULL;
+ destroyOperator(pOperator);
+ }
pTaskInfo->code = code;
return code;
}
@@ -1690,7 +1693,10 @@ _error:
destroyStateWindowOperatorInfo(pInfo);
}
- destroyOperator(pOperator);
+ if (pOperator != NULL) {
+ pOperator->info = NULL;
+ destroyOperator(pOperator);
+ }
pTaskInfo->code = code;
return code;
}
@@ -1783,7 +1789,10 @@ int32_t createSessionAggOperatorInfo(SOperatorInfo* downstream, SSessionWinodwPh
_error:
if (pInfo != NULL) destroySWindowOperatorInfo(pInfo);
- destroyOperator(pOperator);
+ if (pOperator != NULL) {
+ pOperator->info = NULL;
+ destroyOperator(pOperator);
+ }
pTaskInfo->code = code;
return code;
}
@@ -2094,8 +2103,11 @@ int32_t createMergeAlignedIntervalOperatorInfo(SOperatorInfo* downstream, SMerge
return code;
_error:
- destroyMAIOperatorInfo(miaInfo);
- destroyOperator(pOperator);
+ if (miaInfo != NULL) destroyMAIOperatorInfo(miaInfo);
+ if (pOperator != NULL) {
+ pOperator->info = NULL;
+ destroyOperator(pOperator);
+ }
pTaskInfo->code = code;
return code;
}
@@ -2427,7 +2439,10 @@ _error:
destroyMergeIntervalOperatorInfo(pMergeIntervalInfo);
}
- destroyOperator(pOperator);
+ if (pOperator != NULL) {
+ pOperator->info = NULL;
+ destroyOperator(pOperator);
+ }
pTaskInfo->code = code;
return code;
}
diff --git a/source/libs/executor/src/tsort.c b/source/libs/executor/src/tsort.c
index 9e902140f4..cedc23ed2d 100644
--- a/source/libs/executor/src/tsort.c
+++ b/source/libs/executor/src/tsort.c
@@ -152,8 +152,10 @@ static void destoryAllocatedTuple(void* t) { taosMemoryFree(t); }
* @param colIndex the columnIndex, for setting null bitmap
* @return the next offset to add field
* */
-static inline size_t tupleAddField(char** t, uint32_t colNum, uint32_t offset, uint32_t colIdx, void* data,
- size_t length, bool isNull, uint32_t tupleLen) {
+static inline int32_t tupleAddField(char** t, uint32_t colNum, uint32_t offset, uint32_t colIdx, void* data,
+ size_t length, bool isNull, uint32_t tupleLen, uint32_t* pOffset) {
+ int32_t code = TSDB_CODE_SUCCESS;
+ int32_t lino = 0;
tupleSetOffset(*t, colIdx, offset);
if (isNull) {
@@ -161,16 +163,20 @@ static inline size_t tupleAddField(char** t, uint32_t colNum, uint32_t offset, u
} else {
if (offset + length > tupleLen + tupleGetDataStartOffset(colNum)) {
void* px = taosMemoryRealloc(*t, offset + length);
- if (px == NULL) {
- return terrno;
- }
+ QUERY_CHECK_NULL(px, code, lino, _end, terrno);
*t = px;
}
tupleSetData(*t, offset, data, length);
}
- return offset + length;
+ (*pOffset) = offset + length;
+
+_end:
+ if (code != TSDB_CODE_SUCCESS) {
+ qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
+ }
+ return code;
}
static void* tupleGetField(char* t, uint32_t colIdx, uint32_t colNum) {
@@ -200,6 +206,7 @@ typedef struct ReferencedTuple {
} ReferencedTuple;
static int32_t createAllocatedTuple(SSDataBlock* pBlock, size_t colNum, uint32_t tupleLen, size_t rowIdx, TupleDesc** pDesc) {
+ int32_t code = TSDB_CODE_SUCCESS;
TupleDesc* t = taosMemoryCalloc(1, sizeof(TupleDesc));
if (t == NULL) {
return terrno;
@@ -216,15 +223,20 @@ static int32_t createAllocatedTuple(SSDataBlock* pBlock, size_t colNum, uint32_t
for (size_t colIdx = 0; colIdx < colNum; ++colIdx) {
SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, colIdx);
if (pCol == NULL) {
+ qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
return terrno;
}
if (colDataIsNull_s(pCol, rowIdx)) {
- offset = tupleAddField((char**)&pTuple, colNum, offset, colIdx, 0, 0, true, tupleLen);
+ code = tupleAddField((char**)&pTuple, colNum, offset, colIdx, 0, 0, true, tupleLen, &offset);
} else {
colLen = colDataGetRowLength(pCol, rowIdx);
- offset =
- tupleAddField((char**)&pTuple, colNum, offset, colIdx, colDataGetData(pCol, rowIdx), colLen, false, tupleLen);
+ code =
+ tupleAddField((char**)&pTuple, colNum, offset, colIdx, colDataGetData(pCol, rowIdx), colLen, false, tupleLen, &offset);
+ }
+ if (code != TSDB_CODE_SUCCESS) {
+ qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code));
+ return code;
}
}
@@ -232,7 +244,7 @@ static int32_t createAllocatedTuple(SSDataBlock* pBlock, size_t colNum, uint32_t
t->data = pTuple;
*pDesc = t;
- return 0;
+ return code;
}
int32_t tupleDescGetField(const TupleDesc* pDesc, int32_t colIdx, uint32_t colNum, void** pResult) {
@@ -259,7 +271,7 @@ int32_t tupleDescGetField(const TupleDesc* pDesc, int32_t colIdx, uint32_t colNu
void destroyTuple(void* t) {
TupleDesc* pDesc = t;
- if (pDesc->type == AllocatedTupleType) {
+ if (pDesc != NULL && pDesc->type == AllocatedTupleType) {
destoryAllocatedTuple(pDesc->data);
taosMemoryFree(pDesc);
}
@@ -1686,6 +1698,7 @@ static int32_t initRowIdSort(SSortHandle* pHandle) {
biTs.compFn = getKeyComparFunc(TSDB_DATA_TYPE_TIMESTAMP, biTs.order);
void* p = taosArrayPush(pOrderInfoList, &biTs);
if (p == NULL) {
+ taosArrayDestroy(pOrderInfoList);
return terrno;
}
@@ -1698,6 +1711,7 @@ static int32_t initRowIdSort(SSortHandle* pHandle) {
void* px = taosArrayPush(pOrderInfoList, &biPk);
if (px == NULL) {
+ taosArrayDestroy(pOrderInfoList);
return terrno;
}
}
diff --git a/source/libs/function/src/tudf.c b/source/libs/function/src/tudf.c
index ad9e5ce7d4..9a751db801 100644
--- a/source/libs/function/src/tudf.c
+++ b/source/libs/function/src/tudf.c
@@ -162,7 +162,7 @@ static int32_t udfSpawnUdfd(SUdfdData *pData) {
fnInfo("[UDFD]Succsess to set TAOS_FQDN:%s", taosFqdn);
} else {
fnError("[UDFD]Failed to allocate memory for TAOS_FQDN");
- return TSDB_CODE_OUT_OF_MEMORY;
+ return terrno;
}
}
@@ -837,10 +837,13 @@ int32_t convertDataBlockToUdfDataBlock(SSDataBlock *block, SUdfDataBlock *udfBlo
udfBlock->numOfRows = block->info.rows;
udfBlock->numOfCols = taosArrayGetSize(block->pDataBlock);
udfBlock->udfCols = taosMemoryCalloc(taosArrayGetSize(block->pDataBlock), sizeof(SUdfColumn *));
+ if((udfBlock->udfCols) == NULL) {
+ return terrno;
+ }
for (int32_t i = 0; i < udfBlock->numOfCols; ++i) {
udfBlock->udfCols[i] = taosMemoryCalloc(1, sizeof(SUdfColumn));
if(udfBlock->udfCols[i] == NULL) {
- return TSDB_CODE_OUT_OF_MEMORY;
+ return terrno;
}
SColumnInfoData *col = (SColumnInfoData *)taosArrayGet(block->pDataBlock, i);
SUdfColumn *udfCol = udfBlock->udfCols[i];
@@ -854,13 +857,13 @@ int32_t convertDataBlockToUdfDataBlock(SSDataBlock *block, SUdfDataBlock *udfBlo
udfCol->colData.varLenCol.varOffsetsLen = sizeof(int32_t) * udfBlock->numOfRows;
udfCol->colData.varLenCol.varOffsets = taosMemoryMalloc(udfCol->colData.varLenCol.varOffsetsLen);
if(udfCol->colData.varLenCol.varOffsets == NULL) {
- return TSDB_CODE_OUT_OF_MEMORY;
+ return terrno;
}
memcpy(udfCol->colData.varLenCol.varOffsets, col->varmeta.offset, udfCol->colData.varLenCol.varOffsetsLen);
udfCol->colData.varLenCol.payloadLen = colDataGetLength(col, udfBlock->numOfRows);
udfCol->colData.varLenCol.payload = taosMemoryMalloc(udfCol->colData.varLenCol.payloadLen);
if(udfCol->colData.varLenCol.payload == NULL) {
- return TSDB_CODE_OUT_OF_MEMORY;
+ return terrno;
}
if (col->reassigned) {
for (int32_t row = 0; row < udfCol->colData.numOfRows; ++row) {
@@ -882,7 +885,7 @@ int32_t convertDataBlockToUdfDataBlock(SSDataBlock *block, SUdfDataBlock *udfBlo
int32_t bitmapLen = udfCol->colData.fixLenCol.nullBitmapLen;
udfCol->colData.fixLenCol.nullBitmap = taosMemoryMalloc(udfCol->colData.fixLenCol.nullBitmapLen);
if(udfCol->colData.fixLenCol.nullBitmap == NULL) {
- return TSDB_CODE_OUT_OF_MEMORY;
+ return terrno;
}
char *bitmap = udfCol->colData.fixLenCol.nullBitmap;
memcpy(bitmap, col->nullbitmap, bitmapLen);
@@ -985,7 +988,7 @@ int32_t convertDataBlockToScalarParm(SSDataBlock *input, SScalarParam *output) {
output->columnData = taosMemoryMalloc(sizeof(SColumnInfoData));
if(output->columnData == NULL) {
- return TSDB_CODE_OUT_OF_MEMORY;
+ return terrno;
}
memcpy(output->columnData, taosArrayGet(input->pDataBlock, 0), sizeof(SColumnInfoData));
output->colAlloced = true;
@@ -1724,7 +1727,7 @@ int32_t udfcStartUvTask(SClientUvTaskNode *uvTask) {
if(conn == NULL) {
fnError("udfc event loop start connect task malloc conn failed.");
taosMemoryFree(pipe);
- return TSDB_CODE_OUT_OF_MEMORY;
+ return terrno;
}
conn->pipe = pipe;
conn->readBuf.len = 0;
@@ -1954,7 +1957,7 @@ int32_t udfcRunUdfUvTask(SClientUdfTask *task, int8_t uvTaskType) {
SClientUvTaskNode *uvTask = taosMemoryCalloc(1, sizeof(SClientUvTaskNode));
if(uvTask == NULL) {
fnError("udfc client task: %p failed to allocate memory for uvTask", task);
- return TSDB_CODE_OUT_OF_MEMORY;
+ return terrno;
}
fnDebug("udfc client task: %p created uvTask: %p. pipe: %p", task, uvTask, task->session->udfUvPipe);
@@ -1986,13 +1989,13 @@ int32_t doSetupUdf(char udfName[], UdfcFuncHandle *funcHandle) {
SClientUdfTask *task = taosMemoryCalloc(1, sizeof(SClientUdfTask));
if(task == NULL) {
fnError("doSetupUdf, failed to allocate memory for task");
- return TSDB_CODE_OUT_OF_MEMORY;
+ return terrno;
}
task->session = taosMemoryCalloc(1, sizeof(SUdfcUvSession));
if(task->session == NULL) {
fnError("doSetupUdf, failed to allocate memory for session");
taosMemoryFree(task);
- return TSDB_CODE_OUT_OF_MEMORY;
+ return terrno;
}
task->session->udfc = &gUdfcProxy;
task->type = UDF_TASK_SETUP;
@@ -2037,7 +2040,7 @@ int32_t callUdf(UdfcFuncHandle handle, int8_t callType, SSDataBlock *input, SUdf
SClientUdfTask *task = taosMemoryCalloc(1, sizeof(SClientUdfTask));
if(task == NULL) {
fnError("udfc call udf. failed to allocate memory for task");
- return TSDB_CODE_OUT_OF_MEMORY;
+ return terrno;
}
task->session = (SUdfcUvSession *)handle;
task->type = UDF_TASK_CALL;
@@ -2169,7 +2172,7 @@ int32_t doTeardownUdf(UdfcFuncHandle handle) {
if(task == NULL) {
fnError("doTeardownUdf, failed to allocate memory for task");
taosMemoryFree(session);
- return TSDB_CODE_OUT_OF_MEMORY;
+ return terrno;
}
task->session = session;
task->type = UDF_TASK_TEARDOWN;
diff --git a/source/libs/function/src/udfd.c b/source/libs/function/src/udfd.c
index 7339f115a3..2d8a926c72 100644
--- a/source/libs/function/src/udfd.c
+++ b/source/libs/function/src/udfd.c
@@ -409,6 +409,10 @@ int32_t udfdInitializePythonPlugin(SUdfScriptPlugin *plugin) {
int16_t lenPythonPath =
strlen(tsUdfdLdLibPath) + strlen(global.udfDataDir) + 1 + 1; // global.udfDataDir:tsUdfdLdLibPath
char *pythonPath = taosMemoryMalloc(lenPythonPath);
+ if(pythonPath == NULL) {
+ uv_dlclose(&plugin->lib);
+ return terrno;
+ }
#ifdef WINDOWS
snprintf(pythonPath, lenPythonPath, "%s;%s", global.udfDataDir, tsUdfdLdLibPath);
#else
@@ -705,6 +709,10 @@ void udfdProcessSetupRequest(SUvUdfWork *uvUdf, SUdfRequest *request) {
uv_mutex_unlock(&udf->lock);
}
SUdfcFuncHandle *handle = taosMemoryMalloc(sizeof(SUdfcFuncHandle));
+ if(handle == NULL) {
+ fnError("udfdProcessSetupRequest: malloc failed.");
+ code = terrno;
+ }
handle->udf = udf;
_send:
@@ -775,7 +783,7 @@ void udfdProcessCallRequest(SUvUdfWork *uvUdf, SUdfRequest *request) {
if (outBuf.buf != NULL) {
code = udf->scriptPlugin->udfAggStartFunc(&outBuf, udf->scriptUdfCtx);
} else {
- code = TSDB_CODE_OUT_OF_MEMORY;
+ code = terrno;
}
subRsp->resultBuf = outBuf;
break;
@@ -784,9 +792,13 @@ void udfdProcessCallRequest(SUvUdfWork *uvUdf, SUdfRequest *request) {
SUdfDataBlock input = {0};
if (convertDataBlockToUdfDataBlock(&call->block, &input) == TSDB_CODE_SUCCESS) {
SUdfInterBuf outBuf = {.buf = taosMemoryMalloc(udf->bufSize), .bufLen = udf->bufSize, .numOfResult = 0};
- code = udf->scriptPlugin->udfAggProcFunc(&input, &call->interBuf, &outBuf, udf->scriptUdfCtx);
- freeUdfInterBuf(&call->interBuf);
- subRsp->resultBuf = outBuf;
+ if (outBuf.buf != NULL) {
+ code = udf->scriptPlugin->udfAggProcFunc(&input, &call->interBuf, &outBuf, udf->scriptUdfCtx);
+ freeUdfInterBuf(&call->interBuf);
+ subRsp->resultBuf = outBuf;
+ } else {
+ code = terrno;
+ }
}
freeUdfDataDataBlock(&input);
@@ -794,18 +806,27 @@ void udfdProcessCallRequest(SUvUdfWork *uvUdf, SUdfRequest *request) {
}
case TSDB_UDF_CALL_AGG_MERGE: {
SUdfInterBuf outBuf = {.buf = taosMemoryMalloc(udf->bufSize), .bufLen = udf->bufSize, .numOfResult = 0};
- code = udf->scriptPlugin->udfAggMergeFunc(&call->interBuf, &call->interBuf2, &outBuf, udf->scriptUdfCtx);
- freeUdfInterBuf(&call->interBuf);
- freeUdfInterBuf(&call->interBuf2);
- subRsp->resultBuf = outBuf;
+ if (outBuf.buf != NULL) {
+ code = udf->scriptPlugin->udfAggMergeFunc(&call->interBuf, &call->interBuf2, &outBuf, udf->scriptUdfCtx);
+ freeUdfInterBuf(&call->interBuf);
+ freeUdfInterBuf(&call->interBuf2);
+ subRsp->resultBuf = outBuf;
+ } else {
+ code = terrno;
+ }
break;
}
case TSDB_UDF_CALL_AGG_FIN: {
SUdfInterBuf outBuf = {.buf = taosMemoryMalloc(udf->bufSize), .bufLen = udf->bufSize, .numOfResult = 0};
- code = udf->scriptPlugin->udfAggFinishFunc(&call->interBuf, &outBuf, udf->scriptUdfCtx);
- freeUdfInterBuf(&call->interBuf);
- subRsp->resultBuf = outBuf;
+ if (outBuf.buf != NULL) {
+ code = udf->scriptPlugin->udfAggFinishFunc(&call->interBuf, &outBuf, udf->scriptUdfCtx);
+ freeUdfInterBuf(&call->interBuf);
+ subRsp->resultBuf = outBuf;
+ } else {
+ code = terrno;
+ }
+
break;
}
default:
@@ -820,19 +841,24 @@ void udfdProcessCallRequest(SUvUdfWork *uvUdf, SUdfRequest *request) {
int32_t len = encodeUdfResponse(NULL, rsp);
if(len < 0) {
fnError("udfdProcessCallRequest: encode udf response failed. len %d", len);
- return;
+ goto _exit;
}
rsp->msgLen = len;
void *bufBegin = taosMemoryMalloc(len);
+ if (bufBegin == NULL) {
+ fnError("udfdProcessCallRequest: malloc failed. len %d", len);
+ goto _exit;
+ }
void *buf = bufBegin;
if(encodeUdfResponse(&buf, rsp) < 0) {
fnError("udfdProcessCallRequest: encode udf response failed. len %d", len);
taosMemoryFree(bufBegin);
- return;
+ goto _exit;
}
uvUdf->output = uv_buf_init(bufBegin, len);
+_exit:
switch (call->callType) {
case TSDB_UDF_CALL_SCALA_PROC: {
blockDataFreeRes(&call->block);
@@ -906,6 +932,10 @@ _send:
}
rsp->msgLen = len;
void *bufBegin = taosMemoryMalloc(len);
+ if(bufBegin == NULL) {
+ fnError("udfdProcessTeardownRequest: malloc failed. len %d", len);
+ return;
+ }
void *buf = bufBegin;
if (encodeUdfResponse(&buf, rsp) < 0) {
fnError("udfdProcessTeardownRequest: encode udf response failed. len %d", len);
@@ -1173,7 +1203,7 @@ int32_t udfdOpenClientRpc() {
global.clientRpc = rpcOpen(&rpcInit);
if (global.clientRpc == NULL) {
fnError("failed to init dnode rpc client");
- return -1;
+ return terrno;
}
return 0;
}
@@ -1210,6 +1240,11 @@ void udfdSendResponse(uv_work_t *work, int status) {
if (udfWork->conn != NULL) {
uv_write_t *write_req = taosMemoryMalloc(sizeof(uv_write_t));
+ if(write_req == NULL) {
+ fnError("udfd send response error, malloc failed");
+ taosMemoryFree(work);
+ return;
+ }
write_req->data = udfWork;
int32_t code = uv_write(write_req, udfWork->conn->client, &udfWork->output, 1, udfdOnWrite);
if (code != 0) {
@@ -1269,7 +1304,16 @@ void udfdHandleRequest(SUdfdUvConn *conn) {
int32_t inputLen = conn->inputLen;
uv_work_t *work = taosMemoryMalloc(sizeof(uv_work_t));
+ if(work == NULL) {
+ fnError("udfd malloc work failed");
+ return;
+ }
SUvUdfWork *udfWork = taosMemoryMalloc(sizeof(SUvUdfWork));
+ if(udfWork == NULL) {
+ fnError("udfd malloc udf work failed");
+ taosMemoryFree(work);
+ return;
+ }
udfWork->conn = conn;
udfWork->pWorkNext = conn->pWorkList;
conn->pWorkList = udfWork;
@@ -1334,6 +1378,10 @@ void udfdOnNewConnection(uv_stream_t *server, int status) {
int32_t code = 0;
uv_pipe_t *client = (uv_pipe_t *)taosMemoryMalloc(sizeof(uv_pipe_t));
+ if(client == NULL) {
+ fnError("udfd pipe malloc failed");
+ return;
+ }
code = uv_pipe_init(global.loop, client, 0);
if (code) {
fnError("udfd pipe init error %s", uv_strerror(code));
@@ -1342,6 +1390,10 @@ void udfdOnNewConnection(uv_stream_t *server, int status) {
}
if (uv_accept(server, (uv_stream_t *)client) == 0) {
SUdfdUvConn *ctx = taosMemoryMalloc(sizeof(SUdfdUvConn));
+ if(ctx == NULL) {
+ fnError("udfd conn malloc failed");
+ goto _exit;
+ }
ctx->pWorkList = NULL;
ctx->client = (uv_stream_t *)client;
ctx->inputBuf = 0;
@@ -1356,9 +1408,11 @@ void udfdOnNewConnection(uv_stream_t *server, int status) {
taosMemoryFree(ctx);
taosMemoryFree(client);
}
- } else {
- uv_close((uv_handle_t *)client, NULL);
+ return;
}
+_exit:
+ uv_close((uv_handle_t *)client, NULL);
+ taosMemoryFree(client);
}
void udfdIntrSignalHandler(uv_signal_t *handle, int signum) {
@@ -1411,6 +1465,10 @@ static int32_t udfdInitLog() {
void udfdCtrlAllocBufCb(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf) {
buf->base = taosMemoryMalloc(suggested_size);
+ if (buf->base == NULL) {
+ fnError("udfd ctrl pipe alloc buffer failed");
+ return;
+ }
buf->len = suggested_size;
}
@@ -1477,13 +1535,13 @@ static int32_t udfdGlobalDataInit() {
uv_loop_t *loop = taosMemoryMalloc(sizeof(uv_loop_t));
if (loop == NULL) {
fnError("udfd init uv loop failed, mem overflow");
- return -1;
+ return terrno;
}
global.loop = loop;
if (uv_mutex_init(&global.scriptPluginsMutex) != 0) {
fnError("udfd init script plugins mutex failed");
- return -1;
+ return TSDB_CODE_UDF_UV_EXEC_FAILURE;
}
global.udfsHash = taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
@@ -1494,7 +1552,7 @@ static int32_t udfdGlobalDataInit() {
if (uv_mutex_init(&global.udfsMutex) != 0) {
fnError("udfd init udfs mutex failed");
- return -2;
+ return TSDB_CODE_UDF_UV_EXEC_FAILURE;
}
return 0;
diff --git a/source/libs/qcom/src/querymsg.c b/source/libs/qcom/src/querymsg.c
index e8deed1df9..207bd91bd9 100644
--- a/source/libs/qcom/src/querymsg.c
+++ b/source/libs/qcom/src/querymsg.c
@@ -34,7 +34,7 @@ int32_t queryBuildUseDbOutput(SUseDbOutput *pOut, SUseDbRsp *usedbRsp) {
pOut->dbVgroup = taosMemoryCalloc(1, sizeof(SDBVgInfo));
if (NULL == pOut->dbVgroup) {
- return TSDB_CODE_OUT_OF_MEMORY;
+ return terrno;
}
pOut->dbVgroup->vgVersion = usedbRsp->vgVersion;
@@ -509,7 +509,7 @@ int32_t queryCreateTableMetaFromMsg(STableMetaRsp *msg, bool isStb, STableMeta *
STableMeta *pTableMeta = taosMemoryCalloc(1, metaSize + schemaExtSize);
if (NULL == pTableMeta) {
qError("calloc size[%d] failed", metaSize);
- return TSDB_CODE_OUT_OF_MEMORY;
+ return terrno;
}
SSchemaExt *pSchemaExt = (SSchemaExt *)((char *)pTableMeta + metaSize);
@@ -764,7 +764,7 @@ int32_t queryProcessGetTbCfgRsp(void *output, char *msg, int32_t msgSize) {
STableCfgRsp *out = taosMemoryCalloc(1, sizeof(STableCfgRsp));
if(out == NULL) {
- return TSDB_CODE_OUT_OF_MEMORY;
+ return terrno;
}
if (tDeserializeSTableCfgRsp(msg, msgSize, out) != 0) {
qError("tDeserializeSTableCfgRsp failed, msgSize:%d", msgSize);
@@ -785,7 +785,7 @@ int32_t queryProcessGetViewMetaRsp(void *output, char *msg, int32_t msgSize) {
SViewMetaRsp *out = taosMemoryCalloc(1, sizeof(SViewMetaRsp));
if (out == NULL) {
- return TSDB_CODE_OUT_OF_MEMORY;
+ return terrno;
}
if (tDeserializeSViewMetaRsp(msg, msgSize, out) != 0) {
qError("tDeserializeSViewMetaRsp failed, msgSize:%d", msgSize);
diff --git a/source/libs/scalar/src/filter.c b/source/libs/scalar/src/filter.c
index 5226668f82..e5d0fe594a 100644
--- a/source/libs/scalar/src/filter.c
+++ b/source/libs/scalar/src/filter.c
@@ -2343,7 +2343,7 @@ _return:
(void)filterFreeRangeCtx(ctx); // No need to handle the return value.
- return TSDB_CODE_SUCCESS;
+ return code;
}
int32_t filterMergeGroupUnits(SFilterInfo *info, SFilterGroupCtx **gRes, int32_t *gResNum) {
@@ -2671,7 +2671,7 @@ _return:
(void)filterFreeRangeCtx(ctx); // No need to handle the return value.
- return TSDB_CODE_SUCCESS;
+ return code;
}
int32_t filterMergeGroups(SFilterInfo *info, SFilterGroupCtx **gRes, int32_t *gResNum) {
@@ -2758,7 +2758,7 @@ _return:
FILTER_SET_FLAG(info->status, FI_STATUS_ALL);
- return TSDB_CODE_SUCCESS;
+ return code;
}
int32_t filterConvertGroupFromArray(SFilterInfo *info, SArray *group) {
@@ -2958,7 +2958,7 @@ _return:
taosMemoryFreeClear(idxNum);
taosMemoryFreeClear(idxs);
- return TSDB_CODE_SUCCESS;
+ return code;
}
int32_t filterPostProcessRange(SFilterInfo *info) {
@@ -3601,12 +3601,12 @@ int32_t filterPreprocess(SFilterInfo *info) {
if (FILTER_GET_FLAG(info->status, FI_STATUS_ALL)) {
fltInfo("Final - FilterInfo: [ALL]");
- goto _return;
+ goto _return1;
}
if (FILTER_GET_FLAG(info->status, FI_STATUS_EMPTY)) {
fltInfo("Final - FilterInfo: [EMPTY]");
- goto _return;
+ goto _return1;
}
FLT_ERR_JRET(filterGenerateColRange(info, gRes, gResNum));
@@ -3619,10 +3619,10 @@ int32_t filterPreprocess(SFilterInfo *info) {
FLT_ERR_JRET(filterGenerateComInfo(info));
+_return1:
+ FLT_ERR_JRET(filterSetExecFunc(info));
+
_return:
-
- FLT_ERR_RET(filterSetExecFunc(info));
-
for (int32_t i = 0; i < gResNum; ++i) {
filterFreeGroupCtx(gRes[i]);
}
@@ -3660,15 +3660,25 @@ int32_t fltInitFromNode(SNode *tree, SFilterInfo *info, uint32_t options) {
FLT_ERR_JRET(terrno);
}
- FLT_ERR_JRET(filterInitUnitsFields(info));
+ code = filterInitUnitsFields(info);
+ if(TSDB_CODE_SUCCESS != code) {
+ taosArrayDestroy(group);
+ goto _return;
+ }
SFltBuildGroupCtx tctx = {.info = info, .group = group};
nodesWalkExpr(tree, fltTreeToGroup, (void *)&tctx);
- FLT_ERR_JRET(tctx.code);
-
- FLT_ERR_JRET(filterConvertGroupFromArray(info, group));
+ if (TSDB_CODE_SUCCESS != tctx.code) {
+ taosArrayDestroy(group);
+ code = tctx.code;
+ goto _return;
+ }
+ code = filterConvertGroupFromArray(info, group);
+ if (TSDB_CODE_SUCCESS != code) {
+ taosArrayDestroy(group);
+ goto _return;
+ }
taosArrayDestroy(group);
-
FLT_ERR_JRET(fltInitValFieldData(info));
if (!FILTER_GET_FLAG(info->options, FLT_OPTION_NO_REWRITE)) {
@@ -4993,7 +5003,7 @@ int32_t fltOptimizeNodes(SFilterInfo *pInfo, SNode **pNode, SFltTreeStat *pStat)
}
_return:
taosArrayDestroy(sclOpList);
- return TSDB_CODE_SUCCESS;
+ return code;
}
int32_t fltGetDataFromColId(void *param, int32_t id, void **data) {
diff --git a/source/libs/scalar/src/scalar.c b/source/libs/scalar/src/scalar.c
index d08f358ce0..9428f051aa 100644
--- a/source/libs/scalar/src/scalar.c
+++ b/source/libs/scalar/src/scalar.c
@@ -904,9 +904,8 @@ int32_t sclExecOperator(SOperatorNode *node, SScalarCtx *ctx, SScalarParam *outp
terrno = TSDB_CODE_SUCCESS;
SCL_ERR_JRET(OperatorFn(pLeft, pRight, output, TSDB_ORDER_ASC));
- SCL_ERR_JRET(terrno);
-_return:
+_return:
sclFreeParamList(params, paramNum);
SCL_RET(code);
}
diff --git a/source/libs/scalar/src/sclfunc.c b/source/libs/scalar/src/sclfunc.c
index cd67b89208..5db7aebeee 100644
--- a/source/libs/scalar/src/sclfunc.c
+++ b/source/libs/scalar/src/sclfunc.c
@@ -2913,7 +2913,7 @@ int32_t histogramScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarP
_return:
taosMemoryFree(bins);
- return TSDB_CODE_SUCCESS;
+ return code;
}
int32_t selectScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
diff --git a/source/libs/sync/test/sync_test_lib/src/syncIO.c b/source/libs/sync/test/sync_test_lib/src/syncIO.c
index 11894f7853..f5a32b98d9 100644
--- a/source/libs/sync/test/sync_test_lib/src/syncIO.c
+++ b/source/libs/sync/test/sync_test_lib/src/syncIO.c
@@ -193,7 +193,7 @@ static int32_t syncIOStartInternal(SSyncIO *io) {
io->clientRpc = rpcOpen(&rpcInit);
if (io->clientRpc == NULL) {
sError("failed to initialize RPC");
- return -1;
+ return terrno;
}
}
@@ -214,7 +214,7 @@ static int32_t syncIOStartInternal(SSyncIO *io) {
void *pRpc = rpcOpen(&rpcInit);
if (pRpc == NULL) {
sError("failed to start RPC server");
- return -1;
+ return terrno;
}
}
diff --git a/source/libs/tdb/src/db/tdbBtree.c b/source/libs/tdb/src/db/tdbBtree.c
index 87ea12dd81..59b7f4af2e 100644
--- a/source/libs/tdb/src/db/tdbBtree.c
+++ b/source/libs/tdb/src/db/tdbBtree.c
@@ -194,7 +194,11 @@ int tdbBtreeInsert(SBTree *pBt, const void *pKey, int kLen, const void *pVal, in
int idx;
int c;
- (void)tdbBtcOpen(&btc, pBt, pTxn);
+ ret = tdbBtcOpen(&btc, pBt, pTxn);
+ if (ret) {
+ tdbError("tdb/btree-insert: btc open failed with ret: %d.", ret);
+ return ret;
+ }
tdbTrace("tdb insert, btc: %p, pTxn: %p", &btc, pTxn);
@@ -235,7 +239,11 @@ int tdbBtreeDelete(SBTree *pBt, const void *pKey, int kLen, TXN *pTxn) {
int c;
int ret;
- (void)tdbBtcOpen(&btc, pBt, pTxn);
+ ret = tdbBtcOpen(&btc, pBt, pTxn);
+ if (ret) {
+ tdbError("tdb/btree-delete: btc open failed with ret: %d.", ret);
+ return ret;
+ }
/*
btc.coder.ofps = taosArrayInit(8, sizeof(SPage *));
// btc.coder.ofps = taosArrayInit(8, sizeof(SPgno));
@@ -337,7 +345,11 @@ int tdbBtreePGet(SBTree *pBt, const void *pKey, int kLen, void **ppKey, int *pkL
void *pTVal = NULL;
SCellDecoder cd = {0};
- (void)tdbBtcOpen(&btc, pBt, NULL);
+ ret = tdbBtcOpen(&btc, pBt, NULL);
+ if (ret) {
+ tdbError("tdb/btree-pget: btc open failed with ret: %d.", ret);
+ return ret;
+ }
tdbTrace("tdb pget, btc: %p", &btc);
diff --git a/source/libs/transport/test/cliBench.c b/source/libs/transport/test/cliBench.c
index 8a5276b814..ec08f1baf0 100644
--- a/source/libs/transport/test/cliBench.c
+++ b/source/libs/transport/test/cliBench.c
@@ -160,7 +160,7 @@ int main(int argc, char *argv[]) {
void *pRpc = rpcOpen(&rpcInit);
if (pRpc == NULL) {
tError("failed to initialize RPC");
- return -1;
+ return terrno;
}
tInfo("client is initialized");
diff --git a/source/util/src/tcompare.c b/source/util/src/tcompare.c
index 4cb48bffe5..670a70a309 100644
--- a/source/util/src/tcompare.c
+++ b/source/util/src/tcompare.c
@@ -1208,20 +1208,28 @@ typedef struct UsingRegex {
regex_t pRegex;
int32_t lastUsedTime;
} UsingRegex;
+typedef UsingRegex* HashRegexPtr;
typedef struct RegexCache {
SHashObj *regexHash;
void *regexCacheTmr;
void *timer;
+ SRWLatch mutex;
+ bool exit;
} RegexCache;
static RegexCache sRegexCache;
#define MAX_REGEX_CACHE_SIZE 20
#define REGEX_CACHE_CLEAR_TIME 30
static void checkRegexCache(void* param, void* tmrId) {
+ int32_t code = 0;
+ taosRLockLatch(&sRegexCache.mutex);
+ if(sRegexCache.exit) {
+ goto _exit;
+ }
(void)taosTmrReset(checkRegexCache, REGEX_CACHE_CLEAR_TIME * 1000, param, sRegexCache.regexCacheTmr, &tmrId);
if (taosHashGetSize(sRegexCache.regexHash) < MAX_REGEX_CACHE_SIZE) {
- return;
+ goto _exit;
}
if (taosHashGetSize(sRegexCache.regexHash) >= MAX_REGEX_CACHE_SIZE) {
@@ -1235,6 +1243,8 @@ static void checkRegexCache(void* param, void* tmrId) {
ppUsingRegex = taosHashIterate(sRegexCache.regexHash, ppUsingRegex);
}
}
+_exit:
+ taosRUnLockLatch(&sRegexCache.mutex);
}
void regexCacheFree(void *ppUsingRegex) {
@@ -1246,30 +1256,35 @@ int32_t InitRegexCache() {
sRegexCache.regexHash = taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_ENTRY_LOCK);
if (sRegexCache.regexHash == NULL) {
uError("failed to create RegexCache");
- return -1;
+ return terrno;
}
taosHashSetFreeFp(sRegexCache.regexHash, regexCacheFree);
sRegexCache.regexCacheTmr = taosTmrInit(0, 0, 0, "REGEXCACHE");
if (sRegexCache.regexCacheTmr == NULL) {
uError("failed to create regex cache check timer");
- terrno = TSDB_CODE_OUT_OF_MEMORY;
- return -1;
+ return terrno;
}
+ sRegexCache.exit = false;
+ taosInitRWLatch(&sRegexCache.mutex);
sRegexCache.timer = taosTmrStart(checkRegexCache, REGEX_CACHE_CLEAR_TIME * 1000, NULL, sRegexCache.regexCacheTmr);
if (sRegexCache.timer == NULL) {
uError("failed to start regex cache timer");
- return -1;
+ return terrno;
}
- return 0;
+ return TSDB_CODE_SUCCESS;
}
void DestroyRegexCache(){
+ int32_t code = 0;
uInfo("[regex cache] destory regex cache");
(void)taosTmrStopA(&sRegexCache.timer);
+ taosWLockLatch(&sRegexCache.mutex);
+ sRegexCache.exit = true;
taosHashCleanup(sRegexCache.regexHash);
taosTmrCleanUp(sRegexCache.regexCacheTmr);
+ taosWUnLockLatch(&sRegexCache.mutex);
}
int32_t checkRegexPattern(const char *pPattern) {
@@ -1290,18 +1305,17 @@ int32_t checkRegexPattern(const char *pPattern) {
return TSDB_CODE_SUCCESS;
}
-static UsingRegex **getRegComp(const char *pPattern) {
- UsingRegex **ppUsingRegex = (UsingRegex **)taosHashAcquire(sRegexCache.regexHash, pPattern, strlen(pPattern));
+int32_t getRegComp(const char *pPattern, HashRegexPtr **regexRet) {
+ HashRegexPtr* ppUsingRegex = (HashRegexPtr*)taosHashAcquire(sRegexCache.regexHash, pPattern, strlen(pPattern));
if (ppUsingRegex != NULL) {
(*ppUsingRegex)->lastUsedTime = taosGetTimestampSec();
- return ppUsingRegex;
+ *regexRet = ppUsingRegex;
+ return TSDB_CODE_SUCCESS;
}
-
UsingRegex *pUsingRegex = taosMemoryMalloc(sizeof(UsingRegex));
if (pUsingRegex == NULL) {
- terrno = TSDB_CODE_OUT_OF_MEMORY;
uError("Failed to Malloc when compile regex pattern %s.", pPattern);
- return NULL;
+ return terrno;
}
int32_t cflags = REG_EXTENDED;
int32_t ret = regcomp(&pUsingRegex->pRegex, pPattern, cflags);
@@ -1310,8 +1324,7 @@ static UsingRegex **getRegComp(const char *pPattern) {
(void)regerror(ret, &pUsingRegex->pRegex, msgbuf, tListLen(msgbuf));
uError("Failed to compile regex pattern %s. reason %s", pPattern, msgbuf);
taosMemoryFree(pUsingRegex);
- terrno = TSDB_CODE_PAR_REGULAR_EXPRESSION_ERROR;
- return NULL;
+ return TSDB_CODE_PAR_REGULAR_EXPRESSION_ERROR;
}
while (true) {
@@ -1319,8 +1332,9 @@ static UsingRegex **getRegComp(const char *pPattern) {
if (code != 0 && code != TSDB_CODE_DUP_KEY) {
regexCacheFree(&pUsingRegex);
uError("Failed to put regex pattern %s into cache, exception internal error.", pPattern);
- terrno = code;
- return NULL;
+ return code;
+ } else if (code == TSDB_CODE_DUP_KEY) {
+ terrno = 0;
}
ppUsingRegex = (UsingRegex **)taosHashAcquire(sRegexCache.regexHash, pPattern, strlen(pPattern));
if (ppUsingRegex) {
@@ -1334,27 +1348,68 @@ static UsingRegex **getRegComp(const char *pPattern) {
}
}
pUsingRegex->lastUsedTime = taosGetTimestampSec();
- return ppUsingRegex;
+ *regexRet = ppUsingRegex;
+ return TSDB_CODE_SUCCESS;
}
void releaseRegComp(UsingRegex **regex){
taosHashRelease(sRegexCache.regexHash, regex);
}
+static threadlocal UsingRegex ** ppUsingRegex;
+static threadlocal regex_t * pRegex;
+static threadlocal char *pOldPattern = NULL;
+void DestoryThreadLocalRegComp() {
+ if (NULL != pOldPattern) {
+ releaseRegComp(ppUsingRegex);
+ taosMemoryFree(pOldPattern);
+ ppUsingRegex = NULL;
+ pRegex = NULL;
+ pOldPattern = NULL;
+ }
+}
+
+int32_t threadGetRegComp(regex_t **regex, const char *pPattern) {
+ if (NULL != pOldPattern) {
+ if (strcmp(pOldPattern, pPattern) == 0) {
+ *regex = pRegex;
+ return 0;
+ } else {
+ DestoryThreadLocalRegComp();
+ }
+ }
+
+ HashRegexPtr *ppRegex = NULL;
+ int32_t code = getRegComp(pPattern, &ppRegex);
+ if (code != TSDB_CODE_SUCCESS) {
+ return code;
+ }
+ pOldPattern = taosStrdup(pPattern);
+ if (NULL == pOldPattern) {
+ uError("Failed to Malloc when compile regex pattern %s.", pPattern);
+ return terrno;
+ }
+ ppUsingRegex = ppRegex;
+ pRegex = &((*ppUsingRegex)->pRegex);
+ *regex = &(*ppRegex)->pRegex;
+ return 0;
+}
+
static int32_t doExecRegexMatch(const char *pString, const char *pPattern) {
int32_t ret = 0;
char msgbuf[256] = {0};
- UsingRegex **pUsingRegex = getRegComp(pPattern);
- if (pUsingRegex == NULL) {
- return 1;
+
+ regex_t *regex = NULL;
+ ret = threadGetRegComp(®ex, pPattern);
+ if (ret != 0) {
+ return ret;
}
regmatch_t pmatch[1];
- ret = regexec(&(*pUsingRegex)->pRegex, pString, 1, pmatch, 0);
- releaseRegComp(pUsingRegex);
+ ret = regexec(regex, pString, 1, pmatch, 0);
if (ret != 0 && ret != REG_NOMATCH) {
terrno = TSDB_CODE_PAR_REGULAR_EXPRESSION_ERROR;
- (void)regerror(ret, &(*pUsingRegex)->pRegex, msgbuf, sizeof(msgbuf));
+ (void)regerror(ret, regex, msgbuf, sizeof(msgbuf));
uDebug("Failed to match %s with pattern %s, reason %s", pString, pPattern, msgbuf)
}
@@ -1365,8 +1420,7 @@ int32_t comparestrRegexMatch(const void *pLeft, const void *pRight) {
size_t sz = varDataLen(pRight);
char *pattern = taosMemoryMalloc(sz + 1);
if (NULL == pattern) {
- terrno = TSDB_CODE_OUT_OF_MEMORY;
- return 1;
+ return 1; // terrno has been set
}
(void)memcpy(pattern, varDataVal(pRight), varDataLen(pRight));
@@ -1376,8 +1430,7 @@ int32_t comparestrRegexMatch(const void *pLeft, const void *pRight) {
char *str = taosMemoryMalloc(sz + 1);
if (NULL == str) {
taosMemoryFree(pattern);
- terrno = TSDB_CODE_OUT_OF_MEMORY;
- return 1;
+ return 1; // terrno has been set
}
(void)memcpy(str, varDataVal(pLeft), sz);
@@ -1395,14 +1448,13 @@ int32_t comparewcsRegexMatch(const void *pString, const void *pPattern) {
size_t len = varDataLen(pPattern);
char *pattern = taosMemoryMalloc(len + 1);
if (NULL == pattern) {
- terrno = TSDB_CODE_OUT_OF_MEMORY;
- return 1;
+ return 1; // terrno has been set
}
int convertLen = taosUcs4ToMbs((TdUcs4 *)varDataVal(pPattern), len, pattern);
if (convertLen < 0) {
taosMemoryFree(pattern);
- return (terrno = TSDB_CODE_APP_ERROR);
+ return 1; // terrno has been set
}
pattern[convertLen] = 0;
@@ -1411,15 +1463,14 @@ int32_t comparewcsRegexMatch(const void *pString, const void *pPattern) {
char *str = taosMemoryMalloc(len + 1);
if (NULL == str) {
taosMemoryFree(pattern);
- terrno = TSDB_CODE_OUT_OF_MEMORY;
- return 1;
+ return 1; // terrno has been set
}
convertLen = taosUcs4ToMbs((TdUcs4 *)varDataVal(pString), len, str);
if (convertLen < 0) {
taosMemoryFree(str);
taosMemoryFree(pattern);
- return (terrno = TSDB_CODE_APP_ERROR);
+ return 1; // terrno has been set
}
str[convertLen] = 0;
diff --git a/source/util/src/tlog.c b/source/util/src/tlog.c
index 1946a0a274..86dc767adc 100644
--- a/source/util/src/tlog.c
+++ b/source/util/src/tlog.c
@@ -567,7 +567,7 @@ static inline void taosPrintLogImp(ELogLevel level, int32_t dflag, const char *b
}
}
-void taosPrintLog(const char *flags, ELogLevel level, int32_t dflag, const char *format, ...) {
+void taosPrintLog(const char *flags, int32_t level, int32_t dflag, const char *format, ...) {
if (!(dflag & DEBUG_FILE) && !(dflag & DEBUG_SCREEN)) return;
char buffer[LOG_MAX_LINE_BUFFER_SIZE];
@@ -590,7 +590,7 @@ void taosPrintLog(const char *flags, ELogLevel level, int32_t dflag, const char
}
}
-void taosPrintLongString(const char *flags, ELogLevel level, int32_t dflag, const char *format, ...) {
+void taosPrintLongString(const char *flags, int32_t level, int32_t dflag, const char *format, ...) {
if (!osLogSpaceAvailable()) return;
if (!(dflag & DEBUG_FILE) && !(dflag & DEBUG_SCREEN)) return;
diff --git a/source/util/src/tworker.c b/source/util/src/tworker.c
index 258d53c335..edf5b0b970 100644
--- a/source/util/src/tworker.c
+++ b/source/util/src/tworker.c
@@ -106,6 +106,7 @@ static void *tQWorkerThreadFp(SQueueWorker *worker) {
}
destroyThreadLocalGeosCtx();
+ DestoryThreadLocalRegComp();
return NULL;
}
@@ -237,6 +238,7 @@ static void *tAutoQWorkerThreadFp(SQueueWorker *worker) {
taosUpdateItemSize(qinfo.queue, 1);
}
+ DestoryThreadLocalRegComp();
return NULL;
}
@@ -664,6 +666,7 @@ static void *tQueryAutoQWorkerThreadFp(SQueryAutoQWorker *worker) {
}
destroyThreadLocalGeosCtx();
+ DestoryThreadLocalRegComp();
return NULL;
}
diff --git a/source/util/test/CMakeLists.txt b/source/util/test/CMakeLists.txt
index e8aabfe338..0d8774ba41 100644
--- a/source/util/test/CMakeLists.txt
+++ b/source/util/test/CMakeLists.txt
@@ -119,6 +119,13 @@ add_test(
COMMAND bufferTest
)
+add_executable(regexTest "regexTest.cpp")
+target_link_libraries(regexTest os util gtest_main )
+add_test(
+ NAME regexTest
+ COMMAND regexTest
+)
+
#add_executable(decompressTest "decompressTest.cpp")
#target_link_libraries(decompressTest os util common gtest_main)
#add_test(
diff --git a/source/util/test/regexTest.cpp b/source/util/test/regexTest.cpp
new file mode 100644
index 0000000000..5fe3701700
--- /dev/null
+++ b/source/util/test/regexTest.cpp
@@ -0,0 +1,344 @@
+
+#include
+#include
+#include
+#include
+#include
+#include "os.h"
+#include "tutil.h"
+#include "regex.h"
+#include "osDef.h"
+#include "tcompare.h"
+
+extern "C" {
+ typedef struct UsingRegex UsingRegex;
+ typedef struct HashRegexPtr HashRegexPtr;
+ int32_t getRegComp(const char *pPattern, HashRegexPtr **regexRet);
+ int32_t threadGetRegComp(regex_t **regex, const char *pPattern);
+}
+
+class regexTest {
+ public:
+ regexTest() { (void)InitRegexCache(); }
+ ~regexTest() { (void)DestroyRegexCache(); }
+};
+static regexTest test;
+
+static threadlocal regex_t pRegex;
+static threadlocal char *pOldPattern = NULL;
+
+void DestoryThreadLocalRegComp1() {
+ if (NULL != pOldPattern) {
+ regfree(&pRegex);
+ taosMemoryFree(pOldPattern);
+ pOldPattern = NULL;
+ }
+}
+
+static regex_t *threadGetRegComp1(const char *pPattern) {
+ if (NULL != pOldPattern) {
+ if( strcmp(pOldPattern, pPattern) == 0) {
+ return &pRegex;
+ } else {
+ DestoryThreadLocalRegComp1();
+ }
+ }
+ pOldPattern = (char*)taosMemoryMalloc(strlen(pPattern) + 1);
+ if (NULL == pOldPattern) {
+ uError("Failed to Malloc when compile regex pattern %s.", pPattern);
+ return NULL;
+ }
+ strcpy(pOldPattern, pPattern);
+ int32_t cflags = REG_EXTENDED;
+ int32_t ret = regcomp(&pRegex, pPattern, cflags);
+ if (ret != 0) {
+ char msgbuf[256] = {0};
+ regerror(ret, &pRegex, msgbuf, tListLen(msgbuf));
+ uError("Failed to compile regex pattern %s. reason %s", pPattern, msgbuf);
+ DestoryThreadLocalRegComp1();
+ return NULL;
+ }
+ return &pRegex;
+}
+
+TEST(testCase, regexCacheTest1) {
+ int times = 100000;
+ char s1[] = "abc";
+ auto start = std::chrono::high_resolution_clock::now();
+
+ uint64_t t0 = taosGetTimestampUs();
+ for (int i = 0; i < times; i++) {
+ HashRegexPtr* ret = NULL;
+ int32_t code = getRegComp(s1, &ret);
+ if (code != 0) {
+ FAIL() << "Failed to compile regex pattern " << s1;
+ }
+ }
+ uint64_t t1 = taosGetTimestampUs();
+
+ printf("%s regex(current) %d times:%" PRIu64 " us.\n", s1, times, t1 - t0);
+
+ uint64_t t2 = taosGetTimestampUs();
+ for(int i = 0; i < times; i++) {
+ regex_t* rex = threadGetRegComp1(s1);
+ }
+ uint64_t t3 = taosGetTimestampUs();
+
+ printf("%s regex(before) %d times:%" PRIu64 " us.\n", s1, times, t3 - t2);
+
+ t2 = taosGetTimestampUs();
+ for(int i = 0; i < times; i++) {
+ regex_t* rex = NULL;
+ (void)threadGetRegComp(&rex, s1);
+ }
+ t3 = taosGetTimestampUs();
+
+ printf("%s regex(new) %d times:%" PRIu64 " us.\n", s1, times, t3 - t2);
+}
+
+TEST(testCase, regexCacheTest2) {
+ int times = 100000;
+ char s1[] = "abc%*";
+ auto start = std::chrono::high_resolution_clock::now();
+
+ uint64_t t0 = taosGetTimestampUs();
+ for (int i = 0; i < times; i++) {
+ HashRegexPtr* ret = NULL;
+ int32_t code = getRegComp(s1, &ret);
+ if (code != 0) {
+ FAIL() << "Failed to compile regex pattern " << s1;
+ }
+ }
+ uint64_t t1 = taosGetTimestampUs();
+
+ printf("%s regex(current) %d times:%" PRIu64 " us.\n", s1, times, t1 - t0);
+
+ uint64_t t2 = taosGetTimestampUs();
+ for(int i = 0; i < times; i++) {
+ regex_t* rex = threadGetRegComp1(s1);
+ }
+ uint64_t t3 = taosGetTimestampUs();
+
+ printf("%s regex(before) %d times:%" PRIu64 " us.\n", s1, times, t3 - t2);
+
+ t2 = taosGetTimestampUs();
+ for(int i = 0; i < times; i++) {
+ regex_t* rex = NULL;
+ (void)threadGetRegComp(&rex, s1);
+ }
+ t3 = taosGetTimestampUs();
+
+ printf("%s regex(new) %d times:%" PRIu64 " us.\n", s1, times, t3 - t2);
+}
+
+TEST(testCase, regexCacheTest3) {
+ int times = 100000;
+ char s1[] = "abc%*";
+ char s2[] = "abc";
+ auto start = std::chrono::high_resolution_clock::now();
+
+ uint64_t t0 = taosGetTimestampUs();
+ for (int i = 0; i < times; i++) {
+ HashRegexPtr* ret = NULL;
+ int32_t code = getRegComp(s1, &ret);
+ if (code != 0) {
+ FAIL() << "Failed to compile regex pattern " << s1;
+ }
+ }
+ uint64_t t1 = taosGetTimestampUs();
+
+ printf("'%s' and '%s' take place by turn regex(current) %d times:%" PRIu64 " us.\n", s1, s2, times, t1 - t0);
+
+ uint64_t t2 = taosGetTimestampUs();
+ for(int i = 0; i < times; i++) {
+ regex_t* rex = threadGetRegComp1(s1);
+ rex = threadGetRegComp1(s2);
+ }
+ uint64_t t3 = taosGetTimestampUs();
+
+ printf("'%s' and '%s' take place by turn regex(before) %d times:%" PRIu64 " us.\n", s1, s2, times, t3 - t2);
+
+ t2 = taosGetTimestampUs();
+ for(int i = 0; i < times; i++) {
+ regex_t* rex = NULL;
+ (void)threadGetRegComp(&rex, s1);
+ (void)threadGetRegComp(&rex, s2);
+ }
+ t3 = taosGetTimestampUs();
+
+ printf("'%s' and '%s' take place by turn regex(new) %d times:%" PRIu64 " us.\n", s1, s2, times, t3 - t2);
+}
+
+TEST(testCase, regexCacheTest4) {
+ int times = 100;
+ int count = 1000;
+ char s1[] = "abc%*";
+ char s2[] = "abc";
+ auto start = std::chrono::high_resolution_clock::now();
+
+ uint64_t t0 = taosGetTimestampUs();
+ for (int i = 0; i < times; i++) {
+ for (int j = 0; j < count; ++j) {
+ HashRegexPtr* ret = NULL;
+ int32_t code = getRegComp(s1, &ret);
+ if (code != 0) {
+ FAIL() << "Failed to compile regex pattern " << s1;
+ }
+ }
+ for (int j = 0; j < count; ++j) {
+ HashRegexPtr* ret = NULL;
+ int32_t code = getRegComp(s2, &ret);
+ if (code != 0) {
+ FAIL() << "Failed to compile regex pattern " << s2;
+ }
+ }
+ }
+ uint64_t t1 = taosGetTimestampUs();
+
+ printf("'%s' and '%s' take place by turn(per %d count) regex(current) %d times:%" PRIu64 " us.\n", s1, s2, count, times, t1 - t0);
+
+ uint64_t t2 = taosGetTimestampUs();
+ for (int i = 0; i < times; i++) {
+ for (int j = 0; j < count; ++j) {
+ regex_t* rex = threadGetRegComp1(s1);
+ }
+ for (int j = 0; j < count; ++j) {
+ regex_t* rex = threadGetRegComp1(s2);
+ }
+ }
+ uint64_t t3 = taosGetTimestampUs();
+
+ printf("'%s' and '%s' take place by turn(per %d count) regex(before) %d times:%" PRIu64 " us.\n", s1, s2, count, times, t3 - t2);
+
+ t2 = taosGetTimestampUs();
+ for (int i = 0; i < times; i++) {
+ for (int j = 0; j < count; ++j) {
+ regex_t* rex = NULL;
+ (void)threadGetRegComp(&rex, s1);
+ }
+ for (int j = 0; j < count; ++j) {
+ regex_t* rex = NULL;
+ (void)threadGetRegComp(&rex, s2);
+ }
+ }
+ t3 = taosGetTimestampUs();
+
+ printf("'%s' and '%s' take place by turn(per %d count) regex(new) %d times:%" PRIu64 " us.\n", s1, s2, count, times, t3 - t2);
+}
+
+// It is not a good idea to test this case, because it will take a long time.
+/*
+TEST(testCase, regexCacheTest5) {
+ int times = 10000;
+ int count = 10000;
+ char s1[] = "abc%*";
+ char s2[] = "abc";
+ auto start = std::chrono::high_resolution_clock::now();
+
+ uint64_t t0 = taosGetTimestampUs();
+ for (int i = 0; i < times; i++) {
+ for (int j = 0; j < count; ++j) {
+ HashRegexPtr* ret = NULL;
+ int32_t code = getRegComp(s1, &ret);
+ if (code != 0) {
+ FAIL() << "Failed to compile regex pattern " << s1;
+ }
+ }
+ for (int j = 0; j < count; ++j) {
+ HashRegexPtr* ret = NULL;
+ int32_t code = getRegComp(s2, &ret);
+ if (code != 0) {
+ FAIL() << "Failed to compile regex pattern " << s2;
+ }
+ }
+ }
+ uint64_t t1 = taosGetTimestampUs();
+
+ printf("'%s' and '%s' take place by turn(per %d count) regex(current) %d times:%" PRIu64 " us.\n", s1, s2, count, times, t1 - t0);
+
+ uint64_t t2 = taosGetTimestampUs();
+ for (int i = 0; i < times; i++) {
+ for (int j = 0; j < count; ++j) {
+ regex_t* rex = threadGetRegComp1(s1);
+ }
+ for (int j = 0; j < count; ++j) {
+ regex_t* rex = threadGetRegComp1(s2);
+ }
+ }
+ uint64_t t3 = taosGetTimestampUs();
+
+ printf("'%s' and '%s' take place by turn(per %d count) regex(before) %d times:%" PRIu64 " us.\n", s1, s2, count, times, t3 - t2);
+
+ t2 = taosGetTimestampUs();
+ for (int i = 0; i < times; i++) {
+ for (int j = 0; j < count; ++j) {
+ regex_t* rex = NULL;
+ (void)threadGetRegComp(&rex, s1);
+ }
+ for (int j = 0; j < count; ++j) {
+ regex_t* rex = NULL;
+ (void)threadGetRegComp(&rex, s2);
+ }
+ }
+ t3 = taosGetTimestampUs();
+
+ printf("'%s' and '%s' take place by turn(per %d count) regex(new) %d times:%" PRIu64 " us.\n", s1, s2, count, times, t3 - t2);
+}
+
+TEST(testCase, regexCacheTest6) {
+ int times = 10000;
+ int count = 1000;
+ char s1[] = "abc%*";
+ char s2[] = "abc";
+ auto start = std::chrono::high_resolution_clock::now();
+
+ uint64_t t0 = taosGetTimestampUs();
+ for (int i = 0; i < times; i++) {
+ for (int j = 0; j < count; ++j) {
+ HashRegexPtr* ret = NULL;
+ int32_t code = getRegComp(s1, &ret);
+ if (code != 0) {
+ FAIL() << "Failed to compile regex pattern " << s1;
+ }
+ }
+ for (int j = 0; j < count; ++j) {
+ HashRegexPtr* ret = NULL;
+ int32_t code = getRegComp(s2, &ret);
+ if (code != 0) {
+ FAIL() << "Failed to compile regex pattern " << s2;
+ }
+ }
+ }
+ uint64_t t1 = taosGetTimestampUs();
+
+ printf("'%s' and '%s' take place by turn(per %d count) regex(current) %d times:%" PRIu64 " us.\n", s1, s2, count, times, t1 - t0);
+
+ uint64_t t2 = taosGetTimestampUs();
+ for (int i = 0; i < times; i++) {
+ for (int j = 0; j < count; ++j) {
+ regex_t* rex = threadGetRegComp1(s1);
+ }
+ for (int j = 0; j < count; ++j) {
+ regex_t* rex = threadGetRegComp1(s2);
+ }
+ }
+ uint64_t t3 = taosGetTimestampUs();
+
+ printf("'%s' and '%s' take place by turn(per %d count) regex(before) %d times:%" PRIu64 " us.\n", s1, s2, count, times, t3 - t2);
+
+ t2 = taosGetTimestampUs();
+ for (int i = 0; i < times; i++) {
+ for (int j = 0; j < count; ++j) {
+ regex_t* rex = NULL;
+ (void)threadGetRegComp(&rex, s1);
+ }
+ for (int j = 0; j < count; ++j) {
+ regex_t* rex = NULL;
+ (void)threadGetRegComp(&rex, s2);
+ }
+ }
+ t3 = taosGetTimestampUs();
+
+ printf("'%s' and '%s' take place by turn(per %d count) regex(new) %d times:%" PRIu64 " us.\n", s1, s2, count, times, t3 - t2);
+}
+*/
diff --git a/tests/script/sh/bit_and.c b/tests/script/sh/bit_and.c
index f3bf71ce94..2cf2157e1c 100644
--- a/tests/script/sh/bit_and.c
+++ b/tests/script/sh/bit_and.c
@@ -8,13 +8,17 @@ DLL_EXPORT int32_t bit_and_init() { return 0; }
DLL_EXPORT int32_t bit_and_destroy() { return 0; }
DLL_EXPORT int32_t bit_and(SUdfDataBlock* block, SUdfColumn* resultCol) {
+ udfTrace("block:%p, processing begins, rows:%d cols:%d", block, block->numOfRows, block->numOfCols);
+
if (block->numOfCols < 2) {
+ udfError("block:%p, cols:%d needs to be greater than 2", block, block->numOfCols);
return TSDB_CODE_UDF_INVALID_INPUT;
}
for (int32_t i = 0; i < block->numOfCols; ++i) {
SUdfColumn* col = block->udfCols[i];
- if (!(col->colMeta.type == TSDB_DATA_TYPE_INT)) {
+ if (col->colMeta.type != TSDB_DATA_TYPE_INT) {
+ udfError("block:%p, col:%d type:%d should be int(%d)", block, i, col->colMeta.type, TSDB_DATA_TYPE_INT);
return TSDB_CODE_UDF_INVALID_INPUT;
}
}
@@ -23,25 +27,35 @@ DLL_EXPORT int32_t bit_and(SUdfDataBlock* block, SUdfColumn* resultCol) {
for (int32_t i = 0; i < block->numOfRows; ++i) {
if (udfColDataIsNull(block->udfCols[0], i)) {
+ udfTrace("block:%p, row:%d result is null since col:0 is null", block, i);
udfColDataSetNull(resultCol, i);
continue;
}
+
int32_t result = *(int32_t*)udfColDataGetData(block->udfCols[0], i);
- int j = 1;
+ udfTrace("block:%p, row:%d col:0 data:%d", block, i, result);
+
+ int32_t j = 1;
for (; j < block->numOfCols; ++j) {
if (udfColDataIsNull(block->udfCols[j], i)) {
+ udfTrace("block:%p, row:%d result is null since col:%d is null", block, i, j);
udfColDataSetNull(resultCol, i);
break;
}
char* colData = udfColDataGetData(block->udfCols[j], i);
result &= *(int32_t*)colData;
+ udfTrace("block:%p, row:%d col:%d data:%d", block, i, j, *(int32_t*)colData);
}
+
if (j == block->numOfCols) {
udfColDataSet(resultCol, i, (char*)&result, false);
+ udfTrace("block:%p, row:%d result is %d", block, i, result);
}
}
+
resultData->numOfRows = block->numOfRows;
+ udfTrace("block:%p, processing completed, rows:%d, cols:%d,", block, block->numOfRows, block->numOfCols);
return TSDB_CODE_SUCCESS;
}
diff --git a/tests/system-test/7-tmq/tmqParamsTest.py b/tests/system-test/7-tmq/tmqParamsTest.py
index a323dff19e..c14c3fc7d1 100644
--- a/tests/system-test/7-tmq/tmqParamsTest.py
+++ b/tests/system-test/7-tmq/tmqParamsTest.py
@@ -104,7 +104,7 @@ class TDTestCase:
stop_flag = 0
try:
while True:
- res = consumer.poll(1)
+ res = consumer.poll(3)
tdSql.query('show consumers;')
consumer_info = tdSql.queryResult[0][-1]
if offset_value == "latest":