diff --git a/docs-cn/12-taos-sql/07-function.md b/docs-cn/12-taos-sql/07-function.md index b924aad042..d2cd89f152 100644 --- a/docs-cn/12-taos-sql/07-function.md +++ b/docs-cn/12-taos-sql/07-function.md @@ -1,966 +1,90 @@ --- sidebar_label: SQL 函数 title: SQL 函数 +toc_max_heading_level: 4 --- -## 聚合函数 +## 单行函数 -TDengine 支持针对数据的聚合查询。提供支持的聚合和选择函数如下: +单行函数为查询结果中的每一行返回一个结果行。 -### COUNT +### 数学函数 -``` -SELECT COUNT([*|field_name]) FROM tb_name [WHERE clause]; -``` - -**功能说明**:统计表/超级表中记录行数或某列的非空值个数。 - -**返回数据类型**:长整型 INT64。 - -**应用字段**:应用全部字段。 - -**适用于**:表、超级表。 - -**使用说明**: - -- 可以使用星号(\*)来替代具体的字段,使用星号(\*)返回全部记录数量。 -- 针对同一表的(不包含 NULL 值)字段查询结果均相同。 -- 如果统计对象是具体的列,则返回该列中非 NULL 值的记录数量。 - -**示例**: - -``` -taos> SELECT COUNT(*), COUNT(voltage) FROM meters; - count(*) | count(voltage) | -================================================ - 9 | 9 | -Query OK, 1 row(s) in set (0.004475s) - -taos> SELECT COUNT(*), COUNT(voltage) FROM d1001; - count(*) | count(voltage) | -================================================ - 3 | 3 | -Query OK, 1 row(s) in set (0.001075s) -``` - -### AVG - -``` -SELECT AVG(field_name) FROM tb_name [WHERE clause]; -``` - -**功能说明**:统计表/超级表中某列的平均值。 - -**返回数据类型**:双精度浮点数 Double。 - -**应用字段**:不能应用在 timestamp、binary、nchar、bool 字段。 - -**适用于**:表、超级表。 - -**示例**: - -``` -taos> SELECT AVG(current), AVG(voltage), AVG(phase) FROM meters; - avg(current) | avg(voltage) | avg(phase) | -==================================================================================== - 11.466666751 | 220.444444444 | 0.293333333 | -Query OK, 1 row(s) in set (0.004135s) - -taos> SELECT AVG(current), AVG(voltage), AVG(phase) FROM d1001; - avg(current) | avg(voltage) | avg(phase) | -==================================================================================== - 11.733333588 | 219.333333333 | 0.316666673 | -Query OK, 1 row(s) in set (0.000943s) -``` - -### TWA - -``` -SELECT TWA(field_name) FROM tb_name WHERE clause; -``` - -**功能说明**:时间加权平均函数。统计表中某列在一段时间内的时间加权平均。 - -**返回数据类型**:双精度浮点数 Double。 - -**应用字段**:不能应用在 timestamp、binary、nchar、bool 类型字段。 - -**适用于**:表、超级表。 - -**使用说明**: - -- 从 2.1.3.0 版本开始,TWA 函数可以在由 GROUP BY 划分出单独时间线的情况下用于超级表(也即 GROUP BY tbname)。 - -### IRATE - -``` -SELECT IRATE(field_name) FROM tb_name WHERE clause; -``` - -**功能说明**:计算瞬时增长率。使用时间区间中最后两个样本数据来计算瞬时增长速率;如果这两个值呈递减关系,那么只取最后一个数用于计算,而不是使用二者差值。 - -**返回数据类型**:双精度浮点数 Double。 - -**应用字段**:不能应用在 timestamp、binary、nchar、bool 类型字段。 - -**适用于**:表、超级表。 - -**使用说明**: - -- 从 2.1.3.0 版本开始此函数可用,IRATE 可以在由 GROUP BY 划分出单独时间线的情况下用于超级表(也即 GROUP BY tbname)。 - -### SUM - -``` -SELECT SUM(field_name) FROM tb_name [WHERE clause]; -``` - -**功能说明**:统计表/超级表中某列的和。 - -**返回数据类型**:双精度浮点数 Double 和长整型 INT64。 - -**应用字段**:不能应用在 timestamp、binary、nchar、bool 类型字段。 - -**适用于**:表、超级表。 - -**示例**: - -``` -taos> SELECT SUM(current), SUM(voltage), SUM(phase) FROM meters; - sum(current) | sum(voltage) | sum(phase) | -================================================================================ - 103.200000763 | 1984 | 2.640000001 | -Query OK, 1 row(s) in set (0.001702s) - -taos> SELECT SUM(current), SUM(voltage), SUM(phase) FROM d1001; - sum(current) | sum(voltage) | sum(phase) | -================================================================================ - 35.200000763 | 658 | 0.950000018 | -Query OK, 1 row(s) in set (0.000980s) -``` - -### STDDEV +#### ABS +```sql + SELECT ABS(field_name) FROM { tb_name | stb_name } [WHERE clause] ``` -SELECT STDDEV(field_name) FROM tb_name [WHERE clause]; -``` - -**功能说明**:统计表中某列的均方差。 - -**返回数据类型**:双精度浮点数 Double。 - -**应用字段**:不能应用在 timestamp、binary、nchar、bool 类型字段。 - -**适用于**:表、超级表(从 2.0.15.1 版本开始) - -**示例**: - -``` -taos> SELECT STDDEV(current) FROM d1001; - stddev(current) | -============================ - 1.020892909 | -Query OK, 1 row(s) in set (0.000915s) -``` - -### LEASTSQUARES - -``` -SELECT LEASTSQUARES(field_name, start_val, step_val) FROM tb_name [WHERE clause]; -``` - -**功能说明**:统计表中某列的值是主键(时间戳)的拟合直线方程。start_val 是自变量初始值,step_val 是自变量的步长值。 - -**返回数据类型**:字符串表达式(斜率, 截距)。 - -**应用字段**:不能应用在 timestamp、binary、nchar、bool 类型字段。 - -**适用于**:表。 - -**示例**: - -``` -taos> SELECT LEASTSQUARES(current, 1, 1) FROM d1001; - leastsquares(current, 1, 1) | -===================================================== -{slop:1.000000, intercept:9.733334} | -Query OK, 1 row(s) in set (0.000921s) -``` - -### MODE - -``` -SELECT MODE(field_name) FROM tb_name [WHERE clause]; -``` - -**功能说明**:返回出现频率最高的值,若存在多个频率相同的最高值,输出空。不能匹配标签、时间戳输出。 - -**返回数据类型**:同应用的字段。 - -**应用字段**:适合于除时间主列外的任何类型字段。 - -**使用说明**:由于返回数据量未知,考虑到内存因素,为了函数可以正常返回结果,建议不重复的数据量在 10 万级别,否则会报错。 - -**支持的版本**:2.6.0.0 及以后的版本。 - -**示例**: - -``` -taos> select voltage from d002; - voltage | -======================== - 1 | - 1 | - 2 | - 19 | -Query OK, 4 row(s) in set (0.003545s) - -taos> select mode(voltage) from d002; - mode(voltage) | -======================== - 1 | -Query OK, 1 row(s) in set (0.019393s) -``` - -### HYPERLOGLOG - -``` -SELECT HYPERLOGLOG(field_name) FROM { tb_name | stb_name } [WHERE clause]; -``` - -**功能说明**: - - 采用 hyperloglog 算法,返回某列的基数。该算法在数据量很大的情况下,可以明显降低内存的占用,但是求出来的基数是个估算值,标准误差(标准误差是多次实验,每次的平均数的标准差,不是与真实结果的误差)为 0.81%。 - - 在数据量较少的时候该算法不是很准确,可以使用 select count(data) from (select unique(col) as data from table) 的方法。 - -**返回结果类型**:整形。 - -**应用字段**:适合于任何类型字段。 - -**支持的版本**:2.6.0.0 及以后的版本。 - -**示例**: - -``` -taos> select dbig from shll; - dbig | -======================== - 1 | - 1 | - 1 | - NULL | - 2 | - 19 | - NULL | - 9 | -Query OK, 8 row(s) in set (0.003755s) - -taos> select hyperloglog(dbig) from shll; - hyperloglog(dbig)| -======================== - 4 | -Query OK, 1 row(s) in set (0.008388s) -``` - -### HISTOGRAM - -``` -SELECT HISTOGRAM(field_name,bin_type, bin_description, normalized) FROM tb_name [WHERE clause]; -``` - -**功能说明**:统计数据按照用户指定区间的分布。 - -**返回结果类型**:如归一化参数 normalized 设置为 1,返回结果为双精度浮点类型 DOUBLE,否则为长整形 INT64。 - -**应用字段**:数值型字段。 - -**支持的版本**:2.6.0.0 及以后的版本。 - -**适用于**: 表和超级表。 - -**说明**: -1. bin_type 用户指定的分桶类型, 有效输入类型为"user_input“, ”linear_bin", "log_bin"。 -2. bin_description 描述如何生成分桶区间,针对三种桶类型,分别为以下描述格式(均为 JSON 格式字符串): - - "user_input": "[1, 3, 5, 7]" - 用户指定 bin 的具体数值。 - - - "linear_bin": "{"start": 0.0, "width": 5.0, "count": 5, "infinity": true}" - "start" 表示数据起始点,"width" 表示每次 bin 偏移量, "count" 为 bin 的总数,"infinity" 表示是否添加(-inf, inf)作为区间起点跟终点, - 生成区间为[-inf, 0.0, 5.0, 10.0, 15.0, 20.0, +inf]。 - - - "log_bin": "{"start":1.0, "factor": 2.0, "count": 5, "infinity": true}" - "start" 表示数据起始点,"factor" 表示按指数递增的因子,"count" 为 bin 的总数,"infinity" 表示是否添加(-inf, inf)作为区间起点跟终点, - 生成区间为[-inf, 1.0, 2.0, 4.0, 8.0, 16.0, +inf]。 -3. normalized 是否将返回结果归一化到 0~1 之间 。有效输入为 0 和 1。 - -**示例**: - -```mysql -taos> SELECT HISTOGRAM(voltage, "user_input", "[1,3,5,7]", 1) FROM meters; - histogram(voltage, "user_input", "[1,3,5,7]", 1) | - ======================================================= - {"lower_bin":1, "upper_bin":3, "count":0.333333} | - {"lower_bin":3, "upper_bin":5, "count":0.333333} | - {"lower_bin":5, "upper_bin":7, "count":0.333333} | - Query OK, 3 row(s) in set (0.004273s) - -taos> SELECT HISTOGRAM(voltage, 'linear_bin', '{"start": 1, "width": 3, "count": 3, "infinity": false}', 0) FROM meters; - histogram(voltage, 'linear_bin', '{"start": 1, "width": 3, " | - =================================================================== - {"lower_bin":1, "upper_bin":4, "count":3} | - {"lower_bin":4, "upper_bin":7, "count":3} | - {"lower_bin":7, "upper_bin":10, "count":3} | - Query OK, 3 row(s) in set (0.004887s) - -taos> SELECT HISTOGRAM(voltage, 'log_bin', '{"start": 1, "factor": 3, "count": 3, "infinity": true}', 0) FROM meters; - histogram(voltage, 'log_bin', '{"start": 1, "factor": 3, "count" | - =================================================================== - {"lower_bin":-inf, "upper_bin":1, "count":3} | - {"lower_bin":1, "upper_bin":3, "count":2} | - {"lower_bin":3, "upper_bin":9, "count":6} | - {"lower_bin":9, "upper_bin":27, "count":3} | - {"lower_bin":27, "upper_bin":inf, "count":1} | -``` - -### ELAPSED - -```mysql -SELECT ELAPSED(field_name[, time_unit]) FROM { tb_name | stb_name } [WHERE clause] [INTERVAL(interval [, offset]) [SLIDING sliding]]; -``` - -**功能说明**:elapsed函数表达了统计周期内连续的时间长度,和twa函数配合使用可以计算统计曲线下的面积。在通过INTERVAL子句指定窗口的情况下,统计在给定时间范围内的每个窗口内有数据覆盖的时间范围;如果没有INTERVAL子句,则返回整个给定时间范围内的有数据覆盖的时间范围。注意,ELAPSED返回的并不是时间范围的绝对值,而是绝对值除以time_unit所得到的单位个数。 - -**返回结果类型**:Double - -**应用字段**:Timestamp类型 - -**支持的版本**:2.6.0.0 及以后的版本。 - -**适用于**: 表,超级表,嵌套查询的外层查询 - -**说明**: -- field_name参数只能是表的第一列,即timestamp主键列。 -- 按time_unit参数指定的时间单位返回,最小是数据库的时间分辨率。time_unit参数未指定时,以数据库的时间分辨率为时间单位。 -- 可以和interval组合使用,返回每个时间窗口的时间戳差值。需要特别注意的是,除第一个时间窗口和最后一个时间窗口外,中间窗口的时间戳差值均为窗口长度。 -- order by asc/desc不影响差值的计算结果。 -- 对于超级表,需要和group by tbname子句组合使用,不可以直接使用。 -- 对于普通表,不支持和group by子句组合使用。 -- 对于嵌套查询,仅当内层查询会输出隐式时间戳列时有效。例如select elapsed(ts) from (select diff(value) from sub1)语句,diff函数会让内层查询输出隐式时间戳列,此为主键列,可以用于elapsed函数的第一个参数。相反,例如select elapsed(ts) from (select * from sub1) 语句,ts列输出到外层时已经没有了主键列的含义,无法使用elapsed函数。此外,elapsed函数作为一个与时间线强依赖的函数,形如select elapsed(ts) from (select diff(value) from st group by tbname)尽管会返回一条计算结果,但并无实际意义,这种用法后续也将被限制。 -- 不支持与leastsquares、diff、derivative、top、bottom、last_row、interp等函数混合使用。 - -## 选择函数 - -在使用所有的选择函数的时候,可以同时指定输出 ts 列或标签列(包括 tbname),这样就可以方便地知道被选出的值是源于哪个数据行的。 - -### MIN - -``` -SELECT MIN(field_name) FROM {tb_name | stb_name} [WHERE clause]; -``` - -**功能说明**:统计表/超级表中某列的值最小值。 - -**返回数据类型**:同应用的字段。 - -**应用字段**:不能应用在 timestamp、binary、nchar、bool 类型字段。 - -**适用于**:表、超级表。 - -**示例**: - -``` -taos> SELECT MIN(current), MIN(voltage) FROM meters; - min(current) | min(voltage) | -====================================== - 10.20000 | 218 | -Query OK, 1 row(s) in set (0.001765s) - -taos> SELECT MIN(current), MIN(voltage) FROM d1001; - min(current) | min(voltage) | -====================================== - 10.30000 | 218 | -Query OK, 1 row(s) in set (0.000950s) -``` - -### MAX - -``` -SELECT MAX(field_name) FROM { tb_name | stb_name } [WHERE clause]; -``` - -**功能说明**:统计表/超级表中某列的值最大值。 - -**返回数据类型**:同应用的字段。 - -**应用字段**:不能应用在 timestamp、binary、nchar、bool 类型字段。 - -**适用于**:表、超级表。 - -**示例**: - -``` -taos> SELECT MAX(current), MAX(voltage) FROM meters; - max(current) | max(voltage) | -====================================== - 13.40000 | 223 | -Query OK, 1 row(s) in set (0.001123s) - -taos> SELECT MAX(current), MAX(voltage) FROM d1001; - max(current) | max(voltage) | -====================================== - 12.60000 | 221 | -Query OK, 1 row(s) in set (0.000987s) -``` - -### FIRST - -``` -SELECT FIRST(field_name) FROM { tb_name | stb_name } [WHERE clause]; -``` - -**功能说明**:统计表/超级表中某列的值最先写入的非 NULL 值。 - -**返回数据类型**:同应用的字段。 - -**应用字段**:所有字段。 - -**适用于**:表、超级表。 - -**使用说明**: - -- 如果要返回各个列的首个(时间戳最小)非 NULL 值,可以使用 FIRST(\*); -- 如果结果集中的某列全部为 NULL 值,则该列的返回结果也是 NULL; -- 如果结果集中所有列全部为 NULL 值,则不返回结果。 - -**示例**: - -``` -taos> SELECT FIRST(*) FROM meters; - first(ts) | first(current) | first(voltage) | first(phase) | -========================================================================================= -2018-10-03 14:38:04.000 | 10.20000 | 220 | 0.23000 | -Query OK, 1 row(s) in set (0.004767s) - -taos> SELECT FIRST(current) FROM d1002; - first(current) | -======================= - 10.20000 | -Query OK, 1 row(s) in set (0.001023s) -``` - -### LAST - -``` -SELECT LAST(field_name) FROM { tb_name | stb_name } [WHERE clause]; -``` - -**功能说明**:统计表/超级表中某列的值最后写入的非 NULL 值。 - -**返回数据类型**:同应用的字段。 - -**应用字段**:所有字段。 - -**适用于**:表、超级表。 - -**使用说明**: - -- 如果要返回各个列的最后(时间戳最大)一个非 NULL 值,可以使用 LAST(\*); -- 如果结果集中的某列全部为 NULL 值,则该列的返回结果也是 NULL;如果结果集中所有列全部为 NULL 值,则不返回结果。 -- 在用于超级表时,时间戳完全一样且同为最大的数据行可能有多个,那么会从中随机返回一条,而并不保证多次运行所挑选的数据行必然一致。 - - -**示例**: - -``` -taos> SELECT LAST(*) FROM meters; - last(ts) | last(current) | last(voltage) | last(phase) | -======================================================================================== -2018-10-03 14:38:16.800 | 12.30000 | 221 | 0.31000 | -Query OK, 1 row(s) in set (0.001452s) - -taos> SELECT LAST(current) FROM d1002; - last(current) | -======================= - 10.30000 | -Query OK, 1 row(s) in set (0.000843s) -``` - -### TOP - -``` -SELECT TOP(field_name, K) FROM { tb_name | stb_name } [WHERE clause]; -``` - -**功能说明**: 统计表/超级表中某列的值最大 _k_ 个非 NULL 值。如果多条数据取值一样,全部取用又会超出 k 条限制时,系统会从相同值中随机选取符合要求的数量返回。 - -**返回数据类型**:同应用的字段。 - -**应用字段**:不能应用在 timestamp、binary、nchar、bool 类型字段。 - -**适用于**:表、超级表。 - -**使用说明**: - -- *k*值取值范围 1≤*k*≤100; -- 系统同时返回该记录关联的时间戳列; -- 限制:TOP 函数不支持 FILL 子句。 - -**示例**: - -``` -taos> SELECT TOP(current, 3) FROM meters; - ts | top(current, 3) | -================================================= -2018-10-03 14:38:15.000 | 12.60000 | -2018-10-03 14:38:16.600 | 13.40000 | -2018-10-03 14:38:16.800 | 12.30000 | -Query OK, 3 row(s) in set (0.001548s) - -taos> SELECT TOP(current, 2) FROM d1001; - ts | top(current, 2) | -================================================= -2018-10-03 14:38:15.000 | 12.60000 | -2018-10-03 14:38:16.800 | 12.30000 | -Query OK, 2 row(s) in set (0.000810s) -``` - -### BOTTOM - -``` -SELECT BOTTOM(field_name, K) FROM { tb_name | stb_name } [WHERE clause]; -``` - -**功能说明**:统计表/超级表中某列的值最小 _k_ 个非 NULL 值。如果多条数据取值一样,全部取用又会超出 k 条限制时,系统会从相同值中随机选取符合要求的数量返回。 - -**返回数据类型**:同应用的字段。 - -**应用字段**:不能应用在 timestamp、binary、nchar、bool 类型字段。 - -**适用于**:表、超级表。 - -**使用说明**: - -- *k*值取值范围 1≤*k*≤100; -- 系统同时返回该记录关联的时间戳列; -- 限制:BOTTOM 函数不支持 FILL 子句。 - -**示例**: - -``` -taos> SELECT BOTTOM(voltage, 2) FROM meters; - ts | bottom(voltage, 2) | -=============================================== -2018-10-03 14:38:15.000 | 218 | -2018-10-03 14:38:16.650 | 218 | -Query OK, 2 row(s) in set (0.001332s) - -taos> SELECT BOTTOM(current, 2) FROM d1001; - ts | bottom(current, 2) | -================================================= -2018-10-03 14:38:05.000 | 10.30000 | -2018-10-03 14:38:16.800 | 12.30000 | -Query OK, 2 row(s) in set (0.000793s) -``` - -### PERCENTILE - -``` -SELECT PERCENTILE(field_name, P) FROM { tb_name } [WHERE clause]; -``` - -**功能说明**:统计表中某列的值百分比分位数。 - -**返回数据类型**: 双精度浮点数 Double。 - -**应用字段**:不能应用在 timestamp、binary、nchar、bool 类型字段。 - -**适用于**:表。 - -**使用说明**:*P*值取值范围 0≤*P*≤100,为 0 的时候等同于 MIN,为 100 的时候等同于 MAX。 - -**示例**: - -``` -taos> SELECT PERCENTILE(current, 20) FROM d1001; -percentile(current, 20) | -============================ - 11.100000191 | -Query OK, 1 row(s) in set (0.000787s) -``` - -### APERCENTILE - -``` -SELECT APERCENTILE(field_name, P[, algo_type]) -FROM { tb_name | stb_name } [WHERE clause] -``` - -**功能说明**:统计表/超级表中指定列的值百分比分位数,与 PERCENTILE 函数相似,但是返回近似结果。 - -**返回数据类型**: 双精度浮点数 Double。 - -**应用字段**:不能应用在 timestamp、binary、nchar、bool 类型字段。 -**适用于**:表、超级表。 +**功能说明**:获得指定列的绝对值 -**使用说明** +**返回结果类型**:如果输入值为整数,输出值是 UBIGINT 类型。如果输入值是 FLOAT/DOUBLE 数据类型,输出值是 DOUBLE 数据类型。 -- **P**值有效取值范围 0≤P≤100,为 0 的时候等同于 MIN,为 100 的时候等同于 MAX; -- **algo_type**的有效输入:**default** 和 **t-digest** -- 用于指定计算近似分位数的算法。可不提供第三个参数的输入,此时将使用 default 的算法进行计算,即 apercentile(column_name, 50, "default") 与 apercentile(column_name, 50) 等价。 -- 当使用“t-digest”参数的时候,将使用 t-digest 方式采样计算近似分位数。但该参数指定计算算法的功能从 2.2.0.x 版本开始支持,2.2.0.0 之前的版本不支持指定使用算法的功能。 +**适用数据类型**:不能应用在 timestamp、binary、nchar、bool 类型字段上;在超级表查询中使用时,不能应用在 tag 列 **嵌套子查询支持**:适用于内层查询和外层查询。 -``` -taos> SELECT APERCENTILE(current, 20) FROM d1001; -apercentile(current, 20) | -============================ - 10.300000191 | -Query OK, 1 row(s) in set (0.000645s) +**适用于**: 表和超级表 -taos> select apercentile (count, 80, 'default') from stb1; - apercentile (c0, 80, 'default') | -================================== - 601920857.210056424 | -Query OK, 1 row(s) in set (0.012363s) +**使用说明**:只能与普通列,选择(Selection)、投影(Projection)函数一起使用,不能与聚合(Aggregation)函数一起使用。 -taos> select apercentile (count, 80, 't-digest') from stb1; - apercentile (c0, 80, 't-digest') | -=================================== - 605869120.966666579 | -Query OK, 1 row(s) in set (0.011639s) +#### ACOS + +```sql + SELECT ACOS(field_name) FROM { tb_name | stb_name } [WHERE clause] ``` -### LAST_ROW +**功能说明**:获得指定列的反余弦结果 -``` -SELECT LAST_ROW(field_name) FROM { tb_name | stb_name }; +**返回结果类型**:DOUBLE。如果输入值为 NULL,输出值也为 NULL + +**适用数据类型**:不能应用在 timestamp、binary、nchar、bool 类型字段上;在超级表查询中使用时,不能应用在 tag 列 + +**嵌套子查询支持**:适用于内层查询和外层查询。 + +**适用于**: 表和超级表 + +**使用说明**:只能与普通列,选择(Selection)、投影(Projection)函数一起使用,不能与聚合(Aggregation)函数一起使用。 + +#### ASIN + +```sql + SELECT ASIN(field_name) FROM { tb_name | stb_name } [WHERE clause] ``` -**功能说明**:返回表/超级表的最后一条记录。 +**功能说明**:获得指定列的反正弦结果 -**返回数据类型**:同应用的字段。 +**返回结果类型**:DOUBLE。如果输入值为 NULL,输出值也为 NULL -**应用字段**:所有字段。 +**适用数据类型**:不能应用在 timestamp、binary、nchar、bool 类型字段上;在超级表查询中使用时,不能应用在 tag 列 -**适用于**:表、超级表。 +**嵌套子查询支持**:适用于内层查询和外层查询。 -**使用说明**: +**适用于**: 表和超级表 -- 在用于超级表时,时间戳完全一样且同为最大的数据行可能有多个,那么会从中随机返回一条,而并不保证多次运行所挑选的数据行必然一致。 -- 不能与 INTERVAL 一起使用。 +**使用说明**:只能与普通列,选择(Selection)、投影(Projection)函数一起使用,不能与聚合(Aggregation)函数一起使用。 -**示例**: -``` - taos> SELECT LAST_ROW(current) FROM meters; - last_row(current) | - ======================= - 12.30000 | - Query OK, 1 row(s) in set (0.001238s) +#### ATAN - taos> SELECT LAST_ROW(current) FROM d1002; - last_row(current) | - ======================= - 10.30000 | - Query OK, 1 row(s) in set (0.001042s) +```sql + SELECT ATAN(field_name) FROM { tb_name | stb_name } [WHERE clause] ``` -### INTERP [2.3.1 及之后的版本] +**功能说明**:获得指定列的反正切结果 -``` -SELECT INTERP(field_name) FROM { tb_name | stb_name } [WHERE where_condition] [ RANGE(timestamp1,timestamp2) ] [EVERY(interval)] [FILL ({ VALUE | PREV | NULL | LINEAR | NEXT})]; -``` +**返回结果类型**:DOUBLE。如果输入值为 NULL,输出值也为 NULL -**功能说明**:返回表/超级表的指定时间截面指定列的记录值(插值)。 +**适用数据类型**:不能应用在 timestamp、binary、nchar、bool 类型字段上;在超级表查询中使用时,不能应用在 tag 列 -**返回数据类型**:同字段类型。 +**嵌套子查询支持**:适用于内层查询和外层查询。 -**应用字段**:数值型字段。 +**适用于**: 表和超级表 -**适用于**:表、超级表、嵌套查询。 +**使用说明**:只能与普通列,选择(Selection)、投影(Projection)函数一起使用,不能与聚合(Aggregation)函数一起使用。 -**使用说明** - -- INTERP 用于在指定时间断面获取指定列的记录值,如果该时间断面不存在符合条件的行数据,那么会根据 FILL 参数的设定进行插值。 -- INTERP 的输入数据为指定列的数据,可以通过条件语句(where 子句)来对原始列数据进行过滤,如果没有指定过滤条件则输入为全部数据。 -- INTERP 的输出时间范围根据 RANGE(timestamp1,timestamp2)字段来指定,需满足 timestamp1<=timestamp2。其中 timestamp1(必选值)为输出时间范围的起始值,即如果 timestamp1 时刻符合插值条件则 timestamp1 为输出的第一条记录,timestamp2(必选值)为输出时间范围的结束值,即输出的最后一条记录的 timestamp 不能大于 timestamp2。如果没有指定 RANGE,那么满足过滤条件的输入数据中第一条记录的 timestamp 即为 timestamp1,最后一条记录的 timestamp 即为 timestamp2,同样也满足 timestamp1 <= timestamp2。 -- INTERP 根据 EVERY 字段来确定输出时间范围内的结果条数,即从 timestamp1 开始每隔固定长度的时间(EVERY 值)进行插值。如果没有指定 EVERY,则默认窗口大小为无穷大,即从 timestamp1 开始只有一个窗口。 -- INTERP 根据 FILL 字段来决定在每个符合输出条件的时刻如何进行插值,如果没有 FILL 字段则默认不插值,即输出为原始记录值或不输出(原始记录不存在)。 -- INTERP 只能在一个时间序列内进行插值,因此当作用于超级表时必须跟 group by tbname 一起使用,当作用嵌套查询外层时内层子查询不能含 GROUP BY 信息。 -- INTERP 的插值结果不受 ORDER BY timestamp 的影响,ORDER BY timestamp 只影响输出结果的排序。 - -**SQL示例(基于文档中广泛使用的电表 schema )**: - -- 单点线性插值 - -``` - taos> SELECT INTERP(current) FROM t1 RANGE('2017-7-14 18:40:00','2017-7-14 18:40:00') FILL(LINEAR); -``` - -- 在2017-07-14 18:00:00到2017-07-14 19:00:00间每隔5秒钟进行取值(不插值) - -``` - taos> SELECT INTERP(current) FROM t1 RANGE('2017-7-14 18:00:00','2017-7-14 19:00:00') EVERY(5s); -``` - -- 在2017-07-14 18:00:00到2017-07-14 19:00:00间每隔5秒钟进行线性插值 - -``` - taos> SELECT INTERP(current) FROM t1 RANGE('2017-7-14 18:00:00','2017-7-14 19:00:00') EVERY(5s) FILL(LINEAR); -``` - -- 在所有时间范围内每隔 5 秒钟进行向后插值 - -``` - taos> SELECT INTERP(current) FROM t1 EVERY(5s) FILL(NEXT); -``` - -- 根据 2017-07-14 17:00:00 到 2017-07-14 20:00:00 间的数据进行从 2017-07-14 18:00:00 到 2017-07-14 19:00:00 间每隔 5 秒钟进行线性插值 - -``` - taos> SELECT INTERP(current) FROM t1 where ts >= '2017-07-14 17:00:00' and ts <= '2017-07-14 20:00:00' RANGE('2017-7-14 18:00:00','2017-7-14 19:00:00') EVERY(5s) FILL(LINEAR); -``` - -### INTERP [2.3.1 之前的版本] - -``` -SELECT INTERP(field_name) FROM { tb_name | stb_name } WHERE ts='timestamp' [FILL ({ VALUE | PREV | NULL | LINEAR | NEXT})]; -``` - -**功能说明**:返回表/超级表的指定时间截面、指定字段的记录。 - -**返回数据类型**:同字段类型。 - -**应用字段**:数值型字段。 - -**适用于**:表、超级表。 - -**使用说明**: - -- 从 2.0.15.0 及以后版本可用 -- INTERP 必须指定时间断面,如果该时间断面不存在直接对应的数据,那么会根据 FILL 参数的设定进行插值。此外,条件语句里面可附带筛选条件,例如标签、tbname。 -- INTERP 查询要求查询的时间区间必须位于数据集合(表)的所有记录的时间范围之内。如果给定的时间戳位于时间范围之外,即使有插值指令,仍然不返回结果。 -- 单个 INTERP 函数查询只能够针对一个时间点进行查询,如果需要返回等时间间隔的断面数据,可以通过 INTERP 配合 EVERY 的方式来进行查询处理(而不是使用 INTERVAL),其含义是每隔固定长度的时间进行插值 - -**示例**: - -``` - taos> SELECT INTERP(*) FROM meters WHERE ts='2017-7-14 18:40:00.004'; - interp(ts) | interp(current) | interp(voltage) | interp(phase) | - ========================================================================================== - 2017-07-14 18:40:00.004 | 9.84020 | 216 | 0.32222 | - Query OK, 1 row(s) in set (0.002652s) -``` - -如果给定的时间戳无对应的数据,在不指定插值生成策略的情况下,不会返回结果,如果指定了插值策略,会根据插值策略返回结果。 - -``` - taos> SELECT INTERP(*) FROM meters WHERE tbname IN ('d636') AND ts='2017-7-14 18:40:00.005'; - Query OK, 0 row(s) in set (0.004022s) - - taos> SELECT INTERP(*) FROM meters WHERE tbname IN ('d636') AND ts='2017-7-14 18:40:00.005' FILL(PREV); - interp(ts) | interp(current) | interp(voltage) | interp(phase) | - ========================================================================================== - 2017-07-14 18:40:00.005 | 9.88150 | 217 | 0.32500 | - Query OK, 1 row(s) in set (0.003056s) -``` - -如下所示代码表示在时间区间 `['2017-7-14 18:40:00', '2017-7-14 18:40:00.014']` 中每隔 5 毫秒 进行一次断面计算。 - -``` - taos> SELECT INTERP(current) FROM d636 WHERE ts>='2017-7-14 18:40:00' AND ts<='2017-7-14 18:40:00.014' EVERY(5a); - ts | interp(current) | - ================================================= - 2017-07-14 18:40:00.000 | 10.04179 | - 2017-07-14 18:40:00.010 | 10.16123 | - Query OK, 2 row(s) in set (0.003487s) -``` - -### TAIL - -``` -SELECT TAIL(field_name, k, offset_val) FROM {tb_name | stb_name} [WHERE clause]; -``` - -**功能说明**:返回跳过最后 offset_val 个,然后取连续 k 个记录,不忽略 NULL 值。offset_val 可以不输入。此时返回最后的 k 个记录。当有 offset_val 输入的情况下,该函数功能等效于 `order by ts desc LIMIT k OFFSET offset_val`。 - -**参数范围**:k: [1,100] offset_val: [0,100]。 - -**返回结果数据类型**:同应用的字段。 - -**应用字段**:适合于除时间主列外的任何类型字段。 - -**支持版本**:2.6.0.0 及之后的版本。 - -**示例**: - -``` -taos> select ts,dbig from tail2; - ts | dbig | -================================================== -2021-10-15 00:31:33.000 | 1 | -2021-10-17 00:31:31.000 | NULL | -2021-12-24 00:31:34.000 | 2 | -2022-01-01 08:00:05.000 | 19 | -2022-01-01 08:00:06.000 | NULL | -2022-01-01 08:00:07.000 | 9 | -Query OK, 6 row(s) in set (0.001952s) - -taos> select tail(dbig,2,2) from tail2; -ts | tail(dbig,2,2) | -================================================== -2021-12-24 00:31:34.000 | 2 | -2022-01-01 08:00:05.000 | 19 | -Query OK, 2 row(s) in set (0.002307s) -``` - -### UNIQUE - -``` -SELECT UNIQUE(field_name) FROM {tb_name | stb_name} [WHERE clause]; -``` - -**功能说明**:返回该列的数值首次出现的值。该函数功能与 distinct 相似,但是可以匹配标签和时间戳信息。可以针对除时间列以外的字段进行查询,可以匹配标签和时间戳,其中的标签和时间戳是第一次出现时刻的标签和时间戳。 - -**返回结果数据类型**:同应用的字段。 - -**应用字段**:适合于除时间类型以外的字段。 - -**支持版本**:2.6.0.0 及之后的版本。 - -**使用说明**: - -- 该函数可以应用在普通表和超级表上。不能和窗口操作一起使用,例如 interval/state_window/session_window 。 -- 由于返回数据量未知,考虑到内存因素,为了函数可以正常返回结果,建议不重复的数据量在 10 万级别,否则会报错。 - -**示例**: - -``` -taos> select ts,voltage from unique1; - ts | voltage | -================================================== -2021-10-17 00:31:31.000 | 1 | -2022-01-24 00:31:31.000 | 1 | -2021-10-17 00:31:31.000 | 1 | -2021-12-24 00:31:31.000 | 2 | -2022-01-01 08:00:01.000 | 19 | -2021-10-17 00:31:31.000 | NULL | -2022-01-01 08:00:02.000 | NULL | -2022-01-01 08:00:03.000 | 9 | -Query OK, 8 row(s) in set (0.003018s) - -taos> select unique(voltage) from unique1; -ts | unique(voltage) | -================================================== -2021-10-17 00:31:31.000 | 1 | -2021-10-17 00:31:31.000 | NULL | -2021-12-24 00:31:31.000 | 2 | -2022-01-01 08:00:01.000 | 19 | -2022-01-01 08:00:03.000 | 9 | -Query OK, 5 row(s) in set (0.108458s) -``` - -## 计算函数 - -### DIFF - - ```sql - SELECT {DIFF(field_name, ignore_negative) | DIFF(field_name)} FROM tb_name [WHERE clause]; - ``` - -**功能说明**:统计表中某列的值与前一行对应值的差。 ignore_negative 取值为 0|1 , 可以不填,默认值为 0. 不忽略负值。ignore_negative 为 1 时表示忽略负数。 - -**返回结果数据类型**:同应用字段。 - -**应用字段**:不能应用在 timestamp、binary、nchar、bool 类型字段。 - -**适用于**:表、超级表。 - -**使用说明**: - -- 输出结果行数是范围内总行数减一,第一行没有结果输出。 -- 从 2.1.3.0 版本开始,DIFF 函数可以在由 GROUP BY 划分出单独时间线的情况下用于超级表(也即 GROUP BY tbname)。 -- 从 2.6.0 开始,DIFF 函数支持 ignore_negative 参数 - -**示例**: - - ```sql - taos> SELECT DIFF(current) FROM d1001; - ts | diff(current) | - ================================================= - 2018-10-03 14:38:15.000 | 2.30000 | - 2018-10-03 14:38:16.800 | -0.30000 | - Query OK, 2 row(s) in set (0.001162s) - ``` - -### DERIVATIVE - -``` -SELECT DERIVATIVE(field_name, time_interval, ignore_negative) FROM tb_name [WHERE clause]; -``` - -**功能说明**:统计表中某列数值的单位变化率。其中单位时间区间的长度可以通过 time_interval 参数指定,最小可以是 1 秒(1s);ignore_negative 参数的值可以是 0 或 1,为 1 时表示忽略负值。 - -**返回数据类型**:双精度浮点数。 - -**应用字段**:不能应用在 timestamp、binary、nchar、bool 类型字段。 - -**适用于**:表、超级表 - -**使用说明**: - -- 从 2.1.3.0 及以后版本可用;输出结果行数是范围内总行数减一,第一行没有结果输出。 -- DERIVATIVE 函数可以在由 GROUP BY 划分出单独时间线的情况下用于超级表(也即 GROUP BY tbname)。 - -**示例**: - -``` -taos> select derivative(current, 10m, 0) from t1; - ts | derivative(current, 10m, 0) | -======================================================== - 2021-08-20 10:11:22.790 | 0.500000000 | - 2021-08-20 11:11:22.791 | 0.166666620 | - 2021-08-20 12:11:22.791 | 0.000000000 | - 2021-08-20 13:11:22.792 | 0.166666620 | - 2021-08-20 14:11:22.792 | -0.666666667 | -Query OK, 5 row(s) in set (0.004883s) -``` - -### SPREAD - -``` -SELECT SPREAD(field_name) FROM { tb_name | stb_name } [WHERE clause]; -``` - -**功能说明**:统计表/超级表中某列的最大值和最小值之差。 - -**返回数据类型**:双精度浮点数。 - -**应用字段**:不能应用在 binary、nchar、bool 类型字段。 - -**适用于**:表、超级表。 - -**使用说明**:可用于 TIMESTAMP 字段,此时表示记录的时间覆盖范围。 - -**示例**: - -``` -taos> SELECT SPREAD(voltage) FROM meters; - spread(voltage) | -============================ - 5.000000000 | -Query OK, 1 row(s) in set (0.001792s) - -taos> SELECT SPREAD(voltage) FROM d1001; - spread(voltage) | -============================ - 3.000000000 | -Query OK, 1 row(s) in set (0.000836s) -``` - -### CEIL +#### CEIL ``` SELECT CEIL(field_name) FROM { tb_name | stb_name } [WHERE clause]; @@ -981,170 +105,7 @@ SELECT CEIL(field_name) FROM { tb_name | stb_name } [WHERE clause]; - 支持 +、-、\*、/ 运算,如 ceil(col1) + ceil(col2)。 - 只能与普通列,选择(Selection)、投影(Projection)函数一起使用,不能与聚合(Aggregation)函数一起使用。 -### FLOOR - -``` -SELECT FLOOR(field_name) FROM { tb_name | stb_name } [WHERE clause]; -``` - -**功能说明**:获得指定列的向下取整数的结果。 - 其他使用说明参见 CEIL 函数描述。 - -### ROUND - -``` -SELECT ROUND(field_name) FROM { tb_name | stb_name } [WHERE clause]; -``` - -**功能说明**:获得指定列的四舍五入的结果。 - 其他使用说明参见 CEIL 函数描述。 - -### CSUM - -```sql - SELECT CSUM(field_name) FROM { tb_name | stb_name } [WHERE clause] -``` - - **功能说明**:累加和(Cumulative sum),输出行与输入行数相同。 - - **返回结果类型**: 输入列如果是整数类型返回值为长整型 (int64_t),浮点数返回值为双精度浮点数(Double)。无符号整数类型返回值为无符号长整型(uint64_t)。 返回结果中同时带有每行记录对应的时间戳。 - - **适用数据类型**:不能应用在 timestamp、binary、nchar、bool 类型字段上;在超级表查询中使用时,不能应用在标签之上。 - - **嵌套子查询支持**: 适用于内层查询和外层查询。 - - **使用说明**: - - - 不支持 +、-、*、/ 运算,如 csum(col1) + csum(col2)。 - - 只能与聚合(Aggregation)函数一起使用。 该函数可以应用在普通表和超级表上。 - - 使用在超级表上的时候,需要搭配 Group by tbname使用,将结果强制规约到单个时间线。 - -**支持版本**: 从2.3.0.x开始支持 - -### MAVG - -```sql - SELECT MAVG(field_name, K) FROM { tb_name | stb_name } [WHERE clause] -``` - - **功能说明**: 计算连续 k 个值的移动平均数(moving average)。如果输入行数小于 k,则无结果输出。参数 k 的合法输入范围是 1≤ k ≤ 1000。 - - **返回结果类型**: 返回双精度浮点数类型。 - - **适用数据类型**: 不能应用在 timestamp、binary、nchar、bool 类型上;在超级表查询中使用时,不能应用在标签之上。 - - **嵌套子查询支持**: 适用于内层查询和外层查询。 - - **使用说明**: - - - 不支持 +、-、*、/ 运算,如 mavg(col1, k1) + mavg(col2, k1); - - 只能与普通列,选择(Selection)、投影(Projection)函数一起使用,不能与聚合(Aggregation)函数一起使用; - - 该函数可以应用在普通表和超级表上;使用在超级表上的时候,需要搭配 Group by tbname使用,将结果强制规约到单个时间线。 - -**支持版本**: 从2.3.0.x开始支持 - -### SAMPLE - -```sql - SELECT SAMPLE(field_name, K) FROM { tb_name | stb_name } [WHERE clause] -``` - - **功能说明**: 获取数据的 k 个采样值。参数 k 的合法输入范围是 1≤ k ≤ 1000。 - - **返回结果类型**: 同原始数据类型, 返回结果中带有该行记录的时间戳。 - - **适用数据类型**: 在超级表查询中使用时,不能应用在标签之上。 - - **嵌套子查询支持**: 适用于内层查询和外层查询。 - - **使用说明**: - - - 不能参与表达式计算;该函数可以应用在普通表和超级表上; - - 使用在超级表上的时候,需要搭配 Group by tbname 使用,将结果强制规约到单个时间线。 - -**支持版本**: 从2.3.0.x开始支持 - -### ASIN - -```sql - SELECT ASIN(field_name) FROM { tb_name | stb_name } [WHERE clause] -``` - -**功能说明**:获得指定列的反正弦结果 - -**返回结果类型**:DOUBLE。如果输入值为 NULL,输出值也为 NULL - -**适用数据类型**:不能应用在 timestamp、binary、nchar、bool 类型字段上;在超级表查询中使用时,不能应用在 tag 列 - -**嵌套子查询支持**:适用于内层查询和外层查询。 - -**使用说明**: - -- 只能与普通列,选择(Selection)、投影(Projection)函数一起使用,不能与聚合(Aggregation)函数一起使用。 -- 该函数可以应用在普通表和超级表上。 -- 版本2.6.0.x后支持 - -### ACOS - -```sql - SELECT ACOS(field_name) FROM { tb_name | stb_name } [WHERE clause] -``` - -**功能说明**:获得指定列的反余弦结果 - -**返回结果类型**:DOUBLE。如果输入值为 NULL,输出值也为 NULL - -**适用数据类型**:不能应用在 timestamp、binary、nchar、bool 类型字段上;在超级表查询中使用时,不能应用在 tag 列 - -**嵌套子查询支持**:适用于内层查询和外层查询。 - -**使用说明**: - -- 只能与普通列,选择(Selection)、投影(Projection)函数一起使用,不能与聚合(Aggregation)函数一起使用。 -- 该函数可以应用在普通表和超级表上。 -- 版本2.6.0.x后支持 - -### ATAN - -```sql - SELECT ATAN(field_name) FROM { tb_name | stb_name } [WHERE clause] -``` - -**功能说明**:获得指定列的反正切结果 - -**返回结果类型**:DOUBLE。如果输入值为 NULL,输出值也为 NULL - -**适用数据类型**:不能应用在 timestamp、binary、nchar、bool 类型字段上;在超级表查询中使用时,不能应用在 tag 列 - -**嵌套子查询支持**:适用于内层查询和外层查询。 - -**使用说明**: - -- 只能与普通列,选择(Selection)、投影(Projection)函数一起使用,不能与聚合(Aggregation)函数一起使用。 -- 该函数可以应用在普通表和超级表上。 -- 版本2.6.0.x后支持 - -### SIN - -```sql - SELECT SIN(field_name) FROM { tb_name | stb_name } [WHERE clause] -``` - -**功能说明**:获得指定列的正弦结果 - -**返回结果类型**:DOUBLE。如果输入值为 NULL,输出值也为 NULL - -**适用数据类型**:不能应用在 timestamp、binary、nchar、bool 类型字段上;在超级表查询中使用时,不能应用在 tag 列 - -**嵌套子查询支持**:适用于内层查询和外层查询。 - -**使用说明**: - -- 只能与普通列,选择(Selection)、投影(Projection)函数一起使用,不能与聚合(Aggregation)函数一起使用。 -- 该函数可以应用在普通表和超级表上。 -- 版本2.6.0.x后支持 - -### COS +#### COS ```sql SELECT COS(field_name) FROM { tb_name | stb_name } [WHERE clause] @@ -1158,53 +119,20 @@ SELECT ROUND(field_name) FROM { tb_name | stb_name } [WHERE clause]; **嵌套子查询支持**:适用于内层查询和外层查询。 -**使用说明**: +**适用于**: 表和超级表 -- 只能与普通列,选择(Selection)、投影(Projection)函数一起使用,不能与聚合(Aggregation)函数一起使用。 -- 该函数可以应用在普通表和超级表上。 -- 版本2.6.0.x后支持 +**使用说明**:只能与普通列,选择(Selection)、投影(Projection)函数一起使用,不能与聚合(Aggregation)函数一起使用。 -### TAN +#### FLOOR -```sql - SELECT TAN(field_name) FROM { tb_name | stb_name } [WHERE clause] +``` +SELECT FLOOR(field_name) FROM { tb_name | stb_name } [WHERE clause]; ``` -**功能说明**:获得指定列的正切结果 +**功能说明**:获得指定列的向下取整数的结果。 + 其他使用说明参见 CEIL 函数描述。 -**返回结果类型**:DOUBLE。如果输入值为 NULL,输出值也为 NULL - -**适用数据类型**:不能应用在 timestamp、binary、nchar、bool 类型字段上;在超级表查询中使用时,不能应用在 tag 列 - -**嵌套子查询支持**:适用于内层查询和外层查询。 - -**使用说明**: - -- 只能与普通列,选择(Selection)、投影(Projection)函数一起使用,不能与聚合(Aggregation)函数一起使用。 -- 该函数可以应用在普通表和超级表上。 -- 版本2.6.0.x后支持 - -### POW - -```sql - SELECT POW(field_name, power) FROM { tb_name | stb_name } [WHERE clause] -``` - -**功能说明**:获得指定列的指数为 power 的幂 - -**返回结果类型**:DOUBLE。如果输入值为 NULL,输出值也为 NULL - -**适用数据类型**:不能应用在 timestamp、binary、nchar、bool 类型字段上;在超级表查询中使用时,不能应用在 tag 列 - -**嵌套子查询支持**:适用于内层查询和外层查询。 - -**使用说明**: - -- 只能与普通列,选择(Selection)、投影(Projection)函数一起使用,不能与聚合(Aggregation)函数一起使用。 -- 该函数可以应用在普通表和超级表上。 -- 版本2.6.0.x后支持 - -### LOG +#### LOG ```sql SELECT LOG(field_name, base) FROM { tb_name | stb_name } [WHERE clause] @@ -1218,33 +146,59 @@ SELECT ROUND(field_name) FROM { tb_name | stb_name } [WHERE clause]; **嵌套子查询支持**:适用于内层查询和外层查询。 -**使用说明**: +**适用于**: 表和超级表 -- 只能与普通列,选择(Selection)、投影(Projection)函数一起使用,不能与聚合(Aggregation)函数一起使用。 -- 该函数可以应用在普通表和超级表上。 -- 版本2.6.0.x后支持 +**使用说明**:只能与普通列,选择(Selection)、投影(Projection)函数一起使用,不能与聚合(Aggregation)函数一起使用。 -### ABS + +#### POW ```sql - SELECT ABS(field_name) FROM { tb_name | stb_name } [WHERE clause] + SELECT POW(field_name, power) FROM { tb_name | stb_name } [WHERE clause] ``` -**功能说明**:获得指定列的绝对值 +**功能说明**:获得指定列的指数为 power 的幂 -**返回结果类型**:如果输入值为整数,输出值是 UBIGINT 类型。如果输入值是 FLOAT/DOUBLE 数据类型,输出值是 DOUBLE 数据类型。 +**返回结果类型**:DOUBLE。如果输入值为 NULL,输出值也为 NULL **适用数据类型**:不能应用在 timestamp、binary、nchar、bool 类型字段上;在超级表查询中使用时,不能应用在 tag 列 **嵌套子查询支持**:适用于内层查询和外层查询。 -**使用说明**: +**适用于**: 表和超级表 -- 只能与普通列,选择(Selection)、投影(Projection)函数一起使用,不能与聚合(Aggregation)函数一起使用。 -- 该函数可以应用在普通表和超级表上。 -- 版本2.6.0.x后支持 +**使用说明**:只能与普通列,选择(Selection)、投影(Projection)函数一起使用,不能与聚合(Aggregation)函数一起使用。 -### SQRT + +#### ROUND + +``` +SELECT ROUND(field_name) FROM { tb_name | stb_name } [WHERE clause]; +``` + +**功能说明**:获得指定列的四舍五入的结果。 + 其他使用说明参见 CEIL 函数描述。 + + +#### SIN + +```sql + SELECT SIN(field_name) FROM { tb_name | stb_name } [WHERE clause] +``` + +**功能说明**:获得指定列的正弦结果 + +**返回结果类型**:DOUBLE。如果输入值为 NULL,输出值也为 NULL + +**适用数据类型**:不能应用在 timestamp、binary、nchar、bool 类型字段上;在超级表查询中使用时,不能应用在 tag 列 + +**嵌套子查询支持**:适用于内层查询和外层查询。 + +**适用于**: 表和超级表 + +**使用说明**:只能与普通列,选择(Selection)、投影(Projection)函数一起使用,不能与聚合(Aggregation)函数一起使用。 + +#### SQRT ```sql SELECT SQRT(field_name) FROM { tb_name | stb_name } [WHERE clause] @@ -1258,39 +212,49 @@ SELECT ROUND(field_name) FROM { tb_name | stb_name } [WHERE clause]; **嵌套子查询支持**:适用于内层查询和外层查询。 -**使用说明**: +**适用于**: 表和超级表 -- 只能与普通列,选择(Selection)、投影(Projection)函数一起使用,不能与聚合(Aggregation)函数一起使用。 -- 该函数可以应用在普通表和超级表上。 -- 版本2.6.0.x后支持 +**使用说明**:只能与普通列,选择(Selection)、投影(Projection)函数一起使用,不能与聚合(Aggregation)函数一起使用。 -### CAST +#### TAN ```sql - SELECT CAST(expression AS type_name) FROM { tb_name | stb_name } [WHERE clause] + SELECT TAN(field_name) FROM { tb_name | stb_name } [WHERE clause] ``` -**功能说明**:数据类型转换函数,输入参数 expression 支持普通列、常量、标量函数及它们之间的四则运算,不支持 tag 列,只适用于 select 子句中。 +**功能说明**:获得指定列的正切结果 -**返回结果类型**:CAST 中指定的类型(type_name)。 +**返回结果类型**:DOUBLE。如果输入值为 NULL,输出值也为 NULL -**适用数据类型**: +**适用数据类型**:不能应用在 timestamp、binary、nchar、bool 类型字段上;在超级表查询中使用时,不能应用在 tag 列 -- 输入参数 expression 的类型可以是除 JSON 外目前所有类型字段(BOOL/TINYINT/SMALLINT/INT/BIGINT/FLOAT/DOUBLE/BINARY(M)/TIMESTAMP/NCHAR(M)/TINYINT UNSIGNED/SMALLINT UNSIGNED/INT UNSIGNED/BIGINT UNSIGNED); -- 输出目标类型只支持 BIGINT/BINARY(N)/TIMESTAMP/NCHAR(N)/BIGINT UNSIGNED。 +**嵌套子查询支持**:适用于内层查询和外层查询。 -**使用说明**: +**适用于**: 表和超级表 -- 对于不能支持的类型转换会直接报错。 -- 如果输入值为NULL则输出值也为NULL。 -- 对于类型支持但某些值无法正确转换的情况对应的转换后的值以转换函数输出为准。目前可能遇到的几种情况: - 1)BINARY/NCHAR转BIGINT/BIGINT UNSIGNED时可能出现的无效字符情况,例如"a"可能转为0。 - 2)有符号数或TIMESTAMP转BIGINT UNSIGNED可能遇到的溢出问题。 - 3)BIGINT UNSIGNED转BIGINT可能遇到的溢出问题。 - 4)FLOAT/DOUBLE转BIGINT/BIGINT UNSIGNED可能遇到的溢出问题。 -- 版本2.6.0.x后支持 +**使用说明**:只能与普通列,选择(Selection)、投影(Projection)函数一起使用,不能与聚合(Aggregation)函数一起使用。 -### CONCAT +### 字符串函数 + +字符串函数的输入参数为字符串类型,返回结果为数值类型或字符串类型。 + +#### CHAR_LENGTH + +``` + SELECT CHAR_LENGTH(str|column) FROM { tb_name | stb_name } [WHERE clause] +``` + +**功能说明**:以字符计数的字符串长度。 + +**返回结果类型**:INT。如果输入值为NULL,输出值为NULL。 + +**适用数据类型**:输入参数是 BINARY 类型或者 NCHAR 类型的字符串或者列。不能应用在 TAG 列。 + +**嵌套子查询支持**:适用于内层查询和外层查询。 + +**适用于**: 表和超级表 + +#### CONCAT ```sql SELECT CONCAT(str1|column1, str2|column2, ...) FROM { tb_name | stb_name } [WHERE clause] @@ -1298,19 +262,16 @@ SELECT ROUND(field_name) FROM { tb_name | stb_name } [WHERE clause]; **功能说明**:字符串连接函数。 -**返回结果类型**:同输入参数类型,BINARY 或者 NCHAR。 +**返回结果类型**:如果所有参数均为BINARY类型,则结果类型为BINARY。如果参数包含NCHAR类型,则结果类型为NCHAR。如果输入值为NULL,输出值为NULL。 -**适用数据类型**:输入参数或者全部是 BINARY 格式的字符串或者列,或者全部是 NCHAR 格式的字符串或者列。不能应用在 TAG 列。 +**适用数据类型**:BINARY, NCHAR。不能应用在 TAG 列。 该函数最小参数个数为2个,最大参数个数为8个。 -**使用说明**: +**嵌套子查询支持**:适用于内层查询和外层查询。 -- 如果输入值为NULL,输出值为NULL。 -- 该函数最小参数个数为2个,最大参数个数为8个。 -- 该函数可以应用在普通表和超级表上。 -- 该函数适用于内层查询和外层查询。 -- 版本2.6.0.x后支持 +**适用于**: 表和超级表 -### CONCAT_WS + +#### CONCAT_WS ``` SELECT CONCAT_WS(separator, str1|column1, str2|column2, ...) FROM { tb_name | stb_name } [WHERE clause] @@ -1318,19 +279,16 @@ SELECT ROUND(field_name) FROM { tb_name | stb_name } [WHERE clause]; **功能说明**:带分隔符的字符串连接函数。 -**返回结果类型**:同输入参数类型,BINARY 或者 NCHAR。 +**返回结果类型**:如果所有参数均为BINARY类型,则结果类型为BINARY。如果参数包含NCHAR类型,则结果类型为NCHAR。如果输入值为NULL,输出值为NULL。如果separator值不为NULL,其他输入为NULL,输出为空串。 -**适用数据类型**:输入参数或者全部是 BINARY 格式的字符串或者列,或者全部是 NCHAR 格式的字符串或者列。不能应用在 TAG 列。 +**适用数据类型**:BINARY, NCHAR。不能应用在 TAG 列。 该函数最小参数个数为3个,最大参数个数为9个。 -**使用说明**: +**嵌套子查询支持**:适用于内层查询和外层查询。 -- 如果separator值为NULL,输出值为NULL。如果separator值不为NULL,其他输入为NULL,输出为空串 -- 该函数最小参数个数为3个,最大参数个数为9个。 -- 该函数可以应用在普通表和超级表上。 -- 该函数适用于内层查询和外层查询。 -- 版本2.6.0.x后支持 +**适用于**: 表和超级表 -### LENGTH + +#### LENGTH ``` SELECT LENGTH(str|column) FROM { tb_name | stb_name } [WHERE clause] @@ -1342,33 +300,12 @@ SELECT ROUND(field_name) FROM { tb_name | stb_name } [WHERE clause]; **适用数据类型**:输入参数是 BINARY 类型或者 NCHAR 类型的字符串或者列。不能应用在 TAG 列。 -**使用说明** +**嵌套子查询支持**:适用于内层查询和外层查询。 -- 如果输入值为NULL,输出值为NULL。 -- 该函数可以应用在普通表和超级表上。 -- 函数适用于内层查询和外层查询。 -- 版本2.6.0.x后支持 +**适用于**: 表和超级表 -### CHAR_LENGTH -``` - SELECT CHAR_LENGTH(str|column) FROM { tb_name | stb_name } [WHERE clause] -``` - -**功能说明**:以字符计数的字符串长度。 - -**返回结果类型**:INT。 - -**适用数据类型**:输入参数是 BINARY 类型或者 NCHAR 类型的字符串或者列。不能应用在 TAG 列。 - -**使用说明** - -- 如果输入值为NULL,输出值为NULL。 -- 该函数可以应用在普通表和超级表上。 -- 该函数适用于内层查询和外层查询。 -- 版本2.6.0.x后支持 - -### LOWER +#### LOWER ``` SELECT LOWER(str|column) FROM { tb_name | stb_name } [WHERE clause] @@ -1376,37 +313,16 @@ SELECT ROUND(field_name) FROM { tb_name | stb_name } [WHERE clause]; **功能说明**:将字符串参数值转换为全小写字母。 -**返回结果类型**:同输入类型。 +**返回结果类型**:同输入类型。如果输入值为NULL,输出值为NULL。 **适用数据类型**:输入参数是 BINARY 类型或者 NCHAR 类型的字符串或者列。不能应用在 TAG 列。 -**使用说明**: +**嵌套子查询支持**:适用于内层查询和外层查询。 -- 如果输入值为NULL,输出值为NULL。 -- 该函数可以应用在普通表和超级表上。 -- 该函数适用于内层查询和外层查询。 -- 版本2.6.0.x后支持 +**适用于**: 表和超级表 -### UPPER -``` - SELECT UPPER(str|column) FROM { tb_name | stb_name } [WHERE clause] -``` - -**功能说明**:将字符串参数值转换为全大写字母。 - -**返回结果类型**:同输入类型。 - -**适用数据类型**:输入参数是 BINARY 类型或者 NCHAR 类型的字符串或者列。不能应用在 TAG 列。 - -**使用说明**: - -- 如果输入值为NULL,输出值为NULL。 -- 该函数可以应用在普通表和超级表上。 -- 该函数适用于内层查询和外层查询。 -- 版本2.6.0.x后支持 - -### LTRIM +#### LTRIM ``` SELECT LTRIM(str|column) FROM { tb_name | stb_name } [WHERE clause] @@ -1414,37 +330,33 @@ SELECT ROUND(field_name) FROM { tb_name | stb_name } [WHERE clause]; **功能说明**:返回清除左边空格后的字符串。 -**返回结果类型**:同输入类型。 +**返回结果类型**:同输入类型。如果输入值为NULL,输出值为NULL。 **适用数据类型**:输入参数是 BINARY 类型或者 NCHAR 类型的字符串或者列。不能应用在 TAG 列。 -**使用说明**: +**嵌套子查询支持**:适用于内层查询和外层查询。 -- 如果输入值为NULL,输出值为NULL。 -- 该函数可以应用在普通表和超级表上。 -- 该函数适用于内层查询和外层查询。 -- 版本2.6.0.x后支持 +**适用于**: 表和超级表 -### RTRIM + +#### RTRIM ``` - SELECT RTRIM(str|column) FROM { tb_name | stb_name } [WHERE clause] + SELECT LTRIM(str|column) FROM { tb_name | stb_name } [WHERE clause] ``` **功能说明**:返回清除右边空格后的字符串。 -**返回结果类型**:同输入类型。 +**返回结果类型**:同输入类型。如果输入值为NULL,输出值为NULL。 **适用数据类型**:输入参数是 BINARY 类型或者 NCHAR 类型的字符串或者列。不能应用在 TAG 列。 -**使用说明**: +**嵌套子查询支持**:适用于内层查询和外层查询。 -- 如果输入值为NULL,输出值为NULL。 -- 该函数可以应用在普通表和超级表上。 -- 该函数适用于内层查询和外层查询。 -- 版本2.6.0.x后支持 +**适用于**: 表和超级表 -### SUBSTR + +#### SUBSTR ``` SELECT SUBSTR(str,pos[,len]) FROM { tb_name | stb_name } [WHERE clause] @@ -1452,128 +364,121 @@ SELECT ROUND(field_name) FROM { tb_name | stb_name } [WHERE clause]; **功能说明**:从源字符串 str 中的指定位置 pos 开始取一个长度为 len 的子串并返回。 -**返回结果类型**:同输入类型。 +**返回结果类型**:同输入类型。如果输入值为NULL,输出值为NULL。 + +**适用数据类型**:输入参数是 BINARY 类型或者 NCHAR 类型的字符串或者列。不能应用在 TAG 列。输入参数pos可以为正数,也可以为负数。如果pos是正数,表示开始位置从字符串开头正数计算。如果pos为负数,表示开始位置从字符串结尾倒数计算。如果输入参数len被忽略,返回的子串包含从pos开始的整个字串。 + +**嵌套子查询支持**:适用于内层查询和外层查询。 + +**适用于**: 表和超级表 + + +#### UPPER + +``` + SELECT UPPER(str|column) FROM { tb_name | stb_name } [WHERE clause] +``` + +**功能说明**:将字符串参数值转换为全大写字母。 + +**返回结果类型**:同输入类型。如果输入值为NULL,输出值为NULL。 **适用数据类型**:输入参数是 BINARY 类型或者 NCHAR 类型的字符串或者列。不能应用在 TAG 列。 -**使用说明**: +**嵌套子查询支持**:适用于内层查询和外层查询。 -- 如果输入值为NULL,输出值为NULL。 -- 输入参数pos可以为正数,也可以为负数。如果pos是正数,表示开始位置从字符串开头正数计算。如果pos为负数,表示开始位置从字符串结尾倒数计算。如果输入参数len被忽略,返回的子串包含从pos开始的整个字串。 -- 该函数可以应用在普通表和超级表上。 -- 该函数适用于内层查询和外层查询。 -- 版本2.6.0.x后支持 +**适用于**: 表和超级表 -### STATECOUNT -``` -SELECT STATECOUNT(field_name, oper, val) FROM { tb_name | stb_name } [WHERE clause]; -``` +### 转换函数 -**功能说明**:返回满足某个条件的连续记录的个数,结果作为新的一列追加在每行后面。条件根据参数计算,如果条件为 true 则加 1,条件为 false 则重置为-1,如果数据为 NULL,跳过该条数据。 +转换函数将值从一种数据类型转换为另一种数据类型。 -**参数范围**: - -- oper : LT (小于)、GT(大于)、LE(小于等于)、GE(大于等于)、NE(不等于)、EQ(等于),不区分大小写。 -- val : 数值型 - -**返回结果类型**:整形。 - -**适用数据类型**:不能应用在 timestamp、binary、nchar、bool 类型字段上。 - -**嵌套子查询支持**:不支持应用在子查询上。 - -**支持的版本**:2.6 开始的版本。 - -**使用说明**: - -- 该函数可以应用在普通表上,在由 GROUP BY 划分出单独时间线的情况下用于超级表(也即 GROUP BY tbname) -- 不能和窗口操作一起使用,例如 interval/state_window/session_window。 - -**示例**: - -``` -taos> select ts,dbig from statef2; - ts | dbig | -======================================================== -2021-10-15 00:31:33.000000000 | 1 | -2021-10-17 00:31:31.000000000 | NULL | -2021-12-24 00:31:34.000000000 | 2 | -2022-01-01 08:00:05.000000000 | 19 | -2022-01-01 08:00:06.000000000 | NULL | -2022-01-01 08:00:07.000000000 | 9 | -Query OK, 6 row(s) in set (0.002977s) - -taos> select stateCount(dbig,GT,2) from statef2; -ts | dbig | statecount(dbig,gt,2) | -================================================================================ -2021-10-15 00:31:33.000000000 | 1 | -1 | -2021-10-17 00:31:31.000000000 | NULL | NULL | -2021-12-24 00:31:34.000000000 | 2 | -1 | -2022-01-01 08:00:05.000000000 | 19 | 1 | -2022-01-01 08:00:06.000000000 | NULL | NULL | -2022-01-01 08:00:07.000000000 | 9 | 2 | -Query OK, 6 row(s) in set (0.002791s) -``` - -### STATEDURATION +#### CAST ```sql -SELECT stateDuration(field_name, oper, val, unit) FROM { tb_name | stb_name } [WHERE clause]; + SELECT CAST(expression AS type_name) FROM { tb_name | stb_name } [WHERE clause] ``` -**功能说明**:返回满足某个条件的连续记录的时间长度,结果作为新的一列追加在每行后面。条件根据参数计算,如果条件为 true 则加上两个记录之间的时间长度(第一个满足条件的记录时间长度记为 0),条件为 false 则重置为-1,如果数据为 NULL,跳过该条数据。 +**功能说明**:数据类型转换函数,输入参数 expression 支持普通列、常量、标量函数及它们之间的四则运算,不支持 tag 列,只适用于 select 子句中。 -**参数范围**: +**返回结果类型**:CAST 中指定的类型(type_name),可以是 BIGINT、BIGINT UNSIGNED、BINARY、VARCHAR、NCHAR和TIMESTAMP。 -- oper : LT (小于)、GT(大于)、LE(小于等于)、GE(大于等于)、NE(不等于)、EQ(等于),不区分大小写。 -- val : 数值型 -- unit : 时间长度的单位,范围[1s、1m、1h ],不足一个单位舍去。默认为 1s。 - -**返回结果类型**:整形。 - -**适用数据类型**:不能应用在 timestamp、binary、nchar、bool 类型字段上。 - -**嵌套子查询支持**:不支持应用在子查询上。 - -**支持的版本**:2.6 开始的版本。 +**适用数据类型**:输入参数 expression 的类型可以是BLOB、MEDIUMBLOB和JSON外的所有类型 **使用说明**: -- 该函数可以应用在普通表上,在由 GROUP BY 划分出单独时间线的情况下用于超级表(也即 GROUP BY tbname) -- 不能和窗口操作一起使用,例如 interval/state_window/session_window。 +- 对于不能支持的类型转换会直接报错。 +- 如果输入值为NULL则输出值也为NULL。 +- 对于类型支持但某些值无法正确转换的情况对应的转换后的值以转换函数输出为准。目前可能遇到的几种情况: + 1)字符串类型转换数值类型时可能出现的无效字符情况,例如"a"可能转为0,但不会报错。 + 2)转换到数值类型时,数值大于type_name可表示的范围时,则会溢出,但不会报错。 + 3)转换到字符串类型时,如果转换后长度超过type_name的长度,则会截断,但不会报错。 -**示例**: +#### TO_ISO8601 -``` -taos> select ts,dbig from statef2; - ts | dbig | -======================================================== -2021-10-15 00:31:33.000000000 | 1 | -2021-10-17 00:31:31.000000000 | NULL | -2021-12-24 00:31:34.000000000 | 2 | -2022-01-01 08:00:05.000000000 | 19 | -2022-01-01 08:00:06.000000000 | NULL | -2022-01-01 08:00:07.000000000 | 9 | -Query OK, 6 row(s) in set (0.002407s) - -taos> select stateDuration(dbig,GT,2) from statef2; -ts | dbig | stateduration(dbig,gt,2) | -=================================================================================== -2021-10-15 00:31:33.000000000 | 1 | -1 | -2021-10-17 00:31:31.000000000 | NULL | NULL | -2021-12-24 00:31:34.000000000 | 2 | -1 | -2022-01-01 08:00:05.000000000 | 19 | 0 | -2022-01-01 08:00:06.000000000 | NULL | NULL | -2022-01-01 08:00:07.000000000 | 9 | 2 | -Query OK, 6 row(s) in set (0.002613s) +```sql +SELECT TO_ISO8601(ts_val | ts_col) FROM { tb_name | stb_name } [WHERE clause]; ``` -## 时间函数 +**功能说明**:将 UNIX 时间戳转换成为 ISO8601 标准的日期时间格式,并附加客户端时区信息。 -从 2.6.0.0 版本开始,TDengine 查询引擎支持以下时间相关函数: +**返回结果数据类型**:BINARY 类型。 -### NOW +**适用数据类型**:UNIX 时间戳常量或是 TIMESTAMP 类型的列 + +**适用于**:表、超级表。 + +**使用说明**: + +- 如果输入是 UNIX 时间戳常量,返回格式精度由时间戳的位数决定; +- 如果输入是 TIMSTAMP 类型的列,返回格式的时间戳精度与当前 DATABASE 设置的时间精度一致。 + + +#### TO_JSON + +```sql +SELECT TO_JSON(str_literal) FROM { tb_name | stb_name } [WHERE clause]; +``` + +**功能说明**: 将字符串常量转换为 JSON 类型。 + +**返回结果数据类型**: JSON + +**适用数据类型**: JSON 字符串,形如 '{ "literal" : literal }'。'{}'表示空值。键必须为字符串字面量,值可以为数值字面量、字符串字面量、布尔字面量或空值字面量。str_literal中不支持转义符。 + +**适用于**: 表和超级表 + +**嵌套子查询支持**:适用于内层查询和外层查询。 + + +#### TO_UNIXTIMESTAMP + +```sql +SELECT TO_UNIXTIMESTAMP(datetime_string | ts_col) FROM { tb_name | stb_name } [WHERE clause]; +``` + +**功能说明**:将日期时间格式的字符串转换成为 UNIX 时间戳。 + +**返回结果数据类型**:长整型 INT64。 + +**应用字段**:字符串常量或是 BINARY/NCHAR 类型的列。 + +**适用于**:表、超级表。 + +**使用说明**: + +- 输入的日期时间字符串须符合 ISO8601/RFC3339 标准,无法转换的字符串格式将返回 0。 +- 返回的时间戳精度与当前 DATABASE 设置的时间精度一致。 + + +### 时间和日期函数 + +时间和日期函数对时间戳类型进行操作。 + +所有返回当前时间的函数,如NOW、TODAY和TIMEZONE,在一条SQL语句中不论出现多少次都只会被计算一次。 + +#### NOW ```sql SELECT NOW() FROM { tb_name | stb_name } [WHERE clause]; @@ -1595,32 +500,63 @@ INSERT INTO tb_name VALUES (NOW(), ...); b(纳秒)、u(微秒)、a(毫秒)、s(秒)、m(分)、h(小时)、d(天)、w(周)。 - 返回的时间戳精度与当前 DATABASE 设置的时间精度一致。 -**示例**: + +#### TIMEDIFF ```sql -taos> SELECT NOW() FROM meters; - now() | -========================== - 2022-02-02 02:02:02.456 | -Query OK, 1 row(s) in set (0.002093s) - -taos> SELECT NOW() + 1h FROM meters; - now() + 1h | -========================== - 2022-02-02 03:02:02.456 | -Query OK, 1 row(s) in set (0.002093s) - -taos> SELECT COUNT(voltage) FROM d1001 WHERE ts < NOW(); - count(voltage) | -============================= - 5 | -Query OK, 5 row(s) in set (0.004475s) - -taos> INSERT INTO d1001 VALUES (NOW(), 10.2, 219, 0.32); -Query OK, 1 of 1 row(s) in database (0.002210s) +SELECT TIMEDIFF(ts_val1 | datetime_string1 | ts_col1, ts_val2 | datetime_string2 | ts_col2 [, time_unit]) FROM { tb_name | stb_name } [WHERE clause]; ``` -### TODAY +**功能说明**:计算两个时间戳之间的差值,并近似到时间单位 time_unit 指定的精度。 + +**返回结果数据类型**:长整型 INT64。 + +**应用字段**:UNIX 时间戳,日期时间格式的字符串,或者 TIMESTAMP 类型的列。 + +**适用于**:表、超级表。 + +**使用说明**: +- 支持的时间单位 time_unit 如下: + 1u(微秒),1a(毫秒),1s(秒),1m(分),1h(小时),1d(天)。 +- 如果时间单位 time_unit 未指定, 返回的时间差值精度与当前 DATABASE 设置的时间精度一致。 + + +#### TIMETRUNCATE + +```sql +SELECT TIMETRUNCATE(ts_val | datetime_string | ts_col, time_unit) FROM { tb_name | stb_name } [WHERE clause]; +``` + +**功能说明**:将时间戳按照指定时间单位 time_unit 进行截断。 + +**返回结果数据类型**:TIMESTAMP 时间戳类型。 + +**应用字段**:UNIX 时间戳,日期时间格式的字符串,或者 TIMESTAMP 类型的列。 + +**适用于**:表、超级表。 + +**使用说明**: +- 支持的时间单位 time_unit 如下: + 1u(微秒),1a(毫秒),1s(秒),1m(分),1h(小时),1d(天)。 +- 返回的时间戳精度与当前 DATABASE 设置的时间精度一致。 + + +#### TIMEZONE + +```sql +SELECT TIMEZONE() FROM { tb_name | stb_name } [WHERE clause]; +``` + +**功能说明**:返回客户端当前时区信息。 + +**返回结果数据类型**:BINARY 类型。 + +**应用字段**:无 + +**适用于**:表、超级表。 + + +#### TODAY ```sql SELECT TODAY() FROM { tb_name | stb_name } [WHERE clause]; @@ -1642,212 +578,640 @@ INSERT INTO tb_name VALUES (TODAY(), ...); b(纳秒),u(微秒),a(毫秒),s(秒),m(分),h(小时),d(天),w(周)。 - 返回的时间戳精度与当前 DATABASE 设置的时间精度一致。 -**示例**: -```sql -taos> SELECT TODAY() FROM meters; - today() | -========================== - 2022-02-02 00:00:00.000 | -Query OK, 1 row(s) in set (0.002093s) +## 聚合函数 -taos> SELECT TODAY() + 1h FROM meters; - today() + 1h | -========================== - 2022-02-02 01:00:00.000 | -Query OK, 1 row(s) in set (0.002093s) +聚合函数为查询结果集的每一个分组返回单个结果行。可以由 GROUP BY 或窗口切分子句指定分组,如果没有,则整个查询结果集视为一个分组。 -taos> SELECT COUNT(voltage) FROM d1001 WHERE ts < TODAY(); - count(voltage) | -============================= - 5 | -Query OK, 5 row(s) in set (0.004475s) +TDengine 支持针对数据的聚合查询。提供如下聚合函数。 -taos> INSERT INTO d1001 VALUES (TODAY(), 10.2, 219, 0.32); -Query OK, 1 of 1 row(s) in database (0.002210s) +### AVG + +``` +SELECT AVG(field_name) FROM tb_name [WHERE clause]; ``` -### TIMEZONE +**功能说明**:统计表/超级表中某列的平均值。 -```sql -SELECT TIMEZONE() FROM { tb_name | stb_name } [WHERE clause]; -``` +**返回数据类型**:双精度浮点数 Double。 -**功能说明**:返回客户端当前时区信息。 - -**返回结果数据类型**:BINARY 类型。 - -**应用字段**:无 +**适用数据类型**:数值类型。 **适用于**:表、超级表。 -**示例**: -```sql -taos> SELECT TIMEZONE() FROM meters; - timezone() | -================================= - UTC (UTC, +0000) | -Query OK, 1 row(s) in set (0.002093s) +### COUNT + +``` +SELECT COUNT([*|field_name]) FROM tb_name [WHERE clause]; ``` -### TO_ISO8601 +**功能说明**:统计表/超级表中记录行数或某列的非空值个数。 -```sql -SELECT TO_ISO8601(ts_val | ts_col) FROM { tb_name | stb_name } [WHERE clause]; -``` +**返回数据类型**:长整型 INT64。 -**功能说明**:将 UNIX 时间戳转换成为 ISO8601 标准的日期时间格式,并附加客户端时区信息。 - -**返回结果数据类型**:BINARY 类型。 - -**应用字段**:UNIX 时间戳常量或是 TIMESTAMP 类型的列 +**适用数据类型**:应用全部字段。 **适用于**:表、超级表。 -**使用说明**: +**使用说明**: -- 如果输入是 UNIX 时间戳常量,返回格式精度由时间戳的位数决定; -- 如果输入是 TIMSTAMP 类型的列,返回格式的时间戳精度与当前 DATABASE 设置的时间精度一致。 +- 可以使用星号(\*)来替代具体的字段,使用星号(\*)返回全部记录数量。 +- 针对同一表的(不包含 NULL 值)字段查询结果均相同。 +- 如果统计对象是具体的列,则返回该列中非 NULL 值的记录数量。 -**示例**: -```sql -taos> SELECT TO_ISO8601(1643738400) FROM meters; - to_iso8601(1643738400) | -============================== - 2022-02-02T02:00:00+0800 | +### ELAPSED -taos> SELECT TO_ISO8601(ts) FROM meters; - to_iso8601(ts) | -============================== - 2022-02-02T02:00:00+0800 | - 2022-02-02T02:00:00+0800 | - 2022-02-02T02:00:00+0800 | +```mysql +SELECT ELAPSED(ts_primary_key [, time_unit]) FROM { tb_name | stb_name } [WHERE clause] [INTERVAL(interval [, offset]) [SLIDING sliding]]; ``` -### TO_UNIXTIMESTAMP +**功能说明**:elapsed函数表达了统计周期内连续的时间长度,和twa函数配合使用可以计算统计曲线下的面积。在通过INTERVAL子句指定窗口的情况下,统计在给定时间范围内的每个窗口内有数据覆盖的时间范围;如果没有INTERVAL子句,则返回整个给定时间范围内的有数据覆盖的时间范围。注意,ELAPSED返回的并不是时间范围的绝对值,而是绝对值除以time_unit所得到的单位个数。 -```sql -SELECT TO_UNIXTIMESTAMP(datetime_string | ts_col) FROM { tb_name | stb_name } [WHERE clause]; -``` +**返回结果类型**:Double -**功能说明**:将日期时间格式的字符串转换成为 UNIX 时间戳。 - -**返回结果数据类型**:长整型 INT64。 - -**应用字段**:字符串常量或是 BINARY/NCHAR 类型的列。 - -**适用于**:表、超级表。 - -**使用说明**: - -- 输入的日期时间字符串须符合 ISO8601/RFC3339 标准,无法转换的字符串格式将返回 0。 -- 返回的时间戳精度与当前 DATABASE 设置的时间精度一致。 - -**示例**: - -```sql -taos> SELECT TO_UNIXTIMESTAMP("2022-02-02T02:00:00.000Z") FROM meters; -to_unixtimestamp("2022-02-02T02:00:00.000Z") | -============================================== - 1643767200000 | - -taos> SELECT TO_UNIXTIMESTAMP(col_binary) FROM meters; - to_unixtimestamp(col_binary) | -======================================== - 1643767200000 | - 1643767200000 | - 1643767200000 | -``` - -### TIMETRUNCATE - -```sql -SELECT TIMETRUNCATE(ts_val | datetime_string | ts_col, time_unit) FROM { tb_name | stb_name } [WHERE clause]; -``` - -**功能说明**:将时间戳按照指定时间单位 time_unit 进行截断。 - -**返回结果数据类型**:TIMESTAMP 时间戳类型。 - -**应用字段**:UNIX 时间戳,日期时间格式的字符串,或者 TIMESTAMP 类型的列。 - -**适用于**:表、超级表。 - -**使用说明**: -- 支持的时间单位 time_unit 如下: - 1u(微秒),1a(毫秒),1s(秒),1m(分),1h(小时),1d(天)。 -- 返回的时间戳精度与当前 DATABASE 设置的时间精度一致。 - -**示例**: - -```sql -taos> SELECT TIMETRUNCATE(1643738522000, 1h) FROM meters; - timetruncate(1643738522000, 1h) | -=================================== - 2022-02-02 02:00:00.000 | -Query OK, 1 row(s) in set (0.001499s) - -taos> SELECT TIMETRUNCATE("2022-02-02 02:02:02", 1h) FROM meters; - timetruncate("2022-02-02 02:02:02", 1h) | -=========================================== - 2022-02-02 02:00:00.000 | -Query OK, 1 row(s) in set (0.003903s) - -taos> SELECT TIMETRUNCATE(ts, 1h) FROM meters; - timetruncate(ts, 1h) | -========================== - 2022-02-02 02:00:00.000 | - 2022-02-02 02:00:00.000 | - 2022-02-02 02:00:00.000 | -Query OK, 3 row(s) in set (0.003903s) -``` - -### TIMEDIFF - -```sql -SELECT TIMEDIFF(ts_val1 | datetime_string1 | ts_col1, ts_val2 | datetime_string2 | ts_col2 [, time_unit]) FROM { tb_name | stb_name } [WHERE clause]; -``` - -**功能说明**:计算两个时间戳之间的差值,并近似到时间单位 time_unit 指定的精度。 - -**返回结果数据类型**:长整型 INT64。 - -**应用字段**:UNIX 时间戳,日期时间格式的字符串,或者 TIMESTAMP 类型的列。 - -**适用于**:表、超级表。 - -**使用说明**: -- 支持的时间单位 time_unit 如下: - 1u(微秒),1a(毫秒),1s(秒),1m(分),1h(小时),1d(天)。 -- 如果时间单位 time_unit 未指定, 返回的时间差值精度与当前 DATABASE 设置的时间精度一致。 +**适用数据类型**:Timestamp类型 **支持的版本**:2.6.0.0 及以后的版本。 -**示例**: +**适用于**: 表,超级表,嵌套查询的外层查询 + +**说明**: +- field_name参数只能是表的第一列,即timestamp主键列。 +- 按time_unit参数指定的时间单位返回,最小是数据库的时间分辨率。time_unit参数未指定时,以数据库的时间分辨率为时间单位。 +- 可以和interval组合使用,返回每个时间窗口的时间戳差值。需要特别注意的是,除第一个时间窗口和最后一个时间窗口外,中间窗口的时间戳差值均为窗口长度。 +- order by asc/desc不影响差值的计算结果。 +- 对于超级表,需要和group by tbname子句组合使用,不可以直接使用。 +- 对于普通表,不支持和group by子句组合使用。 +- 对于嵌套查询,仅当内层查询会输出隐式时间戳列时有效。例如select elapsed(ts) from (select diff(value) from sub1)语句,diff函数会让内层查询输出隐式时间戳列,此为主键列,可以用于elapsed函数的第一个参数。相反,例如select elapsed(ts) from (select * from sub1) 语句,ts列输出到外层时已经没有了主键列的含义,无法使用elapsed函数。此外,elapsed函数作为一个与时间线强依赖的函数,形如select elapsed(ts) from (select diff(value) from st group by tbname)尽管会返回一条计算结果,但并无实际意义,这种用法后续也将被限制。 +- 不支持与leastsquares、diff、derivative、top、bottom、last_row、interp等函数混合使用。 + +### LEASTSQUARES + +``` +SELECT LEASTSQUARES(field_name, start_val, step_val) FROM tb_name [WHERE clause]; +``` + +**功能说明**:统计表中某列的值是主键(时间戳)的拟合直线方程。start_val 是自变量初始值,step_val 是自变量的步长值。 + +**返回数据类型**:字符串表达式(斜率, 截距)。 + +**适用数据类型**:field_name 必须是数值类型。 + +**适用于**:表。 + + +### MODE + +``` +SELECT MODE(field_name) FROM tb_name [WHERE clause]; +``` + +**功能说明**:返回出现频率最高的值,若存在多个频率相同的最高值,输出空。不能匹配标签、时间戳输出。 + +**返回数据类型**:同应用的字段。 + +**适用数据类型**: 数值类型。 + +**适用于**:表和超级表。 + + +### SPREAD + +``` +SELECT SPREAD(field_name) FROM { tb_name | stb_name } [WHERE clause]; +``` + +**功能说明**:统计表/超级表中某列的最大值和最小值之差。 + +**返回数据类型**:双精度浮点数。 + +**适用数据类型**:数值类型或TIMESTAMP类型。 + +**适用于**:表和超级表。 + + +### STDDEV + +``` +SELECT STDDEV(field_name) FROM tb_name [WHERE clause]; +``` + +**功能说明**:统计表中某列的均方差。 + +**返回数据类型**:双精度浮点数 Double。 + +**适用数据类型**:数值类型。 + +**适用于**:表和超级表。 + + +### SUM + +``` +SELECT SUM(field_name) FROM tb_name [WHERE clause]; +``` + +**功能说明**:统计表/超级表中某列的和。 + +**返回数据类型**:双精度浮点数 Double 和长整型 INT64。 + +**适用数据类型**:数值类型。 + +**适用于**:表和超级表。 + + +### HYPERLOGLOG + +``` +SELECT HYPERLOGLOG(field_name) FROM { tb_name | stb_name } [WHERE clause]; +``` + +**功能说明**: + - 采用 hyperloglog 算法,返回某列的基数。该算法在数据量很大的情况下,可以明显降低内存的占用,但是求出来的基数是个估算值,标准误差(标准误差是多次实验,每次的平均数的标准差,不是与真实结果的误差)为 0.81%。 + - 在数据量较少的时候该算法不是很准确,可以使用 select count(data) from (select unique(col) as data from table) 的方法。 + +**返回结果类型**:整形。 + +**适用数据类型**:任何类型。 + +**适用于**:表和超级表。 + + +### HISTOGRAM + +``` +SELECT HISTOGRAM(field_name,bin_type, bin_description, normalized) FROM tb_name [WHERE clause]; +``` + +**功能说明**:统计数据按照用户指定区间的分布。 + +**返回结果类型**:如归一化参数 normalized 设置为 1,返回结果为双精度浮点类型 DOUBLE,否则为长整形 INT64。 + +**适用数据类型**:数值型字段。 + +**适用于**: 表和超级表。 + +**详细说明**: +1. bin_type 用户指定的分桶类型, 有效输入类型为"user_input“, ”linear_bin", "log_bin"。 +2. bin_description 描述如何生成分桶区间,针对三种桶类型,分别为以下描述格式(均为 JSON 格式字符串): + - "user_input": "[1, 3, 5, 7]" + 用户指定 bin 的具体数值。 + + - "linear_bin": "{"start": 0.0, "width": 5.0, "count": 5, "infinity": true}" + "start" 表示数据起始点,"width" 表示每次 bin 偏移量, "count" 为 bin 的总数,"infinity" 表示是否添加(-inf, inf)作为区间起点跟终点, + 生成区间为[-inf, 0.0, 5.0, 10.0, 15.0, 20.0, +inf]。 + + - "log_bin": "{"start":1.0, "factor": 2.0, "count": 5, "infinity": true}" + "start" 表示数据起始点,"factor" 表示按指数递增的因子,"count" 为 bin 的总数,"infinity" 表示是否添加(-inf, inf)作为区间起点跟终点, + 生成区间为[-inf, 1.0, 2.0, 4.0, 8.0, 16.0, +inf]。 +3. normalized 是否将返回结果归一化到 0~1 之间 。有效输入为 0 和 1。 + + +## 选择函数 + +选择函数根据语义在查询结果集中选择一行或多行结果返回。用户可以同时指定输出 ts 列或其他列(包括 tbname 和标签列),这样就可以方便地知道被选出的值是源于哪个数据行的。 + +### APERCENTILE + +``` +SELECT APERCENTILE(field_name, P[, algo_type]) +FROM { tb_name | stb_name } [WHERE clause] +``` + +**功能说明**:统计表/超级表中指定列的值的近似百分比分位数,与 PERCENTILE 函数相似,但是返回近似结果。 + +**返回数据类型**: 双精度浮点数 Double。 + +**适用数据类型**:数值类型。P值范围是[0,100],当为0时等同于MIN,为100时等同于MAX。如果不指定 algo_type 则使用默认算法 。 + +**适用于**:表、超级表。 + +### BOTTOM + +``` +SELECT BOTTOM(field_name, K) FROM { tb_name | stb_name } [WHERE clause]; +``` + +**功能说明**:统计表/超级表中某列的值最小 _k_ 个非 NULL 值。如果多条数据取值一样,全部取用又会超出 k 条限制时,系统会从相同值中随机选取符合要求的数量返回。 + +**返回数据类型**:同应用的字段。 + +**适用数据类型**:数值类型。 + +**适用于**:表和超级表。 + +**使用说明**: + +- *k*值取值范围 1≤*k*≤100; +- 系统同时返回该记录关联的时间戳列; +- 限制:BOTTOM 函数不支持 FILL 子句。 + + +### INTERP + +``` +SELECT INTERP(field_name) FROM { tb_name | stb_name } [WHERE where_condition] [ RANGE(timestamp1,timestamp2) ] [EVERY(interval)] [FILL ({ VALUE | PREV | NULL | LINEAR | NEXT})]; +``` + +**功能说明**:返回指定时间截面指定列的记录值或插值。 + +**返回数据类型**:同字段类型。 + +**适用数据类型**:数值类型。 + +**适用于**:表、超级表。 + +**使用说明** + +- INTERP 用于在指定时间断面获取指定列的记录值,如果该时间断面不存在符合条件的行数据,那么会根据 FILL 参数的设定进行插值。 +- INTERP 的输入数据为指定列的数据,可以通过条件语句(where 子句)来对原始列数据进行过滤,如果没有指定过滤条件则输入为全部数据。 +- INTERP 的输出时间范围根据 RANGE(timestamp1,timestamp2)字段来指定,需满足 timestamp1<=timestamp2。其中 timestamp1(必选值)为输出时间范围的起始值,即如果 timestamp1 时刻符合插值条件则 timestamp1 为输出的第一条记录,timestamp2(必选值)为输出时间范围的结束值,即输出的最后一条记录的 timestamp 不能大于 timestamp2。如果没有指定 RANGE,那么满足过滤条件的输入数据中第一条记录的 timestamp 即为 timestamp1,最后一条记录的 timestamp 即为 timestamp2,同样也满足 timestamp1 <= timestamp2。 +- INTERP 根据 EVERY 字段来确定输出时间范围内的结果条数,即从 timestamp1 开始每隔固定长度的时间(EVERY 值)进行插值。如果没有指定 EVERY,则默认窗口大小为无穷大,即从 timestamp1 开始只有一个窗口。 +- INTERP 根据 FILL 字段来决定在每个符合输出条件的时刻如何进行插值,如果没有 FILL 字段则默认不插值,即输出为原始记录值或不输出(原始记录不存在)。 +- INTERP 只能在一个时间序列内进行插值,因此当作用于超级表时必须跟 group by tbname 一起使用,当作用嵌套查询外层时内层子查询不能含 GROUP BY 信息。 +- INTERP 的插值结果不受 ORDER BY timestamp 的影响,ORDER BY timestamp 只影响输出结果的排序。 + +### LAST + +``` +SELECT LAST(field_name) FROM { tb_name | stb_name } [WHERE clause]; +``` + +**功能说明**:统计表/超级表中某列的值最后写入的非 NULL 值。 + +**返回数据类型**:同应用的字段。 + +**适用数据类型**:所有字段。 + +**适用于**:表和超级表。 + +**使用说明**: + +- 如果要返回各个列的最后(时间戳最大)一个非 NULL 值,可以使用 LAST(\*); +- 如果结果集中的某列全部为 NULL 值,则该列的返回结果也是 NULL;如果结果集中所有列全部为 NULL 值,则不返回结果。 +- 在用于超级表时,时间戳完全一样且同为最大的数据行可能有多个,那么会从中随机返回一条,而并不保证多次运行所挑选的数据行必然一致。 + + +### LAST_ROW + +``` +SELECT LAST_ROW(field_name) FROM { tb_name | stb_name }; +``` + +**功能说明**:返回表/超级表的最后一条记录。 + +**返回数据类型**:同应用的字段。 + +**适用数据类型**:所有字段。 + +**适用于**:表和超级表。 + +**使用说明**: + +- 在用于超级表时,时间戳完全一样且同为最大的数据行可能有多个,那么会从中随机返回一条,而并不保证多次运行所挑选的数据行必然一致。 +- 不能与 INTERVAL 一起使用。 + +### MAX + +``` +SELECT MAX(field_name) FROM { tb_name | stb_name } [WHERE clause]; +``` + +**功能说明**:统计表/超级表中某列的值最大值。 + +**返回数据类型**:同应用的字段。 + +**适用数据类型**:数值类型。 + +**适用于**:表和超级表。 + + +### MIN + +``` +SELECT MIN(field_name) FROM {tb_name | stb_name} [WHERE clause]; +``` + +**功能说明**:统计表/超级表中某列的值最小值。 + +**返回数据类型**:同应用的字段。 + +**适用数据类型**:数值类型。 + +**适用于**:表和超级表。 + + +### PERCENTILE + +``` +SELECT PERCENTILE(field_name, P) FROM { tb_name } [WHERE clause]; +``` + +**功能说明**:统计表中某列的值百分比分位数。 + +**返回数据类型**: 双精度浮点数 Double。 + +**应用字段**:数值类型。 + +**适用于**:表。 + +**使用说明**:*P*值取值范围 0≤*P*≤100,为 0 的时候等同于 MIN,为 100 的时候等同于 MAX。 + +### FIRST + +``` +SELECT FIRST(field_name) FROM { tb_name | stb_name } [WHERE clause]; +``` + +**功能说明**:统计表/超级表中某列的值最先写入的非 NULL 值。 + +**返回数据类型**:同应用的字段。 + +**适用数据类型**:所有字段。 + +**适用于**:表和超级表。 + +**使用说明**: + +- 如果要返回各个列的首个(时间戳最小)非 NULL 值,可以使用 FIRST(\*); +- 如果结果集中的某列全部为 NULL 值,则该列的返回结果也是 NULL; +- 如果结果集中所有列全部为 NULL 值,则不返回结果。 + +### TAIL + +``` +SELECT TAIL(field_name, k, offset_val) FROM {tb_name | stb_name} [WHERE clause]; +``` + +**功能说明**:返回跳过最后 offset_val 个,然后取连续 k 个记录,不忽略 NULL 值。offset_val 可以不输入。此时返回最后的 k 个记录。当有 offset_val 输入的情况下,该函数功能等效于 `order by ts desc LIMIT k OFFSET offset_val`。 + +**参数范围**:k: [1,100] offset_val: [0,100]。 + +**返回数据类型**:同应用的字段。 + +**适用数据类型**:适合于除时间主列外的任何类型。 + +**适用于**:表、超级表。 + + +### TOP + +``` +SELECT TOP(field_name, K) FROM { tb_name | stb_name } [WHERE clause]; +``` + +**功能说明**: 统计表/超级表中某列的值最大 _k_ 个非 NULL 值。如果多条数据取值一样,全部取用又会超出 k 条限制时,系统会从相同值中随机选取符合要求的数量返回。 + +**返回数据类型**:同应用的字段。 + +**适用数据类型**:数值类型。 + +**适用于**:表、超级表。 + +**使用说明**: + +- *k*值取值范围 1≤*k*≤100; +- 系统同时返回该记录关联的时间戳列; +- 限制:TOP 函数不支持 FILL 子句。 + +### UNIQUE + +``` +SELECT UNIQUE(field_name) FROM {tb_name | stb_name} [WHERE clause]; +``` + +**功能说明**:返回该列的数值首次出现的值。该函数功能与 distinct 相似,但是可以匹配标签和时间戳信息。可以针对除时间列以外的字段进行查询,可以匹配标签和时间戳,其中的标签和时间戳是第一次出现时刻的标签和时间戳。 + +**返回数据类型**:同应用的字段。 + +**适用数据类型**:适合于除时间类型以外的字段。 + +**适用于**: 表和超级表。 + + +## 时序数据特有函数 + +时序数据特有函数是 TDengine 为了满足时序数据的查询场景而量身定做出来的。在通用数据库中,实现类似功能通常需要复杂的查询语法,且效率很低。TDengine 以函数的方式内置了这些功能,最大程度的减轻了用户的使用成本。 + +### CSUM ```sql -taos> SELECT TIMEDIFF(1643738400000, 1643742000000) FROM meters; - timediff(1643738400000, 1643742000000) | -========================================= - 3600000 | -Query OK, 1 row(s) in set (0.002553s) -taos> SELECT TIMEDIFF(1643738400000, 1643742000000, 1h) FROM meters; - timediff(1643738400000, 1643742000000, 1h) | -============================================= - 1 | -Query OK, 1 row(s) in set (0.003726s) - -taos> SELECT TIMEDIFF("2022-02-02 03:00:00", "2022-02-02 02:00:00", 1h) FROM meters; - timediff("2022-02-02 03:00:00", "2022-02-02 02:00:00", 1h) | -============================================================= - 1 | -Query OK, 1 row(s) in set (0.001937s) - -taos> SELECT TIMEDIFF(ts_col1, ts_col2, 1h) FROM meters; - timediff(ts_col1, ts_col2, 1h) | -=================================== - 1 | -Query OK, 1 row(s) in set (0.001937s) + SELECT CSUM(field_name) FROM { tb_name | stb_name } [WHERE clause] ``` + +**功能说明**:累加和(Cumulative sum),输出行与输入行数相同。 + +**返回结果类型**: 输入列如果是整数类型返回值为长整型 (int64_t),浮点数返回值为双精度浮点数(Double)。无符号整数类型返回值为无符号长整型(uint64_t)。 返回结果中同时带有每行记录对应的时间戳。 + +**适用数据类型**:不能应用在 timestamp、binary、nchar、bool 类型字段上;在超级表查询中使用时,不能应用在标签之上。 + +**嵌套子查询支持**: 适用于内层查询和外层查询。 + +**适用于**:表和超级表 + +**使用说明**: + + - 不支持 +、-、*、/ 运算,如 csum(col1) + csum(col2)。 + - 只能与聚合(Aggregation)函数一起使用。 该函数可以应用在普通表和超级表上。 + - 使用在超级表上的时候,需要搭配 Group by tbname使用,将结果强制规约到单个时间线。 + + +### DERIVATIVE + +``` +SELECT DERIVATIVE(field_name, time_interval, ignore_negative) FROM tb_name [WHERE clause]; +``` + +**功能说明**:统计表中某列数值的单位变化率。其中单位时间区间的长度可以通过 time_interval 参数指定,最小可以是 1 秒(1s);ignore_negative 参数的值可以是 0 或 1,为 1 时表示忽略负值。 + +**返回数据类型**:双精度浮点数。 + +**适用数据类型**:数值类型。 + +**适用于**:表、超级表 + +**使用说明**: DERIVATIVE 函数可以在由 GROUP BY 划分出单独时间线的情况下用于超级表(也即 GROUP BY tbname)。 + + +### DIFF + + ```sql + SELECT {DIFF(field_name, ignore_negative) | DIFF(field_name)} FROM tb_name [WHERE clause]; + ``` + +**功能说明**:统计表中某列的值与前一行对应值的差。 ignore_negative 取值为 0|1 , 可以不填,默认值为 0. 不忽略负值。ignore_negative 为 1 时表示忽略负数。 + +**返回数据类型**:同应用字段。 + +**适用数据类型**:数值类型。 + +**适用于**:表、超级表。 + +**使用说明**: 输出结果行数是范围内总行数减一,第一行没有结果输出。 + + +### IRATE + +``` +SELECT IRATE(field_name) FROM tb_name WHERE clause; +``` + +**功能说明**:计算瞬时增长率。使用时间区间中最后两个样本数据来计算瞬时增长速率;如果这两个值呈递减关系,那么只取最后一个数用于计算,而不是使用二者差值。 + +**返回数据类型**:双精度浮点数 Double。 + +**适用数据类型**:数值类型。 + +**适用于**:表、超级表。 + +### MAVG + +```sql + SELECT MAVG(field_name, K) FROM { tb_name | stb_name } [WHERE clause] +``` + + **功能说明**: 计算连续 k 个值的移动平均数(moving average)。如果输入行数小于 k,则无结果输出。参数 k 的合法输入范围是 1≤ k ≤ 1000。 + + **返回结果类型**: 返回双精度浮点数类型。 + + **适用数据类型**: 不能应用在 timestamp、binary、nchar、bool 类型上;在超级表查询中使用时,不能应用在标签之上。 + + **嵌套子查询支持**: 适用于内层查询和外层查询。 + + **适用于**:表和超级表 + + **使用说明**: + + - 不支持 +、-、*、/ 运算,如 mavg(col1, k1) + mavg(col2, k1); + - 只能与普通列,选择(Selection)、投影(Projection)函数一起使用,不能与聚合(Aggregation)函数一起使用; + - 使用在超级表上的时候,需要搭配 Group by tbname使用,将结果强制规约到单个时间线。 + +### SAMPLE + +```sql + SELECT SAMPLE(field_name, K) FROM { tb_name | stb_name } [WHERE clause] +``` + + **功能说明**: 获取数据的 k 个采样值。参数 k 的合法输入范围是 1≤ k ≤ 1000。 + + **返回结果类型**: 同原始数据类型, 返回结果中带有该行记录的时间戳。 + + **适用数据类型**: 在超级表查询中使用时,不能应用在标签之上。 + + **嵌套子查询支持**: 适用于内层查询和外层查询。 + + **适用于**:表和超级表 + + **使用说明**: + + - 不能参与表达式计算;该函数可以应用在普通表和超级表上; + - 使用在超级表上的时候,需要搭配 Group by tbname 使用,将结果强制规约到单个时间线。 + +### STATECOUNT + +``` +SELECT STATECOUNT(field_name, oper, val) FROM { tb_name | stb_name } [WHERE clause]; +``` + +**功能说明**:返回满足某个条件的连续记录的个数,结果作为新的一列追加在每行后面。条件根据参数计算,如果条件为 true 则加 1,条件为 false 则重置为-1,如果数据为 NULL,跳过该条数据。 + +**参数范围**: + +- oper : LT (小于)、GT(大于)、LE(小于等于)、GE(大于等于)、NE(不等于)、EQ(等于),不区分大小写。 +- val : 数值型 + +**返回结果类型**:整形。 + +**适用数据类型**:不能应用在 timestamp、binary、nchar、bool 类型字段上。 + +**嵌套子查询支持**:不支持应用在子查询上。 + +**适用于**:表和超级表。 + +**使用说明**: + +- 该函数可以应用在普通表上,在由 GROUP BY 划分出单独时间线的情况下用于超级表(也即 GROUP BY tbname) +- 不能和窗口操作一起使用,例如 interval/state_window/session_window。 + + +### STATEDURATION + +```sql +SELECT stateDuration(field_name, oper, val, unit) FROM { tb_name | stb_name } [WHERE clause]; +``` + +**功能说明**:返回满足某个条件的连续记录的时间长度,结果作为新的一列追加在每行后面。条件根据参数计算,如果条件为 true 则加上两个记录之间的时间长度(第一个满足条件的记录时间长度记为 0),条件为 false 则重置为-1,如果数据为 NULL,跳过该条数据。 + +**参数范围**: + +- oper : LT (小于)、GT(大于)、LE(小于等于)、GE(大于等于)、NE(不等于)、EQ(等于),不区分大小写。 +- val : 数值型 +- unit : 时间长度的单位,范围[1s、1m、1h ],不足一个单位舍去。默认为 1s。 + +**返回结果类型**:整形。 + +**适用数据类型**:不能应用在 timestamp、binary、nchar、bool 类型字段上。 + +**嵌套子查询支持**:不支持应用在子查询上。 + +**适用于**:表和超级表。 + +**使用说明**: + +- 该函数可以应用在普通表上,在由 GROUP BY 划分出单独时间线的情况下用于超级表(也即 GROUP BY tbname) +- 不能和窗口操作一起使用,例如 interval/state_window/session_window。 + + +### TWA + +``` +SELECT TWA(field_name) FROM tb_name WHERE clause; +``` + +**功能说明**:时间加权平均函数。统计表中某列在一段时间内的时间加权平均。 + +**返回数据类型**:双精度浮点数 Double。 + +**适用数据类型**:数值类型。 + +**适用于**:表、超级表。 + +**使用说明**: TWA 函数可以在由 GROUP BY 划分出单独时间线的情况下用于超级表(也即 GROUP BY tbname)。 + + +## 系统信息函数 + +### DATABASE + +``` +SELECT DATABASE(); +``` + +**说明**:返回当前登录的数据库。如果登录的时候没有指定默认数据库,且没有使用USE命令切换数据库,则返回NULL。 + + +### CLIENT_VERSION + +``` +SELECT CLIENT_VERSION(); +``` + +**说明**:返回客户端版本。 + +### SERVER_VERSION + +``` +SELECT SERVER_VERSION(); +``` + +**说明**:返回服务端版本。 + +### SERVER_STATUS + +``` +SELECT SERVER_VERSION(); +``` + +**说明**:返回服务端当前的状态。 diff --git a/docs-cn/12-taos-sql/12-keywords.md b/docs-cn/12-taos-sql/12-keywords.md index 0e8e1edfee..5c68e5da7e 100644 --- a/docs-cn/12-taos-sql/12-keywords.md +++ b/docs-cn/12-taos-sql/12-keywords.md @@ -93,10 +93,13 @@ title: TDengine 参数限制与保留关键字 `TBNAME` 可以视为超级表中一个特殊的标签,代表子表的表名。 获取一个超级表所有的子表名及相关的标签信息: + ```mysql SELECT TBNAME, location FROM meters; +``` 统计超级表下辖子表数量: + ```mysql SELECT COUNT(TBNAME) FROM meters; ``` diff --git a/docs-en/12-taos-sql/12-keywords.md b/docs-en/12-taos-sql/12-keywords.md index 8f045f4801..ed0c96b4e4 100644 --- a/docs-en/12-taos-sql/12-keywords.md +++ b/docs-en/12-taos-sql/12-keywords.md @@ -56,6 +56,7 @@ There are about 200 keywords reserved by TDengine, they can't be used as the nam Get the table name and tag values of all subtables in a STable. ```mysql SELECT TBNAME, location FROM meters; +``` Count the number of subtables in a STable. ```mysql diff --git a/example/src/tmq.c b/example/src/tmq.c index 7e4de21f2e..5eecb5e4cc 100644 --- a/example/src/tmq.c +++ b/example/src/tmq.c @@ -196,8 +196,9 @@ void basic_consume_loop(tmq_t* tmq, tmq_list_t* topics) { TAOS_RES* tmqmessage = tmq_consumer_poll(tmq, 0); if (tmqmessage) { cnt++; + msg_process(tmqmessage); + if (cnt >= 2) break; /*printf("get data\n");*/ - /*msg_process(tmqmessage);*/ taos_free_result(tmqmessage); /*} else {*/ /*break;*/ @@ -253,39 +254,6 @@ void sync_consume_loop(tmq_t* tmq, tmq_list_t* topics) { fprintf(stderr, "%% Consumer closed\n"); } -void perf_loop(tmq_t* tmq, tmq_list_t* topics) { - tmq_resp_err_t err; - - if ((err = tmq_subscribe(tmq, topics))) { - fprintf(stderr, "%% Failed to start consuming topics: %s\n", tmq_err2str(err)); - printf("subscribe err\n"); - return; - } - int32_t batchCnt = 0; - int32_t skipLogNum = 0; - clock_t startTime = clock(); - while (running) { - TAOS_RES* tmqmessage = tmq_consumer_poll(tmq, 500); - if (tmqmessage) { - batchCnt++; - /*skipLogNum += tmqGetSkipLogNum(tmqmessage);*/ - /*msg_process(tmqmessage);*/ - taos_free_result(tmqmessage); - } else { - break; - } - } - clock_t endTime = clock(); - printf("log batch cnt: %d, skip log cnt: %d, time used:%f s\n", batchCnt, skipLogNum, - (double)(endTime - startTime) / CLOCKS_PER_SEC); - - err = tmq_consumer_close(tmq); - if (err) - fprintf(stderr, "%% Failed to close consumer: %s\n", tmq_err2str(err)); - else - fprintf(stderr, "%% Consumer closed\n"); -} - int main(int argc, char* argv[]) { if (argc > 1) { printf("env init\n"); @@ -296,7 +264,6 @@ int main(int argc, char* argv[]) { } tmq_t* tmq = build_consumer(); tmq_list_t* topic_list = build_topic_list(); - /*perf_loop(tmq, topic_list);*/ - /*basic_consume_loop(tmq, topic_list);*/ - sync_consume_loop(tmq, topic_list); + basic_consume_loop(tmq, topic_list); + /*sync_consume_loop(tmq, topic_list);*/ } diff --git a/include/client/taos.h b/include/client/taos.h index 0b8c67aa79..beeb3a104e 100644 --- a/include/client/taos.h +++ b/include/client/taos.h @@ -230,7 +230,7 @@ DLL_EXPORT const char *tmq_err2str(tmq_resp_err_t); DLL_EXPORT tmq_resp_err_t tmq_subscribe(tmq_t *tmq, const tmq_list_t *topic_list); DLL_EXPORT tmq_resp_err_t tmq_unsubscribe(tmq_t *tmq); DLL_EXPORT tmq_resp_err_t tmq_subscription(tmq_t *tmq, tmq_list_t **topics); -DLL_EXPORT TAOS_RES *tmq_consumer_poll(tmq_t *tmq, int64_t wait_time); +DLL_EXPORT TAOS_RES *tmq_consumer_poll(tmq_t *tmq, int64_t timeout); DLL_EXPORT tmq_resp_err_t tmq_consumer_close(tmq_t *tmq); DLL_EXPORT tmq_resp_err_t tmq_commit_sync(tmq_t *tmq, const tmq_topic_vgroup_list_t *offsets); DLL_EXPORT void tmq_commit_async(tmq_t *tmq, const tmq_topic_vgroup_list_t *offsets, tmq_commit_cb *cb, void *param); diff --git a/include/common/tmsg.h b/include/common/tmsg.h index cf30ca8590..5ca83fe825 100644 --- a/include/common/tmsg.h +++ b/include/common/tmsg.h @@ -1033,6 +1033,7 @@ typedef struct { // for tsma int8_t isTsma; + void* pTsma; } SCreateVnodeReq; @@ -2446,7 +2447,7 @@ typedef struct { int32_t epoch; uint64_t reqId; int64_t consumerId; - int64_t waitTime; + int64_t timeout; int64_t currentOffset; } SMqPollReq; diff --git a/include/util/taoserror.h b/include/util/taoserror.h index 65cfe8de0b..be82e14708 100644 --- a/include/util/taoserror.h +++ b/include/util/taoserror.h @@ -182,7 +182,7 @@ int32_t* taosGetErrno(); #define TSDB_CODE_MND_BNODE_ALREADY_EXIST TAOS_DEF_ERROR_CODE(0, 0x0356) #define TSDB_CODE_MND_BNODE_NOT_EXIST TAOS_DEF_ERROR_CODE(0, 0x0357) #define TSDB_CODE_MND_TOO_FEW_MNODES TAOS_DEF_ERROR_CODE(0, 0x0358) -#define TSDB_CODE_MND_MNODE_DEPLOYED TAOS_DEF_ERROR_CODE(0, 0x0359) +#define TSDB_CODE_MND_TOO_MANY_MNODES TAOS_DEF_ERROR_CODE(0, 0x0359) #define TSDB_CODE_MND_CANT_DROP_MASTER TAOS_DEF_ERROR_CODE(0, 0x035A) // mnode-acct diff --git a/include/util/tdef.h b/include/util/tdef.h index 839fd0b263..de139368c9 100644 --- a/include/util/tdef.h +++ b/include/util/tdef.h @@ -253,8 +253,7 @@ typedef enum ELogicConditionType { #define TSDB_TRANS_STAGE_LEN 12 #define TSDB_TRANS_TYPE_LEN 16 -#define TSDB_TRANS_ERROR_LEN 64 -#define TSDB_TRANS_DESC_LEN 128 +#define TSDB_TRANS_ERROR_LEN 512 #define TSDB_STEP_NAME_LEN 32 #define TSDB_STEP_DESC_LEN 128 @@ -343,7 +342,7 @@ typedef enum ELogicConditionType { #define TSDB_DEFAULT_DB_SCHEMALESS TSDB_DB_SCHEMALESS_OFF #define TSDB_MIN_ROLLUP_FILE_FACTOR 0 -#define TSDB_MAX_ROLLUP_FILE_FACTOR 1 +#define TSDB_MAX_ROLLUP_FILE_FACTOR 10 #define TSDB_DEFAULT_ROLLUP_FILE_FACTOR 0.1 #define TSDB_MIN_TABLE_TTL 0 #define TSDB_DEFAULT_TABLE_TTL 0 diff --git a/include/util/tencode.h b/include/util/tencode.h index c1c5c1150d..3e1d675870 100644 --- a/include/util/tencode.h +++ b/include/util/tencode.h @@ -378,14 +378,16 @@ static FORCE_INLINE int32_t tDecodeDouble(SDecoder* pCoder, double* val) { } static FORCE_INLINE int32_t tDecodeBinary(SDecoder* pCoder, uint8_t** val, uint32_t* len) { - if (tDecodeU32v(pCoder, len) < 0) return -1; + uint32_t length = 0; + if (tDecodeU32v(pCoder, &length) < 0) return -1; + if (len) *len = length; - if (TD_CODER_CHECK_CAPACITY_FAILED(pCoder, *len)) return -1; + if (TD_CODER_CHECK_CAPACITY_FAILED(pCoder, length)) return -1; if (val) { *val = (uint8_t*)TD_CODER_CURRENT(pCoder); } - TD_CODER_MOVE_POS(pCoder, *len); + TD_CODER_MOVE_POS(pCoder, length); return 0; } @@ -410,14 +412,16 @@ static int32_t tDecodeCStrTo(SDecoder* pCoder, char* val) { } static FORCE_INLINE int32_t tDecodeBinaryAlloc(SDecoder* pCoder, void** val, uint64_t* len) { - if (tDecodeU64v(pCoder, len) < 0) return -1; + uint64_t length = 0; + if (tDecodeU64v(pCoder, &length) < 0) return -1; + if (len) *len = length; - if (TD_CODER_CHECK_CAPACITY_FAILED(pCoder, *len)) return -1; - *val = taosMemoryMalloc(*len); + if (TD_CODER_CHECK_CAPACITY_FAILED(pCoder, length)) return -1; + *val = taosMemoryMalloc(length); if (*val == NULL) return -1; - memcpy(*val, TD_CODER_CURRENT(pCoder), *len); + memcpy(*val, TD_CODER_CURRENT(pCoder), length); - TD_CODER_MOVE_POS(pCoder, *len); + TD_CODER_MOVE_POS(pCoder, length); return 0; } diff --git a/source/client/src/tmq.c b/source/client/src/tmq.c index dfa56f80c4..416d1a6f26 100644 --- a/source/client/src/tmq.c +++ b/source/client/src/tmq.c @@ -1243,7 +1243,7 @@ tmq_resp_err_t tmq_seek(tmq_t* tmq, const tmq_topic_vgroup_t* offset) { return TMQ_RESP_ERR__FAIL; } -SMqPollReq* tmqBuildConsumeReqImpl(tmq_t* tmq, int64_t waitTime, SMqClientTopic* pTopic, SMqClientVg* pVg) { +SMqPollReq* tmqBuildConsumeReqImpl(tmq_t* tmq, int64_t timeout, SMqClientTopic* pTopic, SMqClientVg* pVg) { int64_t reqOffset; if (pVg->currentOffset >= 0) { reqOffset = pVg->currentOffset; @@ -1269,7 +1269,7 @@ SMqPollReq* tmqBuildConsumeReqImpl(tmq_t* tmq, int64_t waitTime, SMqClientTopic* strcpy(pReq->subKey + tlen + 1, pTopic->topicName); pReq->withTbName = tmq->withTbName; - pReq->waitTime = waitTime; + pReq->timeout = timeout; pReq->consumerId = tmq->consumerId; pReq->epoch = tmq->epoch; pReq->currentOffset = reqOffset; @@ -1297,7 +1297,7 @@ SMqRspObj* tmqBuildRspFromWrapper(SMqPollRspWrapper* pWrapper) { return pRspObj; } -int32_t tmqPollImpl(tmq_t* tmq, int64_t waitTime) { +int32_t tmqPollImpl(tmq_t* tmq, int64_t timeout) { /*printf("call poll\n");*/ for (int i = 0; i < taosArrayGetSize(tmq->clientTopics); i++) { SMqClientTopic* pTopic = taosArrayGet(tmq->clientTopics, i); @@ -1318,7 +1318,7 @@ int32_t tmqPollImpl(tmq_t* tmq, int64_t waitTime) { #endif } atomic_store_32(&pVg->vgSkipCnt, 0); - SMqPollReq* pReq = tmqBuildConsumeReqImpl(tmq, waitTime, pTopic, pVg); + SMqPollReq* pReq = tmqBuildConsumeReqImpl(tmq, timeout, pTopic, pVg); if (pReq == NULL) { atomic_store_32(&pVg->vgStatus, TMQ_VG_STATUS__IDLE); tsem_post(&tmq->rspSem); @@ -1388,7 +1388,7 @@ int32_t tmqHandleNoPollRsp(tmq_t* tmq, SMqRspWrapper* rspWrapper, bool* pReset) return 0; } -SMqRspObj* tmqHandleAllRsp(tmq_t* tmq, int64_t waitTime, bool pollIfReset) { +SMqRspObj* tmqHandleAllRsp(tmq_t* tmq, int64_t timeout, bool pollIfReset) { while (1) { SMqRspWrapper* rspWrapper = NULL; taosGetQitem(tmq->qall, (void**)&rspWrapper); @@ -1428,17 +1428,17 @@ SMqRspObj* tmqHandleAllRsp(tmq_t* tmq, int64_t waitTime, bool pollIfReset) { taosFreeQitem(rspWrapper); if (pollIfReset && reset) { tscDebug("consumer %ld reset and repoll", tmq->consumerId); - tmqPollImpl(tmq, waitTime); + tmqPollImpl(tmq, timeout); } } } } -TAOS_RES* tmq_consumer_poll(tmq_t* tmq, int64_t wait_time) { +TAOS_RES* tmq_consumer_poll(tmq_t* tmq, int64_t timeout) { SMqRspObj* rspObj; int64_t startTime = taosGetTimestampMs(); - rspObj = tmqHandleAllRsp(tmq, wait_time, false); + rspObj = tmqHandleAllRsp(tmq, timeout, false); if (rspObj) { return (TAOS_RES*)rspObj; } @@ -1450,16 +1450,16 @@ TAOS_RES* tmq_consumer_poll(tmq_t* tmq, int64_t wait_time) { while (1) { tmqHandleAllDelayedTask(tmq); - if (tmqPollImpl(tmq, wait_time) < 0) return NULL; + if (tmqPollImpl(tmq, timeout) < 0) return NULL; - rspObj = tmqHandleAllRsp(tmq, wait_time, false); + rspObj = tmqHandleAllRsp(tmq, timeout, false); if (rspObj) { return (TAOS_RES*)rspObj; } - if (wait_time != 0) { + if (timeout != 0) { int64_t endTime = taosGetTimestampMs(); int64_t leftTime = endTime - startTime; - if (leftTime > wait_time) { + if (leftTime > timeout) { tscDebug("consumer %ld (epoch %d) timeout, no rsp", tmq->consumerId, tmq->epoch); return NULL; } @@ -1474,10 +1474,7 @@ TAOS_RES* tmq_consumer_poll(tmq_t* tmq, int64_t wait_time) { tmq_resp_err_t tmq_consumer_close(tmq_t* tmq) { if (tmq->status == TMQ_CONSUMER_STATUS__READY) { tmq_resp_err_t rsp = tmq_commit_sync(tmq, NULL); - if (rsp == TMQ_RESP_ERR__SUCCESS) { - // TODO: free resources - return TMQ_RESP_ERR__SUCCESS; - } else { + if (rsp == TMQ_RESP_ERR__FAIL) { return TMQ_RESP_ERR__FAIL; } @@ -1485,10 +1482,7 @@ tmq_resp_err_t tmq_consumer_close(tmq_t* tmq) { rsp = tmq_subscribe(tmq, lst); tmq_list_destroy(lst); - if (rsp == TMQ_RESP_ERR__SUCCESS) { - // TODO: free resources - return TMQ_RESP_ERR__SUCCESS; - } else { + if (rsp == TMQ_RESP_ERR__FAIL) { return TMQ_RESP_ERR__FAIL; } } diff --git a/source/common/src/systable.c b/source/common/src/systable.c index 38a6bafe9a..8207ffb22f 100644 --- a/source/common/src/systable.c +++ b/source/common/src/systable.c @@ -215,7 +215,6 @@ static const SSysDbTableSchema transSchema[] = { {.name = "create_time", .bytes = 8, .type = TSDB_DATA_TYPE_TIMESTAMP}, {.name = "stage", .bytes = TSDB_TRANS_STAGE_LEN + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR}, {.name = "db", .bytes = SYSTABLE_SCH_DB_NAME_LEN, .type = TSDB_DATA_TYPE_VARCHAR}, - {.name = "type", .bytes = TSDB_TRANS_TYPE_LEN + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR}, {.name = "failed_times", .bytes = 4, .type = TSDB_DATA_TYPE_INT}, {.name = "last_exec_time", .bytes = 8, .type = TSDB_DATA_TYPE_TIMESTAMP}, {.name = "last_error", .bytes = (TSDB_TRANS_ERROR_LEN - 1) + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR}, diff --git a/source/common/src/tmsg.c b/source/common/src/tmsg.c index 2dd0c20c78..c540c0e82d 100644 --- a/source/common/src/tmsg.c +++ b/source/common/src/tmsg.c @@ -2973,6 +2973,11 @@ int32_t tSerializeSCreateVnodeReq(void *buf, int32_t bufLen, SCreateVnodeReq *pR } if (tEncodeI8(&encoder, pReq->isTsma) < 0) return -1; + if (pReq->isTsma) { + uint32_t tsmaLen = (uint32_t)(htonl(((SMsgHead *)pReq->pTsma)->contLen)); + if (tEncodeBinary(&encoder, (const uint8_t *)pReq->pTsma, tsmaLen) < 0) return -1; + } + tEndEncode(&encoder); int32_t tlen = encoder.pos; @@ -3036,6 +3041,9 @@ int32_t tDeserializeSCreateVnodeReq(void *buf, int32_t bufLen, SCreateVnodeReq * } if (tDecodeI8(&decoder, &pReq->isTsma) < 0) return -1; + if (pReq->isTsma) { + if (tDecodeBinaryAlloc(&decoder, &pReq->pTsma, NULL) < 0) return -1; + } tEndDecode(&decoder); tDecoderClear(&decoder); @@ -3045,6 +3053,9 @@ int32_t tDeserializeSCreateVnodeReq(void *buf, int32_t bufLen, SCreateVnodeReq * int32_t tFreeSCreateVnodeReq(SCreateVnodeReq *pReq) { taosArrayDestroy(pReq->pRetensions); pReq->pRetensions = NULL; + if(pReq->isTsma) { + taosMemoryFreeClear(pReq->pTsma); + } return 0; } diff --git a/source/dnode/mgmt/mgmt_vnode/src/vmHandle.c b/source/dnode/mgmt/mgmt_vnode/src/vmHandle.c index 8374db129f..27ea19a5dc 100644 --- a/source/dnode/mgmt/mgmt_vnode/src/vmHandle.c +++ b/source/dnode/mgmt/mgmt_vnode/src/vmHandle.c @@ -140,6 +140,7 @@ static void vmGenerateVnodeCfg(SCreateVnodeReq *pCreate, SVnodeCfg *pCfg) { pCfg->szCache = pCreate->pages; pCfg->szBuf = (uint64_t)pCreate->buffer * 1024 * 1024; pCfg->isWeak = true; + pCfg->isTsma = pCreate->isTsma; pCfg->tsdbCfg.compression = pCreate->compression; pCfg->tsdbCfg.precision = pCreate->precision; pCfg->tsdbCfg.days = pCreate->daysPerFile; @@ -209,7 +210,7 @@ int32_t vmProcessCreateVnodeReq(SVnodeMgmt *pMgmt, SRpcMsg *pMsg) { SVnode *pImpl = vnodeOpen(path, pMgmt->pTfs, pMgmt->msgCb); if (pImpl == NULL) { - dError("vgId:%d, failed to create vnode since %s", createReq.vgId, terrstr()); + dError("vgId:%d, failed to open vnode since %s", createReq.vgId, terrstr()); code = terrno; goto _OVER; } diff --git a/source/dnode/mnode/impl/inc/mndDef.h b/source/dnode/mnode/impl/inc/mndDef.h index 07097123f2..d0c737ae5a 100644 --- a/source/dnode/mnode/impl/inc/mndDef.h +++ b/source/dnode/mnode/impl/inc/mndDef.h @@ -54,9 +54,11 @@ typedef enum { } EAuthOp; typedef enum { - TRN_STEP_LOG = 1, - TRN_STEP_ACTION = 2, -} ETrnStep; + TRN_CONFLICT_NOTHING = 0, + TRN_CONFLICT_GLOBAL = 1, + TRN_CONFLICT_DB = 2, + TRN_CONFLICT_DB_INSIDE = 3, +} ETrnConflct; typedef enum { TRN_STAGE_PREPARE = 0, @@ -68,69 +70,15 @@ typedef enum { TRN_STAGE_FINISHED = 6 } ETrnStage; -typedef enum { - TRN_TYPE_BASIC_SCOPE = 1000, - TRN_TYPE_CREATE_ACCT = 1001, - TRN_TYPE_CREATE_CLUSTER = 1002, - TRN_TYPE_CREATE_USER = 1003, - TRN_TYPE_ALTER_USER = 1004, - TRN_TYPE_DROP_USER = 1005, - TRN_TYPE_CREATE_FUNC = 1006, - TRN_TYPE_DROP_FUNC = 1007, - - TRN_TYPE_CREATE_SNODE = 1010, - TRN_TYPE_DROP_SNODE = 1011, - TRN_TYPE_CREATE_QNODE = 1012, - TRN_TYPE_DROP_QNODE = 10013, - TRN_TYPE_CREATE_BNODE = 1014, - TRN_TYPE_DROP_BNODE = 1015, - TRN_TYPE_CREATE_MNODE = 1016, - TRN_TYPE_DROP_MNODE = 1017, - - TRN_TYPE_CREATE_TOPIC = 1020, - TRN_TYPE_DROP_TOPIC = 1021, - TRN_TYPE_SUBSCRIBE = 1022, - TRN_TYPE_REBALANCE = 1023, - TRN_TYPE_COMMIT_OFFSET = 1024, - TRN_TYPE_CREATE_STREAM = 1025, - TRN_TYPE_DROP_STREAM = 1026, - TRN_TYPE_ALTER_STREAM = 1027, - TRN_TYPE_CONSUMER_LOST = 1028, - TRN_TYPE_CONSUMER_RECOVER = 1029, - TRN_TYPE_DROP_CGROUP = 1030, - TRN_TYPE_BASIC_SCOPE_END, - - TRN_TYPE_GLOBAL_SCOPE = 2000, - TRN_TYPE_CREATE_DNODE = 2001, - TRN_TYPE_DROP_DNODE = 2002, - TRN_TYPE_GLOBAL_SCOPE_END, - - TRN_TYPE_DB_SCOPE = 3000, - TRN_TYPE_CREATE_DB = 3001, - TRN_TYPE_ALTER_DB = 3002, - TRN_TYPE_DROP_DB = 3003, - TRN_TYPE_SPLIT_VGROUP = 3004, - TRN_TYPE_MERGE_VGROUP = 3015, - TRN_TYPE_DB_SCOPE_END, - - TRN_TYPE_STB_SCOPE = 4000, - TRN_TYPE_CREATE_STB = 4001, - TRN_TYPE_ALTER_STB = 4002, - TRN_TYPE_DROP_STB = 4003, - TRN_TYPE_CREATE_SMA = 4004, - TRN_TYPE_DROP_SMA = 4005, - TRN_TYPE_STB_SCOPE_END, -} ETrnType; - typedef enum { TRN_POLICY_ROLLBACK = 0, TRN_POLICY_RETRY = 1, } ETrnPolicy; typedef enum { - TRN_EXEC_PARALLEL = 0, - TRN_EXEC_NO_PARALLEL = 1, -} ETrnExecType; + TRN_EXEC_PRARLLEL = 0, + TRN_EXEC_SERIAL = 1, +} ETrnExec; typedef enum { DND_REASON_ONLINE = 0, @@ -159,8 +107,8 @@ typedef struct { int32_t id; ETrnStage stage; ETrnPolicy policy; - ETrnType type; - ETrnExecType parallel; + ETrnConflct conflict; + ETrnExec exec; int32_t code; int32_t failedTimes; SRpcHandleInfo rpcInfo; @@ -172,10 +120,11 @@ typedef struct { SArray* commitActions; int64_t createdTime; int64_t lastExecTime; - int64_t dbUid; + int32_t lastErrorAction; + int32_t lastErrorNo; + tmsg_t lastErrorMsgType; + SEpSet lastErrorEpset; char dbname[TSDB_DB_FNAME_LEN]; - char lastError[TSDB_TRANS_ERROR_LEN]; - char desc[TSDB_TRANS_DESC_LEN]; int32_t startFunc; int32_t stopFunc; int32_t paramLen; @@ -344,6 +293,7 @@ typedef struct { int8_t isTsma; int8_t replica; SVnodeGid vnodeGid[TSDB_MAX_REPLICA]; + void* pTsma; } SVgObj; typedef struct { diff --git a/source/dnode/mnode/impl/inc/mndTrans.h b/source/dnode/mnode/impl/inc/mndTrans.h index ba6f5faf1e..9b063fb44f 100644 --- a/source/dnode/mnode/impl/inc/mndTrans.h +++ b/source/dnode/mnode/impl/inc/mndTrans.h @@ -34,7 +34,7 @@ typedef struct { int32_t errCode; int32_t acceptableCode; int8_t stage; - int8_t isRaw; + int8_t actionType; // 0-msg, 1-raw int8_t rawWritten; int8_t msgSent; int8_t msgReceived; @@ -52,7 +52,7 @@ void mndCleanupTrans(SMnode *pMnode); STrans *mndAcquireTrans(SMnode *pMnode, int32_t transId); void mndReleaseTrans(SMnode *pMnode, STrans *pTrans); -STrans *mndTransCreate(SMnode *pMnode, ETrnPolicy policy, ETrnType type, const SRpcMsg *pReq); +STrans *mndTransCreate(SMnode *pMnode, ETrnPolicy policy, ETrnConflct conflict, const SRpcMsg *pReq); void mndTransDrop(STrans *pTrans); int32_t mndTransAppendRedolog(STrans *pTrans, SSdbRaw *pRaw); int32_t mndTransAppendUndolog(STrans *pTrans, SSdbRaw *pRaw); @@ -62,7 +62,7 @@ int32_t mndTransAppendUndoAction(STrans *pTrans, STransAction *pAction); void mndTransSetRpcRsp(STrans *pTrans, void *pCont, int32_t contLen); void mndTransSetCb(STrans *pTrans, ETrnFunc startFunc, ETrnFunc stopFunc, void *param, int32_t paramLen); void mndTransSetDbInfo(STrans *pTrans, SDbObj *pDb); -void mndTransSetNoParallel(STrans *pTrans); +void mndTransSetSerial(STrans *pTrans); int32_t mndTransPrepare(SMnode *pMnode, STrans *pTrans); void mndTransProcessRsp(SRpcMsg *pRsp); diff --git a/source/dnode/mnode/impl/src/mndAcct.c b/source/dnode/mnode/impl/src/mndAcct.c index f3ec3a421b..0ce4a8c76e 100644 --- a/source/dnode/mnode/impl/src/mndAcct.c +++ b/source/dnode/mnode/impl/src/mndAcct.c @@ -80,7 +80,7 @@ static int32_t mndCreateDefaultAcct(SMnode *pMnode) { mDebug("acct:%s, will be created when deploying, raw:%p", acctObj.acct, pRaw); - STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_TYPE_CREATE_ACCT, NULL); + STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_NOTHING, NULL); if (pTrans == NULL) { mError("acct:%s, failed to create since %s", acctObj.acct, terrstr()); return -1; diff --git a/source/dnode/mnode/impl/src/mndBnode.c b/source/dnode/mnode/impl/src/mndBnode.c index 3316a09462..801f335a80 100644 --- a/source/dnode/mnode/impl/src/mndBnode.c +++ b/source/dnode/mnode/impl/src/mndBnode.c @@ -246,7 +246,7 @@ static int32_t mndCreateBnode(SMnode *pMnode, SRpcMsg *pReq, SDnodeObj *pDnode, bnodeObj.createdTime = taosGetTimestampMs(); bnodeObj.updateTime = bnodeObj.createdTime; - STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_TYPE_CREATE_BNODE, pReq); + STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_CONFLICT_NOTHING, pReq); if (pTrans == NULL) goto _OVER; mDebug("trans:%d, used to create bnode:%d", pTrans->id, pCreate->dnodeId); @@ -363,7 +363,7 @@ static int32_t mndSetDropBnodeRedoActions(STrans *pTrans, SDnodeObj *pDnode, SBn static int32_t mndDropBnode(SMnode *pMnode, SRpcMsg *pReq, SBnodeObj *pObj) { int32_t code = -1; - STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_TYPE_DROP_BNODE, pReq); + STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_NOTHING, pReq); if (pTrans == NULL) goto _OVER; mDebug("trans:%d, used to drop bnode:%d", pTrans->id, pObj->id); diff --git a/source/dnode/mnode/impl/src/mndCluster.c b/source/dnode/mnode/impl/src/mndCluster.c index 76c8acf407..bb3377d16a 100644 --- a/source/dnode/mnode/impl/src/mndCluster.c +++ b/source/dnode/mnode/impl/src/mndCluster.c @@ -179,10 +179,8 @@ static int32_t mndCreateDefaultCluster(SMnode *pMnode) { sdbSetRawStatus(pRaw, SDB_STATUS_READY); mDebug("cluster:%" PRId64 ", will be created when deploying, raw:%p", clusterObj.id, pRaw); -#if 0 - return sdbWrite(pMnode->pSdb, pRaw); -#else - STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_TYPE_CREATE_CLUSTER, NULL); + + STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_NOTHING, NULL); if (pTrans == NULL) { mError("cluster:%" PRId64 ", failed to create since %s", clusterObj.id, terrstr()); return -1; @@ -204,7 +202,6 @@ static int32_t mndCreateDefaultCluster(SMnode *pMnode) { mndTransDrop(pTrans); return 0; -#endif } static int32_t mndRetrieveClusters(SRpcMsg *pMsg, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows) { diff --git a/source/dnode/mnode/impl/src/mndConsumer.c b/source/dnode/mnode/impl/src/mndConsumer.c index c3eaeb73b2..0314891d59 100644 --- a/source/dnode/mnode/impl/src/mndConsumer.c +++ b/source/dnode/mnode/impl/src/mndConsumer.c @@ -97,7 +97,7 @@ static int32_t mndProcessConsumerLostMsg(SRpcMsg *pMsg) { mndReleaseConsumer(pMnode, pConsumer); - STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_TYPE_CONSUMER_LOST, pMsg); + STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_NOTHING, pMsg); if (pTrans == NULL) goto FAIL; if (mndSetConsumerCommitLogs(pMnode, pTrans, pConsumerNew) != 0) goto FAIL; if (mndTransPrepare(pMnode, pTrans) != 0) goto FAIL; @@ -121,7 +121,7 @@ static int32_t mndProcessConsumerRecoverMsg(SRpcMsg *pMsg) { mndReleaseConsumer(pMnode, pConsumer); - STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_TYPE_CONSUMER_RECOVER, pMsg); + STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_NOTHING, pMsg); if (pTrans == NULL) goto FAIL; if (mndSetConsumerCommitLogs(pMnode, pTrans, pConsumerNew) != 0) goto FAIL; if (mndTransPrepare(pMnode, pTrans) != 0) goto FAIL; @@ -403,7 +403,7 @@ static int32_t mndProcessSubscribeReq(SRpcMsg *pMsg) { int32_t newTopicNum = taosArrayGetSize(newSub); // check topic existance - STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_TYPE_SUBSCRIBE, pMsg); + STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_NOTHING, pMsg); if (pTrans == NULL) goto SUBSCRIBE_OVER; for (int32_t i = 0; i < newTopicNum; i++) { diff --git a/source/dnode/mnode/impl/src/mndDb.c b/source/dnode/mnode/impl/src/mndDb.c index a0d940c049..5d79708109 100644 --- a/source/dnode/mnode/impl/src/mndDb.c +++ b/source/dnode/mnode/impl/src/mndDb.c @@ -545,7 +545,7 @@ static int32_t mndCreateDb(SMnode *pMnode, SRpcMsg *pReq, SCreateDbReq *pCreate, } int32_t code = -1; - STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_TYPE_CREATE_DB, pReq); + STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_CONFLICT_DB, pReq); if (pTrans == NULL) goto _OVER; mDebug("trans:%d, used to create db:%s", pTrans->id, pCreate->db); @@ -775,7 +775,7 @@ static int32_t mndSetAlterDbRedoActions(SMnode *pMnode, STrans *pTrans, SDbObj * static int32_t mndAlterDb(SMnode *pMnode, SRpcMsg *pReq, SDbObj *pOld, SDbObj *pNew) { int32_t code = -1; - STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_TYPE_ALTER_DB, pReq); + STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_DB, pReq); if (pTrans == NULL) goto _OVER; mDebug("trans:%d, used to alter db:%s", pTrans->id, pOld->name); @@ -1036,7 +1036,7 @@ static int32_t mndBuildDropDbRsp(SDbObj *pDb, int32_t *pRspLen, void **ppRsp, bo static int32_t mndDropDb(SMnode *pMnode, SRpcMsg *pReq, SDbObj *pDb) { int32_t code = -1; - STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_TYPE_DROP_DB, pReq); + STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_DB, pReq); if (pTrans == NULL) goto _OVER; mDebug("trans:%d, used to drop db:%s", pTrans->id, pDb->name); diff --git a/source/dnode/mnode/impl/src/mndDnode.c b/source/dnode/mnode/impl/src/mndDnode.c index d2d97e1405..aeff018aa8 100644 --- a/source/dnode/mnode/impl/src/mndDnode.c +++ b/source/dnode/mnode/impl/src/mndDnode.c @@ -101,10 +101,7 @@ static int32_t mndCreateDefaultDnode(SMnode *pMnode) { mDebug("dnode:%d, will be created when deploying, raw:%p", dnodeObj.id, pRaw); -#if 0 - return sdbWrite(pMnode->pSdb, pRaw); -#else - STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_TYPE_CREATE_DNODE, NULL); + STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_GLOBAL, NULL); if (pTrans == NULL) { mError("dnode:%s, failed to create since %s", dnodeObj.ep, terrstr()); return -1; @@ -126,7 +123,6 @@ static int32_t mndCreateDefaultDnode(SMnode *pMnode) { mndTransDrop(pTrans); return 0; -#endif } static SSdbRaw *mndDnodeActionEncode(SDnodeObj *pDnode) { @@ -260,7 +256,7 @@ int32_t mndGetDnodeSize(SMnode *pMnode) { bool mndIsDnodeOnline(SMnode *pMnode, SDnodeObj *pDnode, int64_t curMs) { int64_t interval = TABS(pDnode->lastAccessTime - curMs); - if (interval > 30000 * tsStatusInterval) { + if (interval > 5000 * tsStatusInterval) { if (pDnode->rebootTime > 0) { pDnode->offlineReason = DND_REASON_STATUS_MSG_TIMEOUT; } @@ -488,7 +484,7 @@ static int32_t mndCreateDnode(SMnode *pMnode, SRpcMsg *pReq, SCreateDnodeReq *pC memcpy(dnodeObj.fqdn, pCreate->fqdn, TSDB_FQDN_LEN); snprintf(dnodeObj.ep, TSDB_EP_LEN, "%s:%u", dnodeObj.fqdn, dnodeObj.port); - STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_TYPE_CREATE_DNODE, pReq); + STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_CONFLICT_GLOBAL, pReq); if (pTrans == NULL) { mError("dnode:%s, failed to create since %s", dnodeObj.ep, terrstr()); return -1; @@ -564,7 +560,7 @@ CREATE_DNODE_OVER: } static int32_t mndDropDnode(SMnode *pMnode, SRpcMsg *pReq, SDnodeObj *pDnode) { - STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_TYPE_DROP_DNODE, pReq); + STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_CONFLICT_GLOBAL, pReq); if (pTrans == NULL) { mError("dnode:%d, failed to drop since %s", pDnode->id, terrstr()); return -1; @@ -617,7 +613,7 @@ static int32_t mndProcessDropDnodeReq(SRpcMsg *pReq) { pMObj = mndAcquireMnode(pMnode, dropReq.dnodeId); if (pMObj != NULL) { - terrno = TSDB_CODE_MND_MNODE_DEPLOYED; + terrno = TSDB_CODE_MND_MNODE_NOT_EXIST; goto DROP_DNODE_OVER; } diff --git a/source/dnode/mnode/impl/src/mndFunc.c b/source/dnode/mnode/impl/src/mndFunc.c index 9107dab693..bf4baebd85 100644 --- a/source/dnode/mnode/impl/src/mndFunc.c +++ b/source/dnode/mnode/impl/src/mndFunc.c @@ -215,7 +215,7 @@ static int32_t mndCreateFunc(SMnode *pMnode, SRpcMsg *pReq, SCreateFuncReq *pCre } memcpy(func.pCode, pCreate->pCode, func.codeSize); - pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_TYPE_CREATE_FUNC, pReq); + pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_CONFLICT_NOTHING, pReq); if (pTrans == NULL) goto _OVER; mDebug("trans:%d, used to create func:%s", pTrans->id, pCreate->name); @@ -245,7 +245,7 @@ _OVER: static int32_t mndDropFunc(SMnode *pMnode, SRpcMsg *pReq, SFuncObj *pFunc) { int32_t code = -1; - STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_TYPE_DROP_FUNC, pReq); + STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_CONFLICT_NOTHING, pReq); if (pTrans == NULL) goto _OVER; mDebug("trans:%d, used to drop user:%s", pTrans->id, pFunc->name); diff --git a/source/dnode/mnode/impl/src/mndMain.c b/source/dnode/mnode/impl/src/mndMain.c index 2a2a45a45d..3a3fd7ebdb 100644 --- a/source/dnode/mnode/impl/src/mndMain.c +++ b/source/dnode/mnode/impl/src/mndMain.c @@ -369,7 +369,7 @@ int32_t mndProcessSyncMsg(SRpcMsg *pMsg) { mError("failed to process sync msg:%p type:%s since %s", pMsg, TMSG_INFO(pMsg->msgType), terrstr()); return TAOS_SYNC_PROPOSE_OTHER_ERROR; } - + char logBuf[512] = {0}; char *syncNodeStr = sync2SimpleStr(pMgmt->sync); snprintf(logBuf, sizeof(logBuf), "==vnodeProcessSyncReq== msgType:%d, syncNode: %s", pMsg->msgType, syncNodeStr); @@ -472,7 +472,7 @@ int32_t mndProcessRpcMsg(SRpcMsg *pMsg) { } else if (code == 0) { mTrace("msg:%p, successfully processed and response", pMsg); } else { - mDebug("msg:%p, failed to process since %s, app:%p type:%s", pMsg, terrstr(), pMsg->info.ahandle, + mError("msg:%p, failed to process since %s, app:%p type:%s", pMsg, terrstr(), pMsg->info.ahandle, TMSG_INFO(pMsg->msgType)); } @@ -686,4 +686,4 @@ void mndReleaseSyncRef(SMnode *pMnode) { int32_t ref = atomic_sub_fetch_32(&pMnode->syncRef, 1); mTrace("mnode sync is released, ref:%d", ref); taosThreadRwlockUnlock(&pMnode->lock); -} \ No newline at end of file +} diff --git a/source/dnode/mnode/impl/src/mndMnode.c b/source/dnode/mnode/impl/src/mndMnode.c index 5b8ba6deaa..4578d81efb 100644 --- a/source/dnode/mnode/impl/src/mndMnode.c +++ b/source/dnode/mnode/impl/src/mndMnode.c @@ -18,9 +18,9 @@ #include "mndAuth.h" #include "mndDnode.h" #include "mndShow.h" +#include "mndSync.h" #include "mndTrans.h" #include "mndUser.h" -#include "mndSync.h" #define MNODE_VER_NUMBER 1 #define MNODE_RESERVE_SIZE 64 @@ -92,10 +92,7 @@ static int32_t mndCreateDefaultMnode(SMnode *pMnode) { mDebug("mnode:%d, will be created when deploying, raw:%p", mnodeObj.id, pRaw); -#if 0 - return sdbWrite(pMnode->pSdb, pRaw); -#else - STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_TYPE_CREATE_DNODE, NULL); + STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_GLOBAL, NULL); if (pTrans == NULL) { mError("mnode:%d, failed to create since %s", mnodeObj.id, terrstr()); return -1; @@ -117,7 +114,6 @@ static int32_t mndCreateDefaultMnode(SMnode *pMnode) { mndTransDrop(pTrans); return 0; -#endif } static SSdbRaw *mndMnodeActionEncode(SMnodeObj *pObj) { @@ -363,11 +359,11 @@ static int32_t mndCreateMnode(SMnode *pMnode, SRpcMsg *pReq, SDnodeObj *pDnode, mnodeObj.createdTime = taosGetTimestampMs(); mnodeObj.updateTime = mnodeObj.createdTime; - STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_TYPE_CREATE_MNODE, pReq); + STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_GLOBAL, pReq); if (pTrans == NULL) goto _OVER; mDebug("trans:%d, used to create mnode:%d", pTrans->id, pCreate->dnodeId); - mndTransSetNoParallel(pTrans); + mndTransSetSerial(pTrans); if (mndSetCreateMnodeRedoLogs(pMnode, pTrans, &mnodeObj) != 0) goto _OVER; if (mndSetCreateMnodeCommitLogs(pMnode, pTrans, &mnodeObj) != 0) goto _OVER; if (mndSetCreateMnodeRedoActions(pMnode, pTrans, pDnode, &mnodeObj) != 0) goto _OVER; @@ -396,6 +392,11 @@ static int32_t mndProcessCreateMnodeReq(SRpcMsg *pReq) { mDebug("mnode:%d, start to create", createReq.dnodeId); + if (sdbGetSize(pMnode->pSdb, SDB_MNODE) >= 3) { + terrno = TSDB_CODE_MND_TOO_MANY_MNODES; + goto _OVER; + } + pObj = mndAcquireMnode(pMnode, createReq.dnodeId); if (pObj != NULL) { terrno = TSDB_CODE_MND_MNODE_ALREADY_EXIST; @@ -535,11 +536,11 @@ static int32_t mndSetDropMnodeRedoActions(SMnode *pMnode, STrans *pTrans, SDnode static int32_t mndDropMnode(SMnode *pMnode, SRpcMsg *pReq, SMnodeObj *pObj) { int32_t code = -1; - STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_TYPE_DROP_MNODE, pReq); + STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_GLOBAL, pReq); if (pTrans == NULL) goto _OVER; mDebug("trans:%d, used to drop mnode:%d", pTrans->id, pObj->id); - mndTransSetNoParallel(pTrans); + mndTransSetSerial(pTrans); if (mndSetDropMnodeRedoLogs(pMnode, pTrans, pObj) != 0) goto _OVER; if (mndSetDropMnodeCommitLogs(pMnode, pTrans, pObj) != 0) goto _OVER; if (mndSetDropMnodeRedoActions(pMnode, pTrans, pObj->pDnode, pObj) != 0) goto _OVER; @@ -632,6 +633,7 @@ static int32_t mndRetrieveMnodes(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pB int32_t cols = 0; SMnodeObj *pObj = NULL; char *pWrite; + int64_t curMs = taosGetTimestampMs(); while (numOfRows < rows) { pShow->pIter = sdbFetch(pSdb, SDB_MNODE, pShow->pIter, (void **)&pObj); @@ -647,11 +649,16 @@ static int32_t mndRetrieveMnodes(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pB pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); colDataAppend(pColInfo, numOfRows, b1, false); + bool online = mndIsDnodeOnline(pMnode, pObj->pDnode, curMs); const char *roles = NULL; if (pObj->id == pMnode->selfDnodeId) { roles = syncStr(TAOS_SYNC_STATE_LEADER); } else { - roles = syncStr(pObj->state); + if (!online) { + roles = "OFFLINE"; + } else { + roles = syncStr(pObj->state); + } } char *b2 = taosMemoryCalloc(1, 12 + VARSTR_HEADER_SIZE); STR_WITH_MAXSIZE_TO_VARSTR(b2, roles, pShow->pMeta->pSchemas[cols].bytes); diff --git a/source/dnode/mnode/impl/src/mndOffset.c b/source/dnode/mnode/impl/src/mndOffset.c index 6cbaca3c07..00c8bb30d0 100644 --- a/source/dnode/mnode/impl/src/mndOffset.c +++ b/source/dnode/mnode/impl/src/mndOffset.c @@ -179,7 +179,7 @@ static int32_t mndProcessCommitOffsetReq(SRpcMsg *pMsg) { tDecodeSMqCMCommitOffsetReq(&decoder, &commitOffsetReq); - STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_TYPE_COMMIT_OFFSET, pMsg); + STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_CONFLICT_NOTHING, pMsg); for (int32_t i = 0; i < commitOffsetReq.num; i++) { SMqOffset *pOffset = &commitOffsetReq.offsets[i]; diff --git a/source/dnode/mnode/impl/src/mndQnode.c b/source/dnode/mnode/impl/src/mndQnode.c index 7c7bdc2e3a..27881865af 100644 --- a/source/dnode/mnode/impl/src/mndQnode.c +++ b/source/dnode/mnode/impl/src/mndQnode.c @@ -248,7 +248,7 @@ static int32_t mndCreateQnode(SMnode *pMnode, SRpcMsg *pReq, SDnodeObj *pDnode, qnodeObj.createdTime = taosGetTimestampMs(); qnodeObj.updateTime = qnodeObj.createdTime; - STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_TYPE_CREATE_QNODE, pReq); + STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_CONFLICT_NOTHING, pReq); if (pTrans == NULL) goto _OVER; mDebug("trans:%d, used to create qnode:%d", pTrans->id, pCreate->dnodeId); @@ -365,7 +365,7 @@ static int32_t mndSetDropQnodeRedoActions(STrans *pTrans, SDnodeObj *pDnode, SQn static int32_t mndDropQnode(SMnode *pMnode, SRpcMsg *pReq, SQnodeObj *pObj) { int32_t code = -1; - STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_TYPE_DROP_QNODE, pReq); + STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_NOTHING, pReq); if (pTrans == NULL) goto _OVER; mDebug("trans:%d, used to drop qnode:%d", pTrans->id, pObj->id); diff --git a/source/dnode/mnode/impl/src/mndSma.c b/source/dnode/mnode/impl/src/mndSma.c index 0493b00d33..8b09674179 100644 --- a/source/dnode/mnode/impl/src/mndSma.c +++ b/source/dnode/mnode/impl/src/mndSma.c @@ -409,7 +409,8 @@ static int32_t mndSetCreateSmaRedoActions(SMnode *pMnode, STrans *pTrans, SDbObj return 0; } -static int32_t mndSetCreateSmaVgroupRedoActions(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup) { +static int32_t mndSetCreateSmaVgroupRedoActions(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup, + SSmaObj *pSma) { SVnodeGid *pVgid = pVgroup->vnodeGid + 0; SDnodeObj *pDnode = mndAcquireDnode(pMnode, pVgid->dnodeId); if (pDnode == NULL) return -1; @@ -419,9 +420,14 @@ static int32_t mndSetCreateSmaVgroupRedoActions(SMnode *pMnode, STrans *pTrans, mndReleaseDnode(pMnode, pDnode); // todo add sma info here + int32_t smaContLen = 0; + void *pSmaReq = mndBuildVCreateSmaReq(pMnode, pVgroup, pSma, &smaContLen); + if (pSmaReq == NULL) return -1; + pVgroup->pTsma = pSmaReq; int32_t contLen = 0; void *pReq = mndBuildCreateVnodeReq(pMnode, pDnode, pDb, pVgroup, &contLen); + taosMemoryFreeClear(pSmaReq); if (pReq == NULL) return -1; action.pCont = pReq; @@ -502,19 +508,19 @@ static int32_t mndCreateSma(SMnode *pMnode, SRpcMsg *pReq, SMCreateSmaReq *pCrea streamObj.fixedSinkVgId = smaObj.dstVgId; int32_t code = -1; - STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_TYPE_CREATE_SMA, pReq); + STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_DB, pReq); if (pTrans == NULL) goto _OVER; mDebug("trans:%d, used to create sma:%s", pTrans->id, pCreate->name); mndTransSetDbInfo(pTrans, pDb); - mndTransSetNoParallel(pTrans); + mndTransSetSerial(pTrans); if (mndSetCreateSmaRedoLogs(pMnode, pTrans, &smaObj) != 0) goto _OVER; if (mndSetCreateSmaVgroupRedoLogs(pMnode, pTrans, &streamObj.fixedSinkVg) != 0) goto _OVER; if (mndSetCreateSmaCommitLogs(pMnode, pTrans, &smaObj) != 0) goto _OVER; if (mndSetCreateSmaVgroupCommitLogs(pMnode, pTrans, &streamObj.fixedSinkVg) != 0) goto _OVER; if (mndSetCreateSmaRedoActions(pMnode, pTrans, pDb, &smaObj) != 0) goto _OVER; - if (mndSetCreateSmaVgroupRedoActions(pMnode, pTrans, pDb, &streamObj.fixedSinkVg) != 0) goto _OVER; + if (mndSetCreateSmaVgroupRedoActions(pMnode, pTrans, pDb, &streamObj.fixedSinkVg, &smaObj) != 0) goto _OVER; if (mndAddStreamToTrans(pMnode, &streamObj, pCreate->ast, STREAM_TRIGGER_AT_ONCE, 0, pTrans) != 0) goto _OVER; if (mndTransPrepare(pMnode, pTrans) != 0) goto _OVER; @@ -747,7 +753,7 @@ static int32_t mndDropSma(SMnode *pMnode, SRpcMsg *pReq, SDbObj *pDb, SSmaObj *p pVgroup = mndAcquireVgroup(pMnode, pSma->dstVgId); if (pVgroup == NULL) goto _OVER; - pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_TYPE_DROP_SMA, pReq); + pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_CONFLICT_DB, pReq); if (pTrans == NULL) goto _OVER; mDebug("trans:%d, used to drop sma:%s", pTrans->id, pSma->name); diff --git a/source/dnode/mnode/impl/src/mndSnode.c b/source/dnode/mnode/impl/src/mndSnode.c index 87b61f59ec..c6acb4fef4 100644 --- a/source/dnode/mnode/impl/src/mndSnode.c +++ b/source/dnode/mnode/impl/src/mndSnode.c @@ -253,7 +253,7 @@ static int32_t mndCreateSnode(SMnode *pMnode, SRpcMsg *pReq, SDnodeObj *pDnode, snodeObj.createdTime = taosGetTimestampMs(); snodeObj.updateTime = snodeObj.createdTime; - STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_TYPE_CREATE_SNODE, pReq); + STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_CONFLICT_NOTHING, pReq); if (pTrans == NULL) goto _OVER; mDebug("trans:%d, used to create snode:%d", pTrans->id, pCreate->dnodeId); @@ -372,7 +372,7 @@ static int32_t mndSetDropSnodeRedoActions(STrans *pTrans, SDnodeObj *pDnode, SSn static int32_t mndDropSnode(SMnode *pMnode, SRpcMsg *pReq, SSnodeObj *pObj) { int32_t code = -1; - STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_TYPE_DROP_SNODE, pReq); + STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_NOTHING, pReq); if (pTrans == NULL) goto _OVER; mDebug("trans:%d, used to drop snode:%d", pTrans->id, pObj->id); diff --git a/source/dnode/mnode/impl/src/mndStb.c b/source/dnode/mnode/impl/src/mndStb.c index 53befd731c..9ca7613519 100644 --- a/source/dnode/mnode/impl/src/mndStb.c +++ b/source/dnode/mnode/impl/src/mndStb.c @@ -735,7 +735,7 @@ static int32_t mndCreateStb(SMnode *pMnode, SRpcMsg *pReq, SMCreateStbReq *pCrea int32_t code = -1; - STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_TYPE_CREATE_STB, pReq); + STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_CONFLICT_DB_INSIDE, pReq); if (pTrans == NULL) goto _OVER; mDebug("trans:%d, used to create stb:%s", pTrans->id, pCreate->name); @@ -1257,7 +1257,7 @@ static int32_t mndAlterStb(SMnode *pMnode, SRpcMsg *pReq, const SMAlterStbReq *p if (code != 0) goto _OVER; code = -1; - pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_TYPE_ALTER_STB, pReq); + pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_DB_INSIDE, pReq); if (pTrans == NULL) goto _OVER; mDebug("trans:%d, used to alter stb:%s", pTrans->id, pAlter->name); @@ -1403,7 +1403,7 @@ static int32_t mndSetDropStbRedoActions(SMnode *pMnode, STrans *pTrans, SDbObj * static int32_t mndDropStb(SMnode *pMnode, SRpcMsg *pReq, SDbObj *pDb, SStbObj *pStb) { int32_t code = -1; - STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_TYPE_DROP_STB, pReq); + STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_CONFLICT_DB_INSIDE, pReq); if (pTrans == NULL) goto _OVER; mDebug("trans:%d, used to drop stb:%s", pTrans->id, pStb->name); diff --git a/source/dnode/mnode/impl/src/mndStream.c b/source/dnode/mnode/impl/src/mndStream.c index 13071b5c53..5ee5b06a57 100644 --- a/source/dnode/mnode/impl/src/mndStream.c +++ b/source/dnode/mnode/impl/src/mndStream.c @@ -402,7 +402,7 @@ static int32_t mndCreateStream(SMnode *pMnode, SRpcMsg *pReq, SCMCreateStreamReq tstrncpy(streamObj.targetDb, pDb->name, TSDB_DB_FNAME_LEN); } - STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_TYPE_CREATE_STREAM, pReq); + STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_CONFLICT_NOTHING, pReq); if (pTrans == NULL) { mError("stream:%s, failed to create since %s", pCreate->name, terrstr()); return -1; diff --git a/source/dnode/mnode/impl/src/mndSubscribe.c b/source/dnode/mnode/impl/src/mndSubscribe.c index 2dbc0cbbc1..fc736809fd 100644 --- a/source/dnode/mnode/impl/src/mndSubscribe.c +++ b/source/dnode/mnode/impl/src/mndSubscribe.c @@ -394,8 +394,8 @@ static int32_t mndDoRebalance(SMnode *pMnode, const SMqRebInputObj *pInput, SMqR mInfo("rebalance calculation completed, rebalanced vg:"); for (int32_t i = 0; i < taosArrayGetSize(pOutput->rebVgs); i++) { SMqRebOutputVg *pOutputRebVg = taosArrayGet(pOutput->rebVgs, i); - mInfo("vg: %d moved from consumer %ld to consumer %ld", pOutputRebVg->pVgEp->vgId, pOutputRebVg->oldConsumerId, - pOutputRebVg->newConsumerId); + mInfo("vgId:%d moved from consumer %" PRId64 " to consumer %" PRId64, pOutputRebVg->pVgEp->vgId, + pOutputRebVg->oldConsumerId, pOutputRebVg->newConsumerId); } // 9. clear @@ -405,10 +405,9 @@ static int32_t mndDoRebalance(SMnode *pMnode, const SMqRebInputObj *pInput, SMqR } static int32_t mndPersistRebResult(SMnode *pMnode, SRpcMsg *pMsg, const SMqRebOutputObj *pOutput) { - STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_TYPE_REBALANCE, pMsg); - if (pTrans == NULL) { - return -1; - } + STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_CONFLICT_NOTHING, pMsg); + if (pTrans == NULL) return -1; + // make txn: // 1. redo action: action to all vg const SArray *rebVgs = pOutput->rebVgs; @@ -625,7 +624,7 @@ static int32_t mndProcessDropCgroupReq(SRpcMsg *pReq) { return -1; } - STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_TYPE_DROP_CGROUP, pReq); + STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_CONFLICT_NOTHING, pReq); if (pTrans == NULL) { mError("cgroup: %s on topic:%s, failed to drop since %s", dropReq.cgroup, dropReq.topic, terrstr()); mndReleaseSubscribe(pMnode, pSub); diff --git a/source/dnode/mnode/impl/src/mndTopic.c b/source/dnode/mnode/impl/src/mndTopic.c index 02f06a0de8..446992a245 100644 --- a/source/dnode/mnode/impl/src/mndTopic.c +++ b/source/dnode/mnode/impl/src/mndTopic.c @@ -383,7 +383,7 @@ static int32_t mndCreateTopic(SMnode *pMnode, SRpcMsg *pReq, SCMCreateTopicReq * /*topicObj.withSchema = 1;*/ } - STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_TYPE_CREATE_TOPIC, pReq); + STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_CONFLICT_NOTHING, pReq); if (pTrans == NULL) { mError("topic:%s, failed to create since %s", pCreate->name, terrstr()); taosMemoryFreeClear(topicObj.ast); @@ -551,7 +551,7 @@ static int32_t mndProcessDropTopicReq(SRpcMsg *pReq) { } #endif - STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_TYPE_DROP_TOPIC, pReq); + STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_CONFLICT_NOTHING, pReq); if (pTrans == NULL) { mError("topic:%s, failed to drop since %s", pTopic->name, terrstr()); return -1; diff --git a/source/dnode/mnode/impl/src/mndTrans.c b/source/dnode/mnode/impl/src/mndTrans.c index ad6388c585..bad513a89d 100644 --- a/source/dnode/mnode/impl/src/mndTrans.c +++ b/source/dnode/mnode/impl/src/mndTrans.c @@ -88,12 +88,12 @@ static int32_t mndTransGetActionsSize(SArray *pArray) { for (int32_t i = 0; i < actionNum; ++i) { STransAction *pAction = taosArrayGet(pArray, i); - if (pAction->isRaw) { + if (pAction->actionType) { rawDataLen += (sdbGetRawTotalSize(pAction->pRaw) + sizeof(int32_t)); } else { rawDataLen += (sizeof(STransAction) + pAction->contLen); } - rawDataLen += sizeof(pAction->isRaw); + rawDataLen += sizeof(pAction->actionType); } return rawDataLen; @@ -117,8 +117,8 @@ static SSdbRaw *mndTransActionEncode(STrans *pTrans) { SDB_SET_INT32(pRaw, dataPos, pTrans->id, _OVER) SDB_SET_INT16(pRaw, dataPos, pTrans->stage, _OVER) SDB_SET_INT16(pRaw, dataPos, pTrans->policy, _OVER) - SDB_SET_INT16(pRaw, dataPos, pTrans->type, _OVER) - SDB_SET_INT16(pRaw, dataPos, pTrans->parallel, _OVER) + SDB_SET_INT16(pRaw, dataPos, pTrans->conflict, _OVER) + SDB_SET_INT16(pRaw, dataPos, pTrans->exec, _OVER) SDB_SET_INT64(pRaw, dataPos, pTrans->createdTime, _OVER) SDB_SET_BINARY(pRaw, dataPos, pTrans->dbname, TSDB_DB_FNAME_LEN, _OVER) SDB_SET_INT32(pRaw, dataPos, pTrans->redoActionPos, _OVER) @@ -135,9 +135,9 @@ static SSdbRaw *mndTransActionEncode(STrans *pTrans) { SDB_SET_INT32(pRaw, dataPos, pAction->id, _OVER) SDB_SET_INT32(pRaw, dataPos, pAction->errCode, _OVER) SDB_SET_INT32(pRaw, dataPos, pAction->acceptableCode, _OVER) - SDB_SET_INT8(pRaw, dataPos, pAction->isRaw, _OVER) + SDB_SET_INT8(pRaw, dataPos, pAction->actionType, _OVER) SDB_SET_INT8(pRaw, dataPos, pAction->stage, _OVER) - if (pAction->isRaw) { + if (pAction->actionType) { int32_t len = sdbGetRawTotalSize(pAction->pRaw); SDB_SET_INT8(pRaw, dataPos, pAction->rawWritten, _OVER) SDB_SET_INT32(pRaw, dataPos, len, _OVER) @@ -157,9 +157,9 @@ static SSdbRaw *mndTransActionEncode(STrans *pTrans) { SDB_SET_INT32(pRaw, dataPos, pAction->id, _OVER) SDB_SET_INT32(pRaw, dataPos, pAction->errCode, _OVER) SDB_SET_INT32(pRaw, dataPos, pAction->acceptableCode, _OVER) - SDB_SET_INT8(pRaw, dataPos, pAction->isRaw, _OVER) + SDB_SET_INT8(pRaw, dataPos, pAction->actionType, _OVER) SDB_SET_INT8(pRaw, dataPos, pAction->stage, _OVER) - if (pAction->isRaw) { + if (pAction->actionType) { int32_t len = sdbGetRawTotalSize(pAction->pRaw); SDB_SET_INT8(pRaw, dataPos, pAction->rawWritten, _OVER) SDB_SET_INT32(pRaw, dataPos, len, _OVER) @@ -179,9 +179,9 @@ static SSdbRaw *mndTransActionEncode(STrans *pTrans) { SDB_SET_INT32(pRaw, dataPos, pAction->id, _OVER) SDB_SET_INT32(pRaw, dataPos, pAction->errCode, _OVER) SDB_SET_INT32(pRaw, dataPos, pAction->acceptableCode, _OVER) - SDB_SET_INT8(pRaw, dataPos, pAction->isRaw, _OVER) + SDB_SET_INT8(pRaw, dataPos, pAction->actionType, _OVER) SDB_SET_INT8(pRaw, dataPos, pAction->stage, _OVER) - if (pAction->isRaw) { + if (pAction->actionType) { int32_t len = sdbGetRawTotalSize(pAction->pRaw); SDB_SET_INT8(pRaw, dataPos, pAction->rawWritten, _OVER) SDB_SET_INT32(pRaw, dataPos, len, _OVER) @@ -250,16 +250,16 @@ static SSdbRow *mndTransActionDecode(SSdbRaw *pRaw) { int16_t stage = 0; int16_t policy = 0; - int16_t type = 0; - int16_t parallel = 0; + int16_t conflict = 0; + int16_t exec = 0; SDB_GET_INT16(pRaw, dataPos, &stage, _OVER) SDB_GET_INT16(pRaw, dataPos, &policy, _OVER) - SDB_GET_INT16(pRaw, dataPos, &type, _OVER) - SDB_GET_INT16(pRaw, dataPos, ¶llel, _OVER) + SDB_GET_INT16(pRaw, dataPos, &conflict, _OVER) + SDB_GET_INT16(pRaw, dataPos, &exec, _OVER) pTrans->stage = stage; pTrans->policy = policy; - pTrans->type = type; - pTrans->parallel = parallel; + pTrans->conflict = conflict; + pTrans->exec = exec; SDB_GET_INT64(pRaw, dataPos, &pTrans->createdTime, _OVER) SDB_GET_BINARY(pRaw, dataPos, pTrans->dbname, TSDB_DB_FNAME_LEN, _OVER) SDB_GET_INT32(pRaw, dataPos, &pTrans->redoActionPos, _OVER) @@ -279,9 +279,9 @@ static SSdbRow *mndTransActionDecode(SSdbRaw *pRaw) { SDB_GET_INT32(pRaw, dataPos, &action.id, _OVER) SDB_GET_INT32(pRaw, dataPos, &action.errCode, _OVER) SDB_GET_INT32(pRaw, dataPos, &action.acceptableCode, _OVER) - SDB_GET_INT8(pRaw, dataPos, &action.isRaw, _OVER) + SDB_GET_INT8(pRaw, dataPos, &action.actionType, _OVER) SDB_GET_INT8(pRaw, dataPos, &action.stage, _OVER) - if (action.isRaw) { + if (action.actionType) { SDB_GET_INT8(pRaw, dataPos, &action.rawWritten, _OVER) SDB_GET_INT32(pRaw, dataPos, &dataLen, _OVER) action.pRaw = taosMemoryMalloc(dataLen); @@ -308,9 +308,9 @@ static SSdbRow *mndTransActionDecode(SSdbRaw *pRaw) { SDB_GET_INT32(pRaw, dataPos, &action.id, _OVER) SDB_GET_INT32(pRaw, dataPos, &action.errCode, _OVER) SDB_GET_INT32(pRaw, dataPos, &action.acceptableCode, _OVER) - SDB_GET_INT8(pRaw, dataPos, &action.isRaw, _OVER) + SDB_GET_INT8(pRaw, dataPos, &action.actionType, _OVER) SDB_GET_INT8(pRaw, dataPos, &action.stage, _OVER) - if (action.isRaw) { + if (action.actionType) { SDB_GET_INT8(pRaw, dataPos, &action.rawWritten, _OVER) SDB_GET_INT32(pRaw, dataPos, &dataLen, _OVER) action.pRaw = taosMemoryMalloc(dataLen); @@ -337,9 +337,9 @@ static SSdbRow *mndTransActionDecode(SSdbRaw *pRaw) { SDB_GET_INT32(pRaw, dataPos, &action.id, _OVER) SDB_GET_INT32(pRaw, dataPos, &action.errCode, _OVER) SDB_GET_INT32(pRaw, dataPos, &action.acceptableCode, _OVER) - SDB_GET_INT8(pRaw, dataPos, &action.isRaw, _OVER) + SDB_GET_INT8(pRaw, dataPos, &action.actionType, _OVER) SDB_GET_INT8(pRaw, dataPos, &action.stage, _OVER) - if (action.isRaw) { + if (action.actionType) { SDB_GET_INT8(pRaw, dataPos, &action.rawWritten, _OVER) SDB_GET_INT32(pRaw, dataPos, &dataLen, _OVER) action.pRaw = taosMemoryMalloc(dataLen); @@ -408,81 +408,6 @@ static const char *mndTransStr(ETrnStage stage) { } } -static const char *mndTransType(ETrnType type) { - switch (type) { - case TRN_TYPE_CREATE_USER: - return "create-user"; - case TRN_TYPE_ALTER_USER: - return "alter-user"; - case TRN_TYPE_DROP_USER: - return "drop-user"; - case TRN_TYPE_CREATE_FUNC: - return "create-func"; - case TRN_TYPE_DROP_FUNC: - return "drop-func"; - case TRN_TYPE_CREATE_SNODE: - return "create-snode"; - case TRN_TYPE_DROP_SNODE: - return "drop-snode"; - case TRN_TYPE_CREATE_QNODE: - return "create-qnode"; - case TRN_TYPE_DROP_QNODE: - return "drop-qnode"; - case TRN_TYPE_CREATE_BNODE: - return "create-bnode"; - case TRN_TYPE_DROP_BNODE: - return "drop-bnode"; - case TRN_TYPE_CREATE_MNODE: - return "create-mnode"; - case TRN_TYPE_DROP_MNODE: - return "drop-mnode"; - case TRN_TYPE_CREATE_TOPIC: - return "create-topic"; - case TRN_TYPE_DROP_TOPIC: - return "drop-topic"; - case TRN_TYPE_SUBSCRIBE: - return "subscribe"; - case TRN_TYPE_REBALANCE: - return "rebalance"; - case TRN_TYPE_COMMIT_OFFSET: - return "commit-offset"; - case TRN_TYPE_CREATE_STREAM: - return "create-stream"; - case TRN_TYPE_DROP_STREAM: - return "drop-stream"; - case TRN_TYPE_CONSUMER_LOST: - return "consumer-lost"; - case TRN_TYPE_CONSUMER_RECOVER: - return "consumer-recover"; - case TRN_TYPE_CREATE_DNODE: - return "create-qnode"; - case TRN_TYPE_DROP_DNODE: - return "drop-qnode"; - case TRN_TYPE_CREATE_DB: - return "create-db"; - case TRN_TYPE_ALTER_DB: - return "alter-db"; - case TRN_TYPE_DROP_DB: - return "drop-db"; - case TRN_TYPE_SPLIT_VGROUP: - return "split-vgroup"; - case TRN_TYPE_MERGE_VGROUP: - return "merge-vgroup"; - case TRN_TYPE_CREATE_STB: - return "create-stb"; - case TRN_TYPE_ALTER_STB: - return "alter-stb"; - case TRN_TYPE_DROP_STB: - return "drop-stb"; - case TRN_TYPE_CREATE_SMA: - return "create-sma"; - case TRN_TYPE_DROP_SMA: - return "drop-sma"; - default: - return "invalid"; - } -} - static void mndTransTestStartFunc(SMnode *pMnode, void *param, int32_t paramLen) { mInfo("test trans start, param:%s, len:%d", (char *)param, paramLen); } @@ -594,7 +519,7 @@ void mndReleaseTrans(SMnode *pMnode, STrans *pTrans) { sdbRelease(pSdb, pTrans); } -STrans *mndTransCreate(SMnode *pMnode, ETrnPolicy policy, ETrnType type, const SRpcMsg *pReq) { +STrans *mndTransCreate(SMnode *pMnode, ETrnPolicy policy, ETrnConflct conflict, const SRpcMsg *pReq) { STrans *pTrans = taosMemoryCalloc(1, sizeof(STrans)); if (pTrans == NULL) { terrno = TSDB_CODE_OUT_OF_MEMORY; @@ -605,8 +530,8 @@ STrans *mndTransCreate(SMnode *pMnode, ETrnPolicy policy, ETrnType type, const S pTrans->id = sdbGetMaxId(pMnode->pSdb, SDB_TRANS); pTrans->stage = TRN_STAGE_PREPARE; pTrans->policy = policy; - pTrans->type = type; - pTrans->parallel = TRN_EXEC_PARALLEL; + pTrans->conflict = conflict; + pTrans->exec = TRN_EXEC_PRARLLEL; pTrans->createdTime = taosGetTimestampMs(); pTrans->redoActions = taosArrayInit(TRANS_ARRAY_SIZE, sizeof(STransAction)); pTrans->undoActions = taosArrayInit(TRANS_ARRAY_SIZE, sizeof(STransAction)); @@ -627,7 +552,7 @@ static void mndTransDropActions(SArray *pArray) { int32_t size = taosArrayGetSize(pArray); for (int32_t i = 0; i < size; ++i) { STransAction *pAction = taosArrayGet(pArray, i); - if (pAction->isRaw) { + if (pAction->actionType) { taosMemoryFreeClear(pAction->pRaw); } else { taosMemoryFreeClear(pAction->pCont); @@ -658,17 +583,17 @@ static int32_t mndTransAppendAction(SArray *pArray, STransAction *pAction) { } int32_t mndTransAppendRedolog(STrans *pTrans, SSdbRaw *pRaw) { - STransAction action = {.stage = TRN_STAGE_REDO_ACTION, .isRaw = true, .pRaw = pRaw}; + STransAction action = {.stage = TRN_STAGE_REDO_ACTION, .actionType = true, .pRaw = pRaw}; return mndTransAppendAction(pTrans->redoActions, &action); } int32_t mndTransAppendUndolog(STrans *pTrans, SSdbRaw *pRaw) { - STransAction action = {.stage = TRN_STAGE_UNDO_ACTION, .isRaw = true, .pRaw = pRaw}; + STransAction action = {.stage = TRN_STAGE_UNDO_ACTION, .actionType = true, .pRaw = pRaw}; return mndTransAppendAction(pTrans->undoActions, &action); } int32_t mndTransAppendCommitlog(STrans *pTrans, SSdbRaw *pRaw) { - STransAction action = {.stage = TRN_STAGE_COMMIT_ACTION, .isRaw = true, .pRaw = pRaw}; + STransAction action = {.stage = TRN_STAGE_COMMIT_ACTION, .actionType = true, .pRaw = pRaw}; return mndTransAppendAction(pTrans->commitActions, &action); } @@ -698,7 +623,7 @@ void mndTransSetDbInfo(STrans *pTrans, SDbObj *pDb) { memcpy(pTrans->dbname, pDb->name, TSDB_DB_FNAME_LEN); } -void mndTransSetNoParallel(STrans *pTrans) { pTrans->parallel = TRN_EXEC_NO_PARALLEL; } +void mndTransSetSerial(STrans *pTrans) { pTrans->exec = TRN_EXEC_SERIAL; } static int32_t mndTransSync(SMnode *pMnode, STrans *pTrans) { SSdbRaw *pRaw = mndTransActionEncode(pTrans); @@ -721,76 +646,43 @@ static int32_t mndTransSync(SMnode *pMnode, STrans *pTrans) { return 0; } -static bool mndIsBasicTrans(STrans *pTrans) { - return pTrans->type > TRN_TYPE_BASIC_SCOPE && pTrans->type < TRN_TYPE_BASIC_SCOPE_END; -} - -static bool mndIsGlobalTrans(STrans *pTrans) { - return pTrans->type > TRN_TYPE_GLOBAL_SCOPE && pTrans->type < TRN_TYPE_GLOBAL_SCOPE_END; -} - -static bool mndIsDbTrans(STrans *pTrans) { - return pTrans->type > TRN_TYPE_DB_SCOPE && pTrans->type < TRN_TYPE_DB_SCOPE_END; -} - -static bool mndIsStbTrans(STrans *pTrans) { - return pTrans->type > TRN_TYPE_STB_SCOPE && pTrans->type < TRN_TYPE_STB_SCOPE_END; -} - -static bool mndCheckTransConflict(SMnode *pMnode, STrans *pNewTrans) { +static bool mndCheckTransConflict(SMnode *pMnode, STrans *pNew) { STrans *pTrans = NULL; void *pIter = NULL; bool conflict = false; - if (mndIsBasicTrans(pNewTrans)) return conflict; + if (pNew->conflict == TRN_CONFLICT_NOTHING) return conflict; while (1) { pIter = sdbFetch(pMnode->pSdb, SDB_TRANS, pIter, (void **)&pTrans); if (pIter == NULL) break; - if (mndIsGlobalTrans(pNewTrans)) { - if (mndIsDbTrans(pTrans) || mndIsStbTrans(pTrans)) { - mError("trans:%d, can't execute since trans:%d in progress db:%s", pNewTrans->id, pTrans->id, pTrans->dbname); - conflict = true; - } else { - } + if (pNew->conflict == TRN_CONFLICT_GLOBAL) conflict = true; + if (pNew->conflict == TRN_CONFLICT_DB) { + if (pTrans->conflict == TRN_CONFLICT_GLOBAL) conflict = true; + if (pTrans->conflict == TRN_CONFLICT_DB && strcmp(pNew->dbname, pTrans->dbname) == 0) conflict = true; + if (pTrans->conflict == TRN_CONFLICT_DB_INSIDE && strcmp(pNew->dbname, pTrans->dbname) == 0) conflict = true; } - - else if (mndIsDbTrans(pNewTrans)) { - if (mndIsGlobalTrans(pTrans)) { - mError("trans:%d, can't execute since trans:%d in progress", pNewTrans->id, pTrans->id); - conflict = true; - } else if (mndIsDbTrans(pTrans) || mndIsStbTrans(pTrans)) { - if (strcmp(pNewTrans->dbname, pTrans->dbname) == 0) { - mError("trans:%d, can't execute since trans:%d in progress db:%s", pNewTrans->id, pTrans->id, pTrans->dbname); - conflict = true; - } - } else { - } + if (pNew->conflict == TRN_CONFLICT_DB_INSIDE) { + if (pTrans->conflict == TRN_CONFLICT_GLOBAL) conflict = true; + if (pTrans->conflict == TRN_CONFLICT_DB && strcmp(pNew->dbname, pTrans->dbname) == 0) conflict = true; } - - else if (mndIsStbTrans(pNewTrans)) { - if (mndIsGlobalTrans(pTrans)) { - mError("trans:%d, can't execute since trans:%d in progress", pNewTrans->id, pTrans->id); - conflict = true; - } else if (mndIsDbTrans(pTrans)) { - if (strcmp(pNewTrans->dbname, pTrans->dbname) == 0) { - mError("trans:%d, can't execute since trans:%d in progress db:%s", pNewTrans->id, pTrans->id, pTrans->dbname); - conflict = true; - } - } else { - } - } - + mError("trans:%d, can't execute since conflict with trans:%d, db:%s", pNew->id, pTrans->id, pTrans->dbname); sdbRelease(pMnode->pSdb, pTrans); } - sdbCancelFetch(pMnode->pSdb, pIter); - sdbRelease(pMnode->pSdb, pTrans); return conflict; } int32_t mndTransPrepare(SMnode *pMnode, STrans *pTrans) { + if (pTrans->conflict == TRN_CONFLICT_DB || pTrans->conflict == TRN_CONFLICT_DB_INSIDE) { + if (strlen(pTrans->dbname) == 0) { + terrno = TSDB_CODE_MND_TRANS_CONFLICT; + mError("trans:%d, failed to prepare conflict db not set", pTrans->id); + return -1; + } + } + if (mndCheckTransConflict(pMnode, pTrans)) { terrno = TSDB_CODE_MND_TRANS_CONFLICT; mError("trans:%d, failed to prepare since %s", pTrans->id, terrstr()); @@ -921,9 +813,6 @@ void mndTransProcessRsp(SRpcMsg *pRsp) { if (pAction != NULL) { pAction->msgReceived = 1; pAction->errCode = pRsp->code; - if (pAction->errCode != 0) { - tstrncpy(pTrans->lastError, tstrerror(pAction->errCode), TSDB_TRANS_ERROR_LEN); - } } mDebug("trans:%d, %s:%d response is received, code:0x%x, accept:0x%x", transId, mndTransStr(pAction->stage), action, @@ -1004,7 +893,7 @@ static int32_t mndTransSendSingleMsg(SMnode *pMnode, STrans *pTrans, STransActio } static int32_t mndTransExecSingleAction(SMnode *pMnode, STrans *pTrans, STransAction *pAction) { - if (pAction->isRaw) { + if (pAction->actionType) { return mndTransWriteSingleLog(pMnode, pTrans, pAction); } else { return mndTransSendSingleMsg(pMnode, pTrans, pAction); @@ -1032,24 +921,36 @@ static int32_t mndTransExecuteActions(SMnode *pMnode, STrans *pTrans, SArray *pA return -1; } - int32_t numOfExecuted = 0; - int32_t errCode = 0; + int32_t numOfExecuted = 0; + int32_t errCode = 0; + STransAction *pErrAction = NULL; for (int32_t action = 0; action < numOfActions; ++action) { STransAction *pAction = taosArrayGet(pArray, action); if (pAction->msgReceived || pAction->rawWritten) { numOfExecuted++; if (pAction->errCode != 0 && pAction->errCode != pAction->acceptableCode) { errCode = pAction->errCode; + pErrAction = pAction; } } } if (numOfExecuted == numOfActions) { if (errCode == 0) { + pTrans->lastErrorAction = 0; + pTrans->lastErrorNo = 0; + pTrans->lastErrorMsgType = 0; + memset(&pTrans->lastErrorEpset, 0, sizeof(pTrans->lastErrorEpset)); mDebug("trans:%d, all %d actions execute successfully", pTrans->id, numOfActions); return 0; } else { mError("trans:%d, all %d actions executed, code:0x%x", pTrans->id, numOfActions, errCode & 0XFFFF); + if (pErrAction != NULL) { + pTrans->lastErrorMsgType = pErrAction->msgType; + pTrans->lastErrorAction = pErrAction->id; + pTrans->lastErrorNo = pErrAction->errCode; + pTrans->lastErrorEpset = pErrAction->epSet; + } mndTransResetActions(pMnode, pTrans, pArray); terrno = errCode; return errCode; @@ -1084,7 +985,7 @@ static int32_t mndTransExecuteCommitActions(SMnode *pMnode, STrans *pTrans) { return code; } -static int32_t mndTransExecuteRedoActionsNoParallel(SMnode *pMnode, STrans *pTrans) { +static int32_t mndTransExecuteRedoActionsSerial(SMnode *pMnode, STrans *pTrans) { int32_t code = 0; int32_t numOfActions = taosArrayGetSize(pTrans->redoActions); if (numOfActions == 0) return code; @@ -1111,6 +1012,18 @@ static int32_t mndTransExecuteRedoActionsNoParallel(SMnode *pMnode, STrans *pTra } } + if (code == 0) { + pTrans->lastErrorAction = 0; + pTrans->lastErrorNo = 0; + pTrans->lastErrorMsgType = 0; + memset(&pTrans->lastErrorEpset, 0, sizeof(pTrans->lastErrorEpset)); + } else { + pTrans->lastErrorMsgType = pAction->msgType; + pTrans->lastErrorAction = action; + pTrans->lastErrorNo = pAction->errCode; + pTrans->lastErrorEpset = pAction->epSet; + } + if (code == 0) { pTrans->redoActionPos++; mDebug("trans:%d, %s:%d is executed and need sync to other mnodes", pTrans->id, mndTransStr(pAction->stage), @@ -1144,8 +1057,8 @@ static bool mndTransPerformRedoActionStage(SMnode *pMnode, STrans *pTrans) { bool continueExec = true; int32_t code = 0; - if (pTrans->parallel == TRN_EXEC_NO_PARALLEL) { - code = mndTransExecuteRedoActionsNoParallel(pMnode, pTrans); + if (pTrans->exec == TRN_EXEC_SERIAL) { + code = mndTransExecuteRedoActionsSerial(pMnode, pTrans); } else { code = mndTransExecuteRedoActions(pMnode, pTrans); } @@ -1455,11 +1368,6 @@ static int32_t mndRetrieveTrans(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBl pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); colDataAppend(pColInfo, numOfRows, (const char *)dbname, false); - char type[TSDB_TRANS_TYPE_LEN + VARSTR_HEADER_SIZE] = {0}; - STR_WITH_MAXSIZE_TO_VARSTR(type, mndTransType(pTrans->type), pShow->pMeta->pSchemas[cols].bytes); - pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)type, false); - pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); colDataAppend(pColInfo, numOfRows, (const char *)&pTrans->failedTimes, false); @@ -1467,7 +1375,20 @@ static int32_t mndRetrieveTrans(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBl colDataAppend(pColInfo, numOfRows, (const char *)&pTrans->lastExecTime, false); char lastError[TSDB_TRANS_ERROR_LEN + VARSTR_HEADER_SIZE] = {0}; - STR_WITH_MAXSIZE_TO_VARSTR(lastError, pTrans->lastError, pShow->pMeta->pSchemas[cols].bytes); + char detail[TSDB_TRANS_ERROR_LEN] = {0}; + if (pTrans->lastErrorNo != 0) { + int32_t len = snprintf(detail, sizeof(detail), "action:%d errno:0x%x(%s) ", pTrans->lastErrorAction, + pTrans->lastErrorNo & 0xFFFF, tstrerror(pTrans->lastErrorNo)); + SEpSet epset = pTrans->lastErrorEpset; + if (epset.numOfEps > 0) { + len += snprintf(detail + len, sizeof(detail) - len, "msgType:%s numOfEps:%d inUse:%d ", + TMSG_INFO(pTrans->lastErrorMsgType), epset.numOfEps, epset.inUse); + } + for (int32_t i = 0; i < pTrans->lastErrorEpset.numOfEps; ++i) { + len += snprintf(detail + len, sizeof(detail) - len, "ep:%d-%s:%u ", i, epset.eps[i].fqdn, epset.eps[i].port); + } + } + STR_WITH_MAXSIZE_TO_VARSTR(lastError, detail, pShow->pMeta->pSchemas[cols].bytes); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); colDataAppend(pColInfo, numOfRows, (const char *)lastError, false); diff --git a/source/dnode/mnode/impl/src/mndUser.c b/source/dnode/mnode/impl/src/mndUser.c index 83d00c86e3..345d756f43 100644 --- a/source/dnode/mnode/impl/src/mndUser.c +++ b/source/dnode/mnode/impl/src/mndUser.c @@ -79,10 +79,7 @@ static int32_t mndCreateDefaultUser(SMnode *pMnode, char *acct, char *user, char mDebug("user:%s, will be created when deploying, raw:%p", userObj.user, pRaw); -#if 0 - return sdbWrite(pMnode->pSdb, pRaw); -#else - STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_TYPE_CREATE_USER, NULL); + STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_NOTHING, NULL); if (pTrans == NULL) { mError("user:%s, failed to create since %s", userObj.user, terrstr()); return -1; @@ -104,7 +101,6 @@ static int32_t mndCreateDefaultUser(SMnode *pMnode, char *acct, char *user, char mndTransDrop(pTrans); return 0; -#endif } static int32_t mndCreateDefaultUsers(SMnode *pMnode) { @@ -291,7 +287,7 @@ static int32_t mndCreateUser(SMnode *pMnode, char *acct, SCreateUserReq *pCreate userObj.updateTime = userObj.createdTime; userObj.superUser = pCreate->superUser; - STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_TYPE_CREATE_USER, pReq); + STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_CONFLICT_NOTHING, pReq); if (pTrans == NULL) { mError("user:%s, failed to create since %s", pCreate->user, terrstr()); return -1; @@ -371,7 +367,7 @@ _OVER: } static int32_t mndAlterUser(SMnode *pMnode, SUserObj *pOld, SUserObj *pNew, SRpcMsg *pReq) { - STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_TYPE_ALTER_USER, pReq); + STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_CONFLICT_NOTHING, pReq); if (pTrans == NULL) { mError("user:%s, failed to alter since %s", pOld->user, terrstr()); return -1; @@ -578,7 +574,7 @@ _OVER: } static int32_t mndDropUser(SMnode *pMnode, SRpcMsg *pReq, SUserObj *pUser) { - STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_TYPE_DROP_USER, pReq); + STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_CONFLICT_NOTHING, pReq); if (pTrans == NULL) { mError("user:%s, failed to drop since %s", pUser->user, terrstr()); return -1; diff --git a/source/dnode/mnode/impl/src/mndVgroup.c b/source/dnode/mnode/impl/src/mndVgroup.c index 161fc5379c..b5f308fef2 100644 --- a/source/dnode/mnode/impl/src/mndVgroup.c +++ b/source/dnode/mnode/impl/src/mndVgroup.c @@ -218,6 +218,8 @@ void *mndBuildCreateVnodeReq(SMnode *pMnode, SDnodeObj *pDnode, SDbObj *pDb, SVg createReq.hashMethod = pDb->cfg.hashMethod; createReq.numOfRetensions = pDb->cfg.numOfRetensions; createReq.pRetensions = pDb->cfg.pRetensions; + createReq.isTsma = pVgroup->isTsma; + createReq.pTsma = pVgroup->pTsma; for (int32_t v = 0; v < pVgroup->replica; ++v) { SReplica *pReplica = &createReq.replicas[v]; diff --git a/source/dnode/mnode/impl/test/trans/trans2.cpp b/source/dnode/mnode/impl/test/trans/trans2.cpp index cfcfc2490e..d518db2d38 100644 --- a/source/dnode/mnode/impl/test/trans/trans2.cpp +++ b/source/dnode/mnode/impl/test/trans/trans2.cpp @@ -11,6 +11,8 @@ #include +#if 0 + #include "mndTrans.h" #include "mndUser.h" #include "tcache.h" @@ -103,7 +105,7 @@ class MndTestTrans2 : public ::testing::Test { void SetUp() override {} void TearDown() override {} - int32_t CreateUserLog(const char *acct, const char *user, ETrnType type, SDbObj *pDb) { + int32_t CreateUserLog(const char *acct, const char *user, ETrnConflct conflict, SDbObj *pDb) { SUserObj userObj = {0}; taosEncryptPass_c((uint8_t *)"taosdata", strlen("taosdata"), userObj.pass); tstrncpy(userObj.user, user, TSDB_USER_LEN); @@ -113,7 +115,7 @@ class MndTestTrans2 : public ::testing::Test { userObj.superUser = 1; SRpcMsg rpcMsg = {0}; - STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, type, &rpcMsg); + STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, conflict, &rpcMsg); SSdbRaw *pRedoRaw = mndUserActionEncode(&userObj); mndTransAppendRedolog(pTrans, pRedoRaw); sdbSetRawStatus(pRedoRaw, SDB_STATUS_READY); @@ -135,7 +137,7 @@ class MndTestTrans2 : public ::testing::Test { return code; } - int32_t CreateUserAction(const char *acct, const char *user, bool hasUndoAction, ETrnPolicy policy, ETrnType type, + int32_t CreateUserAction(const char *acct, const char *user, bool hasUndoAction, ETrnPolicy policy, ETrnConflct conflict, SDbObj *pDb) { SUserObj userObj = {0}; taosEncryptPass_c((uint8_t *)"taosdata", strlen("taosdata"), userObj.pass); @@ -146,7 +148,7 @@ class MndTestTrans2 : public ::testing::Test { userObj.superUser = 1; SRpcMsg rpcMsg = {0}; - STrans *pTrans = mndTransCreate(pMnode, policy, type, &rpcMsg); + STrans *pTrans = mndTransCreate(pMnode, policy, conflict, &rpcMsg); SSdbRaw *pRedoRaw = mndUserActionEncode(&userObj); mndTransAppendRedolog(pTrans, pRedoRaw); sdbSetRawStatus(pRedoRaw, SDB_STATUS_READY); @@ -218,7 +220,7 @@ class MndTestTrans2 : public ::testing::Test { userObj.superUser = 1; SRpcMsg rpcMsg = {0}; - STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_TYPE_CREATE_USER, &rpcMsg); + STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_CONFLICT_NOTHING, &rpcMsg); SSdbRaw *pRedoRaw = mndUserActionEncode(&userObj); mndTransAppendRedolog(pTrans, pRedoRaw); sdbSetRawStatus(pRedoRaw, SDB_STATUS_READY); @@ -528,3 +530,5 @@ TEST_F(MndTestTrans2, 04_Conflict) { mndReleaseUser(pMnode, pUser); } } + +#endif \ No newline at end of file diff --git a/source/dnode/mnode/impl/test/user/CMakeLists.txt b/source/dnode/mnode/impl/test/user/CMakeLists.txt index b39ea0e73f..ed4d964617 100644 --- a/source/dnode/mnode/impl/test/user/CMakeLists.txt +++ b/source/dnode/mnode/impl/test/user/CMakeLists.txt @@ -5,7 +5,9 @@ target_link_libraries( PUBLIC sut ) -add_test( - NAME userTest - COMMAND userTest -) +if(NOT TD_WINDOWS) + add_test( + NAME userTest + COMMAND userTest + ) +endif(NOT TD_WINDOWS) diff --git a/source/dnode/vnode/inc/vnode.h b/source/dnode/vnode/inc/vnode.h index bcd8cc3393..64c4f24978 100644 --- a/source/dnode/vnode/inc/vnode.h +++ b/source/dnode/vnode/inc/vnode.h @@ -171,12 +171,13 @@ struct SVnodeCfg { uint64_t szBuf; bool isHeap; bool isWeak; + int8_t isTsma; + int8_t hashMethod; STsdbCfg tsdbCfg; SWalCfg walCfg; SSyncCfg syncCfg; uint32_t hashBegin; uint32_t hashEnd; - int8_t hashMethod; }; typedef struct { diff --git a/source/dnode/vnode/src/inc/tq.h b/source/dnode/vnode/src/inc/tq.h index 72138926aa..34a7ff823a 100644 --- a/source/dnode/vnode/src/inc/tq.h +++ b/source/dnode/vnode/src/inc/tq.h @@ -66,12 +66,12 @@ struct STqReadHandle { // tqPush typedef struct { - int64_t consumerId; - int32_t epoch; - int32_t skipLogNum; - int64_t reqOffset; - SRWLatch lock; - SRpcMsg* handle; + int64_t consumerId; + int32_t epoch; + int32_t skipLogNum; + int64_t reqOffset; + SRpcHandleInfo info; + SRWLatch lock; } STqPushHandle; #if 0 diff --git a/source/dnode/vnode/src/sma/smaRollup.c b/source/dnode/vnode/src/sma/smaRollup.c index a1e397f11d..42c215ee7c 100644 --- a/source/dnode/vnode/src/sma/smaRollup.c +++ b/source/dnode/vnode/src/sma/smaRollup.c @@ -414,7 +414,7 @@ static FORCE_INLINE int32_t tdExecuteRSmaImpl(SSma *pSma, const void *pMsg, int3 } taosMemoryFreeClear(pReq); } else { - smaWarn("vgId:%d no rsma % " PRIi8 " data generated since %s", SMA_VID(pSma), level, tstrerror(terrno)); + smaDebug("vgId:%d no rsma % " PRIi8 " data generated since %s", SMA_VID(pSma), level, tstrerror(terrno)); } taosArrayDestroy(pResult); diff --git a/source/dnode/vnode/src/tq/tq.c b/source/dnode/vnode/src/tq/tq.c index b4747f2264..4bce829b10 100644 --- a/source/dnode/vnode/src/tq/tq.c +++ b/source/dnode/vnode/src/tq/tq.c @@ -180,40 +180,6 @@ void tqClose(STQ* pTq) { // TODO } -#if 0 -int32_t tEncodeSTqExec(SEncoder* pEncoder, const STqExec* pExec) { - if (tStartEncode(pEncoder) < 0) return -1; - if (tEncodeCStr(pEncoder, pExec->subKey) < 0) return -1; - if (tEncodeI64(pEncoder, pExec->consumerId) < 0) return -1; - if (tEncodeI32(pEncoder, pExec->epoch) < 0) return -1; - if (tEncodeI8(pEncoder, pExec->subType) < 0) return -1; - /*if (tEncodeI8(pEncoder, pExec->withTbName) < 0) return -1;*/ - /*if (tEncodeI8(pEncoder, pExec->withSchema) < 0) return -1;*/ - /*if (tEncodeI8(pEncoder, pExec->withTag) < 0) return -1;*/ - if (pExec->subType == TOPIC_SUB_TYPE__COLUMN) { - if (tEncodeCStr(pEncoder, pExec->qmsg) < 0) return -1; - } - tEndEncode(pEncoder); - return pEncoder->pos; -} - -int32_t tDecodeSTqExec(SDecoder* pDecoder, STqExec* pExec) { - if (tStartDecode(pDecoder) < 0) return -1; - if (tDecodeCStrTo(pDecoder, pExec->subKey) < 0) return -1; - if (tDecodeI64(pDecoder, &pExec->consumerId) < 0) return -1; - if (tDecodeI32(pDecoder, &pExec->epoch) < 0) return -1; - if (tDecodeI8(pDecoder, &pExec->subType) < 0) return -1; - /*if (tDecodeI8(pDecoder, &pExec->withTbName) < 0) return -1;*/ - /*if (tDecodeI8(pDecoder, &pExec->withSchema) < 0) return -1;*/ - /*if (tDecodeI8(pDecoder, &pExec->withTag) < 0) return -1;*/ - if (pExec->subType == TOPIC_SUB_TYPE__COLUMN) { - if (tDecodeCStrAlloc(pDecoder, &pExec->qmsg) < 0) return -1; - } - tEndDecode(pDecoder); - return 0; -} -#endif - int32_t tEncodeSTqHandle(SEncoder* pEncoder, const STqHandle* pHandle) { if (tStartEncode(pEncoder) < 0) return -1; if (tEncodeCStr(pEncoder, pHandle->subKey) < 0) return -1; @@ -290,8 +256,8 @@ int32_t tqPushMsgNew(STQ* pTq, void* msg, int32_t msgLen, tmsg_t msgType, int64_ taosWLockLatch(&pHandle->pushHandle.lock); - SRpcMsg* pMsg = atomic_load_ptr(&pHandle->pushHandle.handle); - ASSERT(pMsg); + /*SRpcHandleInfo* pInfo = atomic_load_ptr(&pHandle->pushHandle.pInfo);*/ + /*ASSERT(pInfo);*/ SMqDataBlkRsp rsp = {0}; rsp.reqOffset = pHandle->pushHandle.reqOffset; @@ -318,7 +284,7 @@ int32_t tqPushMsgNew(STQ* pTq, void* msg, int32_t msgLen, tmsg_t msgType, int64_ int32_t tlen = sizeof(SMqRspHead) + tEncodeSMqDataBlkRsp(NULL, &rsp); void* buf = rpcMallocCont(tlen); if (buf == NULL) { - pMsg->code = -1; + // todo free return -1; } @@ -329,10 +295,16 @@ int32_t tqPushMsgNew(STQ* pTq, void* msg, int32_t msgLen, tmsg_t msgType, int64_ void* abuf = POINTER_SHIFT(buf, sizeof(SMqRspHead)); tEncodeSMqDataBlkRsp(&abuf, &rsp); - SRpcMsg resp = {.info = handleInfo, .pCont = buf, .contLen = tlen, .code = 0}; + SRpcMsg resp = { + .info = pHandle->pushHandle.info, + .pCont = buf, + .contLen = tlen, + .code = 0, + }; tmsgSendRsp(&resp); - atomic_store_ptr(&pHandle->pushHandle.handle, NULL); + /*atomic_store_ptr(&pHandle->pushHandle.pInfo, NULL);*/ + memset(&pHandle->pushHandle.info, 0, sizeof(SRpcHandleInfo)); taosWUnLockLatch(&pHandle->pushHandle.lock); tqDebug("vg %d offset %ld from consumer %ld (epoch %d) send rsp, block num: %d, reqOffset: %ld, rspOffset: %ld", @@ -374,7 +346,7 @@ int tqCommit(STQ* pTq) { int32_t tqProcessPollReq(STQ* pTq, SRpcMsg* pMsg, int32_t workerId) { SMqPollReq* pReq = pMsg->pCont; int64_t consumerId = pReq->consumerId; - int64_t waitTime = pReq->waitTime; + int64_t waitTime = pReq->timeout; int32_t reqEpoch = pReq->epoch; int64_t fetchOffset; @@ -410,24 +382,22 @@ int32_t tqProcessPollReq(STQ* pTq, SRpcMsg* pMsg, int32_t workerId) { rsp.blockData = taosArrayInit(0, sizeof(void*)); rsp.blockDataLen = taosArrayInit(0, sizeof(int32_t)); - rsp.blockSchema = taosArrayInit(0, sizeof(void*)); - rsp.blockTbName = taosArrayInit(0, sizeof(void*)); rsp.withTbName = pReq->withTbName; + if (rsp.withTbName) { + rsp.blockTbName = taosArrayInit(0, sizeof(void*)); + } if (pHandle->execHandle.subType == TOPIC_SUB_TYPE__COLUMN) { rsp.withSchema = false; + rsp.withTag = false; } else { rsp.withSchema = true; + rsp.blockSchema = taosArrayInit(0, sizeof(void*)); + rsp.withTag = false; } - /*int8_t withTbName = pExec->withTbName;*/ - /*if (pReq->withTbName != -1) {*/ - /*withTbName = pReq->withTbName;*/ - /*}*/ - /*rsp.withTbName = withTbName;*/ - while (1) { consumerEpoch = atomic_load_32(&pHandle->epoch); if (consumerEpoch > reqEpoch) { @@ -443,15 +413,6 @@ int32_t tqProcessPollReq(STQ* pTq, SRpcMsg* pMsg, int32_t workerId) { SWalReadHead* pHead = &pHeadWithCkSum->head; -#if 0 - SWalReadHead* pHead; - if (walReadWithHandle_s(pExec->pWalReader, fetchOffset, &pHead) < 0) { - // TODO: no more log, set timer to wait blocking time - // if data inserted during waiting, launch query and - // response to user - tqDebug("tmq poll: consumer %ld (epoch %d) vg %d offset %ld, no more log to return", consumerId, pReq->epoch, - TD_VID(pTq->pVnode), fetchOffset); - #if 0 // add to pushMgr taosWLockLatch(&pExec->pushHandle.lock); @@ -473,10 +434,6 @@ int32_t tqProcessPollReq(STQ* pTq, SRpcMsg* pMsg, int32_t workerId) { return 0; #endif - break; - } -#endif - tqDebug("tmq poll: consumer %ld (epoch %d) iter log, vg %d offset %ld msgType %d", consumerId, pReq->epoch, TD_VID(pTq->pVnode), fetchOffset, pHead->msgType); @@ -533,8 +490,14 @@ int32_t tqProcessPollReq(STQ* pTq, SRpcMsg* pMsg, int32_t workerId) { // TODO wrap in destroy func taosArrayDestroy(rsp.blockData); taosArrayDestroy(rsp.blockDataLen); - taosArrayDestroyP(rsp.blockSchema, (FDelete)tDeleteSSchemaWrapper); - taosArrayDestroyP(rsp.blockTbName, (FDelete)taosMemoryFree); + + if (rsp.withSchema) { + taosArrayDestroyP(rsp.blockSchema, (FDelete)tDeleteSSchemaWrapper); + } + + if (rsp.withTbName) { + taosArrayDestroyP(rsp.blockTbName, (FDelete)taosMemoryFree); + } return 0; } diff --git a/source/dnode/vnode/src/vnd/vnodeCfg.c b/source/dnode/vnode/src/vnd/vnodeCfg.c index a66ecc493d..56cc3d6374 100644 --- a/source/dnode/vnode/src/vnd/vnodeCfg.c +++ b/source/dnode/vnode/src/vnd/vnodeCfg.c @@ -56,6 +56,7 @@ int vnodeEncodeConfig(const void *pObj, SJson *pJson) { if (tjsonAddIntegerToObject(pJson, "szBuf", pCfg->szBuf) < 0) return -1; if (tjsonAddIntegerToObject(pJson, "isHeap", pCfg->isHeap) < 0) return -1; if (tjsonAddIntegerToObject(pJson, "isWeak", pCfg->isWeak) < 0) return -1; + if (tjsonAddIntegerToObject(pJson, "isTsma", pCfg->isTsma) < 0) return -1; if (tjsonAddIntegerToObject(pJson, "precision", pCfg->tsdbCfg.precision) < 0) return -1; if (tjsonAddIntegerToObject(pJson, "update", pCfg->tsdbCfg.update) < 0) return -1; if (tjsonAddIntegerToObject(pJson, "compression", pCfg->tsdbCfg.compression) < 0) return -1; @@ -130,6 +131,8 @@ int vnodeDecodeConfig(const SJson *pJson, void *pObj) { if(code < 0) return -1; tjsonGetNumberValue(pJson, "isWeak", pCfg->isWeak, code); if(code < 0) return -1; + tjsonGetNumberValue(pJson, "isTsma", pCfg->isTsma, code); + if(code < 0) return -1; tjsonGetNumberValue(pJson, "precision", pCfg->tsdbCfg.precision, code); if(code < 0) return -1; tjsonGetNumberValue(pJson, "update", pCfg->tsdbCfg.update, code); diff --git a/source/dnode/vnode/src/vnd/vnodeOpen.c b/source/dnode/vnode/src/vnd/vnodeOpen.c index a90bb7afcb..178ef28e5d 100644 --- a/source/dnode/vnode/src/vnd/vnodeOpen.c +++ b/source/dnode/vnode/src/vnd/vnodeOpen.c @@ -97,7 +97,7 @@ SVnode *vnodeOpen(const char *path, STfs *pTfs, SMsgCb msgCb) { } // open tsdb - if (!vnodeIsRollup(pVnode) && tsdbOpen(pVnode, &VND_TSDB(pVnode), VNODE_TSDB_DIR, TSDB_TYPE_TSDB) < 0) { + if (!vnodeIsRollup(pVnode) && tsdbOpen(pVnode, &VND_TSDB(pVnode), VNODE_TSDB_DIR, NULL) < 0) { vError("vgId:%d failed to open vnode tsdb since %s", TD_VID(pVnode), tstrerror(terrno)); goto _err; } diff --git a/source/libs/function/src/builtinsimpl.c b/source/libs/function/src/builtinsimpl.c index 3f6f13a572..a7e93246b7 100644 --- a/source/libs/function/src/builtinsimpl.c +++ b/source/libs/function/src/builtinsimpl.c @@ -1646,8 +1646,8 @@ bool leastSQRFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInf pInfo->startVal = IS_FLOAT_TYPE(pCtx->param[1].param.nType) ? pCtx->param[1].param.d : (double)pCtx->param[1].param.i; - pInfo->stepVal = IS_FLOAT_TYPE(pCtx->param[1].param.nType) ? pCtx->param[2].param.d : - (double)pCtx->param[1].param.i; + pInfo->stepVal = IS_FLOAT_TYPE(pCtx->param[2].param.nType) ? pCtx->param[2].param.d : + (double)pCtx->param[2].param.i; return true; } diff --git a/source/libs/scalar/test/scalar/CMakeLists.txt b/source/libs/scalar/test/scalar/CMakeLists.txt index 86b936d93a..672cb5a3de 100644 --- a/source/libs/scalar/test/scalar/CMakeLists.txt +++ b/source/libs/scalar/test/scalar/CMakeLists.txt @@ -17,7 +17,9 @@ TARGET_INCLUDE_DIRECTORIES( PUBLIC "${TD_SOURCE_DIR}/source/libs/parser/inc" PRIVATE "${TD_SOURCE_DIR}/source/libs/scalar/inc" ) -add_test( - NAME scalarTest - COMMAND scalarTest -) +if(NOT TD_WINDOWS) + add_test( + NAME scalarTest + COMMAND scalarTest + ) +endif(NOT TD_WINDOWS) diff --git a/source/os/CMakeLists.txt b/source/os/CMakeLists.txt index b6e131d4cc..e15627fe66 100644 --- a/source/os/CMakeLists.txt +++ b/source/os/CMakeLists.txt @@ -10,7 +10,11 @@ target_include_directories( PUBLIC "${TD_SOURCE_DIR}/contrib/msvcregex" ) # iconv -find_path(IconvApiIncludes iconv.h PATHS) +if(TD_WINDOWS) + find_path(IconvApiIncludes iconv.h "${TD_SOURCE_DIR}/contrib/iconv") +else() + find_path(IconvApiIncludes iconv.h PATHS) +endif(TD_WINDOWS) if(NOT IconvApiIncludes) add_definitions(-DDISALLOW_NCHAR_WITHOUT_ICONV) endif () diff --git a/source/util/src/terror.c b/source/util/src/terror.c index 575ae10bbb..c1f5c92be7 100644 --- a/source/util/src/terror.c +++ b/source/util/src/terror.c @@ -186,9 +186,9 @@ TAOS_DEFINE_ERROR(TSDB_CODE_MND_SNODE_ALREADY_EXIST, "Snode already exists" TAOS_DEFINE_ERROR(TSDB_CODE_MND_SNODE_NOT_EXIST, "Snode not there") TAOS_DEFINE_ERROR(TSDB_CODE_MND_BNODE_ALREADY_EXIST, "Bnode already exists") TAOS_DEFINE_ERROR(TSDB_CODE_MND_BNODE_NOT_EXIST, "Bnode not there") -TAOS_DEFINE_ERROR(TSDB_CODE_MND_TOO_FEW_MNODES, "Too few mnodes") -TAOS_DEFINE_ERROR(TSDB_CODE_MND_MNODE_DEPLOYED, "Mnode deployed in this dnode") -TAOS_DEFINE_ERROR(TSDB_CODE_MND_CANT_DROP_MASTER, "Can't drop mnode which is master") +TAOS_DEFINE_ERROR(TSDB_CODE_MND_TOO_FEW_MNODES, "The replicas of mnode cannot less than 1") +TAOS_DEFINE_ERROR(TSDB_CODE_MND_TOO_MANY_MNODES, "The replicas of mnode cannot exceed 3") +TAOS_DEFINE_ERROR(TSDB_CODE_MND_CANT_DROP_MASTER, "Can't drop mnode which is LEADER") // mnode-acct TAOS_DEFINE_ERROR(TSDB_CODE_MND_ACCT_ALREADY_EXIST, "Account already exists") diff --git a/tests/script/jenkins/basic.txt b/tests/script/jenkins/basic.txt index ca0db9e32a..12b678eeae 100644 --- a/tests/script/jenkins/basic.txt +++ b/tests/script/jenkins/basic.txt @@ -57,7 +57,6 @@ # ---- mnode ./test.sh -f tsim/mnode/basic1.sim ./test.sh -f tsim/mnode/basic2.sim -./test.sh -f tsim/mnode/basic3.sim # ---- show ./test.sh -f tsim/show/basic.sim diff --git a/tests/script/tsim/mnode/basic3.sim b/tests/script/tsim/mnode/basic3.sim index b0ee23cd8c..3c69e6ed51 100644 --- a/tests/script/tsim/mnode/basic3.sim +++ b/tests/script/tsim/mnode/basic3.sim @@ -2,14 +2,17 @@ system sh/stop_dnodes.sh system sh/deploy.sh -n dnode1 -i 1 system sh/deploy.sh -n dnode2 -i 2 system sh/deploy.sh -n dnode3 -i 3 +system sh/deploy.sh -n dnode4 -i 4 system sh/exec.sh -n dnode1 -s start system sh/exec.sh -n dnode2 -s start system sh/exec.sh -n dnode3 -s start +system sh/exec.sh -n dnode4 -s start sql connect print =============== step1: create dnodes sql create dnode $hostname port 7200 sql create dnode $hostname port 7300 +sql create dnode $hostname port 7400 $x = 0 step1: @@ -32,6 +35,7 @@ endi print =============== step2: create mnode 2 sql create mnode on dnode 2 sql create mnode on dnode 3 +sql_error create mnode on dnode 4 $x = 0 step2: @@ -106,6 +110,10 @@ print $data(1)[0] $data(1)[1] $data(1)[2] print $data(2)[0] $data(2)[1] $data(2)[2] print $data(3)[0] $data(3)[1] $data(3)[2] +if $data(2)[2] != OFFLINE then + goto step5 +endi + sql show users if $rows != 2 then return -1 @@ -134,4 +142,5 @@ endi system sh/exec.sh -n dnode1 -s stop system sh/exec.sh -n dnode2 -s stop -system sh/exec.sh -n dnode3 -s stop \ No newline at end of file +system sh/exec.sh -n dnode3 -s stop +system sh/exec.sh -n dnode4 -s stop \ No newline at end of file diff --git a/tests/script/tsim/trans/create_db.sim b/tests/script/tsim/trans/create_db.sim index ae6b7eab16..158a6b9f92 100644 --- a/tests/script/tsim/trans/create_db.sim +++ b/tests/script/tsim/trans/create_db.sim @@ -76,14 +76,6 @@ if $data[0][3] != d1 then return -1 endi -if $data[0][4] != create-db then - return -1 -endi - -if $data[0][7] != @Unable to establish connection@ then - return -1 -endi - sql_error create database d1 vgroups 2; print =============== start dnode2 @@ -125,15 +117,7 @@ endi if $data[0][3] != d2 then return -1 endi - -if $data[0][4] != create-db then - return -1 -endi - -if $data[0][7] != @Unable to establish connection@ then - return -1 -endi - +return sql_error create database d2 vgroups 2; print =============== kill transaction diff --git a/tests/test/c/sdbDump.c b/tests/test/c/sdbDump.c index 3b3a9fc85e..1781dd3183 100644 --- a/tests/test/c/sdbDump.c +++ b/tests/test/c/sdbDump.c @@ -279,9 +279,9 @@ void dumpTrans(SSdb *pSdb, SJson *json) { tjsonAddIntegerToObject(item, "id", pObj->id); tjsonAddIntegerToObject(item, "stage", pObj->stage); tjsonAddIntegerToObject(item, "policy", pObj->policy); - tjsonAddIntegerToObject(item, "type", pObj->type); + tjsonAddIntegerToObject(item, "conflict", pObj->conflict); + tjsonAddIntegerToObject(item, "exec", pObj->exec); tjsonAddStringToObject(item, "createdTime", i642str(pObj->createdTime)); - tjsonAddStringToObject(item, "dbUid", i642str(pObj->dbUid)); tjsonAddStringToObject(item, "dbname", pObj->dbname); tjsonAddIntegerToObject(item, "commitLogNum", taosArrayGetSize(pObj->commitActions)); tjsonAddIntegerToObject(item, "redoActionNum", taosArrayGetSize(pObj->redoActions)); diff --git a/tools/taos-tools b/tools/taos-tools index 4d83d8c629..717f5aaa5f 160000 --- a/tools/taos-tools +++ b/tools/taos-tools @@ -1 +1 @@ -Subproject commit 4d83d8c62973506f760bcaa3a33f4665ed9046d0 +Subproject commit 717f5aaa5f0a1b4d92bb2ae68858fec554fb5eda