diff --git a/documentation20/cn/12.taos-sql/docs.md b/documentation20/cn/12.taos-sql/docs.md
index 9edfe172c26fa5b0a4cb84f950ef7a6697dbf417..c22b20914a26c5e9503dbd6fcd4abf6b6fb67e54 100755
--- a/documentation20/cn/12.taos-sql/docs.md
+++ b/documentation20/cn/12.taos-sql/docs.md
@@ -1083,7 +1083,71 @@ TDengine支持针对数据的聚合查询。提供支持的聚合和选择函数
{slop:1.000000, intercept:9.733334} |
Query OK, 1 row(s) in set (0.000921s)
```
+
+- **MODE**
+ ```mysql
+ SELECT MODE(field_name) FROM tb_name [WHERE clause];
+ ```
+ 功能说明:返回出现频率最高的值,若存在多个频率相同的最高值,输出空。不能匹配标签、时间戳输出。
+
+ 返回结果数据类型:同应用的字段。
+
+ 应用字段:适合于除时间主列外的任何类型字段。
+ 适用于:**表**。
+
+ 示例:
+ ```mysql
+ 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**
+ ```mysql
+ SELECT HYPERLOGLOG(field_name) FROM { tb_name | stb_name } [WHERE clause];
+ ```
+ 功能说明:采用hyperloglog算法,返回某列的基数。该算法在数据量很大的情况下,可以明显降低内存的占用,但是求出来的基数是个估算值,标准误差为0.81%。
+
+ 返回结果类型:整形。
+
+ 适用数据类型:适合于任何类型字段。
+
+ 支持的版本:2.6.0.x 之后的版本。
+
+ 示例:
+ ```mysql
+ 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)
+ ```
+
### 选择函数
在使用所有的选择函数的时候,可以同时指定输出 ts 列或标签列(包括 tbname),这样就可以方便地知道被选出的值是源于哪个数据行的。
@@ -1482,6 +1546,84 @@ TDengine支持针对数据的聚合查询。提供支持的聚合和选择函数
Query OK, 2 row(s) in set (0.003487s)
```
+- **TAIL**
+ ```mysql
+ SELECT TAIL(field_name, k, offset_val) FROM {tb_name | stb_name} [WHERE clause];
+ ```
+ 功能说明:返回跳过最后 offset_value个,然后取连续 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.x 之后的版本。
+
+ 示例:
+ ```mysql
+ 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**
+ ```mysql
+ SELECT UNIQUE(field_name) FROM {tb_name | stb_name} [WHERE clause];
+ ```
+ 功能说明:返回该列的数值首次出现的值。该函数功能与 distinct 相似,但是可以匹配标签和时间戳信息。可以针对除时间列以外的字段进行查询,可以匹配标签和时间戳,其中的标签和时间戳是第一次出现时刻的标签和时间戳。
+
+ 返回结果数据类型:同应用的字段。
+
+ 应用字段:适合于除时间类型以外的字段。
+
+ 适用于:**表、超级表**。
+
+ 支持版本:2.6.0.x 之后的版本。
+
+ 说明:该函数可以应用在普通表和超级表上。不能和窗口操作一起使用,例如 interval/state_window/session_window 。
+
+ 示例:
+ ```mysql
+ 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**
@@ -1623,6 +1765,106 @@ TDengine支持针对数据的聚合查询。提供支持的聚合和选择函数
80.810000718 |
Query OK, 3 row(s) in set (0.001046s)
```
+
+- **STATECOUNT**
+ ```mysql
+ 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.0.x 之后的版本。
+
+ 说明:
+
+ - 该函数可以应用在普通表上,在由 GROUP BY 划分出单独时间线的情况下用于超级表(也即 GROUP BY tbname)
+
+ - 不能和窗口操作一起使用,例如interval/state_window/session_window。
+
+ 示例:
+ ```mysql
+ 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**
+ ```mysql
+ 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 类型字段上。
+
+ 嵌套子查询支持:不支持应用在子查询上。
+
+ 支持的版本:2.6.0.x 之后的版本。
+
+ 说明:
+
+ - 该函数可以应用在普通表上,在由 GROUP BY 划分出单独时间线的情况下用于超级表(也即 GROUP BY tbname)
+
+ - 不能和窗口操作一起使用,例如interval/state_window/session_window。
+
+ 示例:
+ ```mysql
+ 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)
+ ```
+
### 时间函数
- **NOW**
diff --git a/documentation20/en/12.taos-sql/docs.md b/documentation20/en/12.taos-sql/docs.md
index cbd2d77a507e0d55f1d870423d517cd1b79aac10..9a68e071782bce8ac17768c01a4d7d0823538598 100755
--- a/documentation20/en/12.taos-sql/docs.md
+++ b/documentation20/en/12.taos-sql/docs.md
@@ -852,6 +852,69 @@ TDengine supports aggregations over data, they are listed below:
Query OK, 1 row(s) in set (0.000921s)
```
+- **MODE**
+ ```mysql
+ SELECT MODE(field_name) FROM tb_name [WHERE clause];
+ ```
+ Function: Returns the value with the highest frequency. If there are multiple highest values with the same frequency, the output is NULL.
+
+ Return Data Type: Same as applicable fields.
+
+ Applicable Fields: All types except timestamp.
+
+ Supported version: Version after 2.6.0 .
+
+ Example:
+ ```mysql
+ 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**
+ ```mysql
+ SELECT HYPERLOGLOG(field_name) FROM { tb_name | stb_name } [WHERE clause];
+ ```
+ Function: The hyperloglog algorithm is used to return the cardinality of a column. In the case of large amount of data, the algorithm can significantly reduce the occupation of memory, but the cardinality is an estimated value, and the standard error is 0.81%.
+
+ Return Data Type:Integer.
+
+ Applicable Fields: All types.
+
+ Supported version: Version after 2.6.0 .
+
+ Example:
+ ```mysql
+ 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)
+
### Selector Functions
- **MIN**
@@ -1102,6 +1165,83 @@ TDengine supports aggregations over data, they are listed below:
Query OK, 1 row(s) in set (0.001042s)
```
+- **TAIL**
+ ```mysql
+ SELECT TAIL(field_name, k, offset_val) FROM {tb_name | stb_name} [WHERE clause];
+ ```
+ Function: Skip the last num of offset_value, return the k consecutive records without ignoring NULL value. offset_val can be empty, then the last K records are returned.The function is equivalent to:order by ts desc LIMIT k OFFSET offset_val.
+
+ Range:k: [1,100] offset_val: [0,100]。
+
+ Return Data Type: Same as applicable fields.
+
+ Applicable Fields: All types except timestamp.
+
+ Applied to: **table stable**.
+
+ Supported version: Version after 2.6.0 .
+
+ Example:
+ ```mysql
+ 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**
+ ```mysql
+ SELECT UNIQUE(field_name) FROM {tb_name | stb_name} [WHERE clause];
+ ```
+ Function: Returns the first occurrence of a value in this column.
+
+ Return Data Type: Same as applicable fields.
+
+ Applicable Fields: All types except timestamp.
+
+ Applied to: **table stable**.
+
+ Supported version: Version after 2.6.0 .
+
+ Note: This function can be applied to ordinary tables and super tables. Cannot be used with window operations,such as interval/state_window/session_window.
+
+ Example:
+ ```mysql
+ 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)
+
### Computing Functions
- **DIFF**
@@ -1172,6 +1312,97 @@ TDengine supports aggregations over data, they are listed below:
1. Calculation between two or more columns is supported, and the calculation priorities can be controlled by parentheses();
2. The NULL field does not participate in the calculation. If a row involved in calculation contains NULL, the calculation result of the row is NULL.
+- **STATECOUNT**
+ ```mysql
+ SELECT STATECOUNT(field_name, oper, val) FROM { tb_name | stb_name } [WHERE clause];
+ ```
+ Function: Returns the number of consecutive records that meet a certain condition, and the result is appended to each row as a new column. The condition is calculated according to the parameters. If the condition is true, it will be increased by 1. If the condition is false, it will be reset to -1. If the data is NULL, the data will be skipped.
+
+ Range:
+ - oper : LT(<),GT(>),LE(<=),GE(>=),NE(!=),EQ(=),case insensitive.
+ - val : Number.
+
+ Returned Data Type: Integer。
+
+ Applicable Fields: All types except timestamp, binary, nchar, bool.
+
+ Supported version: Version after 2.6.0 .
+
+ Note:
+ - This function can be applied to ordinary tables. When a separate timeline is divided by group by, it is used for super tables (i.e. group by TBNAME).
+ - Cannot be used with window operations,such as interval/state_window/session_window.
+
+ Example:
+ ```mysql
+ 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**
+ ```mysql
+ SELECT stateDuration(field_name, oper, val, unit) FROM { tb_name | stb_name } [WHERE clause];
+ ```
+ Function: Returns the length of time of continuous records that meet a certain condition, and the result is appended to each row as a new column. The condition is calculated according to the parameters. If the condition is true, the length of time between two records will be added (the length of time of the first record that meets the condition is recorded as 0). If the condition is false, it will be reset to -1. If the data is NULL, the data will be skipped.
+
+ Range:
+ - oper : LT(<),GT(>),LE(<=),GE(>=),NE(!=),EQ(=),case insensitive.
+ - val : Number.
+ - unit : Unit of time length, range [1s, 1M, 1H], less than one unit is rounded off. The default is 1s.
+
+ Returned Data Type: Integer。
+
+ Applicable Fields: All types except timestamp, binary, nchar, bool.
+
+ Supported version: Version after 2.6.0 .
+
+ Note:
+ - This function can be applied to ordinary tables. When a separate timeline is divided by group by, it is used for super tables (i.e. group by TBNAME).
+ - Cannot be used with window operations,such as interval/state_window/session_window.
+
+ Example:
+ ```mysql
+ 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)
+ ```
+
## Time-dimension Aggregation
TDengine supports aggregating by intervals (time range). Data in a table can partitioned by intervals and aggregated to generate results. For example, a temperature sensor collects data once per second, but the average temperature needs to be queried every 10 minutes. This aggregation is suitable for down sample operation, and the syntax is as follows:
diff --git a/src/client/jni/com_taosdata_jdbc_TSDBJNIConnector.h b/src/client/jni/com_taosdata_jdbc_TSDBJNIConnector.h
index 4c999b710a62d1e620064af4d5647ee46d9a570e..6b987141996d3c9a0bf78e162f1c11b758008536 100644
--- a/src/client/jni/com_taosdata_jdbc_TSDBJNIConnector.h
+++ b/src/client/jni/com_taosdata_jdbc_TSDBJNIConnector.h
@@ -11,257 +11,254 @@ extern "C" {
#define com_taosdata_jdbc_TSDBJNIConnector_INVALID_CONNECTION_POINTER_VALUE 0LL
/*
* Class: com_taosdata_jdbc_TSDBJNIConnector
- * Method:
+ * Method:
* Signature: (Ljava/lang/String;)V
*/
-JNIEXPORT void JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setAllocModeImp
- (JNIEnv *, jclass, jint, jstring, jboolean);
+JNIEXPORT void JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setAllocModeImp(JNIEnv *, jclass, jint, jstring,
+ jboolean);
/*
* Class: com_taosdata_jdbc_TSDBJNIConnector
- * Method:
+ * Method:
* Signature: ()Ljava/lang/String;
*/
-JNIEXPORT void JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_dumpMemoryLeakImp
- (JNIEnv *, jclass);
+JNIEXPORT void JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_dumpMemoryLeakImp(JNIEnv *, jclass);
/*
* Class: com_taosdata_jdbc_TSDBJNIConnector
* Method: initImp
* Signature: (Ljava/lang/String;)V
*/
-JNIEXPORT void JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_initImp
- (JNIEnv *, jclass, jstring);
+JNIEXPORT void JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_initImp(JNIEnv *, jclass, jstring);
/*
* Class: com_taosdata_jdbc_TSDBJNIConnector
* Method: setOptions
* Signature: (ILjava/lang/String;)I
*/
-JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setOptions
- (JNIEnv *, jclass, jint, jstring);
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setOptions(JNIEnv *, jclass, jint, jstring);
/*
* Class: com_taosdata_jdbc_TSDBJNIConnector
* Method: setConfigImp
* Signature: (Ljava/lang/String;)Lcom/taosdata/jdbc/TSDBException;
*/
-JNIEXPORT jobject JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setConfigImp
- (JNIEnv *, jclass, jstring);
+JNIEXPORT jobject JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setConfigImp(JNIEnv *, jclass, jstring);
/*
* Class: com_taosdata_jdbc_TSDBJNIConnector
* Method: getTsCharset
* Signature: ()Ljava/lang/String;
*/
-JNIEXPORT jstring JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getTsCharset
- (JNIEnv *, jclass);
+JNIEXPORT jstring JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getTsCharset(JNIEnv *, jclass);
/*
* Class: com_taosdata_jdbc_TSDBJNIConnector
* Method: getResultTimePrecisionImp
* Signature: (JJ)I
*/
-JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TDDBJNIConnector_getResultTimePrecisionImp
- (JNIEnv *, jobject, jlong, jlong);
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TDDBJNIConnector_getResultTimePrecisionImp(JNIEnv *, jobject, jlong,
+ jlong);
/*
* Class: com_taosdata_jdbc_TSDBJNIConnector
* Method: connectImp
* Signature: (Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)J
*/
-JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_connectImp
- (JNIEnv *, jobject, jstring, jint, jstring, jstring, jstring);
+JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_connectImp(JNIEnv *, jobject, jstring, jint, jstring,
+ jstring, jstring);
/*
* Class: com_taosdata_jdbc_TSDBJNIConnector
* Method: executeQueryImp
* Signature: ([BJ)I
*/
-JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_executeQueryImp
- (JNIEnv *, jobject, jbyteArray, jlong);
+JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_executeQueryImp(JNIEnv *, jobject, jbyteArray, jlong);
/*
* Class: com_taosdata_jdbc_TSDBJNIConnector
* Method: getErrCodeImp
* Signature: (J)I
*/
-JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getErrCodeImp
- (JNIEnv *, jobject, jlong, jlong);
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getErrCodeImp(JNIEnv *, jobject, jlong, jlong);
/*
* Class: com_taosdata_jdbc_TSDBJNIConnector
* Method: getErrMsgImp
* Signature: (J)Ljava/lang/String;
*/
-JNIEXPORT jstring JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getErrMsgImp
- (JNIEnv *, jobject, jlong);
+JNIEXPORT jstring JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getErrMsgImp(JNIEnv *, jobject, jlong);
/*
* Class: com_taosdata_jdbc_TSDBJNIConnector
* Method: getResultSetImp
* Signature: (J)J
*/
-JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getResultSetImp
- (JNIEnv *env, jobject jobj, jlong con, jlong tres);
+JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getResultSetImp(JNIEnv *env, jobject jobj, jlong con,
+ jlong tres);
/*
* Class: com_taosdata_jdbc_TSDBJNIConnector
* Method: isUpdateQueryImp
* Signature: (JJ)I
*/
-JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_isUpdateQueryImp
- (JNIEnv *env, jobject jobj, jlong con, jlong tres);
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_isUpdateQueryImp(JNIEnv *env, jobject jobj, jlong con,
+ jlong tres);
/*
* Class: com_taosdata_jdbc_TSDBJNIConnector
* Method: freeResultSetImp
* Signature: (JJ)I
*/
-JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_freeResultSetImp
- (JNIEnv *, jobject, jlong, jlong);
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_freeResultSetImp(JNIEnv *, jobject, jlong, jlong);
/*
* Class: com_taosdata_jdbc_TSDBJNIConnector
* Method: getAffectedRowsImp
* Signature: (J)I
*/
-JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getAffectedRowsImp
- (JNIEnv *env, jobject jobj, jlong con, jlong res);
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getAffectedRowsImp(JNIEnv *env, jobject jobj, jlong con,
+ jlong res);
/*
* Class: com_taosdata_jdbc_TSDBJNIConnector
* Method: getSchemaMetaDataImp
* Signature: (JJLjava/util/List;)I
*/
-JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getSchemaMetaDataImp
- (JNIEnv *, jobject, jlong, jlong, jobject);
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getSchemaMetaDataImp(JNIEnv *, jobject, jlong, jlong,
+ jobject);
/*
* Class: com_taosdata_jdbc_TSDBJNIConnector
* Method: fetchRowImp
* Signature: (JJLcom/taosdata/jdbc/TSDBResultSetRowData;)I
*/
-JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_fetchRowImp
- (JNIEnv *, jobject, jlong, jlong, jobject);
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_fetchRowImp(JNIEnv *, jobject, jlong, jlong, jobject);
/*
* Class: com_taosdata_jdbc_TSDBJNIConnector
* Method: fetchBlockImp
* Signature: (JJLcom/taosdata/jdbc/TSDBResultSetBlockData;)I
*/
-JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_fetchBlockImp
- (JNIEnv *, jobject, jlong, jlong, jobject);
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_fetchBlockImp(JNIEnv *, jobject, jlong, jlong, jobject);
/*
* Class: com_taosdata_jdbc_TSDBJNIConnector
* Method: closeConnectionImp
* Signature: (J)I
*/
-JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_closeConnectionImp
- (JNIEnv *, jobject, jlong);
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_closeConnectionImp(JNIEnv *, jobject, jlong);
/*
* Class: com_taosdata_jdbc_TSDBJNIConnector
* Method: subscribeImp
* Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;JI)J
*/
-JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_subscribeImp
- (JNIEnv *, jobject, jlong, jboolean, jstring, jstring, jint);
+JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_subscribeImp(JNIEnv *, jobject, jlong, jboolean,
+ jstring, jstring, jint);
/*
* Class: com_taosdata_jdbc_TSDBJNIConnector
* Method: consumeImp
* Signature: (J)Lcom/taosdata/jdbc/TSDBResultSetRowData;
*/
-JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_consumeImp
- (JNIEnv *, jobject, jlong);
+JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_consumeImp(JNIEnv *, jobject, jlong);
/*
* Class: com_taosdata_jdbc_TSDBJNIConnector
* Method: unsubscribeImp
* Signature: (J)V
*/
-JNIEXPORT void JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_unsubscribeImp
- (JNIEnv *, jobject, jlong, jboolean);
+JNIEXPORT void JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_unsubscribeImp(JNIEnv *, jobject, jlong, jboolean);
/*
* Class: com_taosdata_jdbc_TSDBJNIConnector
* Method: validateCreateTableSqlImp
* Signature: (J[B)I
*/
-JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_validateCreateTableSqlImp
- (JNIEnv *, jobject, jlong, jbyteArray);
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_validateCreateTableSqlImp(JNIEnv *, jobject, jlong,
+ jbyteArray);
/*
* Class: com_taosdata_jdbc_TSDBJNIConnector
* Method: prepareStmtImp
* Signature: ([BJ)I
*/
-JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_prepareStmtImp
- (JNIEnv *, jobject, jbyteArray, jlong);
+JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_prepareStmtImp(JNIEnv *, jobject, jbyteArray, jlong);
/*
* Class: com_taosdata_jdbc_TSDBJNIConnector
* Method: setBindTableNameImp
* Signature: (JLjava/lang/String;J)I
*/
-JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setBindTableNameImp
- (JNIEnv *, jobject, jlong, jstring, jlong);
-
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setBindTableNameImp(JNIEnv *, jobject, jlong, jstring,
+ jlong);
/**
* Class: com_taosdata_jdbc_TSDBJNIConnector
* Method: setTableNameTagsImp
* Signature: (JLjava/lang/String;I[B[B[B[BJ)I
*/
-JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setTableNameTagsImp
- (JNIEnv *, jobject, jlong, jstring, jint, jbyteArray, jbyteArray, jbyteArray, jbyteArray, jlong);
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setTableNameTagsImp(JNIEnv *, jobject, jlong, jstring,
+ jint, jbyteArray, jbyteArray,
+ jbyteArray, jbyteArray, jlong);
/*
* Class: com_taosdata_jdbc_TSDBJNIConnector
* Method: bindColDataImp
* Signature: (J[B[B[BIIIIJ)J
*/
-JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_bindColDataImp
-(JNIEnv *, jobject, jlong, jbyteArray, jbyteArray, jbyteArray, jint, jint, jint, jint, jlong);
+JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_bindColDataImp(JNIEnv *, jobject, jlong, jbyteArray,
+ jbyteArray, jbyteArray, jint, jint, jint,
+ jint, jlong);
/*
* Class: com_taosdata_jdbc_TSDBJNIConnector
* Method: stmt_add_batch
* Signature: (JJ)I
*/
-JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_addBatchImp(JNIEnv *env, jobject jobj, jlong stmt, jlong con);
-
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_addBatchImp(JNIEnv *env, jobject jobj, jlong stmt,
+ jlong con);
/*
* Class: com_taosdata_jdbc_TSDBJNIConnector
* Method: executeBatchImp
* Signature: (JJ)I
*/
-JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_executeBatchImp(JNIEnv *env, jobject jobj, jlong stmt, jlong con);
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_executeBatchImp(JNIEnv *env, jobject jobj, jlong stmt,
+ jlong con);
/*
* Class: com_taosdata_jdbc_TSDBJNIConnector
* Method: closeStmt
* Signature: (JJ)I
*/
-JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_closeStmt(JNIEnv *env, jobject jobj, jlong stmt, jlong con);
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_closeStmt(JNIEnv *env, jobject jobj, jlong stmt,
+ jlong con);
/*
* Class: com_taosdata_jdbc_TSDBJNIConnector
* Method: stmt_errstr
* Signature: (JJ)I
*/
-JNIEXPORT jstring JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_stmtErrorMsgImp(JNIEnv *env, jobject jobj, jlong stmt, jlong con);
+JNIEXPORT jstring JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_stmtErrorMsgImp(JNIEnv *env, jobject jobj, jlong stmt,
+ jlong con);
/*
* Class: com_taosdata_jdbc_TSDBJNIConnector
* Method: insertLinesImp
* Signature: ([Ljava/lang/String;JII)I
*/
-JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_insertLinesImp
- (JNIEnv *, jobject, jobjectArray, jlong, jint, jint);
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_insertLinesImp(JNIEnv *, jobject, jobjectArray, jlong,
+ jint, jint);
+
+/*
+ * Class: com_taosdata_jdbc_TSDBJNIConnector
+ * Method: schemalessInsertImp
+ * Signature: (J[B[B[BIIIIJ)J
+ */
+JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_schemalessInsertImp(JNIEnv *, jobject, jobjectArray,
+ jlong, jint, jint);
#ifdef __cplusplus
}
diff --git a/src/client/src/TSDBJNIConnector.c b/src/client/src/TSDBJNIConnector.c
index 67a08fa4fac39e2497a3cc0447b73f2a93d0c4ee..49c7008947894eb3506893ae272512f73e7fb295 100644
--- a/src/client/src/TSDBJNIConnector.c
+++ b/src/client/src/TSDBJNIConnector.c
@@ -945,7 +945,7 @@ JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_bindColDataImp(
}
JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_addBatchImp(JNIEnv *env, jobject jobj, jlong stmt,
- jlong con) {
+ jlong con) {
TAOS *tscon = (TAOS *)con;
if (tscon == NULL) {
jniError("jobj:%p, connection already closed", jobj);
@@ -1017,7 +1017,7 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_closeStmt(JNIEnv
}
JNIEXPORT jstring JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_stmtErrorMsgImp(JNIEnv *env, jobject jobj, jlong stmt,
- jlong con) {
+ jlong con) {
char errMsg[128];
TAOS *tscon = (TAOS *)con;
if (tscon == NULL) {
@@ -1036,20 +1036,12 @@ JNIEXPORT jstring JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_stmtErrorMsgIm
return (*env)->NewStringUTF(env, taos_stmt_errstr((TAOS_STMT *)stmt));
}
-JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_insertLinesImp(JNIEnv *env, jobject jobj,
- jobjectArray lines, jlong conn,
- jint protocol, jint precision) {
- TAOS *taos = (TAOS *)conn;
- if (taos == NULL) {
- jniError("jobj:%p, connection already closed", jobj);
- return JNI_CONNECTION_NULL;
- }
-
+SSqlObj *schemalessInsert(JNIEnv *env, jobject jobj, jobjectArray lines, TAOS *taos, jint protocol, jint precision) {
int numLines = (*env)->GetArrayLength(env, lines);
char **c_lines = calloc(numLines, sizeof(char *));
if (c_lines == NULL) {
jniError("c_lines:%p, alloc memory failed", c_lines);
- return JNI_OUT_OF_MEMORY;
+ return NULL;
}
for (int i = 0; i < numLines; ++i) {
jstring line = (jstring)((*env)->GetObjectArrayElement(env, lines, i));
@@ -1057,7 +1049,6 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_insertLinesImp(JN
}
SSqlObj *result = (SSqlObj *)taos_schemaless_insert(taos, c_lines, numLines, protocol, precision);
- int code = taos_errno(result);
for (int i = 0; i < numLines; ++i) {
jstring line = (jstring)((*env)->GetObjectArrayElement(env, lines, i));
@@ -1065,6 +1056,24 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_insertLinesImp(JN
}
tfree(c_lines);
+ return result;
+}
+
+JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_insertLinesImp(JNIEnv *env, jobject jobj,
+ jobjectArray lines, jlong conn,
+ jint protocol, jint precision) {
+ TAOS *taos = (TAOS *)conn;
+ if (taos == NULL) {
+ jniError("jobj:%p, connection already closed", jobj);
+ return JNI_CONNECTION_NULL;
+ }
+
+ SSqlObj *result = (SSqlObj *)schemalessInsert(env, jobj, lines, taos, protocol, precision);
+
+ if (result == NULL) {
+ return JNI_OUT_OF_MEMORY;
+ }
+ int code = taos_errno(result);
if (code != TSDB_CODE_SUCCESS) {
jniError("jobj:%p, conn:%p, code:%s, msg:%s", jobj, taos, tstrerror(code), taos_errstr(result));
taos_free_result((void *)result);
@@ -1074,3 +1083,19 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_insertLinesImp(JN
return JNI_SUCCESS;
}
+
+JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_schemalessInsertImp(JNIEnv *env, jobject jobj,
+ jobjectArray lines, jlong conn,
+ jint protocol, jint precision) {
+ TAOS *taos = (TAOS *)conn;
+ if (taos == NULL) {
+ jniError("jobj:%p, connection already closed", jobj);
+ return JNI_CONNECTION_NULL;
+ }
+
+ SSqlObj *result = schemalessInsert(env, jobj, lines, taos, protocol, precision);
+ if (result == NULL) {
+ return JNI_OUT_OF_MEMORY;
+ }
+ return (jlong)result;
+}
\ No newline at end of file
diff --git a/src/client/src/tscParseLineProtocol.c b/src/client/src/tscParseLineProtocol.c
index 5d1173e8cf3859403c765a514c07120cb0f18ba7..e45c1bc956a9c55c316141423c81c726df696b39 100644
--- a/src/client/src/tscParseLineProtocol.c
+++ b/src/client/src/tscParseLineProtocol.c
@@ -2140,64 +2140,331 @@ static int32_t parseSmlKey(TAOS_SML_KV *pKV, const char **index, SHashObj *pHash
static int32_t parseSmlValue(TAOS_SML_KV *pKV, const char **index,
bool *is_last_kv, SSmlLinesInfo* info, bool isTag) {
- const char *start, *cur, *tmp;
- int32_t ret = TSDB_CODE_SUCCESS;
- char *value = NULL;
- int16_t len = 0;
- bool searchQuote = false;
- start = cur = *index;
+ const char *start, *cur;
+ int32_t ret = TSDB_CODE_SUCCESS;
+ char *value = NULL;
+ int16_t len = 0;
+
+ bool kv_done = false;
+ bool back_slash = false;
+ bool double_quote = false;
+ size_t line_len = 0;
+
+ enum {
+ tag_common,
+ tag_lqoute,
+ tag_rqoute
+ } tag_state;
+
+ enum {
+ val_common,
+ val_lqoute,
+ val_rqoute
+ } val_state;
- //if field value is string
- if (!isTag) {
- if (*cur == '"') {
- searchQuote = true;
- cur += 1;
- len += 1;
- } else if (*cur == 'L' && *(cur + 1) == '"') {
- searchQuote = true;
- cur += 2;
- len += 2;
- }
- }
+ start = cur = *index;
+ tag_state = tag_common;
+ val_state = val_common;
while (1) {
- // unescaped ',' or ' ' or '\0' identifies a value
- if (((*cur == ',' || *cur == ' ' ) && *(cur - 1) != '\\') || *cur == '\0') {
- if (searchQuote == true) {
- //first quote ignored while searching
- if (*(cur - 1) == '"' && len != 1 && len != 2) {
- *is_last_kv = (*cur == ' ' || *cur == '\0') ? true : false;
+ if (isTag) {
+ /* ',', '=' and spaces MUST be escaped */
+ switch (tag_state) {
+ case tag_common:
+ if (back_slash == true) {
+ if (*cur != ',' && *cur != '=' && *cur != ' ') {
+ tscError("SML:0x%"PRIx64" tag value: state(%d), incorrect character(%c) escaped", info->id, tag_state, *cur);
+ ret = TSDB_CODE_TSC_LINE_SYNTAX_ERROR;
+ goto error;
+ }
+
+ back_slash = false;
+ cur++;
+ len++;
+ break;
+ }
+
+ if (*cur == '"') {
+ if (cur == *index) {
+ tag_state = tag_lqoute;
+ }
+ cur += 1;
+ len += 1;
+ break;
+ } else if (*cur == 'L') {
+ line_len = strlen(*index);
+
+ /* common character at the end */
+ if (cur + 1 >= *index + line_len) {
+ *is_last_kv = true;
+ kv_done = true;
+ break;
+ }
+
+ if (*(cur + 1) == '"') {
+ /* string starts here */
+ if (cur + 1 == *index + 1) {
+ tag_state = tag_lqoute;
+ }
+ cur += 2;
+ len += 2;
+ break;
+ }
+ }
+
+ switch (*cur) {
+ case '\\':
+ back_slash = true;
+ cur++;
+ len++;
+ break;
+ case ',':
+ kv_done = true;
+ break;
+
+ case ' ':
+ /* fall through */
+ case '\0':
+ *is_last_kv = true;
+ kv_done = true;
break;
- } else if (*cur == '\0') {
+
+ default:
+ cur++;
+ len++;
+ }
+
+ break;
+ case tag_lqoute:
+ if (back_slash == true) {
+ if (*cur != ',' && *cur != '=' && *cur != ' ') {
+ tscError("SML:0x%"PRIx64" tag value: state(%d), incorrect character(%c) escaped", info->id, tag_state, *cur);
+ ret = TSDB_CODE_TSC_LINE_SYNTAX_ERROR;
+ goto error;
+ }
+
+ back_slash = false;
+ cur++;
+ len++;
+ break;
+ } else if (double_quote == true) {
+ if (*cur != ' ' && *cur != ',' && *cur != '\0') {
+ tscError("SML:0x%"PRIx64" tag value: state(%d), incorrect character(%c) behind closing \"", info->id, tag_state, *cur);
+ ret = TSDB_CODE_TSC_LINE_SYNTAX_ERROR;
+ goto error;
+ }
+
+ if (*cur == ' ' || *cur == '\0') {
+ *is_last_kv = true;
+ }
+
+ double_quote = false;
+ tag_state = tag_rqoute;
+ break;
+ }
+
+ switch (*cur) {
+ case '\\':
+ back_slash = true;
+ cur++;
+ len++;
+ break;
+
+ case '"':
+ double_quote = true;
+ cur++;
+ len++;
+ break;
+
+ case ',':
+ /* fall through */
+ case '=':
+ /* fall through */
+ case ' ':
+ if (*(cur - 1) != '\\') {
+ tscError("SML:0x%"PRIx64" tag value: state(%d), character(%c) not escaped", info->id, tag_state, *cur);
+ ret = TSDB_CODE_TSC_LINE_SYNTAX_ERROR;
+ kv_done = true;
+ }
+ break;
+
+ case '\0':
+ tscError("SML:0x%"PRIx64" tag value: state(%d), closing \" not found", info->id, tag_state);
ret = TSDB_CODE_TSC_LINE_SYNTAX_ERROR;
- goto error;
- } else {
+ kv_done = true;
+ break;
+
+ default:
cur++;
len++;
- continue;
}
+
+ break;
+
+ default:
+ kv_done = true;
}
- //unescaped ' ' or '\0' indicates end of value
- *is_last_kv = (*cur == ' ' || *cur == '\0') ? true : false;
- if (*cur == ' ' && *(cur + 1) == ' ') {
- cur++;
- continue;
- } else {
+ } else {
+ switch (val_state) {
+ case val_common:
+ if (back_slash == true) {
+ if (*cur != '\\' && *cur != '"') {
+ tscError("SML:0x%"PRIx64" field value: state(%d), incorrect character(%c) escaped", info->id, val_state, *cur);
+ ret = TSDB_CODE_TSC_LINE_SYNTAX_ERROR;
+ goto error;
+ }
+
+ back_slash = false;
+ cur++;
+ len++;
+ break;
+ }
+
+ if (*cur == '"') {
+ if (cur == *index) {
+ val_state = val_lqoute;
+ } else {
+ if (*(cur - 1) != '\\') {
+ tscError("SML:0x%"PRIx64" field value: state(%d), \" not escaped", info->id, val_state);
+ ret = TSDB_CODE_TSC_LINE_SYNTAX_ERROR;
+ goto error;
+ }
+ }
+
+ cur += 1;
+ len += 1;
+ break;
+ } else if (*cur == 'L') {
+ line_len = strlen(*index);
+
+ /* common character at the end */
+ if (cur + 1 >= *index + line_len) {
+ *is_last_kv = true;
+ kv_done = true;
+ break;
+ }
+
+ if (*(cur + 1) == '"') {
+ /* string starts here */
+ if (cur + 1 == *index + 1) {
+ val_state = val_lqoute;
+ cur += 2;
+ len += 2;
+ } else {
+ /* MUST at the end of string */
+ if (cur + 2 >= *index + line_len) {
+ cur += 2;
+ len += 2;
+ *is_last_kv = true;
+ kv_done = true;
+ } else {
+ if (*(cur + 2) != ' ' && *(cur + 2) != ',') {
+ tscError("SML:0x%"PRIx64" field value: state(%d), not closing character(L\")", info->id, val_state);
+ ret = TSDB_CODE_TSC_LINE_SYNTAX_ERROR;
+ goto error;
+ } else {
+ if (*(cur + 2) == ' ') {
+ *is_last_kv = true;
+ }
+
+ cur += 2;
+ len += 2;
+ kv_done = true;
+ }
+ }
+ }
+ break;
+ }
+ }
+
+ switch (*cur) {
+ case '\\':
+ back_slash = true;
+ cur++;
+ len++;
+ break;
+
+ case ',':
+ kv_done = true;
+ break;
+
+ case ' ':
+ /* fall through */
+ case '\0':
+ *is_last_kv = true;
+ kv_done = true;
+ break;
+
+ default:
+ cur++;
+ len++;
+ }
+
break;
+ case val_lqoute:
+ if (back_slash == true) {
+ if (*cur != '\\' && *cur != '"') {
+ tscError("SML:0x%"PRIx64" field value: state(%d), incorrect character(%c) escaped", info->id, val_state, *cur);
+ ret = TSDB_CODE_TSC_LINE_SYNTAX_ERROR;
+ goto error;
+ }
+
+ back_slash = false;
+ cur++;
+ len++;
+ break;
+ } else if (double_quote == true) {
+ if (*cur != ' ' && *cur != ',' && *cur != '\0') {
+ tscError("SML:0x%"PRIx64" field value: state(%d), incorrect character(%c) behind closing \"", info->id, val_state, *cur);
+ ret = TSDB_CODE_TSC_LINE_SYNTAX_ERROR;
+ goto error;
+ }
+
+ if (*cur == ' ' || *cur == '\0') {
+ *is_last_kv = true;
+ }
+
+ double_quote = false;
+ val_state = val_rqoute;
+ break;
+ }
+
+ switch (*cur) {
+ case '\\':
+ back_slash = true;
+ cur++;
+ len++;
+ break;
+
+ case '"':
+ double_quote = true;
+ cur++;
+ len++;
+ break;
+
+ case '\0':
+ tscError("SML:0x%"PRIx64" field value: state(%d), closing \" not found", info->id, val_state);
+ ret = TSDB_CODE_TSC_LINE_SYNTAX_ERROR;
+ kv_done = true;
+ break;
+
+ default:
+ cur++;
+ len++;
+ }
+
+ break;
+ default:
+ kv_done = true;
}
}
- //Escape special character
- if (*cur == '\\') {
- tmp = cur;
- escapeSpecialCharacter(isTag ? 2 : 3, &cur);
- if (tmp != cur) {
- continue;
- }
+
+ if (kv_done == true) {
+ break;
}
- cur++;
- len++;
}
- if (len == 0) {
+
+ if (len == 0 || ret != TSDB_CODE_SUCCESS) {
free(pKV->key);
pKV->key = NULL;
return TSDB_CODE_TSC_LINE_SYNTAX_ERROR;
diff --git a/src/client/src/tscUtil.c b/src/client/src/tscUtil.c
index 91e2d0c388d0b6dd50ca999d35be7712f8bb18dd..653df4baa1db9e2d13ebbcae5b11b9af93a2d1c5 100644
--- a/src/client/src/tscUtil.c
+++ b/src/client/src/tscUtil.c
@@ -4946,7 +4946,7 @@ static int32_t createGlobalAggregateExpr(SQueryAttr* pQueryAttr, SQueryInfo* pQu
pse->colType = pExpr->base.resType;
if(pExpr->base.resBytes > INT16_MAX &&
(pExpr->base.functionId == TSDB_FUNC_UNIQUE || pExpr->base.functionId == TSDB_FUNC_MODE
- || pExpr->base.functionId == TSDB_FUNC_TAIL)){
+ || pExpr->base.functionId == TSDB_FUNC_TAIL || pExpr->base.functionId == TSDB_FUNC_SAMPLE)){
pQueryAttr->interBytesForGlobal = pExpr->base.resBytes;
}else{
pse->colBytes = pExpr->base.resBytes;
diff --git a/src/common/inc/tname.h b/src/common/inc/tname.h
index 9c8e31a9131d0d9ffa3d4cb71e813e3d2a34f2b7..6c4b54ec3cfb2f46acf5341ecda7015035866e59 100644
--- a/src/common/inc/tname.h
+++ b/src/common/inc/tname.h
@@ -54,8 +54,8 @@ typedef struct SSqlExpr {
int32_t resBytes; // length of return value
int32_t interBytes; // inter result buffer size
- int16_t colType; // table column type, this should be int32_t, because it is too small for globale merge stage, pQueryAttr->interBytesForGlobal
- int16_t colBytes; // table column bytes
+ int16_t colType; // table column type
+ int16_t colBytes; // table column bytes,it should be int32_t, because it is too small for globale merge stage, pQueryAttr->interBytesForGlobal
int16_t numOfParams; // argument value of each function
tVariant param[3]; // parameters are not more than 3
diff --git a/src/common/src/tdataformat.c b/src/common/src/tdataformat.c
index d8999a0b6fece9cda4d5c8e2af82e65afa4ed580..55afd4c62096974e379e78d448086f10e9860764 100644
--- a/src/common/src/tdataformat.c
+++ b/src/common/src/tdataformat.c
@@ -624,8 +624,9 @@ static void tdMergeTwoDataCols(SDataCols *target, SDataCols *src1, int *iter1, i
if ((key1 > key2) || (key1 == key2 && !TKEY_IS_DELETED(tkey2))) {
for (int i = 0; i < src2->numOfCols; i++) {
ASSERT(target->cols[i].type == src2->cols[i].type);
- if (src2->cols[i].len > 0 && !isNull(src2->cols[i].pData, src2->cols[i].type)) {
- dataColAppendVal(&(target->cols[i]), tdGetColDataOfRow(src2->cols + i, *iter2), target->numOfRows,
+ const void *src2Val = tdGetColDataOfRow(src2->cols + i, *iter2);
+ if (src2->cols[i].len > 0 && !isNull(src2Val, src2->cols[i].type)) {
+ dataColAppendVal(&(target->cols[i]), src2Val, target->numOfRows,
target->maxPoints, 0);
} else if(!forceSetNull && key1 == key2 && src1->cols[i].len > 0) {
dataColAppendVal(&(target->cols[i]), tdGetColDataOfRow(src1->cols + i, *iter1), target->numOfRows,
diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBJNIConnector.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBJNIConnector.java
index 093baef3cac5b33e6be74248a289addbc1e18e9d..3cc28b4de68cae7bcf337b12ba924454d5653706 100755
--- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBJNIConnector.java
+++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBJNIConnector.java
@@ -338,7 +338,7 @@ public class TSDBJNIConnector {
public void addBatch(long stmt) throws SQLException {
int code = addBatchImp(stmt, this.taos);
- if (code != TSDBConstants.JNI_SUCCESS){
+ if (code != TSDBConstants.JNI_SUCCESS) {
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNKNOWN, stmtErrorMsgImp(stmt, this.taos));
}
}
@@ -361,13 +361,24 @@ public class TSDBJNIConnector {
/*************************************************************************************************/
// NOTE: schemaless-lines
public void insertLines(String[] lines, SchemalessProtocolType protocolType, SchemalessTimestampType timestampType) throws SQLException {
- int code = insertLinesImp(lines, this.taos, protocolType.ordinal(), timestampType.ordinal());
- if (code != TSDBConstants.JNI_SUCCESS) {
- throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNKNOWN, "failed to insertLines");
+ long pSql = schemalessInsertImp(lines, this.taos, protocolType.ordinal(), timestampType.ordinal());
+ try {
+ if (pSql == TSDBConstants.JNI_CONNECTION_NULL) {
+ throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_JNI_CONNECTION_NULL);
+ }
+ if (pSql == TSDBConstants.JNI_OUT_OF_MEMORY) {
+ throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_JNI_OUT_OF_MEMORY);
+ }
+
+ int code = this.getErrCode(pSql);
+ if (code != TSDBConstants.JNI_SUCCESS) {
+ String msg = this.getErrMsg(pSql);
+ throw TSDBError.createSQLException(code, msg);
+ }
+ } finally {
+ this.freeResultSetImp(this.taos, pSql);
}
}
- private native int insertLinesImp(String[] lines, long conn, int type, int precision);
-
-
+ private native long schemalessInsertImp(String[] lines, long conn, int type, int precision);
}
diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSet.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSet.java
index 003324d27a57c3557f0bb3205fcee208aa776ed5..e1e15d0332ca465c31c2ef2726b181716298378e 100644
--- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSet.java
+++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSet.java
@@ -19,7 +19,6 @@ import com.google.common.primitives.Longs;
import com.google.common.primitives.Shorts;
import java.math.BigDecimal;
-import java.nio.charset.StandardCharsets;
import java.sql.*;
import java.util.ArrayList;
import java.util.Calendar;
@@ -53,7 +52,7 @@ public class TSDBResultSet extends AbstractResultSet implements ResultSet {
return rowData;
}
- public TSDBResultSet(TSDBStatement statement, TSDBJNIConnector connector, long resultSetPointer) throws SQLException {
+ public TSDBResultSet(TSDBStatement statement, TSDBJNIConnector connector, long resultSetPointer, int timestampPrecision) throws SQLException {
this.statement = statement;
this.jniConnector = connector;
this.resultSetPointer = resultSetPointer;
@@ -69,7 +68,8 @@ public class TSDBResultSet extends AbstractResultSet implements ResultSet {
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_JNI_NUM_OF_FIELDS_0);
}
this.rowData = new TSDBResultSetRowData(this.columnMetaDataList.size());
- this.blockData = new TSDBResultSetBlockData(this.columnMetaDataList, this.columnMetaDataList.size());
+ this.blockData = new TSDBResultSetBlockData(this.columnMetaDataList, this.columnMetaDataList.size(), timestampPrecision);
+ this.timestampPrecision = timestampPrecision;
}
public boolean next() throws SQLException {
@@ -268,7 +268,7 @@ public class TSDBResultSet extends AbstractResultSet implements ResultSet {
checkAvailability(columnIndex, this.columnMetaDataList.size());
if (this.getBatchFetch())
- return this.blockData.getString(columnIndex).getBytes();
+ return this.blockData.getBytes(columnIndex -1);
Object value = this.rowData.getObject(columnIndex);
this.lastWasNull = value == null;
@@ -343,7 +343,7 @@ public class TSDBResultSet extends AbstractResultSet implements ResultSet {
@Override
public BigDecimal getBigDecimal(int columnIndex) throws SQLException {
if (this.getBatchFetch())
- return new BigDecimal(this.blockData.getLong(columnIndex - 1));
+ return BigDecimal.valueOf(this.blockData.getDouble(columnIndex - 1));
this.lastWasNull = this.rowData.wasNull(columnIndex);
if (lastWasNull)
diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetBlockData.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetBlockData.java
index a74c9cbb8831c5b1142b5ddd3b6b17f95249b873..cdf30dd6974f01677186e432c53fd4649234b2bd 100644
--- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetBlockData.java
+++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetBlockData.java
@@ -25,10 +25,15 @@ import java.nio.ShortBuffer;
import java.sql.SQLDataException;
import java.sql.SQLException;
import java.sql.Timestamp;
+import java.time.Instant;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import com.google.common.primitives.Ints;
+import com.google.common.primitives.Longs;
+import com.google.common.primitives.Shorts;
+import com.taosdata.jdbc.enums.TimestampPrecision;
import com.taosdata.jdbc.utils.NullType;
public class TSDBResultSetBlockData {
@@ -39,9 +44,12 @@ public class TSDBResultSetBlockData {
private List columnMetaDataList;
private ArrayList